• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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