1 //===- OrcABISupport.h - ABI support code -----------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // ABI specific code for Orc, e.g. callback assembly.
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
16 //===----------------------------------------------------------------------===//
18 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
19 #define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
21 #include "llvm/ExecutionEngine/JITSymbol.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/Memory.h"
31 /// Generic ORC ABI support.
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.
39 static const unsigned PointerSize = sizeof(uintptr_t);
40 static const unsigned TrampolineSize = 1;
41 static const unsigned ResolverCodeSize = 1;
43 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
46 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
48 llvm_unreachable("writeResolverCode is not supported by the generic host "
52 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
53 unsigned NumTrampolines) {
54 llvm_unreachable("writeTrampolines is not supported by the generic host "
58 class IndirectStubsInfo {
60 const static unsigned StubSize = 1;
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"); }
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");
74 /// Provide information about stub blocks generated by the
75 /// makeIndirectStubsBlock function.
76 template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
78 const static unsigned StubSize = StubSizeVal;
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)) {
88 GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
89 NumStubs = Other.NumStubs;
91 StubsMem = std::move(Other.StubsMem);
95 /// Number of stubs in this block.
96 unsigned getNumStubs() const { return NumStubs; }
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;
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;
112 unsigned NumStubs = 0;
113 sys::OwningMemoryBlock StubsMem;
118 static const unsigned PointerSize = 8;
119 static const unsigned TrampolineSize = 12;
120 static const unsigned ResolverCodeSize = 0x120;
122 using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
124 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
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,
132 /// Write the requsted number of trampolines into the given memory,
133 /// which must be big enough to hold 1 pointer, plus NumTrampolines
135 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
136 unsigned NumTrampolines);
138 /// Emit at least MinStubs worth of indirect call stubs, rounded out to
139 /// the nearest page size.
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);
148 /// X86_64 code that's common to all ABIs.
150 /// X86_64 supports lazy JITing.
151 class OrcX86_64_Base {
153 static const unsigned PointerSize = 8;
154 static const unsigned TrampolineSize = 8;
156 using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
158 /// Write the requsted number of trampolines into the given memory,
159 /// which must be big enough to hold 1 pointer, plus NumTrampolines
161 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
162 unsigned NumTrampolines);
164 /// Emit at least MinStubs worth of indirect call stubs, rounded out to
165 /// the nearest page size.
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);
174 /// X86_64 support for SysV ABI (Linux, MacOSX).
176 /// X86_64_SysV supports lazy JITing.
177 class OrcX86_64_SysV : public OrcX86_64_Base {
179 static const unsigned ResolverCodeSize = 0x6C;
181 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
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,
190 /// X86_64 support for Win32.
192 /// X86_64_Win32 supports lazy JITing.
193 class OrcX86_64_Win32 : public OrcX86_64_Base {
195 static const unsigned ResolverCodeSize = 0x74;
197 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
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,
208 /// I386 supports lazy JITing.
211 static const unsigned PointerSize = 4;
212 static const unsigned TrampolineSize = 8;
213 static const unsigned ResolverCodeSize = 0x4a;
215 using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
217 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
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,
225 /// Write the requsted number of trampolines into the given memory,
226 /// which must be big enough to hold 1 pointer, plus NumTrampolines
228 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
229 unsigned NumTrampolines);
231 /// Emit at least MinStubs worth of indirect call stubs, rounded out to
232 /// the nearest page size.
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);
241 // @brief Mips32 support.
243 // Mips32 supports lazy JITing.
244 class OrcMips32_Base {
246 static const unsigned PointerSize = 4;
247 static const unsigned TrampolineSize = 20;
248 static const unsigned ResolverCodeSize = 0xfc;
249 using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
251 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
253 /// @brief Write the requsted number of trampolines into the given memory,
254 /// which must be big enough to hold 1 pointer, plus NumTrampolines
256 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
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.
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);
271 class OrcMips32Le : public OrcMips32_Base {
273 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
274 { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
277 class OrcMips32Be : public OrcMips32_Base {
279 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
280 { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
283 // @brief Mips64 support.
285 // Mips64 supports lazy JITing.
288 static const unsigned PointerSize = 8;
289 static const unsigned TrampolineSize = 40;
290 static const unsigned ResolverCodeSize = 0x120;
292 using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
293 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
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);
299 /// @brief Write the requsted number of trampolines into the given memory,
300 /// which must be big enough to hold 1 pointer, plus NumTrampolines
302 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
304 /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
305 /// the nearest page size.
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);
313 } // end namespace orc
314 } // end namespace llvm
315 #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H