[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / include / llvm / ExecutionEngine / Orc / OrcABISupport.h
blob38246bc480b64fc0563304758b08eff981b30d48
1 //===- OrcABISupport.h - ABI support code -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // ABI specific code for Orc, e.g. callback assembly.
11 // ABI classes should be part of the JIT *target* process, not the host
12 // process (except where you're doing hosted JITing and the two are one and the
13 // same).
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
18 #define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
20 #include "llvm/ExecutionEngine/JITSymbol.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/Memory.h"
24 #include <algorithm>
25 #include <cstdint>
27 namespace llvm {
28 namespace orc {
30 /// Generic ORC ABI support.
31 ///
32 /// This class can be substituted as the target architecure support class for
33 /// ORC templates that require one (e.g. IndirectStubsManagers). It does not
34 /// support lazy JITing however, and any attempt to use that functionality
35 /// will result in execution of an llvm_unreachable.
36 class OrcGenericABI {
37 public:
38 static const unsigned PointerSize = sizeof(uintptr_t);
39 static const unsigned TrampolineSize = 1;
40 static const unsigned ResolverCodeSize = 1;
42 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
43 void *TrampolineId);
45 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
46 void *CallbackMgr) {
47 llvm_unreachable("writeResolverCode is not supported by the generic host "
48 "support class");
51 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
52 unsigned NumTrampolines) {
53 llvm_unreachable("writeTrampolines is not supported by the generic host "
54 "support class");
57 class IndirectStubsInfo {
58 public:
59 const static unsigned StubSize = 1;
61 unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
62 void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
63 void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
66 static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
67 unsigned MinStubs, void *InitialPtrVal) {
68 llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
69 "host support class");
73 /// Provide information about stub blocks generated by the
74 /// makeIndirectStubsBlock function.
75 template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
76 public:
77 const static unsigned StubSize = StubSizeVal;
79 GenericIndirectStubsInfo() = default;
80 GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
81 : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
82 GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other)
83 : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
84 Other.NumStubs = 0;
87 GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
88 NumStubs = Other.NumStubs;
89 Other.NumStubs = 0;
90 StubsMem = std::move(Other.StubsMem);
91 return *this;
94 /// Number of stubs in this block.
95 unsigned getNumStubs() const { return NumStubs; }
97 /// Get a pointer to the stub at the given index, which must be in
98 /// the range 0 .. getNumStubs() - 1.
99 void *getStub(unsigned Idx) const {
100 return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
103 /// Get a pointer to the implementation-pointer at the given index,
104 /// which must be in the range 0 .. getNumStubs() - 1.
105 void **getPtr(unsigned Idx) const {
106 char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
107 return reinterpret_cast<void **>(PtrsBase) + Idx;
110 private:
111 unsigned NumStubs = 0;
112 sys::OwningMemoryBlock StubsMem;
115 class OrcAArch64 {
116 public:
117 static const unsigned PointerSize = 8;
118 static const unsigned TrampolineSize = 12;
119 static const unsigned ResolverCodeSize = 0x120;
121 using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
123 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
124 void *TrampolineId);
126 /// Write the resolver code into the given memory. The user is be
127 /// responsible for allocating the memory and setting permissions.
128 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
129 void *CallbackMgr);
131 /// Write the requsted number of trampolines into the given memory,
132 /// which must be big enough to hold 1 pointer, plus NumTrampolines
133 /// trampolines.
134 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
135 unsigned NumTrampolines);
137 /// Emit at least MinStubs worth of indirect call stubs, rounded out to
138 /// the nearest page size.
140 /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
141 /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
142 /// will return a block of 1024 (2-pages worth).
143 static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
144 unsigned MinStubs, void *InitialPtrVal);
147 /// X86_64 code that's common to all ABIs.
149 /// X86_64 supports lazy JITing.
150 class OrcX86_64_Base {
151 public:
152 static const unsigned PointerSize = 8;
153 static const unsigned TrampolineSize = 8;
155 using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
157 /// Write the requsted number of trampolines into the given memory,
158 /// which must be big enough to hold 1 pointer, plus NumTrampolines
159 /// trampolines.
160 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
161 unsigned NumTrampolines);
163 /// Emit at least MinStubs worth of indirect call stubs, rounded out to
164 /// the nearest page size.
166 /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
167 /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
168 /// will return a block of 1024 (2-pages worth).
169 static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
170 unsigned MinStubs, void *InitialPtrVal);
173 /// X86_64 support for SysV ABI (Linux, MacOSX).
175 /// X86_64_SysV supports lazy JITing.
176 class OrcX86_64_SysV : public OrcX86_64_Base {
177 public:
178 static const unsigned ResolverCodeSize = 0x6C;
180 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
181 void *TrampolineId);
183 /// Write the resolver code into the given memory. The user is be
184 /// responsible for allocating the memory and setting permissions.
185 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
186 void *CallbackMgr);
189 /// X86_64 support for Win32.
191 /// X86_64_Win32 supports lazy JITing.
192 class OrcX86_64_Win32 : public OrcX86_64_Base {
193 public:
194 static const unsigned ResolverCodeSize = 0x74;
196 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
197 void *TrampolineId);
199 /// Write the resolver code into the given memory. The user is be
200 /// responsible for allocating the memory and setting permissions.
201 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
202 void *CallbackMgr);
205 /// I386 support.
207 /// I386 supports lazy JITing.
208 class OrcI386 {
209 public:
210 static const unsigned PointerSize = 4;
211 static const unsigned TrampolineSize = 8;
212 static const unsigned ResolverCodeSize = 0x4a;
214 using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
216 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
217 void *TrampolineId);
219 /// Write the resolver code into the given memory. The user is be
220 /// responsible for allocating the memory and setting permissions.
221 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
222 void *CallbackMgr);
224 /// Write the requsted number of trampolines into the given memory,
225 /// which must be big enough to hold 1 pointer, plus NumTrampolines
226 /// trampolines.
227 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
228 unsigned NumTrampolines);
230 /// Emit at least MinStubs worth of indirect call stubs, rounded out to
231 /// the nearest page size.
233 /// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
234 /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
235 /// will return a block of 1024 (2-pages worth).
236 static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
237 unsigned MinStubs, void *InitialPtrVal);
240 // @brief Mips32 support.
242 // Mips32 supports lazy JITing.
243 class OrcMips32_Base {
244 public:
245 static const unsigned PointerSize = 4;
246 static const unsigned TrampolineSize = 20;
247 static const unsigned ResolverCodeSize = 0xfc;
248 using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
250 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
251 void *TrampolineId);
252 /// @brief Write the requsted number of trampolines into the given memory,
253 /// which must be big enough to hold 1 pointer, plus NumTrampolines
254 /// trampolines.
255 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
257 /// @brief Write the resolver code into the given memory. The user is be
258 /// responsible for allocating the memory and setting permissions.
259 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian);
260 /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
261 /// the nearest page size.
263 /// E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k
264 /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
265 /// will return a block of 1024 (2-pages worth).
266 static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
270 class OrcMips32Le : public OrcMips32_Base {
271 public:
272 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
273 { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
276 class OrcMips32Be : public OrcMips32_Base {
277 public:
278 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
279 { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
282 // @brief Mips64 support.
284 // Mips64 supports lazy JITing.
285 class OrcMips64 {
286 public:
287 static const unsigned PointerSize = 8;
288 static const unsigned TrampolineSize = 40;
289 static const unsigned ResolverCodeSize = 0x120;
291 using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
292 using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
293 void *TrampolineId);
294 /// @brief Write the resolver code into the given memory. The user is be
295 /// responsible for allocating the memory and setting permissions.
296 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr);
298 /// @brief Write the requsted number of trampolines into the given memory,
299 /// which must be big enough to hold 1 pointer, plus NumTrampolines
300 /// trampolines.
301 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
303 /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
304 /// the nearest page size.
306 /// E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k
307 /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
308 /// will return a block of 1024 (2-pages worth).
309 static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
312 } // end namespace orc
313 } // end namespace llvm
314 #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H