1 //===--- OrcCBindingsStack.h - Orc JIT stack for C bindings ---*- C++ -*---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
11 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
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"
23 class OrcCBindingsStack {
28 typedef orc::TargetAddress (*CExternalSymbolResolverFn)(const char *Name,
31 typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
32 typedef orc::ObjectLinkingLayer<> ObjLayerT;
33 typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
34 typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr> CODLayerT;
36 typedef std::function<
37 std::unique_ptr<CompileCallbackMgr>(CompileLayerT&,
38 RuntimeDyld::MemoryManager&,
40 CallbackManagerBuilder;
42 typedef CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder;
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;
53 struct ModuleHandleData {
55 ModuleHandleData() : Type(Invalid) {}
57 ModuleHandleData(ObjLayerT::ObjSetHandleT H)
58 : Type(ObjectLayerHandle) {
59 RawHandle.Obj = std::move(H);
62 ModuleHandleData(CODLayerT::ModuleSetHandleT H)
63 : Type(CODLayerHandle) {
64 RawHandle.COD = std::move(H);
68 RawHandleUnion RawHandle;
73 // We need a 'ModuleSetHandleT' to conform to the layer concept.
74 typedef unsigned ModuleSetHandleT;
76 typedef unsigned ModuleHandleT;
78 static CallbackManagerBuilder createCallbackManagerBuilder(Triple T);
79 static IndirectStubsManagerBuilder createIndirectStubsMgrBuilder(Triple T);
81 OrcCBindingsStack(TargetMachine &TM, LLVMContext &Context,
82 CallbackManagerBuilder &BuildCallbackMgr,
83 IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
84 : DL(TM.createDataLayout()),
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); }) {}
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);
101 std::string mangle(StringRef Name) {
102 std::string MangledName;
104 raw_string_ostream MangledNameStream(MangledName);
105 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
110 template <typename PtrTy>
111 static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
112 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
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) {
122 // 2. Runtime overrides.
123 // 3. External resolver (if present).
125 if (auto Sym = CODLayer.findSymbol(Name, true))
126 return RuntimeDyld::SymbolInfo(Sym.getAddress(),
128 if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
131 if (ExternalResolver)
132 return RuntimeDyld::SymbolInfo(ExternalResolver(Name.c_str(),
133 ExternalResolverCtx),
134 llvm::JITSymbolFlags::Exported);
136 return RuntimeDyld::SymbolInfo(nullptr);
138 [](const std::string &Name) {
139 return RuntimeDyld::SymbolInfo(nullptr);
143 return std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(Resolver));
146 template <typename LayerT>
147 ModuleHandleT addIRModule(LayerT &Layer,
149 std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
150 CExternalSymbolResolverFn ExternalResolver,
151 void *ExternalResolverCtx) {
153 // Attach a data-layout if one isn't already present.
154 if (M->getDataLayout().isDefault())
155 M->setDataLayout(DL);
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()));
165 // Create the resolver.
166 auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
168 // Add the module to the JIT.
169 std::vector<Module*> S;
170 S.push_back(std::move(M));
172 auto LH = Layer.addModuleSet(std::move(S), std::move(MemMgr),
173 std::move(Resolver));
174 ModuleHandleT H = createHandle(LH);
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);
181 IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
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);
194 ModuleHandleT addIRModuleLazy(Module* M,
195 CExternalSymbolResolverFn ExternalResolver,
196 void *ExternalResolverCtx) {
197 return addIRModule(CODLayer, std::move(M), nullptr,
198 std::move(ExternalResolver), ExternalResolverCtx);
201 void removeModule(ModuleHandleT H) {
202 auto &HD = HandleData[H];
204 case ObjectLayerHandle:
205 ObjectLayer.removeObjectSet(HD.RawHandle.Obj);
208 CODLayer.removeModuleSet(HD.RawHandle.COD);
211 llvm_unreachable("removeModule called on invalid handle type");
215 orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
216 return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
219 orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
220 bool ExportedSymbolsOnly) {
221 auto &HD = HandleData[H];
223 case ObjectLayerHandle:
224 return ObjectLayer.findSymbolIn(HD.RawHandle.Obj, mangle(Name),
225 ExportedSymbolsOnly);
227 return CODLayer.findSymbolIn(HD.RawHandle.COD, mangle(Name),
228 ExportedSymbolsOnly);
230 llvm_unreachable("removeModule called on invalid handle type");
236 template <typename LayerHandleT>
237 unsigned createHandle(LayerHandleT LH) {
239 if (!FreeHandles.empty()) {
240 NewHandle = FreeHandles.back();
241 FreeHandles.pop_back();
242 HandleData[NewHandle] = ModuleHandleData(std::move(LH));
245 NewHandle = HandleData.size();
246 HandleData.push_back(ModuleHandleData(std::move(LH)));
252 SectionMemoryManager CCMgrMemMgr;
254 ObjLayerT ObjectLayer;
255 CompileLayerT CompileLayer;
256 std::unique_ptr<CompileCallbackMgr> CCMgr;
259 std::vector<ModuleHandleData> HandleData;
260 std::vector<unsigned> FreeHandles;
262 orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
263 std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
266 } // end namespace llvm
268 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H