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_X86COMPILERFUNC_H 9 #define _ASMJIT_X86_X86COMPILERFUNC_H 10 11 // [Dependencies - AsmJit] 12 #include "../x86/x86assembler.h" 13 #include "../x86/x86compiler.h" 14 #include "../x86/x86compileritem.h" 15 16 // [Api-Begin] 17 #include "../core/apibegin.h" 18 19 namespace AsmJit { 20 21 //! @addtogroup AsmJit_X86 22 //! @{ 23 24 // ============================================================================ 25 // [AsmJit::X86CompilerFuncDecl] 26 // ============================================================================ 27 28 //! @brief @ref X86Compiler specific function declaration item. 29 struct X86CompilerFuncDecl : public CompilerFuncDecl 30 { 31 ASMJIT_NO_COPY(X86CompilerFuncDecl) 32 33 // -------------------------------------------------------------------------- 34 // [Construction / Destruction] 35 // -------------------------------------------------------------------------- 36 37 //! @brief Create a new @ref X86CompilerFuncDecl instance. 38 ASMJIT_API X86CompilerFuncDecl(X86Compiler* x86Compiler); 39 //! @brief Destroy the @ref X86CompilerFuncDecl instance. 40 ASMJIT_API virtual ~X86CompilerFuncDecl(); 41 42 // -------------------------------------------------------------------------- 43 // [Accessors] 44 // -------------------------------------------------------------------------- 45 46 //! @brief Get compiler as @ref X86Compiler. getCompilerX86CompilerFuncDecl47 inline X86Compiler* getCompiler() const 48 { return reinterpret_cast<X86Compiler*>(_compiler); } 49 50 //! @brief Get function end item as @ref X86CompilerFuncEnd. getEndX86CompilerFuncDecl51 inline X86CompilerFuncEnd* getEnd() const 52 { return reinterpret_cast<X86CompilerFuncEnd*>(_end); } 53 54 //! @brief Get function declaration as @ref X86FuncDecl. getDeclX86CompilerFuncDecl55 inline X86FuncDecl* getDecl() const 56 { return reinterpret_cast<X86FuncDecl*>(_decl); } 57 58 //! @brief Get function arguments as variables as @ref X86CompilerVar. getVarsX86CompilerFuncDecl59 inline X86CompilerVar** getVars() const 60 { return reinterpret_cast<X86CompilerVar**>(_vars); } 61 62 //! @brief Get function argument at @a index. getVarX86CompilerFuncDecl63 inline X86CompilerVar* getVar(uint32_t index) const 64 { 65 ASMJIT_ASSERT(index < _x86Decl.getArgumentsCount()); 66 return reinterpret_cast<X86CompilerVar**>(_vars)[index]; 67 } 68 69 //! @brief Get whether it's assumed that stack is aligned to 16 bytes. isAssumed16ByteAlignmentX86CompilerFuncDecl70 inline bool isAssumed16ByteAlignment() const 71 { return hasFuncFlag(kX86FuncFlagAssume16ByteAlignment); } 72 73 //! @brief Get whether it's required to align stack to 16 bytes by function. isPerformed16ByteAlignmentX86CompilerFuncDecl74 inline bool isPerformed16ByteAlignment() const 75 { return hasFuncFlag(kX86FuncFlagPerform16ByteAlignment); } 76 77 //! @brief Get whether the ESP is adjusted. isEspAdjustedX86CompilerFuncDecl78 inline bool isEspAdjusted() const 79 { return hasFuncFlag(kX86FuncFlagIsEspAdjusted); } 80 81 // -------------------------------------------------------------------------- 82 // [Interface] 83 // -------------------------------------------------------------------------- 84 85 ASMJIT_API virtual void prepare(CompilerContext& cc); 86 ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); 87 88 // -------------------------------------------------------------------------- 89 // [Misc] 90 // -------------------------------------------------------------------------- 91 92 ASMJIT_API virtual int getMaxSize() const; 93 94 // -------------------------------------------------------------------------- 95 // [Prototype] 96 // -------------------------------------------------------------------------- 97 98 ASMJIT_API virtual void setPrototype( 99 uint32_t convention, 100 uint32_t returnType, 101 const uint32_t* arguments, 102 uint32_t argumentsCount); 103 104 // -------------------------------------------------------------------------- 105 // [Helpers] 106 // -------------------------------------------------------------------------- 107 108 //! @internal 109 //! 110 //! @brief Get required stack offset needed to subtract/add Esp/Rsp in 111 //! prolog/epilog. _getRequiredStackOffsetX86CompilerFuncDecl112 inline int32_t _getRequiredStackOffset() const 113 { return _funcCallStackSize + _memStackSize16 + _peMovStackSize + _peAdjustStackSize; } 114 115 //! @brief Create variables from FunctionPrototype declaration. This is just 116 //! parsing what FunctionPrototype generated for current function calling 117 //! convention and arguments. 118 ASMJIT_API void _createVariables(); 119 120 //! @brief Prepare variables (ids, names, scope, registers). 121 ASMJIT_API void _prepareVariables(CompilerItem* first); 122 123 //! @brief Allocate variables (setting correct state, changing masks, etc). 124 ASMJIT_API void _allocVariables(CompilerContext& cc); 125 126 ASMJIT_API void _preparePrologEpilog(CompilerContext& cc); 127 ASMJIT_API void _dumpFunction(CompilerContext& cc); 128 ASMJIT_API void _emitProlog(CompilerContext& cc); 129 ASMJIT_API void _emitEpilog(CompilerContext& cc); 130 131 // -------------------------------------------------------------------------- 132 // [Function-Call] 133 // -------------------------------------------------------------------------- 134 135 //! @brief Reserve stack for calling other function and mark function as 136 //! callee. 137 ASMJIT_API void reserveStackForFunctionCall(int32_t size); 138 139 // -------------------------------------------------------------------------- 140 // [Members] 141 // -------------------------------------------------------------------------- 142 143 //! @brief X86 function decl. 144 X86FuncDecl _x86Decl; 145 146 //! @brief Modified and preserved GP registers mask. 147 uint32_t _gpModifiedAndPreserved; 148 //! @brief Modified and preserved MM registers mask. 149 uint32_t _mmModifiedAndPreserved; 150 //! @brief Modified and preserved XMM registers mask. 151 uint32_t _xmmModifiedAndPreserved; 152 153 //! @brief Id of MovDQWord instruction (@c kX86InstMovDQA or @c kX86InstMovDQU). 154 //! 155 //! The value is based on stack alignment. If it's guaranteed that stack 156 //! is aligned to 16-bytes then @c kX86InstMovDQA instruction is used, otherwise 157 //! the @c kX86InstMovDQU instruction is used for 16-byte mov. 158 uint32_t _movDqInstCode; 159 160 //! @brief Prolog / epilog stack size for PUSH/POP sequences. 161 int32_t _pePushPopStackSize; 162 //! @brief Prolog / epilog stack size for MOV sequences. 163 int32_t _peMovStackSize; 164 //! @brief Prolog / epilog stack adjust size (to make it 16-byte aligned). 165 int32_t _peAdjustStackSize; 166 167 //! @brief Memory stack size (for all variables and temporary memory). 168 int32_t _memStackSize; 169 //! @brief Like @c _memStackSize, but aligned to 16-bytes. 170 int32_t _memStackSize16; 171 }; 172 173 // ============================================================================ 174 // [AsmJit::X86CompilerFuncEnd] 175 // ============================================================================ 176 177 //! @brief @ref X86Compiler function end item. 178 struct X86CompilerFuncEnd : public CompilerFuncEnd 179 { 180 ASMJIT_NO_COPY(X86CompilerFuncEnd) 181 182 // -------------------------------------------------------------------------- 183 // [Construction / Destruction] 184 // -------------------------------------------------------------------------- 185 186 //! @brief Create a new @ref X86CompilerFuncEnd instance. 187 ASMJIT_API X86CompilerFuncEnd(X86Compiler* x86Compiler, X86CompilerFuncDecl* func); 188 //! @brief Destroy the @ref X86CompilerFuncEnd instance. 189 ASMJIT_API virtual ~X86CompilerFuncEnd(); 190 191 // -------------------------------------------------------------------------- 192 // [Accessors] 193 // -------------------------------------------------------------------------- 194 195 //! @brief Get compiler as @ref X86Compiler. getCompilerX86CompilerFuncEnd196 inline X86Compiler* getCompiler() const 197 { return reinterpret_cast<X86Compiler*>(_compiler); } 198 199 //! @brief Get related function as @ref X86CompilerFuncDecl. getFuncX86CompilerFuncEnd200 inline X86CompilerFuncDecl* getFunc() const 201 { return reinterpret_cast<X86CompilerFuncDecl*>(_func); } 202 203 // -------------------------------------------------------------------------- 204 // [Interface] 205 // -------------------------------------------------------------------------- 206 207 ASMJIT_API virtual void prepare(CompilerContext& cc); 208 ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); 209 }; 210 211 // ============================================================================ 212 // [AsmJit::X86CompilerFuncRet] 213 // ============================================================================ 214 215 //! @brief Function return. 216 struct X86CompilerFuncRet : public CompilerFuncRet 217 { 218 ASMJIT_NO_COPY(X86CompilerFuncRet) 219 220 // -------------------------------------------------------------------------- 221 // [Construction / Destruction] 222 // -------------------------------------------------------------------------- 223 224 //! @brief Create a new @ref X86CompilerFuncRet instance. 225 ASMJIT_API X86CompilerFuncRet(X86Compiler* c, X86CompilerFuncDecl* func, 226 const Operand* first, const Operand* second); 227 //! @brief Destroy the @ref X86CompilerFuncRet instance. 228 ASMJIT_API virtual ~X86CompilerFuncRet(); 229 230 // -------------------------------------------------------------------------- 231 // [Accessors] 232 // -------------------------------------------------------------------------- 233 234 //! @brief Get compiler as @ref X86Compiler. getCompilerX86CompilerFuncRet235 inline X86Compiler* getCompiler() const 236 { return reinterpret_cast<X86Compiler*>(_compiler); } 237 238 //! @Brief Get related function as @ref X86CompilerFuncDecl. getFuncX86CompilerFuncRet239 inline X86CompilerFuncDecl* getFunc() const 240 { return reinterpret_cast<X86CompilerFuncDecl*>(_func); } 241 242 // -------------------------------------------------------------------------- 243 // [Interface] 244 // -------------------------------------------------------------------------- 245 246 ASMJIT_API virtual void prepare(CompilerContext& cc); 247 ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); 248 ASMJIT_API virtual void emit(Assembler& a); 249 250 // -------------------------------------------------------------------------- 251 // [Misc] 252 // -------------------------------------------------------------------------- 253 254 ASMJIT_API virtual int getMaxSize() const; 255 }; 256 257 // ============================================================================ 258 // [AsmJit::X86CompilerFuncCall] 259 // ============================================================================ 260 261 //! @brief Compiler function call item. 262 struct X86CompilerFuncCall : public CompilerFuncCall 263 { 264 ASMJIT_NO_COPY(X86CompilerFuncCall) 265 266 // -------------------------------------------------------------------------- 267 // [Construction / Destruction] 268 // -------------------------------------------------------------------------- 269 270 //! @brief Create a new @ref X86CompilerFuncCall instance. 271 ASMJIT_API X86CompilerFuncCall(X86Compiler* x86Compiler, X86CompilerFuncDecl* caller, const Operand* target); 272 //! @brief Destroy the @ref X86CompilerFuncCall instance. 273 ASMJIT_API virtual ~X86CompilerFuncCall(); 274 275 // -------------------------------------------------------------------------- 276 // [Accessors] 277 // -------------------------------------------------------------------------- 278 279 //! @brief Get compiler as @ref X86Compiler. getCompilerX86CompilerFuncCall280 inline X86Compiler* getCompiler() const 281 { return reinterpret_cast<X86Compiler*>(_compiler); } 282 283 //! @brief Get caller as @ref X86CompilerFuncDecl. getCallerX86CompilerFuncCall284 inline X86CompilerFuncDecl* getCaller() const 285 { return reinterpret_cast<X86CompilerFuncDecl*>(_caller); } 286 287 //! @brief Get function prototype. getDeclX86CompilerFuncCall288 inline const X86FuncDecl* getDecl() const 289 { return reinterpret_cast<X86FuncDecl*>(_decl); } 290 291 // -------------------------------------------------------------------------- 292 // [Interface] 293 // -------------------------------------------------------------------------- 294 295 ASMJIT_API virtual void prepare(CompilerContext& cc); 296 ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); 297 298 // -------------------------------------------------------------------------- 299 // [Misc] 300 // -------------------------------------------------------------------------- 301 302 ASMJIT_API virtual int getMaxSize() const; 303 ASMJIT_API virtual bool _tryUnuseVar(CompilerVar* v); 304 305 // -------------------------------------------------------------------------- 306 // [Prototype] 307 // -------------------------------------------------------------------------- 308 309 ASMJIT_API virtual void setPrototype(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount); 310 311 //! @brief Set function prototype. setPrototypeX86CompilerFuncCall312 inline void setPrototype(uint32_t convention, const FuncPrototype& func) 313 { setPrototype(convention, func.getReturnType(), func.getArguments(), func.getArgumentsCount()); } 314 315 //! @brief Set return value. 316 ASMJIT_API bool setReturn(const Operand& first, const Operand& second = Operand()); 317 318 //! @brief Set function argument @a i to @a var. 319 ASMJIT_API bool setArgument(uint32_t i, const Var& var); 320 //! @brief Set function argument @a i to @a imm. 321 ASMJIT_API bool setArgument(uint32_t i, const Imm& imm); 322 323 // -------------------------------------------------------------------------- 324 // [Internal] 325 // -------------------------------------------------------------------------- 326 327 ASMJIT_API uint32_t _findTemporaryGpRegister(CompilerContext& cc); 328 ASMJIT_API uint32_t _findTemporaryXmmRegister(CompilerContext& cc); 329 330 ASMJIT_API X86CompilerVar* _getOverlappingVariable(CompilerContext& cc, const FuncArg& argType) const; 331 332 ASMJIT_API void _moveAllocatedVariableToStack(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType); 333 ASMJIT_API void _moveSpilledVariableToStack(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType, 334 uint32_t temporaryGpReg, 335 uint32_t temporaryXmmReg); 336 ASMJIT_API void _moveSrcVariableToRegister(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType); 337 338 // -------------------------------------------------------------------------- 339 // [Members] 340 // -------------------------------------------------------------------------- 341 342 //! @brief X86 declaration. 343 X86FuncDecl _x86Decl; 344 345 //! @brief Mask of GP registers used as function arguments. 346 uint32_t _gpParams; 347 //! @brief Mask of MM registers used as function arguments. 348 uint32_t _mmParams; 349 //! @brief Mask of XMM registers used as function arguments. 350 uint32_t _xmmParams; 351 352 //! @brief Variables count. 353 uint32_t _variablesCount; 354 355 //! @brief Variables (extracted from operands). 356 VarCallRecord* _variables; 357 //! @brief Argument index to @c VarCallRecord. 358 VarCallRecord* _argumentToVarRecord[kFuncArgsMax]; 359 }; 360 361 //! @} 362 363 } // AsmJit namespace 364 365 // [Api-End] 366 #include "../core/apiend.h" 367 368 // [Guard] 369 #endif // _ASMJIT_X86_X86COMPILERFUNC_H 370