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