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