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/Orc/RTDyldObjectLinkingLayer.h" 12 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 13 #include "llvm/IR/Mangler.h" 14 15 namespace llvm { 16 namespace orc { 17 18 Error LLJITBuilderState::prepareForConstruction() { 19 20 if (!JTMB) { 21 if (auto JTMBOrErr = JITTargetMachineBuilder::detectHost()) 22 JTMB = std::move(*JTMBOrErr); 23 else 24 return JTMBOrErr.takeError(); 25 } 26 27 return Error::success(); 28 } 29 30 LLJIT::~LLJIT() { 31 if (CompileThreads) 32 CompileThreads->wait(); 33 } 34 35 Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) { 36 auto InternedName = ES->intern(Name); 37 SymbolMap Symbols({{InternedName, Sym}}); 38 return Main.define(absoluteSymbols(std::move(Symbols))); 39 } 40 41 Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) { 42 assert(TSM && "Can not add null module"); 43 44 if (auto Err = 45 TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); })) 46 return Err; 47 48 return CompileLayer->add(JD, std::move(TSM), ES->allocateVModule()); 49 } 50 51 Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) { 52 assert(Obj && "Can not add null object"); 53 54 return ObjLinkingLayer->add(JD, std::move(Obj), ES->allocateVModule()); 55 } 56 57 Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD, 58 StringRef Name) { 59 return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name)); 60 } 61 62 std::unique_ptr<ObjectLayer> 63 LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) { 64 65 // If the config state provided an ObjectLinkingLayer factory then use it. 66 if (S.CreateObjectLinkingLayer) 67 return S.CreateObjectLinkingLayer(ES, S.JTMB->getTargetTriple()); 68 69 // Otherwise default to creating an RTDyldObjectLinkingLayer that constructs 70 // a new SectionMemoryManager for each object. 71 auto GetMemMgr = []() { return llvm::make_unique<SectionMemoryManager>(); }; 72 auto ObjLinkingLayer = 73 llvm::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr)); 74 75 if (S.JTMB->getTargetTriple().isOSBinFormatCOFF()) 76 ObjLinkingLayer->setOverrideObjectFlagsWithResponsibilityFlags(true); 77 78 return ObjLinkingLayer; 79 } 80 81 Expected<IRCompileLayer::CompileFunction> 82 LLJIT::createCompileFunction(LLJITBuilderState &S, 83 JITTargetMachineBuilder JTMB) { 84 85 /// If there is a custom compile function creator set then use it. 86 if (S.CreateCompileFunction) 87 return S.CreateCompileFunction(std::move(JTMB)); 88 89 // Otherwise default to creating a SimpleCompiler, or ConcurrentIRCompiler, 90 // depending on the number of threads requested. 91 if (S.NumCompileThreads > 0) 92 return ConcurrentIRCompiler(std::move(JTMB)); 93 94 auto TM = JTMB.createTargetMachine(); 95 if (!TM) 96 return TM.takeError(); 97 98 return TMOwningSimpleCompiler(std::move(*TM)); 99 } 100 101 LLJIT::LLJIT(LLJITBuilderState &S, Error &Err) 102 : ES(S.ES ? std::move(S.ES) : llvm::make_unique<ExecutionSession>()), 103 Main(this->ES->getMainJITDylib()), DL(""), CtorRunner(Main), 104 DtorRunner(Main) { 105 106 ErrorAsOutParameter _(&Err); 107 108 ObjLinkingLayer = createObjectLinkingLayer(S, *ES); 109 110 if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget()) 111 DL = std::move(*DLOrErr); 112 else { 113 Err = DLOrErr.takeError(); 114 return; 115 } 116 117 { 118 auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB)); 119 if (!CompileFunction) { 120 Err = CompileFunction.takeError(); 121 return; 122 } 123 CompileLayer = llvm::make_unique<IRCompileLayer>( 124 *ES, *ObjLinkingLayer, std::move(*CompileFunction)); 125 } 126 127 if (S.NumCompileThreads > 0) { 128 CompileLayer->setCloneToNewContextOnEmit(true); 129 CompileThreads = llvm::make_unique<ThreadPool>(S.NumCompileThreads); 130 ES->setDispatchMaterialization( 131 [this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { 132 // FIXME: Switch to move capture once we have c++14. 133 auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU)); 134 auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); }; 135 CompileThreads->async(std::move(Work)); 136 }); 137 } 138 } 139 140 std::string LLJIT::mangle(StringRef UnmangledName) { 141 std::string MangledName; 142 { 143 raw_string_ostream MangledNameStream(MangledName); 144 Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL); 145 } 146 return MangledName; 147 } 148 149 Error LLJIT::applyDataLayout(Module &M) { 150 if (M.getDataLayout().isDefault()) 151 M.setDataLayout(DL); 152 153 if (M.getDataLayout() != DL) 154 return make_error<StringError>( 155 "Added modules have incompatible data layouts", 156 inconvertibleErrorCode()); 157 158 return Error::success(); 159 } 160 161 void LLJIT::recordCtorDtors(Module &M) { 162 CtorRunner.add(getConstructors(M)); 163 DtorRunner.add(getDestructors(M)); 164 } 165 166 Error LLLazyJITBuilderState::prepareForConstruction() { 167 if (auto Err = LLJITBuilderState::prepareForConstruction()) 168 return Err; 169 TT = JTMB->getTargetTriple(); 170 return Error::success(); 171 } 172 173 Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) { 174 assert(TSM && "Can not add null module"); 175 176 if (auto Err = TSM.withModuleDo([&](Module &M) -> Error { 177 if (auto Err = applyDataLayout(M)) 178 return Err; 179 180 recordCtorDtors(M); 181 return Error::success(); 182 })) 183 return Err; 184 185 return CODLayer->add(JD, std::move(TSM), ES->allocateVModule()); 186 } 187 188 LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) { 189 190 // If LLJIT construction failed then bail out. 191 if (Err) 192 return; 193 194 ErrorAsOutParameter _(&Err); 195 196 /// Take/Create the lazy-compile callthrough manager. 197 if (S.LCTMgr) 198 LCTMgr = std::move(S.LCTMgr); 199 else { 200 if (auto LCTMgrOrErr = createLocalLazyCallThroughManager( 201 S.TT, *ES, S.LazyCompileFailureAddr)) 202 LCTMgr = std::move(*LCTMgrOrErr); 203 else { 204 Err = LCTMgrOrErr.takeError(); 205 return; 206 } 207 } 208 209 // Take/Create the indirect stubs manager builder. 210 auto ISMBuilder = std::move(S.ISMBuilder); 211 212 // If none was provided, try to build one. 213 if (!ISMBuilder) 214 ISMBuilder = createLocalIndirectStubsManagerBuilder(S.TT); 215 216 // No luck. Bail out. 217 if (!ISMBuilder) { 218 Err = make_error<StringError>("Could not construct " 219 "IndirectStubsManagerBuilder for target " + 220 S.TT.str(), 221 inconvertibleErrorCode()); 222 return; 223 } 224 225 // Create the transform layer. 226 TransformLayer = llvm::make_unique<IRTransformLayer>(*ES, *CompileLayer); 227 228 // Create the COD layer. 229 CODLayer = llvm::make_unique<CompileOnDemandLayer>( 230 *ES, *TransformLayer, *LCTMgr, std::move(ISMBuilder)); 231 232 if (S.NumCompileThreads > 0) 233 CODLayer->setCloneToNewContextOnEmit(true); 234 } 235 236 } // End namespace orc. 237 } // End namespace llvm. 238