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 // IRCompileLayer::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 return CompileLayer.add(JD, std::move(TSM), ES->allocateVModule()); 69 } 70 71 Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) { 72 assert(Obj && "Can not add null object"); 73 74 return ObjLinkingLayer.add(JD, std::move(Obj), ES->allocateVModule()); 75 } 76 77 Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD, 78 StringRef Name) { 79 return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name)); 80 } 81 82 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, 83 std::unique_ptr<TargetMachine> TM, DataLayout DL) 84 : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)), 85 ObjLinkingLayer( 86 *this->ES, 87 []() { return llvm::make_unique<SectionMemoryManager>(); }), 88 CompileLayer(*this->ES, ObjLinkingLayer, 89 TMOwningSimpleCompiler(std::move(TM))), 90 CtorRunner(Main), DtorRunner(Main) {} 91 92 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB, 93 DataLayout DL, unsigned NumCompileThreads) 94 : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)), 95 ObjLinkingLayer( 96 *this->ES, 97 []() { return llvm::make_unique<SectionMemoryManager>(); }), 98 CompileLayer(*this->ES, ObjLinkingLayer, 99 ConcurrentIRCompiler(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::string LLJIT::mangle(StringRef UnmangledName) { 121 std::string MangledName; 122 { 123 raw_string_ostream MangledNameStream(MangledName); 124 Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL); 125 } 126 return MangledName; 127 } 128 129 Error LLJIT::applyDataLayout(Module &M) { 130 if (M.getDataLayout().isDefault()) 131 M.setDataLayout(DL); 132 133 if (M.getDataLayout() != DL) 134 return make_error<StringError>( 135 "Added modules have incompatible data layouts", 136 inconvertibleErrorCode()); 137 138 return Error::success(); 139 } 140 141 void LLJIT::recordCtorDtors(Module &M) { 142 CtorRunner.add(getConstructors(M)); 143 DtorRunner.add(getDestructors(M)); 144 } 145 146 Expected<std::unique_ptr<LLLazyJIT>> 147 LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL, 148 JITTargetAddress ErrorAddr, unsigned NumCompileThreads) { 149 auto ES = llvm::make_unique<ExecutionSession>(); 150 151 const Triple &TT = JTMB.getTargetTriple(); 152 153 auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, ErrorAddr); 154 if (!LCTMgr) 155 return LCTMgr.takeError(); 156 157 auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT); 158 if (!ISMBuilder) 159 return make_error<StringError>( 160 std::string("No indirect stubs manager builder for ") + TT.str(), 161 inconvertibleErrorCode()); 162 163 if (NumCompileThreads == 0) { 164 auto TM = JTMB.createTargetMachine(); 165 if (!TM) 166 return TM.takeError(); 167 return std::unique_ptr<LLLazyJIT>( 168 new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL), 169 std::move(*LCTMgr), std::move(ISMBuilder))); 170 } 171 172 return std::unique_ptr<LLLazyJIT>(new LLLazyJIT( 173 std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads, 174 std::move(*LCTMgr), std::move(ISMBuilder))); 175 } 176 177 Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) { 178 assert(TSM && "Can not add null module"); 179 180 if (auto Err = applyDataLayout(*TSM.getModule())) 181 return Err; 182 183 recordCtorDtors(*TSM.getModule()); 184 185 return CODLayer.add(JD, std::move(TSM), ES->allocateVModule()); 186 } 187 188 LLLazyJIT::LLLazyJIT( 189 std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM, 190 DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr, 191 std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder) 192 : LLJIT(std::move(ES), std::move(TM), std::move(DL)), 193 LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer), 194 CODLayer(*this->ES, TransformLayer, *this->LCTMgr, 195 std::move(ISMBuilder)) {} 196 197 LLLazyJIT::LLLazyJIT( 198 std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB, 199 DataLayout DL, unsigned NumCompileThreads, 200 std::unique_ptr<LazyCallThroughManager> LCTMgr, 201 std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder) 202 : LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads), 203 LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer), 204 CODLayer(*this->ES, TransformLayer, *this->LCTMgr, 205 std::move(ISMBuilder)) { 206 CODLayer.setCloneToNewContextOnEmit(true); 207 } 208 209 } // End namespace orc. 210 } // End namespace llvm. 211