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