1 //===--- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution --*- 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 // Simple Orc-based JIT. Uses the compile-on-demand layer to break up and 11 // lazily compile modules. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H 16 #define LLVM_TOOLS_LLI_ORCLAZYJIT_H 17 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" 20 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 21 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 22 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 23 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" 24 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 25 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 26 #include "llvm/IR/LLVMContext.h" 27 28 namespace llvm { 29 30 class OrcLazyJIT { 31 public: 32 33 typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr; 34 typedef orc::ObjectLinkingLayer<> ObjLayerT; 35 typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT; 36 typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> 37 TransformFtor; 38 typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT; 39 typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT; 40 typedef CODLayerT::ModuleSetHandleT ModuleHandleT; 41 42 typedef std::function< 43 std::unique_ptr<CompileCallbackMgr>(IRDumpLayerT&, 44 RuntimeDyld::MemoryManager&, 45 LLVMContext&)> 46 CallbackManagerBuilder; 47 48 static CallbackManagerBuilder createCallbackManagerBuilder(Triple T); 49 OrcLazyJIT(std::unique_ptr<TargetMachine> TM,LLVMContext & Context,CallbackManagerBuilder & BuildCallbackMgr)50 OrcLazyJIT(std::unique_ptr<TargetMachine> TM, LLVMContext &Context, 51 CallbackManagerBuilder &BuildCallbackMgr) 52 : TM(std::move(TM)), 53 ObjectLayer(), 54 CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), 55 IRDumpLayer(CompileLayer, createDebugDumper()), 56 CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)), 57 CODLayer(IRDumpLayer, *CCMgr, false), 58 CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {} 59 ~OrcLazyJIT()60 ~OrcLazyJIT() { 61 // Run any destructors registered with __cxa_atexit. 62 CXXRuntimeOverrides.runDestructors(); 63 // Run any IR destructors. 64 for (auto &DtorRunner : IRStaticDestructorRunners) 65 DtorRunner.runViaLayer(CODLayer); 66 } 67 68 template <typename PtrTy> fromTargetAddress(orc::TargetAddress Addr)69 static PtrTy fromTargetAddress(orc::TargetAddress Addr) { 70 return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr)); 71 } 72 addModule(std::unique_ptr<Module> M)73 ModuleHandleT addModule(std::unique_ptr<Module> M) { 74 // Attach a data-layout if one isn't already present. 75 if (M->getDataLayout().isDefault()) 76 M->setDataLayout(*TM->getDataLayout()); 77 78 // Record the static constructors and destructors. We have to do this before 79 // we hand over ownership of the module to the JIT. 80 std::vector<std::string> CtorNames, DtorNames; 81 for (auto Ctor : orc::getConstructors(*M)) 82 CtorNames.push_back(mangle(Ctor.Func->getName())); 83 for (auto Dtor : orc::getDestructors(*M)) 84 DtorNames.push_back(mangle(Dtor.Func->getName())); 85 86 // Symbol resolution order: 87 // 1) Search the JIT symbols. 88 // 2) Check for C++ runtime overrides. 89 // 3) Search the host process (LLI)'s symbol table. 90 std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver = 91 orc::createLambdaResolver( 92 [this](const std::string &Name) { 93 if (auto Sym = CODLayer.findSymbol(Name, true)) 94 return RuntimeDyld::SymbolInfo(Sym.getAddress(), 95 Sym.getFlags()); 96 if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) 97 return Sym; 98 99 if (auto Addr = 100 RTDyldMemoryManager::getSymbolAddressInProcess(Name)) 101 return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported); 102 103 return RuntimeDyld::SymbolInfo(nullptr); 104 }, 105 [](const std::string &Name) { 106 return RuntimeDyld::SymbolInfo(nullptr); 107 } 108 ); 109 110 // Add the module to the JIT. 111 std::vector<std::unique_ptr<Module>> S; 112 S.push_back(std::move(M)); 113 auto H = CODLayer.addModuleSet(std::move(S), nullptr, std::move(Resolver)); 114 115 // Run the static constructors, and save the static destructor runner for 116 // execution when the JIT is torn down. 117 orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H); 118 CtorRunner.runViaLayer(CODLayer); 119 120 IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H); 121 122 return H; 123 } 124 findSymbol(const std::string & Name)125 orc::JITSymbol findSymbol(const std::string &Name) { 126 return CODLayer.findSymbol(mangle(Name), true); 127 } 128 findSymbolIn(ModuleHandleT H,const std::string & Name)129 orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { 130 return CODLayer.findSymbolIn(H, mangle(Name), true); 131 } 132 133 private: 134 mangle(const std::string & Name)135 std::string mangle(const std::string &Name) { 136 std::string MangledName; 137 { 138 raw_string_ostream MangledNameStream(MangledName); 139 Mangler::getNameWithPrefix(MangledNameStream, Name, *TM->getDataLayout()); 140 } 141 return MangledName; 142 } 143 144 static TransformFtor createDebugDumper(); 145 146 std::unique_ptr<TargetMachine> TM; 147 SectionMemoryManager CCMgrMemMgr; 148 149 ObjLayerT ObjectLayer; 150 CompileLayerT CompileLayer; 151 IRDumpLayerT IRDumpLayer; 152 std::unique_ptr<CompileCallbackMgr> CCMgr; 153 CODLayerT CODLayer; 154 155 orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; 156 std::vector<orc::CtorDtorRunner<CODLayerT>> IRStaticDestructorRunners; 157 }; 158 159 int runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]); 160 161 } // end namespace llvm 162 163 #endif 164