|
TPDE
|
The base class for the compiler. More...
#include <CompilerBase.hpp>
Classes | |
| struct | CallArg |
| Call argument, enhancing an IRValueRef with information on how to pass it. More... | |
| class | CallBuilderBase |
| Base class for target-specific CallBuilder implementations. More... | |
| struct | ScratchReg |
| Owned unspillable and unevictable temporary register with RAII semantics. More... | |
| struct | ValRefSpecial |
| A default implementation for ValRefSpecial. More... | |
Public Member Functions | |
| CompilerBase (Adaptor *adaptor) | |
| Initialize a CompilerBase, should be called by the derived classes. | |
| Derived * | derived () |
| shortcut for casting to the Derived class so that overloading works | |
| bool | compile () |
| Compile the functions returned by Adaptor::funcs. | |
| void | reset () |
| Reset any leftover data from the previous compilation such that it will not affect the next compilation. | |
| CCAssigner * | cur_cc_assigner () noexcept |
| Get CCAssigner for current function. | |
| void | release_assignment (ValLocalIdx local_idx, ValueAssignment *) noexcept |
| Release an assignment when reference count drops to zero, either frees the assignment immediately or delays free to the end of the live range. | |
| void | init_variable_ref (ValLocalIdx local_idx, u32 var_ref_data) noexcept |
| Init a variable-ref assignment. | |
| void | init_variable_ref (IRValueRef value, u32 var_ref_data) noexcept |
| Init a variable-ref assignment. | |
| void | prologue_assign_arg (CCAssigner *cc_assigner, u32 arg_idx, IRValueRef arg, u32 align=1, bool allow_split=false) noexcept |
| Assign function argument in prologue. | |
| AsmReg | gval_as_reg (GenericValuePart &gv) noexcept |
| Get generic value part into a single register, evaluating expressions and materializing immediates as required. | |
| AsmReg | gval_as_reg_reuse (GenericValuePart &gv, ScratchReg &dst) noexcept |
| Like gval_as_reg; if the GenericValuePart owns a reusable register (either a ScratchReg, possibly due to materialization, or a reusable ValuePartRef), store it in dst. | |
| void | label_place (Label label) noexcept |
| Convenience function to place a label at the current position. | |
Stack Slots | |
| i32 | allocate_stack_slot (u32 size) noexcept |
| Allocate a static stack slot. | |
| void | free_stack_slot (u32 slot, u32 size) noexcept |
| Free a static stack slot. | |
Value References | |
| ValueRef | val_ref (IRValueRef value) noexcept |
| Get a using reference to a value. | |
| std::pair< ValueRef, ValuePartRef > | val_ref_single (IRValueRef value) noexcept |
| Get a using reference to a single-part value and provide direct access to the only part. | |
| ValueRef | result_ref (IRValueRef value) noexcept |
| Get a defining reference to a value. | |
| std::pair< ValueRef, ValuePartRef > | result_ref_single (IRValueRef value) noexcept |
| Get a defining reference to a single-part value and provide direct access to the only part. | |
| ValueRef | result_ref_alias (IRValueRef dst, ValueRef &&src) noexcept |
| Make dst an alias for src, which must be a non-constant value with an identical part configuration. | |
| ValueRef | result_ref_stack_slot (IRValueRef value, AssignmentPartRef base, i32 off) noexcept |
| Initialize value as a pointer into a stack variable (i.e., a value allocated from cur_static_allocas() or similar) with an offset. | |
Low-Level Assignment Register Handling | |
| Reg | select_reg (RegBank bank, u64 exclusion_mask) noexcept |
| Select an available register, evicting loaded values if needed. | |
| void | reload_to_reg (AsmReg dst, AssignmentPartRef ap) noexcept |
| Reload a value part from memory or recompute variable address. | |
| void | allocate_spill_slot (AssignmentPartRef ap) noexcept |
| Allocate a stack slot for an assignment. | |
| void | spill (AssignmentPartRef ap) noexcept |
| Ensure the value is spilled in its stack slot (except variable refs). | |
| void | evict (AssignmentPartRef ap) noexcept |
| Evict the value from its register, spilling if needed, and free register. | |
| void | evict_reg (Reg reg) noexcept |
| Evict the value from the register, spilling if needed, and free register. | |
| void | free_reg (Reg reg) noexcept |
| Free the register. Requires that the contained value is already spilled. | |
High-Level Branch Generation | |
| void | generate_uncond_branch (IRBlockRef target) noexcept |
| Generate an unconditional branch at the end of a basic block. | |
| template<typename Jump> | |
| void | generate_cond_branch (Jump jmp, IRBlockRef true_target, IRBlockRef false_target) noexcept |
| Generate an conditional branch at the end of a basic block. | |
| void | generate_switch (ScratchReg &&cond, u32 width, IRBlockRef default_block, std::span< const std::pair< u64, IRBlockRef > > cases) noexcept |
| Generate a switch at the end of a basic block. | |
Low-Level Branch Primitives | |
The general flow of using these low-level primitive is: | |
| RegisterFile::RegBitSet | spill_before_branch (bool force_spill=false) noexcept |
| Spill values that need to be spilled for later blocks. | |
| void | release_spilled_regs (typename RegisterFile::RegBitSet) noexcept |
| Free registers marked by spill_before_branch(). | |
| void | release_regs_after_return () noexcept |
| When reaching a point in the function where no other blocks will be reached anymore, use this function to release register assignments after the end of that block so the compiler does not accidentally use registers which don't contain any values. | |
| void | begin_branch_region () noexcept |
| Indicate beginning of region where value-state must not change. | |
| void | end_branch_region () noexcept |
| Indicate end of region where value-state must not change. | |
| template<typename Jump> | |
| void | generate_branch_to_block (Jump jmp, IRBlockRef target, bool needs_split, bool last_inst) noexcept |
| Generate a branch to a basic block; execution continues afterwards. | |
| bool | branch_needs_split (IRBlockRef target) noexcept |
| Whether branch to a block requires additional instructions and therefore a direct jump to the block is not possible. | |
Public Attributes | |
| bool | generating_branch = false |
| Whether we are currently in the middle of generating branch-related code and therefore must not change any value-related state. | |
The base class for the compiler.
It implements the main platform independent compilation logic and houses the analyzer
Definition at line 102 of file CompilerBase.hpp.
| bool tpde::CompilerBase< Adaptor, Derived, Config >::compile | ( | ) |
Compile the functions returned by Adaptor::funcs.
Definition at line 827 of file CompilerBase.hpp.
|
noexcept |
Generate a branch to a basic block; execution continues afterwards.
Multiple calls to this function can be used to build conditional branches.
| Jump | Target-defined Jump type (e.g., CompilerX64::Jump). |
| needs_split | Result of branch_needs_split(); pass false for an unconditional branch. |
| last_inst | Whether fall-through to target is possible. |
Definition at line 1659 of file CompilerBase.hpp.
|
noexcept |
Generate a switch at the end of a basic block.
Only the lowest bits of the condition are considered. The condition must be a general-purpose register. The cases must be sorted and every case value must appear at most once.
Definition at line 1719 of file CompilerBase.hpp.
|
noexcept |
Generate an unconditional branch at the end of a basic block.
No further instructions must follow. If target is the next block in the block order, the branch is omitted.
Definition at line 1678 of file CompilerBase.hpp.
|
noexcept |
Assign function argument in prologue.
align can be used to increase the minimal stack alignment of the first part of the argument. If allow_split is set, the argument can be passed partially in registers, otherwise (default) it must be either passed completely in registers or completely on the stack.
Definition at line 1146 of file CompilerBase.hpp.
|
noexcept |
Make dst an alias for src, which must be a non-constant value with an identical part configuration.
src must be in its last use (is_owned()), and the assignment will be repurposed for dst, keeping all assigned registers and stack slots.
Definition at line 1252 of file CompilerBase.hpp.
|
noexcept |
Get a defining reference to a single-part value and provide direct access to the only part.
Similar to val_ref_single().
Definition at line 1243 of file CompilerBase.hpp.
|
noexcept |
Initialize value as a pointer into a stack variable (i.e., a value allocated from cur_static_allocas() or similar) with an offset.
The result value will be a stack variable itself.
Definition at line 1306 of file CompilerBase.hpp.
|
noexcept |
Spill values that need to be spilled for later blocks.
Returns the set of registers that will be free'd at the end of the block; pass this to release_spilled_regs().
Definition at line 1523 of file CompilerBase.hpp.
|
noexcept |
Get a using reference to a single-part value and provide direct access to the only part.
This is a convenience function; note that the ValueRef must outlive the ValuePartRef (i.e. auto p = val_ref().part(0); won't work, as the value will possibly be deallocated when the ValueRef is destroyed).
Definition at line 1222 of file CompilerBase.hpp.
| bool tpde::CompilerBase< Adaptor, Derived, Config >::frame_used |
Whether the stack frame is used.
If the stack frame is never used, the frame setup can in some cases be omitted entirely.
Definition at line 144 of file CompilerBase.hpp.
| bool tpde::CompilerBase< Adaptor, Derived, Config >::generated_call |
Whether the function actually includes a call.
There are cases, where it is not clear from the beginning whether a function has function calls. If a function has no calls, this will allow using the red zone guaranteed by some ABIs.
Definition at line 141 of file CompilerBase.hpp.
| bool tpde::CompilerBase< Adaptor, Derived, Config >::has_dynamic_alloca |
Whether the stack frame might have dynamic alloca.
Dynamic allocas may require a different and less efficient frame setup.
Definition at line 133 of file CompilerBase.hpp.
| bool tpde::CompilerBase< Adaptor, Derived, Config >::is_leaf_function |
Whether the function is guaranteed to be a leaf function.
Throughout the entire function, the compiler may assume the absence of function calls.
Definition at line 136 of file CompilerBase.hpp.