]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
Merge lld trunk r351319, resolve conflicts, and update FREEBSD-Xlist.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ExecutionEngine / Orc / OrcABISupport.h
1 //===- OrcABISupport.h - ABI support code -----------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // ABI specific code for Orc, e.g. callback assembly.
11 //
12 // ABI classes should be part of the JIT *target* process, not the host
13 // process (except where you're doing hosted JITing and the two are one and the
14 // same).
15 //
16 //===----------------------------------------------------------------------===//
17
18 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
19 #define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
20
21 #include "llvm/ExecutionEngine/JITSymbol.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/Memory.h"
25 #include <algorithm>
26 #include <cstdint>
27
28 namespace llvm {
29 namespace orc {
30
31 /// Generic ORC ABI support.
32 ///
33 /// This class can be substituted as the target architecure support class for
34 /// ORC templates that require one (e.g. IndirectStubsManagers). It does not
35 /// support lazy JITing however, and any attempt to use that functionality
36 /// will result in execution of an llvm_unreachable.
37 class OrcGenericABI {
38 public:
39   static const unsigned PointerSize = sizeof(uintptr_t);
40   static const unsigned TrampolineSize = 1;
41   static const unsigned ResolverCodeSize = 1;
42
43   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
44                                             void *TrampolineId);
45
46   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
47                                 void *CallbackMgr) {
48     llvm_unreachable("writeResolverCode is not supported by the generic host "
49                      "support class");
50   }
51
52   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
53                                unsigned NumTrampolines) {
54     llvm_unreachable("writeTrampolines is not supported by the generic host "
55                      "support class");
56   }
57
58   class IndirectStubsInfo {
59   public:
60     const static unsigned StubSize = 1;
61
62     unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
63     void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
64     void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
65   };
66
67   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
68                                       unsigned MinStubs, void *InitialPtrVal) {
69     llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
70                      "host support class");
71   }
72 };
73
74 /// Provide information about stub blocks generated by the
75 ///        makeIndirectStubsBlock function.
76 template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
77 public:
78   const static unsigned StubSize = StubSizeVal;
79
80   GenericIndirectStubsInfo() = default;
81   GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
82       : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
83   GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other)
84       : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
85     Other.NumStubs = 0;
86   }
87
88   GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
89     NumStubs = Other.NumStubs;
90     Other.NumStubs = 0;
91     StubsMem = std::move(Other.StubsMem);
92     return *this;
93   }
94
95   /// Number of stubs in this block.
96   unsigned getNumStubs() const { return NumStubs; }
97
98   /// Get a pointer to the stub at the given index, which must be in
99   ///        the range 0 .. getNumStubs() - 1.
100   void *getStub(unsigned Idx) const {
101     return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
102   }
103
104   /// Get a pointer to the implementation-pointer at the given index,
105   ///        which must be in the range 0 .. getNumStubs() - 1.
106   void **getPtr(unsigned Idx) const {
107     char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
108     return reinterpret_cast<void **>(PtrsBase) + Idx;
109   }
110
111 private:
112   unsigned NumStubs = 0;
113   sys::OwningMemoryBlock StubsMem;
114 };
115
116 class OrcAArch64 {
117 public:
118   static const unsigned PointerSize = 8;
119   static const unsigned TrampolineSize = 12;
120   static const unsigned ResolverCodeSize = 0x120;
121
122   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
123
124   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
125                                             void *TrampolineId);
126
127   /// Write the resolver code into the given memory. The user is be
128   ///        responsible for allocating the memory and setting permissions.
129   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
130                                 void *CallbackMgr);
131
132   /// Write the requsted number of trampolines into the given memory,
133   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
134   ///        trampolines.
135   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
136                                unsigned NumTrampolines);
137
138   /// Emit at least MinStubs worth of indirect call stubs, rounded out to
139   ///        the nearest page size.
140   ///
141   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
142   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
143   /// will return a block of 1024 (2-pages worth).
144   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
145                                       unsigned MinStubs, void *InitialPtrVal);
146 };
147
148 /// X86_64 code that's common to all ABIs.
149 ///
150 /// X86_64 supports lazy JITing.
151 class OrcX86_64_Base {
152 public:
153   static const unsigned PointerSize = 8;
154   static const unsigned TrampolineSize = 8;
155
156   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
157
158   /// Write the requsted number of trampolines into the given memory,
159   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
160   ///        trampolines.
161   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
162                                unsigned NumTrampolines);
163
164   /// Emit at least MinStubs worth of indirect call stubs, rounded out to
165   ///        the nearest page size.
166   ///
167   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
168   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
169   /// will return a block of 1024 (2-pages worth).
170   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
171                                       unsigned MinStubs, void *InitialPtrVal);
172 };
173
174 /// X86_64 support for SysV ABI (Linux, MacOSX).
175 ///
176 /// X86_64_SysV supports lazy JITing.
177 class OrcX86_64_SysV : public OrcX86_64_Base {
178 public:
179   static const unsigned ResolverCodeSize = 0x6C;
180
181   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
182                                             void *TrampolineId);
183
184   /// Write the resolver code into the given memory. The user is be
185   ///        responsible for allocating the memory and setting permissions.
186   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
187                                 void *CallbackMgr);
188 };
189
190 /// X86_64 support for Win32.
191 ///
192 /// X86_64_Win32 supports lazy JITing.
193 class OrcX86_64_Win32 : public OrcX86_64_Base {
194 public:
195   static const unsigned ResolverCodeSize = 0x74;
196
197   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
198                                             void *TrampolineId);
199
200   /// Write the resolver code into the given memory. The user is be
201   ///        responsible for allocating the memory and setting permissions.
202   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
203                                 void *CallbackMgr);
204 };
205
206 /// I386 support.
207 ///
208 /// I386 supports lazy JITing.
209 class OrcI386 {
210 public:
211   static const unsigned PointerSize = 4;
212   static const unsigned TrampolineSize = 8;
213   static const unsigned ResolverCodeSize = 0x4a;
214
215   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
216
217   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
218                                             void *TrampolineId);
219
220   /// Write the resolver code into the given memory. The user is be
221   ///        responsible for allocating the memory and setting permissions.
222   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
223                                 void *CallbackMgr);
224
225   /// Write the requsted number of trampolines into the given memory,
226   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
227   ///        trampolines.
228   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
229                                unsigned NumTrampolines);
230
231   /// Emit at least MinStubs worth of indirect call stubs, rounded out to
232   ///        the nearest page size.
233   ///
234   ///   E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
235   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
236   /// will return a block of 1024 (2-pages worth).
237   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
238                                       unsigned MinStubs, void *InitialPtrVal);
239 };
240
241 // @brief Mips32 support.
242 //
243 // Mips32 supports lazy JITing.
244 class OrcMips32_Base {
245 public:
246   static const unsigned PointerSize = 4;
247   static const unsigned TrampolineSize = 20;
248   static const unsigned ResolverCodeSize = 0xfc;
249   using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
250
251   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
252                                             void *TrampolineId);
253   /// @brief Write the requsted number of trampolines into the given memory,
254   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
255   ///        trampolines.
256   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
257
258   /// @brief Write the resolver code into the given memory. The user is be
259   ///        responsible for allocating the memory and setting permissions.
260   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian);
261   /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
262   ///        the nearest page size.
263   ///
264   ///   E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k
265   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
266   /// will return a block of 1024 (2-pages worth).
267   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
268 };
269
270
271 class OrcMips32Le : public OrcMips32_Base {
272 public:
273   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
274   { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
275 };
276
277 class OrcMips32Be : public OrcMips32_Base {
278 public:
279   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
280   { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
281 };
282
283 // @brief Mips64 support.
284 //
285 // Mips64 supports lazy JITing.
286 class OrcMips64 {
287 public:
288   static const unsigned PointerSize = 8;
289   static const unsigned TrampolineSize = 40;
290   static const unsigned ResolverCodeSize = 0x120;
291
292   using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
293   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
294                                             void *TrampolineId);
295   /// @brief Write the resolver code into the given memory. The user is be
296   ///        responsible for allocating the memory and setting permissions.
297   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr);
298
299   /// @brief Write the requsted number of trampolines into the given memory,
300   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
301   ///        trampolines.
302   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
303
304   /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
305   ///        the nearest page size.
306   ///
307   ///   E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k
308   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
309   /// will return a block of 1024 (2-pages worth).
310   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
311 };
312
313  } // end namespace orc
314  } // end namespace llvm
315 #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H