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_CORE_FUNC_H 9 #define _ASMJIT_CORE_FUNC_H 10 11 // [Dependencies - AsmJit] 12 #include "../core/assert.h" 13 #include "../core/defs.h" 14 15 // [Api-Begin] 16 #include "../core/apibegin.h" 17 18 namespace AsmJit { 19 20 // ============================================================================ 21 // [Forward Declaration] 22 // ============================================================================ 23 24 template<typename T> 25 struct TypeId; 26 27 // ============================================================================ 28 // [AsmJit::TypeId] 29 // ============================================================================ 30 31 #if defined(ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION) 32 33 #define ASMJIT_DECLARE_TYPE_CORE(_PtrId_) \ 34 template<typename T> \ 35 struct TypeId \ 36 { \ 37 enum \ 38 { \ 39 Id = static_cast<int>(::AsmJit::kVarTypeInvalid) \ 40 }; \ 41 }; \ 42 \ 43 template<typename T> \ 44 struct TypeId<T*> { enum { Id = _PtrId_ }; } 45 46 #else 47 48 // Code without partial template specialization is a bit complex. We need to 49 // determine whether the size of the return value of this function is equal 50 // to sizeof(char) or sizeof(void*). Any sizeof() can be used to distinguish 51 // between these two, but these are commonly used in other libraries as well. 52 template<typename T> 53 char TypeId_NoPtiHelper(T*(*)()); 54 // And specialization. 55 void* TypeId_NoPtiHelper(...); 56 57 #define ASMJIT_DECLARE_TYPE_CORE(_PtrId_) \ 58 template<typename T> \ 59 struct TypeId \ 60 { \ 61 enum \ 62 { \ 63 Id = (sizeof( ::AsmJit::TypeId_NoPtiHelper((T(*)())0) ) == sizeof(char) \ 64 ? static_cast<int>(_PtrId_) \ 65 : static_cast<int>(::AsmJit::kVarTypeInvalid)) \ 66 }; \ 67 } 68 69 #endif // ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION 70 71 //! @brief Declare C/C++ type-id mapped to @c AsmJit::kX86VarType. 72 #define ASMJIT_DECLARE_TYPE_ID(_T_, _Id_) \ 73 template<> \ 74 struct TypeId<_T_> { enum { Id = _Id_ }; } 75 76 // ============================================================================ 77 // [AsmJit::FuncArg] 78 // ============================================================================ 79 80 //! @brief Function argument translated from @ref FuncPrototype. 81 struct FuncArg 82 { 83 // -------------------------------------------------------------------------- 84 // [Accessors] 85 // -------------------------------------------------------------------------- 86 getVarTypeFuncArg87 inline uint32_t getVarType() const 88 { return _varType; } 89 getRegIndexFuncArg90 inline uint32_t getRegIndex() const 91 { return _regIndex; } 92 hasRegIndexFuncArg93 inline bool hasRegIndex() const 94 { return _regIndex != kRegIndexInvalid; } 95 getStackOffsetFuncArg96 inline int32_t getStackOffset() const 97 { return static_cast<int32_t>(_stackOffset); } 98 hasStackOffsetFuncArg99 inline bool hasStackOffset() const 100 { return _stackOffset != kFuncStackInvalid; } 101 102 //! @brief Get whether the argument is assigned, for private use only. isAssignedFuncArg103 inline bool isAssigned() const 104 { return (_regIndex != kRegIndexInvalid) | (_stackOffset != kFuncStackInvalid); } 105 106 // -------------------------------------------------------------------------- 107 // [Reset] 108 // -------------------------------------------------------------------------- 109 110 //! @brief Reset the function argument to "unassigned state". resetFuncArg111 inline void reset() 112 { _packed = 0xFFFFFFFF; } 113 114 // -------------------------------------------------------------------------- 115 // [Members] 116 // -------------------------------------------------------------------------- 117 118 union 119 { 120 struct 121 { 122 //! @brief Variable type, see @c kVarType. 123 uint8_t _varType; 124 //! @brief Register index is argument is passed through register. 125 uint8_t _regIndex; 126 //! @brief Stack offset if argument is passed through stack. 127 int16_t _stackOffset; 128 }; 129 130 //! @brief All members packed into single 32-bit integer. 131 uint32_t _packed; 132 }; 133 }; 134 135 // ============================================================================ 136 // [AsmJit::FuncPrototype] 137 // ============================================================================ 138 139 //! @brief Function prototype. 140 //! 141 //! Function prototype contains information about function return type, count 142 //! of arguments and their types. Function definition is low level structure 143 //! which doesn't contain platform or calling convention specific information. 144 struct FuncPrototype 145 { 146 // -------------------------------------------------------------------------- 147 // [Accessors] 148 // -------------------------------------------------------------------------- 149 150 //! @brief Get function return value. getReturnTypeFuncPrototype151 inline uint32_t getReturnType() const 152 { return _returnType; } 153 154 //! @brief Get count of function arguments. getArgumentsCountFuncPrototype155 inline uint32_t getArgumentsCount() const 156 { return _argumentsCount; } 157 158 //! @brief Get argument at index @a id. getArgumentFuncPrototype159 inline uint32_t getArgument(uint32_t id) const 160 { 161 ASMJIT_ASSERT(id < _argumentsCount); 162 return _arguments[id]; 163 } 164 165 //! @brief Get function arguments' IDs. getArgumentsFuncPrototype166 inline const uint32_t* getArguments() const 167 { return _arguments; } 168 169 //! @brief Set function definition - return type and arguments. _setPrototypeFuncPrototype170 inline void _setPrototype(uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) 171 { 172 _returnType = returnType; 173 _arguments = arguments; 174 _argumentsCount = argumentsCount; 175 } 176 177 // -------------------------------------------------------------------------- 178 // [Members] 179 // -------------------------------------------------------------------------- 180 181 uint32_t _returnType; 182 uint32_t _argumentsCount; 183 const uint32_t* _arguments; 184 }; 185 186 // ============================================================================ 187 // [AsmJit::FuncDecl] 188 // ============================================================================ 189 190 //! @brief Function declaration. 191 struct FuncDecl 192 { 193 // -------------------------------------------------------------------------- 194 // [Accessors] 195 // -------------------------------------------------------------------------- 196 197 //! @brief Get function return value or @ref kInvalidValue if it's void. getReturnTypeFuncDecl198 inline uint32_t getReturnType() const 199 { return _returnType; } 200 201 //! @brief Get count of function arguments. getArgumentsCountFuncDecl202 inline uint32_t getArgumentsCount() const 203 { return _argumentsCount; } 204 205 //! @brief Get function arguments array. getArgumentsFuncDecl206 inline FuncArg* getArguments() 207 { return _arguments; } 208 209 //! @brief Get function arguments array (const). getArgumentsFuncDecl210 inline const FuncArg* getArguments() const 211 { return _arguments; } 212 213 //! @brief Get function argument at index @a index. getArgumentFuncDecl214 inline FuncArg& getArgument(size_t index) 215 { 216 ASMJIT_ASSERT(index < static_cast<size_t>(_argumentsCount)); 217 return _arguments[index]; 218 } 219 220 //! @brief Get function argument at index @a index. getArgumentFuncDecl221 inline const FuncArg& getArgument(size_t index) const 222 { 223 ASMJIT_ASSERT(index < static_cast<size_t>(_argumentsCount)); 224 return _arguments[index]; 225 } 226 227 // -------------------------------------------------------------------------- 228 // [Members] 229 // -------------------------------------------------------------------------- 230 231 //! @brief Function return type. 232 uint8_t _returnType; 233 //! @brief Count of arguments (in @c _argumentsList). 234 uint8_t _argumentsCount; 235 //! @brief Reserved for future use (alignment). 236 uint8_t _reserved0[2]; 237 238 //! @brief Function arguments array. 239 FuncArg _arguments[kFuncArgsMax]; 240 }; 241 242 // ============================================================================ 243 // [AsmJit::FuncBuilderX] 244 // ============================================================================ 245 246 //! @brief Custom function builder for up to 32 function arguments. 247 struct FuncBuilderX : public FuncPrototype 248 { 249 // -------------------------------------------------------------------------- 250 // [Construction / Destruction] 251 // -------------------------------------------------------------------------- 252 FuncBuilderXFuncBuilderX253 inline FuncBuilderX() 254 { _setPrototype(kVarTypeInvalid, _argumentsData, 0); } 255 256 // -------------------------------------------------------------------------- 257 // [Accessors] 258 // -------------------------------------------------------------------------- 259 260 template<typename T> setReturnTypeTFuncBuilderX261 inline void setReturnTypeT() 262 { setReturnTypeRaw(TypeId<ASMJIT_TYPE_TO_TYPE(T)>::Id); } 263 264 template<typename T> setArgumentTFuncBuilderX265 inline void setArgumentT(uint32_t id) 266 { setArgumentRaw(id, TypeId<ASMJIT_TYPE_TO_TYPE(T)>::Id); } 267 268 template<typename T> addArgumentTFuncBuilderX269 inline void addArgumentT() 270 { addArgumentRaw(TypeId<ASMJIT_TYPE_TO_TYPE(T)>::Id); } 271 setReturnTypeRawFuncBuilderX272 inline void setReturnTypeRaw(uint32_t returnType) 273 { _returnType = returnType; } 274 setArgumentRawFuncBuilderX275 inline void setArgumentRaw(uint32_t id, uint32_t type) 276 { 277 ASMJIT_ASSERT(id < _argumentsCount); 278 _argumentsData[id] = type; 279 } 280 addArgumentRawFuncBuilderX281 inline void addArgumentRaw(uint32_t type) 282 { 283 ASMJIT_ASSERT(_argumentsCount < kFuncArgsMax); 284 _argumentsData[_argumentsCount++] = type; 285 } 286 287 // -------------------------------------------------------------------------- 288 // [Members] 289 // -------------------------------------------------------------------------- 290 291 uint32_t _argumentsData[kFuncArgsMax]; 292 }; 293 294 //! @brief Class used to build function without arguments. 295 template<typename RET> 296 struct FuncBuilder0 : public FuncPrototype 297 { FuncBuilder0FuncBuilder0298 inline FuncBuilder0() 299 { 300 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, NULL, 0); 301 } 302 }; 303 304 //! @brief Class used to build function with 1 argument. 305 template<typename RET, typename P0> 306 struct FuncBuilder1 : public FuncPrototype 307 { FuncBuilder1FuncBuilder1308 inline FuncBuilder1() 309 { 310 static const uint32_t arguments[] = 311 { 312 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id 313 }; 314 315 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 316 } 317 }; 318 319 //! @brief Class used to build function with 2 arguments. 320 template<typename RET, typename P0, typename P1> 321 struct FuncBuilder2 : public FuncPrototype 322 { FuncBuilder2FuncBuilder2323 inline FuncBuilder2() 324 { 325 static const uint32_t arguments[] = 326 { 327 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 328 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id 329 }; 330 331 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 332 } 333 }; 334 335 //! @brief Class used to build function with 3 arguments. 336 template<typename RET, typename P0, typename P1, typename P2> 337 struct FuncBuilder3 : public FuncPrototype 338 { FuncBuilder3FuncBuilder3339 inline FuncBuilder3() 340 { 341 static const uint32_t arguments[] = 342 { 343 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 344 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 345 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id 346 }; 347 348 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 349 } 350 }; 351 352 //! @brief Class used to build function with 4 arguments. 353 template<typename RET, typename P0, typename P1, typename P2, typename P3> 354 struct FuncBuilder4 : public FuncPrototype 355 { FuncBuilder4FuncBuilder4356 inline FuncBuilder4() 357 { 358 static const uint32_t arguments[] = 359 { 360 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 361 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 362 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 363 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id 364 }; 365 366 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 367 } 368 }; 369 370 //! @brief Class used to build function with 5 arguments. 371 template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4> 372 struct FuncBuilder5 : public FuncPrototype 373 { FuncBuilder5FuncBuilder5374 inline FuncBuilder5() 375 { 376 static const uint32_t arguments[] = 377 { 378 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 379 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 380 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 381 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id, 382 TypeId<ASMJIT_TYPE_TO_TYPE(P4)>::Id 383 }; 384 385 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 386 } 387 }; 388 389 //! @brief Class used to build function with 6 arguments. 390 template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5> 391 struct FuncBuilder6 : public FuncPrototype 392 { FuncBuilder6FuncBuilder6393 inline FuncBuilder6() 394 { 395 static const uint32_t arguments[] = 396 { 397 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 398 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 399 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 400 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id, 401 TypeId<ASMJIT_TYPE_TO_TYPE(P4)>::Id, 402 TypeId<ASMJIT_TYPE_TO_TYPE(P5)>::Id 403 }; 404 405 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 406 } 407 }; 408 409 //! @brief Class used to build function with 7 arguments. 410 template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6> 411 struct FuncBuilder7 : public FuncPrototype 412 { FuncBuilder7FuncBuilder7413 inline FuncBuilder7() 414 { 415 static const uint32_t arguments[] = 416 { 417 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 418 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 419 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 420 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id, 421 TypeId<ASMJIT_TYPE_TO_TYPE(P4)>::Id, 422 TypeId<ASMJIT_TYPE_TO_TYPE(P5)>::Id, 423 TypeId<ASMJIT_TYPE_TO_TYPE(P6)>::Id 424 }; 425 426 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 427 } 428 }; 429 430 //! @brief Class used to build function with 8 arguments. 431 template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7> 432 struct FuncBuilder8 : public FuncPrototype 433 { FuncBuilder8FuncBuilder8434 inline FuncBuilder8() 435 { 436 static const uint32_t arguments[] = 437 { 438 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 439 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 440 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 441 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id, 442 TypeId<ASMJIT_TYPE_TO_TYPE(P4)>::Id, 443 TypeId<ASMJIT_TYPE_TO_TYPE(P5)>::Id, 444 TypeId<ASMJIT_TYPE_TO_TYPE(P6)>::Id, 445 TypeId<ASMJIT_TYPE_TO_TYPE(P7)>::Id 446 }; 447 448 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 449 } 450 }; 451 452 //! @brief Class used to build function with 9 arguments. 453 template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8> 454 struct FuncBuilder9 : public FuncPrototype 455 { FuncBuilder9FuncBuilder9456 inline FuncBuilder9() 457 { 458 static const uint32_t arguments[] = 459 { 460 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 461 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 462 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 463 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id, 464 TypeId<ASMJIT_TYPE_TO_TYPE(P4)>::Id, 465 TypeId<ASMJIT_TYPE_TO_TYPE(P5)>::Id, 466 TypeId<ASMJIT_TYPE_TO_TYPE(P6)>::Id, 467 TypeId<ASMJIT_TYPE_TO_TYPE(P7)>::Id, 468 TypeId<ASMJIT_TYPE_TO_TYPE(P8)>::Id 469 }; 470 471 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 472 } 473 }; 474 475 //! @brief Class used to build function with 10 arguments. 476 template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9> 477 struct FuncBuilder10 : public FuncPrototype 478 { FuncBuilder10FuncBuilder10479 inline FuncBuilder10() 480 { 481 static const uint32_t arguments[] = 482 { 483 TypeId<ASMJIT_TYPE_TO_TYPE(P0)>::Id, 484 TypeId<ASMJIT_TYPE_TO_TYPE(P1)>::Id, 485 TypeId<ASMJIT_TYPE_TO_TYPE(P2)>::Id, 486 TypeId<ASMJIT_TYPE_TO_TYPE(P3)>::Id, 487 TypeId<ASMJIT_TYPE_TO_TYPE(P4)>::Id, 488 TypeId<ASMJIT_TYPE_TO_TYPE(P5)>::Id, 489 TypeId<ASMJIT_TYPE_TO_TYPE(P6)>::Id, 490 TypeId<ASMJIT_TYPE_TO_TYPE(P7)>::Id, 491 TypeId<ASMJIT_TYPE_TO_TYPE(P8)>::Id, 492 TypeId<ASMJIT_TYPE_TO_TYPE(P9)>::Id 493 }; 494 495 _setPrototype(TypeId<ASMJIT_TYPE_TO_TYPE(RET)>::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); 496 } 497 }; 498 499 } // AsmJit namespace 500 501 // [Api-End] 502 #include "../core/apiend.h" 503 504 // [Guard] 505 #endif // _ASMJIT_CORE_FUNC_H 506