1 //===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===// 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 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 11 #include "llvm/ExecutionEngine/Orc/OrcError.h" 12 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 13 #include "llvm/IR/Mangler.h" 14 15 namespace { 16 17 // A SimpleCompiler that owns its TargetMachine. 18 class TMOwningSimpleCompiler : public llvm::orc::SimpleCompiler { 19 public: 20 TMOwningSimpleCompiler(std::unique_ptr<llvm::TargetMachine> TM) 21 : llvm::orc::SimpleCompiler(*TM), TM(std::move(TM)) {} 22 private: 23 // FIXME: shared because std::functions (and thus 24 // IRCompileLayer2::CompileFunction) are not moveable. 25 std::shared_ptr<llvm::TargetMachine> TM; 26 }; 27 28 } // end anonymous namespace 29 30 namespace llvm { 31 namespace orc { 32 33 LLJIT::~LLJIT() { 34 if (CompileThreads) 35 CompileThreads->wait(); 36 } 37 38 Expected<std::unique_ptr<LLJIT>> 39 LLJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL, 40 unsigned NumCompileThreads) { 41 42 if (NumCompileThreads == 0) { 43 // If NumCompileThreads == 0 then create a single-threaded LLJIT instance. 44 auto TM = JTMB.createTargetMachine(); 45 if (!TM) 46 return TM.takeError(); 47 return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(), 48 std::move(*TM), std::move(DL))); 49 } 50 51 return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(), 52 std::move(JTMB), std::move(DL), 53 NumCompileThreads)); 54 } 55 56 Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) { 57 auto InternedName = ES->intern(Name); 58 SymbolMap Symbols({{InternedName, Sym}}); 59 return Main.define(absoluteSymbols(std::move(Symbols))); 60 } 61 62 Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) { 63 assert(TSM && "Can not add null module"); 64 65 if (auto Err = applyDataLayout(*TSM.getModule())) 66 return Err; 67 68 auto K = ES->allocateVModule(); 69 return CompileLayer.add(JD, K, std::move(TSM)); 70 } 71 72 Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) { 73 assert(Obj && "Can not add null object"); 74 75 auto K = ES->allocateVModule(); 76 return ObjLinkingLayer.add(JD, K, std::move(Obj)); 77 } 78 79 Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD, 80 StringRef Name) { 81 return ES->lookup({&JD}, ES->intern(Name)); 82 } 83 84 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, 85 std::unique_ptr<TargetMachine> TM, DataLayout DL) 86 : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)), 87 ObjLinkingLayer(*this->ES, 88 [this](VModuleKey K) { return getMemoryManager(K); }), 89 CompileLayer(*this->ES, ObjLinkingLayer, 90 TMOwningSimpleCompiler(std::move(TM))), 91 CtorRunner(Main), DtorRunner(Main) {} 92 93 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB, 94 DataLayout DL, unsigned NumCompileThreads) 95 : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)), 96 ObjLinkingLayer(*this->ES, 97 [this](VModuleKey K) { return getMemoryManager(K); }), 98 CompileLayer(*this->ES, ObjLinkingLayer, 99 MultiThreadedSimpleCompiler(std::move(JTMB))), 100 CtorRunner(Main), DtorRunner(Main) { 101 assert(NumCompileThreads != 0 && 102 "Multithreaded LLJIT instance can not be created with 0 threads"); 103 104 // Move modules to new contexts when they're emitted so that we can compile 105 // them in parallel. 106 CompileLayer.setCloneToNewContextOnEmit(true); 107 108 // Create a thread pool to compile on and set the execution session 109 // dispatcher to use the thread pool. 110 CompileThreads = llvm::make_unique<ThreadPool>(NumCompileThreads); 111 this->ES->setDispatchMaterialization( 112 [this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { 113 // FIXME: Switch to move capture once we have c++14. 114 auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU)); 115 auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); }; 116 CompileThreads->async(std::move(Work)); 117 }); 118 } 119 120 std::unique_ptr<RuntimeDyld::MemoryManager> 121 LLJIT::getMemoryManager(VModuleKey K) { 122 return llvm::make_unique<SectionMemoryManager>(); 123 } 124 125 std::string LLJIT::mangle(StringRef UnmangledName) { 126 std::string MangledName; 127 { 128 raw_string_ostream MangledNameStream(MangledName); 129 Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL); 130 } 131 return MangledName; 132 } 133 134 Error LLJIT::applyDataLayout(Module &M) { 135 if (M.getDataLayout().isDefault()) 136 M.setDataLayout(DL); 137 138 if (M.getDataLayout() != DL) 139 return make_error<StringError>( 140 "Added modules have incompatible data layouts", 141 inconvertibleErrorCode()); 142 143 return Error::success(); 144 } 145 146 void LLJIT::recordCtorDtors(Module &M) { 147 CtorRunner.add(getConstructors(M)); 148 DtorRunner.add(getDestructors(M)); 149 } 150 151 Expected<std::unique_ptr<LLLazyJIT>> 152 LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL, 153 unsigned NumCompileThreads) { 154 auto ES = llvm::make_unique<ExecutionSession>(); 155 156 const Triple &TT = JTMB.getTargetTriple(); 157 158 auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, 0); 159 if (!LCTMgr) 160 return LCTMgr.takeError(); 161 162 auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT); 163 if (!ISMBuilder) 164 return make_error<StringError>( 165 std::string("No indirect stubs manager builder for ") + TT.str(), 166 inconvertibleErrorCode()); 167 168 if (NumCompileThreads == 0) { 169 auto TM = JTMB.createTargetMachine(); 170 if (!TM) 171 return TM.takeError(); 172 return std::unique_ptr<LLLazyJIT>( 173 new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL), 174 std::move(*LCTMgr), std::move(ISMBuilder))); 175 } 176 177 return std::unique_ptr<LLLazyJIT>(new LLLazyJIT( 178 std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads, 179 std::move(*LCTMgr), std::move(ISMBuilder))); 180 } 181 182 Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) { 183 assert(TSM && "Can not add null module"); 184 185 if (auto Err = applyDataLayout(*TSM.getModule())) 186 return Err; 187 188 recordCtorDtors(*TSM.getModule()); 189 190 auto K = ES->allocateVModule(); 191 return CODLayer.add(JD, K, std::move(TSM)); 192 } 193 194 LLLazyJIT::LLLazyJIT( 195 std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM, 196 DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr, 197 std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder) 198 : LLJIT(std::move(ES), std::move(TM), std::move(DL)), 199 LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer), 200 CODLayer(*this->ES, TransformLayer, *this->LCTMgr, 201 std::move(ISMBuilder)) {} 202 203 LLLazyJIT::LLLazyJIT( 204 std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB, 205 DataLayout DL, unsigned NumCompileThreads, 206 std::unique_ptr<LazyCallThroughManager> LCTMgr, 207 std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder) 208 : LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads), 209 LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer), 210 CODLayer(*this->ES, TransformLayer, *this->LCTMgr, 211 std::move(ISMBuilder)) { 212 CODLayer.setCloneToNewContextOnEmit(true); 213 } 214 215 } // End namespace orc. 216 } // End namespace llvm. 217