1 // [AsmJit] 2 // Complete JIT Assembler for C++ Language. 3 // 4 // [License] 5 // Zlib - See COPYING file in this package. 6 7 // [Guard] 8 #ifndef _ASMJIT_X86_X86COMPILERCONTEXT_H 9 #define _ASMJIT_X86_X86COMPILERCONTEXT_H 10 11 // [Dependencies - AsmJit] 12 #include "../core/intutil.h" 13 #include "../core/podvector.h" 14 15 #include "../x86/x86assembler.h" 16 #include "../x86/x86compiler.h" 17 #include "../x86/x86compilerfunc.h" 18 #include "../x86/x86compileritem.h" 19 20 // [Api-Begin] 21 #include "../core/apibegin.h" 22 23 namespace AsmJit { 24 25 //! @addtogroup AsmJit_X86 26 //! @{ 27 28 // ============================================================================ 29 // [AsmJit::X86CompilerContext] 30 // ============================================================================ 31 32 //! @internal 33 //! 34 //! @brief Compiler context is used by @ref X86Compiler. 35 //! 36 //! X86Compiler context is used during compilation and normally developer doesn't 37 //! need access to it. The context is user per function (it's reset after each 38 //! function is generated). 39 struct X86CompilerContext : public CompilerContext 40 { 41 // -------------------------------------------------------------------------- 42 // [Construction / Destruction] 43 // -------------------------------------------------------------------------- 44 45 //! @brief Create a new @ref X86CompilerContext instance. 46 ASMJIT_API X86CompilerContext(X86Compiler* x86Compiler); 47 //! @brief Destroy the @ref X86CompilerContext instance. 48 ASMJIT_API ~X86CompilerContext(); 49 50 // -------------------------------------------------------------------------- 51 // [Accessor] 52 // -------------------------------------------------------------------------- 53 54 //! @brief Get compiler as @ref X86Compiler. getCompilerX86CompilerContext55 inline X86Compiler* getCompiler() const 56 { return reinterpret_cast<X86Compiler*>(_compiler); } 57 58 //! @brief Get function as @ref X86CompilerFuncDecl. getFuncX86CompilerContext59 inline X86CompilerFuncDecl* getFunc() const 60 { return reinterpret_cast<X86CompilerFuncDecl*>(_func); } 61 62 // -------------------------------------------------------------------------- 63 // [Clear] 64 // -------------------------------------------------------------------------- 65 66 //! @brief Clear context, preparing it for next function generation. 67 ASMJIT_API void _clear(); 68 69 // -------------------------------------------------------------------------- 70 // [Register Allocator] 71 // -------------------------------------------------------------------------- 72 73 //! @brief Allocate variable 74 //! 75 //! Calls @c allocGpVar, @c allocMmVar or @c allocXmmVar methods. 76 ASMJIT_API void allocVar(X86CompilerVar* cv, uint32_t regMask, uint32_t vflags); 77 78 //! @brief Save variable. 79 //! 80 //! Calls @c saveGpVar, @c saveMmVar or @c saveXmmVar methods. 81 ASMJIT_API void saveVar(X86CompilerVar* cv); 82 83 //! @brief Spill variable. 84 //! 85 //! Calls @c spillGpVar, @c spillMmVar or @c spillXmmVar methods. 86 ASMJIT_API void spillVar(X86CompilerVar* cv); 87 88 //! @brief Unuse variable (didn't spill, just forget about it). 89 ASMJIT_API void unuseVar(X86CompilerVar* cv, uint32_t toState); 90 91 //! @brief Helper method that is called for each variable per item. _unuseVarOnEndOfScopeX86CompilerContext92 inline void _unuseVarOnEndOfScope(CompilerItem* item, X86CompilerVar* cv) 93 { 94 if (cv->lastItem == item) 95 unuseVar(cv, kVarStateUnused); 96 } 97 //! @overload _unuseVarOnEndOfScopeX86CompilerContext98 inline void _unuseVarOnEndOfScope(CompilerItem* item, VarAllocRecord* rec) 99 { 100 X86CompilerVar* cv = rec->vdata; 101 if (cv->lastItem == item || (rec->vflags & kVarAllocUnuseAfterUse)) 102 unuseVar(cv, kVarStateUnused); 103 } 104 //! @overload _unuseVarOnEndOfScopeX86CompilerContext105 inline void _unuseVarOnEndOfScope(CompilerItem* item, VarCallRecord* rec) 106 { 107 X86CompilerVar* v = rec->vdata; 108 if (v->lastItem == item || (rec->flags & VarCallRecord::kFlagUnuseAfterUse)) 109 unuseVar(v, kVarStateUnused); 110 } 111 112 //! @brief Allocate variable (GP). 113 ASMJIT_API void allocGpVar(X86CompilerVar* cv, uint32_t regMask, uint32_t vflags); 114 //! @brief Save variable (GP). 115 ASMJIT_API void saveGpVar(X86CompilerVar* cv); 116 //! @brief Spill variable (GP). 117 ASMJIT_API void spillGpVar(X86CompilerVar* cv); 118 119 //! @brief Allocate variable (MM). 120 ASMJIT_API void allocMmVar(X86CompilerVar* cv, uint32_t regMask, uint32_t vflags); 121 //! @brief Save variable (MM). 122 ASMJIT_API void saveMmVar(X86CompilerVar* cv); 123 //! @brief Spill variable (MM). 124 ASMJIT_API void spillMmVar(X86CompilerVar* cv); 125 126 //! @brief Allocate variable (XMM). 127 ASMJIT_API void allocXmmVar(X86CompilerVar* cv, uint32_t regMask, uint32_t vflags); 128 //! @brief Save variable (XMM). 129 ASMJIT_API void saveXmmVar(X86CompilerVar* cv); 130 //! @brief Spill variable (XMM). 131 ASMJIT_API void spillXmmVar(X86CompilerVar* cv); 132 133 //! @brief Emit load variable instruction(s). 134 ASMJIT_API void emitLoadVar(X86CompilerVar* cv, uint32_t regIndex); 135 //! @brief Emit save variable instruction(s). 136 ASMJIT_API void emitSaveVar(X86CompilerVar* cv, uint32_t regIndex); 137 138 //! @brief Emit move variable instruction(s). 139 ASMJIT_API void emitMoveVar(X86CompilerVar* cv, uint32_t regIndex, uint32_t vflags); 140 //! @brief Emit exchange variable instruction(s). 141 ASMJIT_API void emitExchangeVar(X86CompilerVar* cv, uint32_t regIndex, uint32_t vflags, X86CompilerVar* other); 142 143 //! @brief Called each time a variable is alloceted. 144 ASMJIT_API void _postAlloc(X86CompilerVar* cv, uint32_t vflags); 145 //! @brief Marks variable home memory as used (must be called at least once 146 //! for each variable that uses function local memory - stack). 147 ASMJIT_API void _markMemoryUsed(X86CompilerVar* cv); 148 149 ASMJIT_API Mem _getVarMem(X86CompilerVar* cv); 150 151 ASMJIT_API X86CompilerVar* _getSpillCandidateGP(); 152 ASMJIT_API X86CompilerVar* _getSpillCandidateMM(); 153 ASMJIT_API X86CompilerVar* _getSpillCandidateXMM(); 154 ASMJIT_API X86CompilerVar* _getSpillCandidateGeneric(X86CompilerVar** varArray, uint32_t count); 155 _isActiveX86CompilerContext156 inline bool _isActive(X86CompilerVar* cv) 157 { return cv->nextActive != NULL; } 158 159 ASMJIT_API void _addActive(X86CompilerVar* cv); 160 ASMJIT_API void _freeActive(X86CompilerVar* cv); 161 ASMJIT_API void _freeAllActive(); 162 163 ASMJIT_API void _allocatedVariable(X86CompilerVar* cv); 164 _allocatedGpRegisterX86CompilerContext165 inline void _allocatedGpRegister(uint32_t index) 166 { 167 _x86State.usedGP |= IntUtil::maskFromIndex(index); 168 _modifiedGpRegisters |= IntUtil::maskFromIndex(index); 169 } 170 _allocatedMmRegisterX86CompilerContext171 inline void _allocatedMmRegister(uint32_t index) 172 { 173 _x86State.usedMM |= IntUtil::maskFromIndex(index); 174 _modifiedMmRegisters |= IntUtil::maskFromIndex(index); 175 } 176 _allocatedXmmRegisterX86CompilerContext177 inline void _allocatedXmmRegister(uint32_t index) 178 { 179 _x86State.usedXMM |= IntUtil::maskFromIndex(index); 180 _modifiedXmmRegisters |= IntUtil::maskFromIndex(index); 181 } 182 _freedGpRegisterX86CompilerContext183 inline void _freedGpRegister(uint32_t index) 184 { _x86State.usedGP &= ~IntUtil::maskFromIndex(index); } 185 _freedMmRegisterX86CompilerContext186 inline void _freedMmRegister(uint32_t index) 187 { _x86State.usedMM &= ~IntUtil::maskFromIndex(index); } 188 _freedXmmRegisterX86CompilerContext189 inline void _freedXmmRegister(uint32_t index) 190 { _x86State.usedXMM &= ~IntUtil::maskFromIndex(index); } 191 _markGpRegisterModifiedX86CompilerContext192 inline void _markGpRegisterModified(uint32_t index) 193 { _modifiedGpRegisters |= IntUtil::maskFromIndex(index); } 194 _markMmRegisterModifiedX86CompilerContext195 inline void _markMmRegisterModified(uint32_t index) 196 { _modifiedMmRegisters |= IntUtil::maskFromIndex(index); } 197 _markXmmRegisterModifiedX86CompilerContext198 inline void _markXmmRegisterModified(uint32_t index) 199 { _modifiedXmmRegisters |= IntUtil::maskFromIndex(index); } 200 201 // TODO: Find code which uses this and improve. _newRegisterHomeIndexX86CompilerContext202 inline void _newRegisterHomeIndex(X86CompilerVar* cv, uint32_t idx) 203 { 204 if (cv->homeRegisterIndex == kRegIndexInvalid) 205 cv->homeRegisterIndex = idx; 206 cv->prefRegisterMask |= (1U << idx); 207 } 208 209 // TODO: Find code which uses this and improve. _newRegisterHomeMaskX86CompilerContext210 inline void _newRegisterHomeMask(X86CompilerVar* cv, uint32_t mask) 211 { 212 cv->prefRegisterMask |= mask; 213 } 214 215 // -------------------------------------------------------------------------- 216 // [Operand Patcher] 217 // -------------------------------------------------------------------------- 218 219 ASMJIT_API void translateOperands(Operand* operands, uint32_t count); 220 221 // -------------------------------------------------------------------------- 222 // [Backward Code] 223 // -------------------------------------------------------------------------- 224 225 ASMJIT_API void addBackwardCode(X86CompilerJmpInst* from); 226 227 // -------------------------------------------------------------------------- 228 // [Forward Jump] 229 // -------------------------------------------------------------------------- 230 231 ASMJIT_API void addForwardJump(X86CompilerJmpInst* inst); 232 233 // -------------------------------------------------------------------------- 234 // [State] 235 // -------------------------------------------------------------------------- 236 237 ASMJIT_API X86CompilerState* _saveState(); 238 ASMJIT_API void _assignState(X86CompilerState* state); 239 ASMJIT_API void _restoreState(X86CompilerState* state, uint32_t targetOffset = kInvalidValue); 240 241 // -------------------------------------------------------------------------- 242 // [Memory Allocator] 243 // -------------------------------------------------------------------------- 244 245 ASMJIT_API VarMemBlock* _allocMemBlock(uint32_t size); 246 ASMJIT_API void _freeMemBlock(VarMemBlock* mem); 247 248 ASMJIT_API void _allocMemoryOperands(); 249 ASMJIT_API void _patchMemoryOperands(CompilerItem* start, CompilerItem* stop); 250 251 // -------------------------------------------------------------------------- 252 // [Members] 253 // -------------------------------------------------------------------------- 254 255 //! @brief X86 specific compiler state (linked with @ref _state). 256 X86CompilerState _x86State; 257 258 //! @brief Forward jumps (single linked list). 259 ForwardJumpData* _forwardJumps; 260 261 //! @brief Global modified GP registers mask (per function). 262 uint32_t _modifiedGpRegisters; 263 //! @brief Global modified MM registers mask (per function). 264 uint32_t _modifiedMmRegisters; 265 //! @brief Global modified XMM registers mask (per function). 266 uint32_t _modifiedXmmRegisters; 267 268 //! @brief Whether the EBP/RBP register can be used by register allocator. 269 uint32_t _allocableEBP; 270 271 //! @brief ESP adjust constant (changed during PUSH/POP or when using 272 //! stack. 273 int _adjustESP; 274 275 //! @brief Function arguments base pointer (register). 276 uint32_t _argumentsBaseReg; 277 //! @brief Function arguments base offset. 278 int32_t _argumentsBaseOffset; 279 //! @brief Function arguments displacement. 280 int32_t _argumentsActualDisp; 281 282 //! @brief Function variables base pointer (register). 283 uint32_t _variablesBaseReg; 284 //! @brief Function variables base offset. 285 int32_t _variablesBaseOffset; 286 //! @brief Function variables displacement. 287 int32_t _variablesActualDisp; 288 289 //! @brief Used memory blocks (for variables, here is each created mem block 290 //! that can be also in _memFree list). 291 VarMemBlock* _memUsed; 292 //! @brief Free memory blocks (freed, prepared for another allocation). 293 VarMemBlock* _memFree; 294 //! @brief Count of 4-byte memory blocks used by the function. 295 uint32_t _mem4BlocksCount; 296 //! @brief Count of 8-byte memory blocks used by the function. 297 uint32_t _mem8BlocksCount; 298 //! @brief Count of 16-byte memory blocks used by the function. 299 uint32_t _mem16BlocksCount; 300 //! @brief Count of total bytes of stack memory used by the function. 301 uint32_t _memBytesTotal; 302 303 //! @brief List of items which need to be translated. These items are filled 304 //! by @c addBackwardCode(). 305 PodVector<X86CompilerJmpInst*> _backCode; 306 307 //! @brief Backward code position (starts at 0). 308 sysuint_t _backPos; 309 //! @brief Whether to emit comments. 310 bool _emitComments; 311 }; 312 313 //! @} 314 315 } // AsmJit namespace 316 317 // [Api-End] 318 #include "../core/apiend.h" 319 320 // [Guard] 321 #endif // _ASMJIT_X86_X86COMPILERCONTEXT_H 322