| //===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" | |
| #include "llvm/ExecutionEngine/Orc/Layer.h" | |
| #include "llvm/IR/Module.h" | |
| using namespace llvm; | |
| using namespace llvm::orc; | |
| CompileOnDemandLayer::CompileOnDemandLayer( | |
| ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr, | |
| IndirectStubsManagerBuilder BuildIndirectStubsManager) | |
| : IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer), | |
| LCTMgr(LCTMgr), | |
| BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {} | |
| void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) { | |
| this->AliaseeImpls = Imp; | |
| } | |
| void CompileOnDemandLayer::emit( | |
| std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM) { | |
| assert(TSM && "Null module"); | |
| auto &ES = getExecutionSession(); | |
| // Sort the callables and non-callables, build re-exports and lodge the | |
| // actual module with the implementation dylib. | |
| auto &PDR = getPerDylibResources(R->getTargetJITDylib()); | |
| SymbolAliasMap NonCallables; | |
| SymbolAliasMap Callables; | |
| for (auto &KV : R->getSymbols()) { | |
| auto &Name = KV.first; | |
| auto &Flags = KV.second; | |
| if (Flags.isCallable()) | |
| Callables[Name] = SymbolAliasMapEntry(Name, Flags); | |
| else | |
| NonCallables[Name] = SymbolAliasMapEntry(Name, Flags); | |
| } | |
| // Lodge symbols with the implementation dylib. | |
| if (auto Err = PDR.getImplDylib().define( | |
| std::make_unique<BasicIRLayerMaterializationUnit>( | |
| BaseLayer, *getManglingOptions(), std::move(TSM)))) { | |
| ES.reportError(std::move(Err)); | |
| R->failMaterialization(); | |
| return; | |
| } | |
| if (!NonCallables.empty()) | |
| if (auto Err = | |
| R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables), | |
| JITDylibLookupFlags::MatchAllSymbols))) { | |
| getExecutionSession().reportError(std::move(Err)); | |
| R->failMaterialization(); | |
| return; | |
| } | |
| if (!Callables.empty()) { | |
| if (auto Err = R->replace( | |
| lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(), | |
| std::move(Callables), AliaseeImpls))) { | |
| getExecutionSession().reportError(std::move(Err)); | |
| R->failMaterialization(); | |
| return; | |
| } | |
| } | |
| } | |
| CompileOnDemandLayer::PerDylibResources & | |
| CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) { | |
| std::lock_guard<std::mutex> Lock(CODLayerMutex); | |
| auto I = DylibResources.find(&TargetD); | |
| if (I == DylibResources.end()) { | |
| auto &ImplD = | |
| getExecutionSession().createBareJITDylib(TargetD.getName() + ".impl"); | |
| JITDylibSearchOrder NewLinkOrder; | |
| TargetD.withLinkOrderDo([&](const JITDylibSearchOrder &TargetLinkOrder) { | |
| NewLinkOrder = TargetLinkOrder; | |
| }); | |
| assert(!NewLinkOrder.empty() && NewLinkOrder.front().first == &TargetD && | |
| NewLinkOrder.front().second == | |
| JITDylibLookupFlags::MatchAllSymbols && | |
| "TargetD must be at the front of its own search order and match " | |
| "non-exported symbol"); | |
| NewLinkOrder.insert(std::next(NewLinkOrder.begin()), | |
| {&ImplD, JITDylibLookupFlags::MatchAllSymbols}); | |
| ImplD.setLinkOrder(NewLinkOrder, false); | |
| TargetD.setLinkOrder(std::move(NewLinkOrder), false); | |
| PerDylibResources PDR(ImplD, BuildIndirectStubsManager()); | |
| I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first; | |
| } | |
| return I->second; | |
| } |