//===----- 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 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( 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 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; }