1 //===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===// 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/CompileOnDemandLayer.h" 10 #include "llvm/ExecutionEngine/Orc/Layer.h" 11 #include "llvm/IR/Module.h" 12 13 using namespace llvm; 14 using namespace llvm::orc; 15 16 CompileOnDemandLayer::CompileOnDemandLayer( 17 ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr, 18 IndirectStubsManagerBuilder BuildIndirectStubsManager) 19 : IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer), 20 LCTMgr(LCTMgr), 21 BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {} 22 23 void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) { 24 this->AliaseeImpls = Imp; 25 } 26 27 void CompileOnDemandLayer::emit( 28 std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM) { 29 assert(TSM && "Null module"); 30 31 auto &ES = getExecutionSession(); 32 33 // Sort the callables and non-callables, build re-exports and lodge the 34 // actual module with the implementation dylib. 35 auto &PDR = getPerDylibResources(R->getTargetJITDylib()); 36 37 SymbolAliasMap NonCallables; 38 SymbolAliasMap Callables; 39 40 for (auto &KV : R->getSymbols()) { 41 auto &Name = KV.first; 42 auto &Flags = KV.second; 43 if (Flags.isCallable()) 44 Callables[Name] = SymbolAliasMapEntry(Name, Flags); 45 else 46 NonCallables[Name] = SymbolAliasMapEntry(Name, Flags); 47 } 48 49 // Lodge symbols with the implementation dylib. 50 if (auto Err = PDR.getImplDylib().define( 51 std::make_unique<BasicIRLayerMaterializationUnit>( 52 BaseLayer, *getManglingOptions(), std::move(TSM)))) { 53 ES.reportError(std::move(Err)); 54 R->failMaterialization(); 55 return; 56 } 57 58 if (!NonCallables.empty()) 59 if (auto Err = 60 R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables), 61 JITDylibLookupFlags::MatchAllSymbols))) { 62 getExecutionSession().reportError(std::move(Err)); 63 R->failMaterialization(); 64 return; 65 } 66 if (!Callables.empty()) { 67 if (auto Err = R->replace( 68 lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(), 69 std::move(Callables), AliaseeImpls))) { 70 getExecutionSession().reportError(std::move(Err)); 71 R->failMaterialization(); 72 return; 73 } 74 } 75 } 76 77 CompileOnDemandLayer::PerDylibResources & 78 CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) { 79 std::lock_guard<std::mutex> Lock(CODLayerMutex); 80 81 auto I = DylibResources.find(&TargetD); 82 if (I == DylibResources.end()) { 83 auto &ImplD = 84 getExecutionSession().createBareJITDylib(TargetD.getName() + ".impl"); 85 JITDylibSearchOrder NewLinkOrder; 86 TargetD.withLinkOrderDo([&](const JITDylibSearchOrder &TargetLinkOrder) { 87 NewLinkOrder = TargetLinkOrder; 88 }); 89 90 assert(!NewLinkOrder.empty() && NewLinkOrder.front().first == &TargetD && 91 NewLinkOrder.front().second == 92 JITDylibLookupFlags::MatchAllSymbols && 93 "TargetD must be at the front of its own search order and match " 94 "non-exported symbol"); 95 NewLinkOrder.insert(std::next(NewLinkOrder.begin()), 96 {&ImplD, JITDylibLookupFlags::MatchAllSymbols}); 97 ImplD.setLinkOrder(NewLinkOrder, false); 98 TargetD.setLinkOrder(std::move(NewLinkOrder), false); 99 100 PerDylibResources PDR(ImplD, BuildIndirectStubsManager()); 101 I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first; 102 } 103 104 return I->second; 105 } 106