1 //===--- OrcCBindingsStack.h - Orc JIT stack for C bindings ---*- 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 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
11 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
12
13 #include "llvm-c/OrcBindings.h"
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
16 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
17 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
18 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
19 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/Support/Error.h"
22
23 namespace llvm {
24
25 class OrcCBindingsStack;
26
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack,LLVMOrcJITStackRef)27 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
28 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
29
30 class OrcCBindingsStack {
31 public:
32 typedef orc::JITCompileCallbackManager CompileCallbackMgr;
33 typedef orc::ObjectLinkingLayer<> ObjLayerT;
34 typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
35 typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>
36 CODLayerT;
37
38 typedef std::function<std::unique_ptr<CompileCallbackMgr>()>
39 CallbackManagerBuilder;
40
41 typedef CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder;
42
43 private:
44 class GenericHandle {
45 public:
46 virtual ~GenericHandle() {}
47 virtual orc::JITSymbol findSymbolIn(const std::string &Name,
48 bool ExportedSymbolsOnly) = 0;
49 virtual void removeModule() = 0;
50 };
51
52 template <typename LayerT> class GenericHandleImpl : public GenericHandle {
53 public:
54 GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleSetHandleT Handle)
55 : Layer(Layer), Handle(std::move(Handle)) {}
56
57 orc::JITSymbol findSymbolIn(const std::string &Name,
58 bool ExportedSymbolsOnly) override {
59 return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
60 }
61
62 void removeModule() override { return Layer.removeModuleSet(Handle); }
63
64 private:
65 LayerT &Layer;
66 typename LayerT::ModuleSetHandleT Handle;
67 };
68
69 template <typename LayerT>
70 std::unique_ptr<GenericHandleImpl<LayerT>>
71 createGenericHandle(LayerT &Layer, typename LayerT::ModuleSetHandleT Handle) {
72 return llvm::make_unique<GenericHandleImpl<LayerT>>(Layer,
73 std::move(Handle));
74 }
75
76 public:
77 // We need a 'ModuleSetHandleT' to conform to the layer concept.
78 typedef unsigned ModuleSetHandleT;
79
80 typedef unsigned ModuleHandleT;
81
82 OrcCBindingsStack(TargetMachine &TM,
83 std::unique_ptr<CompileCallbackMgr> CCMgr,
84 IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
85 : DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()),
86 CCMgr(std::move(CCMgr)), ObjectLayer(),
87 CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
88 CODLayer(CompileLayer,
89 [](Function &F) { return std::set<Function *>({&F}); },
90 *this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
91 CXXRuntimeOverrides(
92 [this](const std::string &S) { return mangle(S); }) {}
93
94 ~OrcCBindingsStack() {
95 // Run any destructors registered with __cxa_atexit.
96 CXXRuntimeOverrides.runDestructors();
97 // Run any IR destructors.
98 for (auto &DtorRunner : IRStaticDestructorRunners)
99 DtorRunner.runViaLayer(*this);
100 }
101
102 std::string mangle(StringRef Name) {
103 std::string MangledName;
104 {
105 raw_string_ostream MangledNameStream(MangledName);
106 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
107 }
108 return MangledName;
109 }
110
111 template <typename PtrTy>
112 static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
113 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
114 }
115
116 orc::TargetAddress
117 createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
118 void *CallbackCtx) {
119 auto CCInfo = CCMgr->getCompileCallback();
120 CCInfo.setCompileAction([=]() -> orc::TargetAddress {
121 return Callback(wrap(this), CallbackCtx);
122 });
123 return CCInfo.getAddress();
124 }
125
126 LLVMOrcErrorCode createIndirectStub(StringRef StubName,
127 orc::TargetAddress Addr) {
128 return mapError(
129 IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported));
130 }
131
132 LLVMOrcErrorCode setIndirectStubPointer(StringRef Name,
133 orc::TargetAddress Addr) {
134 return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
135 }
136
137 std::unique_ptr<RuntimeDyld::SymbolResolver>
138 createResolver(LLVMOrcSymbolResolverFn ExternalResolver,
139 void *ExternalResolverCtx) {
140 return orc::createLambdaResolver(
141 [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) {
142 // Search order:
143 // 1. JIT'd symbols.
144 // 2. Runtime overrides.
145 // 3. External resolver (if present).
146
147 if (auto Sym = CODLayer.findSymbol(Name, true))
148 return Sym.toRuntimeDyldSymbol();
149 if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
150 return Sym;
151
152 if (ExternalResolver)
153 return RuntimeDyld::SymbolInfo(
154 ExternalResolver(Name.c_str(), ExternalResolverCtx),
155 llvm::JITSymbolFlags::Exported);
156
157 return RuntimeDyld::SymbolInfo(nullptr);
158 },
159 [](const std::string &Name) {
160 return RuntimeDyld::SymbolInfo(nullptr);
161 });
162 }
163
164 template <typename LayerT>
165 ModuleHandleT addIRModule(LayerT &Layer, Module *M,
166 std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
167 LLVMOrcSymbolResolverFn ExternalResolver,
168 void *ExternalResolverCtx) {
169
170 // Attach a data-layout if one isn't already present.
171 if (M->getDataLayout().isDefault())
172 M->setDataLayout(DL);
173
174 // Record the static constructors and destructors. We have to do this before
175 // we hand over ownership of the module to the JIT.
176 std::vector<std::string> CtorNames, DtorNames;
177 for (auto Ctor : orc::getConstructors(*M))
178 CtorNames.push_back(mangle(Ctor.Func->getName()));
179 for (auto Dtor : orc::getDestructors(*M))
180 DtorNames.push_back(mangle(Dtor.Func->getName()));
181
182 // Create the resolver.
183 auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
184
185 // Add the module to the JIT.
186 std::vector<Module *> S;
187 S.push_back(std::move(M));
188
189 auto LH = Layer.addModuleSet(std::move(S), std::move(MemMgr),
190 std::move(Resolver));
191 ModuleHandleT H = createHandle(Layer, LH);
192
193 // Run the static constructors, and save the static destructor runner for
194 // execution when the JIT is torn down.
195 orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames), H);
196 CtorRunner.runViaLayer(*this);
197
198 IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
199
200 return H;
201 }
202
203 ModuleHandleT addIRModuleEager(Module *M,
204 LLVMOrcSymbolResolverFn ExternalResolver,
205 void *ExternalResolverCtx) {
206 return addIRModule(CompileLayer, std::move(M),
207 llvm::make_unique<SectionMemoryManager>(),
208 std::move(ExternalResolver), ExternalResolverCtx);
209 }
210
211 ModuleHandleT addIRModuleLazy(Module *M,
212 LLVMOrcSymbolResolverFn ExternalResolver,
213 void *ExternalResolverCtx) {
214 return addIRModule(CODLayer, std::move(M),
215 llvm::make_unique<SectionMemoryManager>(),
216 std::move(ExternalResolver), ExternalResolverCtx);
217 }
218
219 void removeModule(ModuleHandleT H) {
220 GenericHandles[H]->removeModule();
221 GenericHandles[H] = nullptr;
222 FreeHandleIndexes.push_back(H);
223 }
224
225 orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
226 if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
227 return Sym;
228 return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
229 }
230
231 orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
232 bool ExportedSymbolsOnly) {
233 return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly);
234 }
235
236 const std::string &getErrorMessage() const { return ErrMsg; }
237
238 private:
239 template <typename LayerT>
240 unsigned createHandle(LayerT &Layer,
241 typename LayerT::ModuleSetHandleT Handle) {
242 unsigned NewHandle;
243 if (!FreeHandleIndexes.empty()) {
244 NewHandle = FreeHandleIndexes.back();
245 FreeHandleIndexes.pop_back();
246 GenericHandles[NewHandle] = createGenericHandle(Layer, std::move(Handle));
247 return NewHandle;
248 } else {
249 NewHandle = GenericHandles.size();
250 GenericHandles.push_back(createGenericHandle(Layer, std::move(Handle)));
251 }
252 return NewHandle;
253 }
254
255 LLVMOrcErrorCode mapError(Error Err) {
256 LLVMOrcErrorCode Result = LLVMOrcErrSuccess;
257 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
258 // Handler of last resort.
259 Result = LLVMOrcErrGeneric;
260 ErrMsg = "";
261 raw_string_ostream ErrStream(ErrMsg);
262 EIB.log(ErrStream);
263 });
264 return Result;
265 }
266
267 DataLayout DL;
268 SectionMemoryManager CCMgrMemMgr;
269
270 std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
271
272 std::unique_ptr<CompileCallbackMgr> CCMgr;
273 ObjLayerT ObjectLayer;
274 CompileLayerT CompileLayer;
275 CODLayerT CODLayer;
276
277 std::vector<std::unique_ptr<GenericHandle>> GenericHandles;
278 std::vector<unsigned> FreeHandleIndexes;
279
280 orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
281 std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
282 std::string ErrMsg;
283 };
284
285 } // end namespace llvm
286
287 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
288