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_FUNCARGSCONTEXT_P_H_INCLUDED 8 : #define ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED 9 : 10 : #include "archtraits.h" 11 : #include "environment.h" 12 : #include "func.h" 13 : #include "operand.h" 14 : #include "radefs_p.h" 15 : #include "support.h" 16 : 17 : ASMJIT_BEGIN_NAMESPACE 18 : 19 : //! \cond INTERNAL 20 : //! \addtogroup asmjit_core 21 : //! \{ 22 : 23 0 : static inline OperandSignature getSuitableRegForMemToMemMove(Arch arch, TypeId dstTypeId, TypeId srcTypeId) noexcept { 24 : const ArchTraits& archTraits = ArchTraits::byArch(arch); 25 : 26 : uint32_t dstSize = TypeUtils::sizeOf(dstTypeId); 27 : uint32_t srcSize = TypeUtils::sizeOf(srcTypeId); 28 : uint32_t maxSize = Support::max<uint32_t>(dstSize, srcSize); 29 : uint32_t regSize = Environment::registerSizeFromArch(arch); 30 : 31 : OperandSignature signature{0}; 32 0 : if (maxSize <= regSize || (TypeUtils::isInt(dstTypeId) && TypeUtils::isInt(srcTypeId))) 33 0 : signature = maxSize <= 4 ? archTraits.regTypeToSignature(RegType::kGp32) 34 : : archTraits.regTypeToSignature(RegType::kGp64); 35 0 : else if (maxSize <= 8 && archTraits.hasRegType(RegType::kVec64)) 36 : signature = archTraits.regTypeToSignature(RegType::kVec64); 37 0 : else if (maxSize <= 16 && archTraits.hasRegType(RegType::kVec128)) 38 : signature = archTraits.regTypeToSignature(RegType::kVec128); 39 0 : else if (maxSize <= 32 && archTraits.hasRegType(RegType::kVec256)) 40 : signature = archTraits.regTypeToSignature(RegType::kVec256); 41 0 : else if (maxSize <= 64 && archTraits.hasRegType(RegType::kVec512)) 42 : signature = archTraits.regTypeToSignature(RegType::kVec512); 43 : 44 0 : return signature; 45 : } 46 : 47 : class FuncArgsContext { 48 : public: 49 : enum VarId : uint32_t { 50 : kVarIdNone = 0xFF 51 : }; 52 : 53 : //! Contains information about a single argument or SA register that may need shuffling. 54 : struct Var { 55 : FuncValue cur; 56 : FuncValue out; 57 : 58 : inline void init(const FuncValue& cur_, const FuncValue& out_) noexcept { 59 0 : cur = cur_; 60 0 : out = out_; 61 : } 62 : 63 : //! Reset the value to its unassigned state. 64 : inline void reset() noexcept { 65 : cur.reset(); 66 : out.reset(); 67 : } 68 : 69 : inline bool isDone() const noexcept { return cur.isDone(); } 70 0 : inline void markDone() noexcept { cur.addFlags(FuncValue::kFlagIsDone); } 71 : }; 72 : 73 : struct WorkData { 74 : //! All allocable registers provided by the architecture. 75 : RegMask _archRegs; 76 : //! All registers that can be used by the shuffler. 77 : RegMask _workRegs; 78 : //! Registers used by the shuffler (all). 79 : RegMask _usedRegs; 80 : //! Assigned registers. 81 : RegMask _assignedRegs; 82 : //! Destination registers assigned to arguments or SA. 83 : RegMask _dstRegs; 84 : //! Destination registers that require shuffling. 85 : RegMask _dstShuf; 86 : //! Number of register swaps. 87 : uint8_t _numSwaps; 88 : //! Number of stack loads. 89 : uint8_t _numStackArgs; 90 : //! Reserved (only used as padding). 91 : uint8_t _reserved[6]; 92 : //! Physical ID to variable ID mapping. 93 : uint8_t _physToVarId[32]; 94 : 95 219936 : inline void reset() noexcept { 96 219936 : _archRegs = 0; 97 219936 : _workRegs = 0; 98 219936 : _usedRegs = 0; 99 219936 : _assignedRegs = 0; 100 219936 : _dstRegs = 0; 101 219936 : _dstShuf = 0; 102 219936 : _numSwaps = 0; 103 219936 : _numStackArgs = 0; 104 219936 : memset(_reserved, 0, sizeof(_reserved)); 105 219936 : memset(_physToVarId, kVarIdNone, 32); 106 219936 : } 107 : 108 : inline bool isAssigned(uint32_t regId) const noexcept { 109 : ASMJIT_ASSERT(regId < 32); 110 27492 : return Support::bitTest(_assignedRegs, regId); 111 : } 112 : 113 0 : inline void assign(uint32_t varId, uint32_t regId) noexcept { 114 : ASMJIT_ASSERT(!isAssigned(regId)); 115 : ASMJIT_ASSERT(_physToVarId[regId] == kVarIdNone); 116 : 117 0 : _physToVarId[regId] = uint8_t(varId); 118 0 : _assignedRegs ^= Support::bitMask(regId); 119 0 : } 120 : 121 0 : inline void reassign(uint32_t varId, uint32_t newId, uint32_t oldId) noexcept { 122 : ASMJIT_ASSERT( isAssigned(oldId)); 123 : ASMJIT_ASSERT(!isAssigned(newId)); 124 : ASMJIT_ASSERT(_physToVarId[oldId] == varId); 125 : ASMJIT_ASSERT(_physToVarId[newId] == kVarIdNone); 126 : 127 0 : _physToVarId[oldId] = uint8_t(kVarIdNone); 128 0 : _physToVarId[newId] = uint8_t(varId); 129 0 : _assignedRegs ^= Support::bitMask(newId) ^ Support::bitMask(oldId); 130 0 : } 131 : 132 : inline void swap(uint32_t aVarId, uint32_t aRegId, uint32_t bVarId, uint32_t bRegId) noexcept { 133 : ASMJIT_ASSERT(isAssigned(aRegId)); 134 : ASMJIT_ASSERT(isAssigned(bRegId)); 135 : ASMJIT_ASSERT(_physToVarId[aRegId] == aVarId); 136 : ASMJIT_ASSERT(_physToVarId[bRegId] == bVarId); 137 : 138 0 : _physToVarId[aRegId] = uint8_t(bVarId); 139 0 : _physToVarId[bRegId] = uint8_t(aVarId); 140 : } 141 : 142 0 : inline void unassign(uint32_t varId, uint32_t regId) noexcept { 143 : ASMJIT_ASSERT(isAssigned(regId)); 144 : ASMJIT_ASSERT(_physToVarId[regId] == varId); 145 : 146 : DebugUtils::unused(varId); 147 0 : _physToVarId[regId] = uint8_t(kVarIdNone); 148 0 : _assignedRegs ^= Support::bitMask(regId); 149 0 : } 150 : 151 219936 : inline RegMask archRegs() const noexcept { return _archRegs; } 152 0 : inline RegMask workRegs() const noexcept { return _workRegs; } 153 109968 : inline RegMask usedRegs() const noexcept { return _usedRegs; } 154 219936 : inline RegMask assignedRegs() const noexcept { return _assignedRegs; } 155 219936 : inline RegMask dstRegs() const noexcept { return _dstRegs; } 156 0 : inline RegMask availableRegs() const noexcept { return _workRegs & ~_assignedRegs; } 157 : }; 158 : 159 : //! Architecture traits. 160 : const ArchTraits* _archTraits = nullptr; 161 : //! Architecture constraints. 162 : const RAConstraints* _constraints = nullptr; 163 : //! Target architecture. 164 : Arch _arch = Arch::kUnknown; 165 : //! Has arguments passed via stack (SRC). 166 : bool _hasStackSrc = false; 167 : //! Has preserved frame-pointer (FP). 168 : bool _hasPreservedFP = false; 169 : //! Has arguments assigned to stack (DST). 170 : uint8_t _stackDstMask = 0; 171 : //! Register swap groups (bit-mask). 172 : uint8_t _regSwapsMask = 0; 173 : uint8_t _saVarId = kVarIdNone; 174 : uint32_t _varCount = 0; 175 : Support::Array<WorkData, Globals::kNumVirtGroups> _workData; 176 : Var _vars[Globals::kMaxFuncArgs * Globals::kMaxValuePack + 1]; 177 : 178 : FuncArgsContext() noexcept; 179 : 180 0 : inline const ArchTraits& archTraits() const noexcept { return *_archTraits; } 181 : inline Arch arch() const noexcept { return _arch; } 182 : 183 : inline uint32_t varCount() const noexcept { return _varCount; } 184 : inline size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); } 185 : 186 : inline Var& var(size_t varId) noexcept { return _vars[varId]; } 187 : inline const Var& var(size_t varId) const noexcept { return _vars[varId]; } 188 : 189 : Error initWorkData(const FuncFrame& frame, const FuncArgsAssignment& args, const RAConstraints* constraints) noexcept; 190 : Error markScratchRegs(FuncFrame& frame) noexcept; 191 : Error markDstRegsDirty(FuncFrame& frame) noexcept; 192 : Error markStackArgsReg(FuncFrame& frame) noexcept; 193 : }; 194 : 195 : //! \} 196 : //! \endcond 197 : 198 : ASMJIT_END_NAMESPACE 199 : 200 : #endif // ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED 201 : 202 : #endif // __PLUMED_HAS_ASMJIT