1 //===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- 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 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
10 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
11
12 #include "llvm-c/OrcBindings.h"
13 #include "llvm-c/TargetMachine.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ExecutionEngine/JITSymbol.h"
17 #include "llvm/ExecutionEngine/JITEventListener.h"
18 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
19 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
20 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
21 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
22 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
23 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
24 #include "llvm/ExecutionEngine/RuntimeDyld.h"
25 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
26 #include "llvm/IR/DataLayout.h"
27 #include "llvm/IR/Mangler.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/Support/CBindingWrapping.h"
30 #include "llvm/Support/Error.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
33 #include <algorithm>
34 #include <cstdint>
35 #include <functional>
36 #include <map>
37 #include <memory>
38 #include <set>
39 #include <string>
40 #include <vector>
41
42 namespace llvm {
43
44 class OrcCBindingsStack;
45
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack,LLVMOrcJITStackRef)46 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
47 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
48
49 namespace detail {
50
51 // FIXME: Kill this off once the Layer concept becomes an interface.
52 class GenericLayer {
53 public:
54 virtual ~GenericLayer() = default;
55
56 virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
57 bool ExportedSymbolsOnly) = 0;
58 virtual Error removeModule(orc::VModuleKey K) = 0;
59 };
60
61 template <typename LayerT> class GenericLayerImpl : public GenericLayer {
62 public:
63 GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
64
65 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
66 bool ExportedSymbolsOnly) override {
67 return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
68 }
69
70 Error removeModule(orc::VModuleKey K) override {
71 return Layer.removeModule(K);
72 }
73
74 private:
75 LayerT &Layer;
76 };
77
78 template <>
79 class GenericLayerImpl<orc::LegacyRTDyldObjectLinkingLayer> : public GenericLayer {
80 private:
81 using LayerT = orc::LegacyRTDyldObjectLinkingLayer;
82 public:
83 GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
84
85 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
86 bool ExportedSymbolsOnly) override {
87 return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
88 }
89
90 Error removeModule(orc::VModuleKey K) override {
91 return Layer.removeObject(K);
92 }
93
94 private:
95 LayerT &Layer;
96 };
97
98 template <typename LayerT>
99 std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
100 return std::make_unique<GenericLayerImpl<LayerT>>(Layer);
101 }
102
103 } // end namespace detail
104
105 class OrcCBindingsStack {
106 public:
107
108 using CompileCallbackMgr = orc::JITCompileCallbackManager;
109 using ObjLayerT = orc::LegacyRTDyldObjectLinkingLayer;
110 using CompileLayerT = orc::LegacyIRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
111 using CODLayerT =
112 orc::LegacyCompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
113
114 using CallbackManagerBuilder =
115 std::function<std::unique_ptr<CompileCallbackMgr>()>;
116
117 using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
118
119 private:
120
121 using OwningObject = object::OwningBinary<object::ObjectFile>;
122
123 class CBindingsResolver : public orc::SymbolResolver {
124 public:
CBindingsResolver(OrcCBindingsStack & Stack,LLVMOrcSymbolResolverFn ExternalResolver,void * ExternalResolverCtx)125 CBindingsResolver(OrcCBindingsStack &Stack,
126 LLVMOrcSymbolResolverFn ExternalResolver,
127 void *ExternalResolverCtx)
128 : Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
129 ExternalResolverCtx(std::move(ExternalResolverCtx)) {}
130
131 orc::SymbolNameSet
getResponsibilitySet(const orc::SymbolNameSet & Symbols)132 getResponsibilitySet(const orc::SymbolNameSet &Symbols) override {
133 orc::SymbolNameSet Result;
134
135 for (auto &S : Symbols) {
136 if (auto Sym = findSymbol(*S)) {
137 if (!Sym.getFlags().isStrong())
138 Result.insert(S);
139 } else if (auto Err = Sym.takeError()) {
140 Stack.reportError(std::move(Err));
141 return orc::SymbolNameSet();
142 }
143 }
144
145 return Result;
146 }
147
148 orc::SymbolNameSet
lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,orc::SymbolNameSet Symbols)149 lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
150 orc::SymbolNameSet Symbols) override {
151 orc::SymbolNameSet UnresolvedSymbols;
152
153 for (auto &S : Symbols) {
154 if (auto Sym = findSymbol(*S)) {
155 if (auto Addr = Sym.getAddress()) {
156 Query->notifySymbolMetRequiredState(
157 S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
158 } else {
159 Stack.ES.legacyFailQuery(*Query, Addr.takeError());
160 return orc::SymbolNameSet();
161 }
162 } else if (auto Err = Sym.takeError()) {
163 Stack.ES.legacyFailQuery(*Query, std::move(Err));
164 return orc::SymbolNameSet();
165 } else
166 UnresolvedSymbols.insert(S);
167 }
168
169 if (Query->isComplete())
170 Query->handleComplete();
171
172 return UnresolvedSymbols;
173 }
174
175 private:
findSymbol(const std::string & Name)176 JITSymbol findSymbol(const std::string &Name) {
177 // Search order:
178 // 1. JIT'd symbols.
179 // 2. Runtime overrides.
180 // 3. External resolver (if present).
181
182 if (Stack.CODLayer) {
183 if (auto Sym = Stack.CODLayer->findSymbol(Name, true))
184 return Sym;
185 else if (auto Err = Sym.takeError())
186 return Sym.takeError();
187 } else {
188 if (auto Sym = Stack.CompileLayer.findSymbol(Name, true))
189 return Sym;
190 else if (auto Err = Sym.takeError())
191 return Sym.takeError();
192 }
193
194 if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
195 return Sym;
196
197 if (ExternalResolver)
198 return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
199 JITSymbolFlags::Exported);
200
201 return JITSymbol(nullptr);
202 }
203
204 OrcCBindingsStack &Stack;
205 LLVMOrcSymbolResolverFn ExternalResolver;
206 void *ExternalResolverCtx = nullptr;
207 };
208
209 public:
OrcCBindingsStack(TargetMachine & TM,IndirectStubsManagerBuilder IndirectStubsMgrBuilder)210 OrcCBindingsStack(TargetMachine &TM,
211 IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
212 : CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()),
213 IndirectStubsMgr(IndirectStubsMgrBuilder()),
214 ObjectLayer(
215 AcknowledgeORCv1Deprecation, ES,
216 [this](orc::VModuleKey K) {
217 auto ResolverI = Resolvers.find(K);
218 assert(ResolverI != Resolvers.end() &&
219 "No resolver for module K");
220 auto Resolver = std::move(ResolverI->second);
221 Resolvers.erase(ResolverI);
222 return ObjLayerT::Resources{
223 std::make_shared<SectionMemoryManager>(), Resolver};
224 },
225 nullptr,
226 [this](orc::VModuleKey K, const object::ObjectFile &Obj,
227 const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
228 this->notifyFinalized(K, Obj, LoadedObjInfo);
229 },
230 [this](orc::VModuleKey K, const object::ObjectFile &Obj) {
231 this->notifyFreed(K, Obj);
232 }),
233 CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
234 orc::SimpleCompiler(TM)),
235 CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(),
236 std::move(IndirectStubsMgrBuilder), Resolvers)),
237 CXXRuntimeOverrides(
238 AcknowledgeORCv1Deprecation,
239 [this](const std::string &S) { return mangle(S); }) {}
240
shutdown()241 Error shutdown() {
242 // Run any destructors registered with __cxa_atexit.
243 CXXRuntimeOverrides.runDestructors();
244 // Run any IR destructors.
245 for (auto &DtorRunner : IRStaticDestructorRunners)
246 if (auto Err = DtorRunner.runViaLayer(*this))
247 return Err;
248 return Error::success();
249 }
250
mangle(StringRef Name)251 std::string mangle(StringRef Name) {
252 std::string MangledName;
253 {
254 raw_string_ostream MangledNameStream(MangledName);
255 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
256 }
257 return MangledName;
258 }
259
260 template <typename PtrTy>
fromTargetAddress(JITTargetAddress Addr)261 static PtrTy fromTargetAddress(JITTargetAddress Addr) {
262 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
263 }
264
265 Expected<JITTargetAddress>
createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,void * CallbackCtx)266 createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
267 void *CallbackCtx) {
268 auto WrappedCallback = [=]() -> JITTargetAddress {
269 return Callback(wrap(this), CallbackCtx);
270 };
271
272 return CCMgr->getCompileCallback(std::move(WrappedCallback));
273 }
274
createIndirectStub(StringRef StubName,JITTargetAddress Addr)275 Error createIndirectStub(StringRef StubName, JITTargetAddress Addr) {
276 return IndirectStubsMgr->createStub(StubName, Addr,
277 JITSymbolFlags::Exported);
278 }
279
setIndirectStubPointer(StringRef Name,JITTargetAddress Addr)280 Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) {
281 return IndirectStubsMgr->updatePointer(Name, Addr);
282 }
283
284 template <typename LayerT>
285 Expected<orc::VModuleKey>
addIRModule(LayerT & Layer,std::unique_ptr<Module> M,std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,LLVMOrcSymbolResolverFn ExternalResolver,void * ExternalResolverCtx)286 addIRModule(LayerT &Layer, std::unique_ptr<Module> M,
287 std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
288 LLVMOrcSymbolResolverFn ExternalResolver,
289 void *ExternalResolverCtx) {
290
291 // Attach a data-layout if one isn't already present.
292 if (M->getDataLayout().isDefault())
293 M->setDataLayout(DL);
294
295 // Record the static constructors and destructors. We have to do this before
296 // we hand over ownership of the module to the JIT.
297 std::vector<std::string> CtorNames, DtorNames;
298 for (auto Ctor : orc::getConstructors(*M))
299 CtorNames.push_back(mangle(Ctor.Func->getName()));
300 for (auto Dtor : orc::getDestructors(*M))
301 DtorNames.push_back(mangle(Dtor.Func->getName()));
302
303 // Add the module to the JIT.
304 auto K = ES.allocateVModule();
305 Resolvers[K] = std::make_shared<CBindingsResolver>(*this, ExternalResolver,
306 ExternalResolverCtx);
307 if (auto Err = Layer.addModule(K, std::move(M)))
308 return std::move(Err);
309
310 KeyLayers[K] = detail::createGenericLayer(Layer);
311
312 // Run the static constructors, and save the static destructor runner for
313 // execution when the JIT is torn down.
314 orc::LegacyCtorDtorRunner<OrcCBindingsStack> CtorRunner(
315 AcknowledgeORCv1Deprecation, std::move(CtorNames), K);
316 if (auto Err = CtorRunner.runViaLayer(*this))
317 return std::move(Err);
318
319 IRStaticDestructorRunners.emplace_back(AcknowledgeORCv1Deprecation,
320 std::move(DtorNames), K);
321
322 return K;
323 }
324
325 Expected<orc::VModuleKey>
addIRModuleEager(std::unique_ptr<Module> M,LLVMOrcSymbolResolverFn ExternalResolver,void * ExternalResolverCtx)326 addIRModuleEager(std::unique_ptr<Module> M,
327 LLVMOrcSymbolResolverFn ExternalResolver,
328 void *ExternalResolverCtx) {
329 return addIRModule(CompileLayer, std::move(M),
330 std::make_unique<SectionMemoryManager>(),
331 std::move(ExternalResolver), ExternalResolverCtx);
332 }
333
334 Expected<orc::VModuleKey>
addIRModuleLazy(std::unique_ptr<Module> M,LLVMOrcSymbolResolverFn ExternalResolver,void * ExternalResolverCtx)335 addIRModuleLazy(std::unique_ptr<Module> M,
336 LLVMOrcSymbolResolverFn ExternalResolver,
337 void *ExternalResolverCtx) {
338 if (!CODLayer)
339 return make_error<StringError>("Can not add lazy module: No compile "
340 "callback manager available",
341 inconvertibleErrorCode());
342
343 return addIRModule(*CODLayer, std::move(M),
344 std::make_unique<SectionMemoryManager>(),
345 std::move(ExternalResolver), ExternalResolverCtx);
346 }
347
removeModule(orc::VModuleKey K)348 Error removeModule(orc::VModuleKey K) {
349 // FIXME: Should error release the module key?
350 if (auto Err = KeyLayers[K]->removeModule(K))
351 return Err;
352 ES.releaseVModule(K);
353 KeyLayers.erase(K);
354 return Error::success();
355 }
356
addObject(std::unique_ptr<MemoryBuffer> ObjBuffer,LLVMOrcSymbolResolverFn ExternalResolver,void * ExternalResolverCtx)357 Expected<orc::VModuleKey> addObject(std::unique_ptr<MemoryBuffer> ObjBuffer,
358 LLVMOrcSymbolResolverFn ExternalResolver,
359 void *ExternalResolverCtx) {
360 if (auto Obj = object::ObjectFile::createObjectFile(
361 ObjBuffer->getMemBufferRef())) {
362
363 auto K = ES.allocateVModule();
364 Resolvers[K] = std::make_shared<CBindingsResolver>(
365 *this, ExternalResolver, ExternalResolverCtx);
366
367 if (auto Err = ObjectLayer.addObject(K, std::move(ObjBuffer)))
368 return std::move(Err);
369
370 KeyLayers[K] = detail::createGenericLayer(ObjectLayer);
371
372 return K;
373 } else
374 return Obj.takeError();
375 }
376
findSymbol(const std::string & Name,bool ExportedSymbolsOnly)377 JITSymbol findSymbol(const std::string &Name,
378 bool ExportedSymbolsOnly) {
379 if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
380 return Sym;
381 if (CODLayer)
382 return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly);
383 return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
384 }
385
findSymbolIn(orc::VModuleKey K,const std::string & Name,bool ExportedSymbolsOnly)386 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
387 bool ExportedSymbolsOnly) {
388 assert(KeyLayers.count(K) && "looking up symbol in unknown module");
389 return KeyLayers[K]->findSymbolIn(K, mangle(Name), ExportedSymbolsOnly);
390 }
391
findSymbolAddress(const std::string & Name,bool ExportedSymbolsOnly)392 Expected<JITTargetAddress> findSymbolAddress(const std::string &Name,
393 bool ExportedSymbolsOnly) {
394 if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
395 // Successful lookup, non-null symbol:
396 if (auto AddrOrErr = Sym.getAddress())
397 return *AddrOrErr;
398 else
399 return AddrOrErr.takeError();
400 } else if (auto Err = Sym.takeError()) {
401 // Lookup failure - report error.
402 return std::move(Err);
403 }
404
405 // No symbol not found. Return 0.
406 return 0;
407 }
408
findSymbolAddressIn(orc::VModuleKey K,const std::string & Name,bool ExportedSymbolsOnly)409 Expected<JITTargetAddress> findSymbolAddressIn(orc::VModuleKey K,
410 const std::string &Name,
411 bool ExportedSymbolsOnly) {
412 if (auto Sym = findSymbolIn(K, Name, ExportedSymbolsOnly)) {
413 // Successful lookup, non-null symbol:
414 if (auto AddrOrErr = Sym.getAddress())
415 return *AddrOrErr;
416 else
417 return AddrOrErr.takeError();
418 } else if (auto Err = Sym.takeError()) {
419 // Lookup failure - report error.
420 return std::move(Err);
421 }
422
423 // Symbol not found. Return 0.
424 return 0;
425 }
426
getErrorMessage()427 const std::string &getErrorMessage() const { return ErrMsg; }
428
RegisterJITEventListener(JITEventListener * L)429 void RegisterJITEventListener(JITEventListener *L) {
430 if (!L)
431 return;
432 EventListeners.push_back(L);
433 }
434
UnregisterJITEventListener(JITEventListener * L)435 void UnregisterJITEventListener(JITEventListener *L) {
436 if (!L)
437 return;
438
439 auto I = find(reverse(EventListeners), L);
440 if (I != EventListeners.rend()) {
441 std::swap(*I, EventListeners.back());
442 EventListeners.pop_back();
443 }
444 }
445
446 private:
447 using ResolverMap =
448 std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>;
449
450 static std::unique_ptr<CompileCallbackMgr>
createCompileCallbackManager(TargetMachine & TM,orc::ExecutionSession & ES)451 createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) {
452 auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0);
453 if (!CCMgr) {
454 // FIXME: It would be good if we could report this somewhere, but we do
455 // have an instance yet.
456 logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: ");
457 return nullptr;
458 }
459 return std::move(*CCMgr);
460 }
461
462 static std::unique_ptr<CODLayerT>
createCODLayer(orc::ExecutionSession & ES,CompileLayerT & CompileLayer,CompileCallbackMgr * CCMgr,IndirectStubsManagerBuilder IndirectStubsMgrBuilder,ResolverMap & Resolvers)463 createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer,
464 CompileCallbackMgr *CCMgr,
465 IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
466 ResolverMap &Resolvers) {
467 // If there is no compile callback manager available we can not create a
468 // compile on demand layer.
469 if (!CCMgr)
470 return nullptr;
471
472 return std::make_unique<CODLayerT>(
473 AcknowledgeORCv1Deprecation, ES, CompileLayer,
474 [&Resolvers](orc::VModuleKey K) {
475 auto ResolverI = Resolvers.find(K);
476 assert(ResolverI != Resolvers.end() && "No resolver for module K");
477 return ResolverI->second;
478 },
479 [&Resolvers](orc::VModuleKey K,
480 std::shared_ptr<orc::SymbolResolver> Resolver) {
481 assert(!Resolvers.count(K) && "Resolver already present");
482 Resolvers[K] = std::move(Resolver);
483 },
484 [](Function &F) { return std::set<Function *>({&F}); }, *CCMgr,
485 std::move(IndirectStubsMgrBuilder), false);
486 }
487
reportError(Error Err)488 void reportError(Error Err) {
489 // FIXME: Report errors on the execution session.
490 logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
491 };
492
notifyFinalized(orc::VModuleKey K,const object::ObjectFile & Obj,const RuntimeDyld::LoadedObjectInfo & LoadedObjInfo)493 void notifyFinalized(orc::VModuleKey K,
494 const object::ObjectFile &Obj,
495 const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
496 uint64_t Key = static_cast<uint64_t>(
497 reinterpret_cast<uintptr_t>(Obj.getData().data()));
498 for (auto &Listener : EventListeners)
499 Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo);
500 }
501
notifyFreed(orc::VModuleKey K,const object::ObjectFile & Obj)502 void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) {
503 uint64_t Key = static_cast<uint64_t>(
504 reinterpret_cast<uintptr_t>(Obj.getData().data()));
505 for (auto &Listener : EventListeners)
506 Listener->notifyFreeingObject(Key);
507 }
508
509 orc::ExecutionSession ES;
510 std::unique_ptr<CompileCallbackMgr> CCMgr;
511
512 std::vector<JITEventListener *> EventListeners;
513
514 DataLayout DL;
515 SectionMemoryManager CCMgrMemMgr;
516
517 std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
518
519 ObjLayerT ObjectLayer;
520 CompileLayerT CompileLayer;
521 std::unique_ptr<CODLayerT> CODLayer;
522
523 std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
524
525 orc::LegacyLocalCXXRuntimeOverrides CXXRuntimeOverrides;
526 std::vector<orc::LegacyCtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
527 std::string ErrMsg;
528
529 ResolverMap Resolvers;
530 };
531
532 } // end namespace llvm
533
534 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
535