//===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===// // // 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/LazyObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/LazyReexports.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/RedirectionManager.h" using namespace llvm; using namespace llvm::jitlink; namespace { constexpr StringRef FnBodySuffix = "$orc_fnbody"; } // anonymous namespace namespace llvm::orc { class LazyObjectLinkingLayer::RenamerPlugin : public ObjectLinkingLayer::Plugin { public: void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &Config) override { // We need to insert this before the mark-live pass to ensure that we don't // delete the bodies (their names won't match the responsibility set until // after this pass completes. Config.PrePrunePasses.insert( Config.PrePrunePasses.begin(), [&MR](LinkGraph &G) { return renameFunctionBodies(G, MR); }); } Error notifyFailed(MaterializationResponsibility &MR) override { return Error::success(); } Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { return Error::success(); } void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override {} private: static Error renameFunctionBodies(LinkGraph &G, MaterializationResponsibility &MR) { DenseMap SymsToRename; for (auto &[Name, Flags] : MR.getSymbols()) if ((*Name).ends_with(FnBodySuffix)) SymsToRename[(*Name).drop_back(FnBodySuffix.size())] = NonOwningSymbolStringPtr(Name); for (auto *Sym : G.defined_symbols()) { if (!Sym->hasName()) continue; auto I = SymsToRename.find(*Sym->getName()); if (I == SymsToRename.end()) continue; Sym->setName(G.intern(G.allocateName(*I->second))); } return Error::success(); } }; LazyObjectLinkingLayer::LazyObjectLinkingLayer(ObjectLinkingLayer &BaseLayer, LazyReexportsManager &LRMgr) : ObjectLayer(BaseLayer.getExecutionSession()), BaseLayer(BaseLayer), LRMgr(LRMgr) { BaseLayer.addPlugin(std::make_unique()); } Error LazyObjectLinkingLayer::add(ResourceTrackerSP RT, std::unique_ptr O, MaterializationUnit::Interface I) { // Object files with initializer symbols can't be lazy. if (I.InitSymbol) return BaseLayer.add(std::move(RT), std::move(O), std::move(I)); auto &ES = getExecutionSession(); SymbolAliasMap LazySymbols; for (auto &[Name, Flags] : I.SymbolFlags) if (Flags.isCallable()) LazySymbols[Name] = {ES.intern((*Name + FnBodySuffix).str()), Flags}; for (auto &[Name, AI] : LazySymbols) { I.SymbolFlags.erase(Name); I.SymbolFlags[AI.Aliasee] = AI.AliasFlags; } if (auto Err = BaseLayer.add(RT, std::move(O), std::move(I))) return Err; auto &JD = RT->getJITDylib(); return JD.define(lazyReexports(LRMgr, std::move(LazySymbols)), std::move(RT)); } void LazyObjectLinkingLayer::emit( std::unique_ptr MR, std::unique_ptr Obj) { return BaseLayer.emit(std::move(MR), std::move(Obj)); } } // namespace llvm::orc