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