| //===---------- 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" | |
| 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<StringRef, NonOwningSymbolStringPtr> 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<RenamerPlugin>()); | |
| } | |
| Error LazyObjectLinkingLayer::add(ResourceTrackerSP RT, | |
| std::unique_ptr<MemoryBuffer> 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<MaterializationResponsibility> MR, | |
| std::unique_ptr<MemoryBuffer> Obj) { | |
| return BaseLayer.emit(std::move(MR), std::move(Obj)); | |
| } | |
| } // namespace llvm::orc |