1 // AsmJit - Machine code generation for C++ 2 // 3 // * Official AsmJit Home Page: https://asmjit.com 4 // * Official Github Repository: https://github.com/asmjit/asmjit 5 // 6 // Copyright (c) 2008-2020 The AsmJit Authors 7 // 8 // This software is provided 'as-is', without any express or implied 9 // warranty. In no event will the authors be held liable for any damages 10 // arising from the use of this software. 11 // 12 // Permission is granted to anyone to use this software for any purpose, 13 // including commercial applications, and to alter it and redistribute it 14 // freely, subject to the following restrictions: 15 // 16 // 1. The origin of this software must not be misrepresented; you must not 17 // claim that you wrote the original software. If you use this software 18 // in a product, an acknowledgment in the product documentation would be 19 // appreciated but is not required. 20 // 2. Altered source versions must be plainly marked as such, and must not be 21 // misrepresented as being the original software. 22 // 3. This notice may not be removed or altered from any source distribution. 23 24 #ifndef ASMJIT_CORE_COMPILERDEFS_H_INCLUDED 25 #define ASMJIT_CORE_COMPILERDEFS_H_INCLUDED 26 27 #include "../core/api-config.h" 28 #include "../core/operand.h" 29 #include "../core/zonestring.h" 30 31 ASMJIT_BEGIN_NAMESPACE 32 33 // ============================================================================ 34 // [Forward Declarations] 35 // ============================================================================ 36 37 class RAWorkReg; 38 39 //! \addtogroup asmjit_compiler 40 //! \{ 41 42 // ============================================================================ 43 // [asmjit::VirtReg] 44 // ============================================================================ 45 46 //! Virtual register data, managed by \ref BaseCompiler. 47 class VirtReg { 48 public: 49 ASMJIT_NONCOPYABLE(VirtReg) 50 51 //! Virtual register id. 52 uint32_t _id = 0; 53 //! Virtual register info (signature). 54 RegInfo _info = {}; 55 //! Virtual register size (can be smaller than `regInfo._size`). 56 uint32_t _virtSize = 0; 57 //! Virtual register alignment (for spilling). 58 uint8_t _alignment = 0; 59 //! Type-id. 60 uint8_t _typeId = 0; 61 //! Virtual register weight for alloc/spill decisions. 62 uint8_t _weight = 1; 63 //! True if this is a fixed register, never reallocated. 64 uint8_t _isFixed : 1; 65 //! True if the virtual register is only used as a stack (never accessed as register). 66 uint8_t _isStack : 1; 67 uint8_t _reserved : 6; 68 69 //! Virtual register name (user provided or automatically generated). 70 ZoneString<16> _name {}; 71 72 // ------------------------------------------------------------------------- 73 // The following members are used exclusively by RAPass. They are initialized 74 // when the VirtReg is created to NULL pointers and then changed during RAPass 75 // execution. RAPass sets them back to NULL before it returns. 76 // ------------------------------------------------------------------------- 77 78 //! Reference to `RAWorkReg`, used during register allocation. 79 RAWorkReg* _workReg = nullptr; 80 81 //! \name Construction & Destruction 82 //! \{ 83 VirtReg(uint32_t id,uint32_t signature,uint32_t virtSize,uint32_t alignment,uint32_t typeId)84 inline VirtReg(uint32_t id, uint32_t signature, uint32_t virtSize, uint32_t alignment, uint32_t typeId) noexcept 85 : _id(id), 86 _info { signature }, 87 _virtSize(virtSize), 88 _alignment(uint8_t(alignment)), 89 _typeId(uint8_t(typeId)), 90 _isFixed(false), 91 _isStack(false), 92 _reserved(0) {} 93 94 //! \} 95 96 //! \name Accessors 97 //! \{ 98 99 //! Returns the virtual register id. id()100 inline uint32_t id() const noexcept { return _id; } 101 102 //! Returns the virtual register name. name()103 inline const char* name() const noexcept { return _name.data(); } 104 //! Returns the size of the virtual register name. nameSize()105 inline uint32_t nameSize() const noexcept { return _name.size(); } 106 107 //! Returns a register information that wraps the register signature. info()108 inline const RegInfo& info() const noexcept { return _info; } 109 //! Returns a virtual register type (maps to the physical register type as well). type()110 inline uint32_t type() const noexcept { return _info.type(); } 111 //! Returns a virtual register group (maps to the physical register group as well). group()112 inline uint32_t group() const noexcept { return _info.group(); } 113 114 //! Returns a real size of the register this virtual register maps to. 115 //! 116 //! For example if this is a 128-bit SIMD register used for a scalar single 117 //! precision floating point value then its virtSize would be 4, however, the 118 //! `regSize` would still say 16 (128-bits), because it's the smallest size 119 //! of that register type. regSize()120 inline uint32_t regSize() const noexcept { return _info.size(); } 121 122 //! Returns a register signature of this virtual register. signature()123 inline uint32_t signature() const noexcept { return _info.signature(); } 124 125 //! Returns the virtual register size. 126 //! 127 //! The virtual register size describes how many bytes the virtual register 128 //! needs to store its content. It can be smaller than the physical register 129 //! size, see `regSize()`. virtSize()130 inline uint32_t virtSize() const noexcept { return _virtSize; } 131 132 //! Returns the virtual register alignment. alignment()133 inline uint32_t alignment() const noexcept { return _alignment; } 134 135 //! Returns the virtual register type id, see `Type::Id`. typeId()136 inline uint32_t typeId() const noexcept { return _typeId; } 137 138 //! Returns the virtual register weight - the register allocator can use it 139 //! as explicit hint for alloc/spill decisions. weight()140 inline uint32_t weight() const noexcept { return _weight; } 141 //! Sets the virtual register weight (0 to 255) - the register allocator can 142 //! use it as explicit hint for alloc/spill decisions and initial bin-packing. setWeight(uint32_t weight)143 inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } 144 145 //! Returns whether the virtual register is always allocated to a fixed 146 //! physical register (and never reallocated). 147 //! 148 //! \note This is only used for special purposes and it's mostly internal. isFixed()149 inline bool isFixed() const noexcept { return bool(_isFixed); } 150 151 //! Returns whether the virtual register is indeed a stack that only uses 152 //! the virtual register id for making it accessible. 153 //! 154 //! \note It's an error if a stack is accessed as a register. isStack()155 inline bool isStack() const noexcept { return bool(_isStack); } 156 hasWorkReg()157 inline bool hasWorkReg() const noexcept { return _workReg != nullptr; } workReg()158 inline RAWorkReg* workReg() const noexcept { return _workReg; } setWorkReg(RAWorkReg * workReg)159 inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } resetWorkReg()160 inline void resetWorkReg() noexcept { _workReg = nullptr; } 161 162 //! \} 163 }; 164 165 //! \} 166 167 ASMJIT_END_NAMESPACE 168 169 #endif // ASMJIT_CORE_COMPILERDEFS_H_INCLUDED 170 171