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