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 27 namespace llvm { 28 29 class OrcLazyJIT { 30 public: 31 32 typedef orc::JITCompileCallbackManager CompileCallbackMgr; 33 typedef orc::ObjectLinkingLayer<> ObjLayerT; 34 typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT; 35 typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> 36 TransformFtor; 37 typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT; 38 typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT; 39 typedef CODLayerT::IndirectStubsManagerBuilderT 40 IndirectStubsManagerBuilder; 41 typedef CODLayerT::ModuleSetHandleT ModuleHandleT; 42 OrcLazyJIT(std::unique_ptr<TargetMachine> TM,std::unique_ptr<CompileCallbackMgr> CCMgr,IndirectStubsManagerBuilder IndirectStubsMgrBuilder,bool InlineStubs)43 OrcLazyJIT(std::unique_ptr<TargetMachine> TM, 44 std::unique_ptr<CompileCallbackMgr> CCMgr, 45 IndirectStubsManagerBuilder IndirectStubsMgrBuilder, 46 bool InlineStubs) 47 : TM(std::move(TM)), DL(this->TM->createDataLayout()), 48 CCMgr(std::move(CCMgr)), 49 ObjectLayer(), 50 CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), 51 IRDumpLayer(CompileLayer, createDebugDumper()), 52 CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr, 53 std::move(IndirectStubsMgrBuilder), InlineStubs), 54 CXXRuntimeOverrides( 55 [this](const std::string &S) { return mangle(S); }) {} 56 ~OrcLazyJIT()57 ~OrcLazyJIT() { 58 // Run any destructors registered with __cxa_atexit. 59 CXXRuntimeOverrides.runDestructors(); 60 // Run any IR destructors. 61 for (auto &DtorRunner : IRStaticDestructorRunners) 62 DtorRunner.runViaLayer(CODLayer); 63 } 64 addModule(std::unique_ptr<Module> M)65 ModuleHandleT addModule(std::unique_ptr<Module> M) { 66 // Attach a data-layout if one isn't already present. 67 if (M->getDataLayout().isDefault()) 68 M->setDataLayout(DL); 69 70 // Record the static constructors and destructors. We have to do this before 71 // we hand over ownership of the module to the JIT. 72 std::vector<std::string> CtorNames, DtorNames; 73 for (auto Ctor : orc::getConstructors(*M)) 74 CtorNames.push_back(mangle(Ctor.Func->getName())); 75 for (auto Dtor : orc::getDestructors(*M)) 76 DtorNames.push_back(mangle(Dtor.Func->getName())); 77 78 // Symbol resolution order: 79 // 1) Search the JIT symbols. 80 // 2) Check for C++ runtime overrides. 81 // 3) Search the host process (LLI)'s symbol table. 82 auto Resolver = 83 orc::createLambdaResolver( 84 [this](const std::string &Name) { 85 if (auto Sym = CODLayer.findSymbol(Name, true)) 86 return Sym.toRuntimeDyldSymbol(); 87 if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) 88 return Sym; 89 90 if (auto Addr = 91 RTDyldMemoryManager::getSymbolAddressInProcess(Name)) 92 return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported); 93 94 return RuntimeDyld::SymbolInfo(nullptr); 95 }, 96 [](const std::string &Name) { 97 return RuntimeDyld::SymbolInfo(nullptr); 98 } 99 ); 100 101 // Add the module to the JIT. 102 std::vector<std::unique_ptr<Module>> S; 103 S.push_back(std::move(M)); 104 auto H = CODLayer.addModuleSet(std::move(S), 105 llvm::make_unique<SectionMemoryManager>(), 106 std::move(Resolver)); 107 108 // Run the static constructors, and save the static destructor runner for 109 // execution when the JIT is torn down. 110 orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H); 111 CtorRunner.runViaLayer(CODLayer); 112 113 IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H); 114 115 return H; 116 } 117 findSymbol(const std::string & Name)118 orc::JITSymbol findSymbol(const std::string &Name) { 119 return CODLayer.findSymbol(mangle(Name), true); 120 } 121 findSymbolIn(ModuleHandleT H,const std::string & Name)122 orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { 123 return CODLayer.findSymbolIn(H, mangle(Name), true); 124 } 125 126 private: 127 mangle(const std::string & Name)128 std::string mangle(const std::string &Name) { 129 std::string MangledName; 130 { 131 raw_string_ostream MangledNameStream(MangledName); 132 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 133 } 134 return MangledName; 135 } 136 extractSingleFunction(Function & F)137 static std::set<Function*> extractSingleFunction(Function &F) { 138 std::set<Function*> Partition; 139 Partition.insert(&F); 140 return Partition; 141 } 142 143 static TransformFtor createDebugDumper(); 144 145 std::unique_ptr<TargetMachine> TM; 146 DataLayout DL; 147 SectionMemoryManager CCMgrMemMgr; 148 149 std::unique_ptr<CompileCallbackMgr> CCMgr; 150 ObjLayerT ObjectLayer; 151 CompileLayerT CompileLayer; 152 IRDumpLayerT IRDumpLayer; 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