Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT 2 : // This file is part of AsmJit project <https://asmjit.com> 3 : // 4 : // See asmjit.h or LICENSE.md for license and copyright information 5 : // SPDX-License-Identifier: Zlib 6 : 7 : #ifndef ASMJIT_CORE_COMPILERDEFS_H_INCLUDED 8 : #define ASMJIT_CORE_COMPILERDEFS_H_INCLUDED 9 : 10 : #include "api-config.h" 11 : #include "operand.h" 12 : #include "type.h" 13 : #include "zonestring.h" 14 : 15 : ASMJIT_BEGIN_NAMESPACE 16 : 17 : class RAWorkReg; 18 : 19 : //! \addtogroup asmjit_compiler 20 : //! \{ 21 : 22 : //! Virtual register data, managed by \ref BaseCompiler. 23 : class VirtReg { 24 : public: 25 : ASMJIT_NONCOPYABLE(VirtReg) 26 : 27 : //! \name Members 28 : //! \{ 29 : 30 : //! Virtual register signature. 31 : OperandSignature _signature {}; 32 : //! Virtual register id. 33 : uint32_t _id = 0; 34 : //! Virtual register size (can be smaller than `_signature._size`). 35 : uint32_t _virtSize = 0; 36 : //! Virtual register alignment (for spilling). 37 : uint8_t _alignment = 0; 38 : //! Type-id. 39 : TypeId _typeId = TypeId::kVoid; 40 : //! Virtual register weight for alloc/spill decisions. 41 : uint8_t _weight = 1; 42 : //! True if this is a fixed register, never reallocated. 43 : uint8_t _isFixed : 1; 44 : //! True if the virtual register is only used as a stack (never accessed as register). 45 : uint8_t _isStack : 1; 46 : //! True if this virtual register has assigned stack offset (can be only valid after register allocation pass). 47 : uint8_t _hasStackSlot : 1; 48 : uint8_t _reservedBits : 5; 49 : 50 : //! Stack offset assigned by the register allocator relative to stack pointer (can be negative as well). 51 : int32_t _stackOffset = 0; 52 : 53 : //! Reserved for future use (padding). 54 : uint32_t _reservedU32 = 0; 55 : 56 : //! Virtual register name (user provided or automatically generated). 57 : ZoneString<16> _name {}; 58 : 59 : // The following members are used exclusively by RAPass. They are initialized when the VirtReg is created to 60 : // null pointers and then changed during RAPass execution. RAPass sets them back to NULL before it returns. 61 : 62 : //! Reference to `RAWorkReg`, used during register allocation. 63 : RAWorkReg* _workReg = nullptr; 64 : 65 : //! \} 66 : 67 : //! \name Construction & Destruction 68 : //! \{ 69 : 70 : inline VirtReg(OperandSignature signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept 71 273777 : : _signature(signature), 72 273777 : _id(id), 73 273777 : _virtSize(virtSize), 74 273777 : _alignment(uint8_t(alignment)), 75 273777 : _typeId(typeId), 76 273777 : _isFixed(false), 77 273777 : _isStack(false), 78 273777 : _hasStackSlot(false), 79 273777 : _reservedBits(0), 80 273777 : _stackOffset(0), 81 273777 : _reservedU32(0) {} 82 : 83 : //! \} 84 : 85 : //! \name Accessors 86 : //! \{ 87 : 88 : //! Returns the virtual register id. 89 545091 : inline uint32_t id() const noexcept { return _id; } 90 : 91 : //! Returns the virtual register name. 92 : inline const char* name() const noexcept { return _name.data(); } 93 : //! Returns the size of the virtual register name. 94 : inline uint32_t nameSize() const noexcept { return _name.size(); } 95 : 96 : //! Returns a register signature of this virtual register. 97 271314 : inline OperandSignature signature() const noexcept { return _signature; } 98 : //! Returns a virtual register type (maps to the physical register type as well). 99 : inline RegType type() const noexcept { return _signature.regType(); } 100 : //! Returns a virtual register group (maps to the physical register group as well). 101 : inline RegGroup group() const noexcept { return _signature.regGroup(); } 102 : 103 : //! Returns a real size of the register this virtual register maps to. 104 : //! 105 : //! For example if this is a 128-bit SIMD register used for a scalar single precision floating point value then 106 : //! its virtSize would be 4, however, the `regSize` would still say 16 (128-bits), because it's the smallest size 107 : //! of that register type. 108 : inline uint32_t regSize() const noexcept { return _signature.size(); } 109 : 110 : //! Returns the virtual register size. 111 : //! 112 : //! The virtual register size describes how many bytes the virtual register needs to store its content. It can be 113 : //! smaller than the physical register size, see `regSize()`. 114 325218 : inline uint32_t virtSize() const noexcept { return _virtSize; } 115 : 116 : //! Returns the virtual register alignment. 117 30798 : inline uint32_t alignment() const noexcept { return _alignment; } 118 : 119 : //! Returns the virtual register type id. 120 50221 : inline TypeId typeId() const noexcept { return _typeId; } 121 : 122 : //! Returns the virtual register weight - the register allocator can use it as explicit hint for alloc/spill 123 : //! decisions. 124 271314 : inline uint32_t weight() const noexcept { return _weight; } 125 : //! Sets the virtual register weight (0 to 255) - the register allocator can use it as explicit hint for 126 : //! alloc/spill decisions and initial bin-packing. 127 188 : inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } 128 : 129 : //! Returns whether the virtual register is always allocated to a fixed physical register (and never reallocated). 130 : //! 131 : //! \note This is only used for special purposes and it's mostly internal. 132 : inline bool isFixed() const noexcept { return bool(_isFixed); } 133 : 134 : //! Tests whether the virtual register is in fact a stack that only uses the virtual register id. 135 : //! 136 : //! \note It's an error if a stack is accessed as a register. 137 271314 : inline bool isStack() const noexcept { return bool(_isStack); } 138 : 139 : //! Tests whether this virtual register (or stack) has assigned a stack offset. 140 : //! 141 : //! If this is a virtual register that was never allocated on stack, it would return false, otherwise if 142 : //! it's a virtual register that was spilled or explicitly allocated stack, the return value would be true. 143 : inline bool hasStackSlot() const noexcept { return bool(_hasStackSlot); } 144 : 145 : //! Assigns a stack offset of this virtual register to `stackOffset` and sets `_hasStackSlot` to true. 146 : inline void assignStackSlot(int32_t stackOffset) noexcept { 147 30798 : _hasStackSlot = 1; 148 30798 : _stackOffset = stackOffset; 149 30798 : } 150 : 151 : //! Returns a stack offset associated with a virtual register or explicit stack allocation. 152 : //! 153 : //! \note Always verify that the stack offset has been assigned by calling \ref hasStackSlot(). The return 154 : //! value will be zero when the stack offset was not assigned. 155 : inline int32_t stackOffset() const noexcept { return _stackOffset; } 156 : 157 : //! Tests whether the virtual register has an associated `RAWorkReg` at the moment. 158 : inline bool hasWorkReg() const noexcept { return _workReg != nullptr; } 159 : //! Returns an associated RAWorkReg with this virtual register (only valid during register allocation). 160 783840 : inline RAWorkReg* workReg() const noexcept { return _workReg; } 161 : //! Associates a RAWorkReg with this virtual register (used by register allocator). 162 271314 : inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } 163 : //! Reset the RAWorkReg association (used by register allocator). 164 : inline void resetWorkReg() noexcept { _workReg = nullptr; } 165 : 166 : //! \} 167 : }; 168 : 169 : //! \} 170 : 171 : ASMJIT_END_NAMESPACE 172 : 173 : #endif // ASMJIT_CORE_COMPILERDEFS_H_INCLUDED 174 : 175 : 176 : #endif // __PLUMED_HAS_ASMJIT