106 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"10#include "llvm/ExecutionEngine/Orc/Layer.h"11#include "llvm/IR/Module.h"12 13using namespace llvm;14using namespace llvm::orc;15 16CompileOnDemandLayer::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 23void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) {24 this->AliaseeImpls = Imp;25}26 27void 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 the34 // 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 else46 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 77CompileOnDemandLayer::PerDylibResources &78CompileOnDemandLayer::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