111c8dfa5SLang Hames //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===// 211c8dfa5SLang Hames // 311c8dfa5SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 411c8dfa5SLang Hames // See https://llvm.org/LICENSE.txt for license information. 511c8dfa5SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 611c8dfa5SLang Hames // 711c8dfa5SLang Hames //===----------------------------------------------------------------------===// 811c8dfa5SLang Hames 911c8dfa5SLang Hames #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 1011c8dfa5SLang Hames #include "llvm/ADT/Optional.h" 111233c15bSLang Hames #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 12ef238923SStefan Gränitz #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" 13ef238923SStefan Gränitz #include "llvm/Support/MemoryBuffer.h" 14367ec775SSimon Pilgrim #include <string> 1511c8dfa5SLang Hames #include <vector> 1611c8dfa5SLang Hames 1711c8dfa5SLang Hames #define DEBUG_TYPE "orc" 1811c8dfa5SLang Hames 1911c8dfa5SLang Hames using namespace llvm; 2011c8dfa5SLang Hames using namespace llvm::jitlink; 2111c8dfa5SLang Hames using namespace llvm::orc; 2211c8dfa5SLang Hames 230fda4c47SLang Hames namespace { 240fda4c47SLang Hames 250fda4c47SLang Hames class LinkGraphMaterializationUnit : public MaterializationUnit { 260fda4c47SLang Hames public: 270fda4c47SLang Hames static std::unique_ptr<LinkGraphMaterializationUnit> 280fda4c47SLang Hames Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 290fda4c47SLang Hames auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 300fda4c47SLang Hames return std::unique_ptr<LinkGraphMaterializationUnit>( 310fda4c47SLang Hames new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 320fda4c47SLang Hames std::move(LGI))); 330fda4c47SLang Hames } 340fda4c47SLang Hames 350fda4c47SLang Hames StringRef getName() const override { return G->getName(); } 360fda4c47SLang Hames void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 370fda4c47SLang Hames ObjLinkingLayer.emit(std::move(MR), std::move(G)); 380fda4c47SLang Hames } 390fda4c47SLang Hames 400fda4c47SLang Hames private: 41ae73f3fdSLang Hames static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 420fda4c47SLang Hames 43ae73f3fdSLang Hames Interface LGI; 440fda4c47SLang Hames 450fda4c47SLang Hames for (auto *Sym : G.defined_symbols()) { 460fda4c47SLang Hames // Skip local symbols. 470fda4c47SLang Hames if (Sym->getScope() == Scope::Local) 480fda4c47SLang Hames continue; 490fda4c47SLang Hames assert(Sym->hasName() && "Anonymous non-local symbol?"); 500fda4c47SLang Hames 510fda4c47SLang Hames JITSymbolFlags Flags; 520fda4c47SLang Hames if (Sym->getScope() == Scope::Default) 530fda4c47SLang Hames Flags |= JITSymbolFlags::Exported; 540fda4c47SLang Hames 550fda4c47SLang Hames if (Sym->isCallable()) 560fda4c47SLang Hames Flags |= JITSymbolFlags::Callable; 570fda4c47SLang Hames 580fda4c47SLang Hames LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags; 590fda4c47SLang Hames } 600fda4c47SLang Hames 61b749ef9eSLang Hames if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) || 62b749ef9eSLang Hames (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G))) 630fda4c47SLang Hames LGI.InitSymbol = makeInitSymbol(ES, G); 640fda4c47SLang Hames 650fda4c47SLang Hames return LGI; 660fda4c47SLang Hames } 670fda4c47SLang Hames 680fda4c47SLang Hames static bool hasMachOInitSection(LinkGraph &G) { 690fda4c47SLang Hames for (auto &Sec : G.sections()) 700fda4c47SLang Hames if (Sec.getName() == "__DATA,__obj_selrefs" || 710fda4c47SLang Hames Sec.getName() == "__DATA,__objc_classlist" || 720fda4c47SLang Hames Sec.getName() == "__TEXT,__swift5_protos" || 730fda4c47SLang Hames Sec.getName() == "__TEXT,__swift5_proto" || 742a739f27SBen Langmuir Sec.getName() == "__TEXT,__swift5_types" || 750fda4c47SLang Hames Sec.getName() == "__DATA,__mod_init_func") 760fda4c47SLang Hames return true; 770fda4c47SLang Hames return false; 780fda4c47SLang Hames } 790fda4c47SLang Hames 80b749ef9eSLang Hames static bool hasELFInitSection(LinkGraph &G) { 81b749ef9eSLang Hames for (auto &Sec : G.sections()) 82b749ef9eSLang Hames if (Sec.getName() == ".init_array") 83b749ef9eSLang Hames return true; 84b749ef9eSLang Hames return false; 85b749ef9eSLang Hames } 86b749ef9eSLang Hames 870fda4c47SLang Hames static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 880fda4c47SLang Hames std::string InitSymString; 890fda4c47SLang Hames raw_string_ostream(InitSymString) 900fda4c47SLang Hames << "$." << G.getName() << ".__inits" << Counter++; 910fda4c47SLang Hames return ES.intern(InitSymString); 920fda4c47SLang Hames } 930fda4c47SLang Hames 940fda4c47SLang Hames LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 95ae73f3fdSLang Hames std::unique_ptr<LinkGraph> G, Interface LGI) 96ae73f3fdSLang Hames : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), 97ae73f3fdSLang Hames G(std::move(G)) {} 980fda4c47SLang Hames 990fda4c47SLang Hames void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 1000fda4c47SLang Hames for (auto *Sym : G->defined_symbols()) 1010fda4c47SLang Hames if (Sym->getName() == *Name) { 1020fda4c47SLang Hames assert(Sym->getLinkage() == Linkage::Weak && 1030fda4c47SLang Hames "Discarding non-weak definition"); 1040fda4c47SLang Hames G->makeExternal(*Sym); 1050fda4c47SLang Hames break; 1060fda4c47SLang Hames } 1070fda4c47SLang Hames } 1080fda4c47SLang Hames 1090fda4c47SLang Hames ObjectLinkingLayer &ObjLinkingLayer; 1100fda4c47SLang Hames std::unique_ptr<LinkGraph> G; 1110fda4c47SLang Hames static std::atomic<uint64_t> Counter; 1120fda4c47SLang Hames }; 1130fda4c47SLang Hames 1140fda4c47SLang Hames std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 1150fda4c47SLang Hames 1160fda4c47SLang Hames } // end anonymous namespace 1170fda4c47SLang Hames 11811c8dfa5SLang Hames namespace llvm { 11911c8dfa5SLang Hames namespace orc { 12011c8dfa5SLang Hames 12111c8dfa5SLang Hames class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 12211c8dfa5SLang Hames public: 1237dcd0042SLang Hames ObjectLinkingLayerJITLinkContext( 1247dcd0042SLang Hames ObjectLinkingLayer &Layer, 1257dcd0042SLang Hames std::unique_ptr<MaterializationResponsibility> MR, 12611c8dfa5SLang Hames std::unique_ptr<MemoryBuffer> ObjBuffer) 12704795ab8SLang Hames : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 12804795ab8SLang Hames MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 12911c8dfa5SLang Hames 130a98546ebSLang Hames ~ObjectLinkingLayerJITLinkContext() { 131a98546ebSLang Hames // If there is an object buffer return function then use it to 132a98546ebSLang Hames // return ownership of the buffer. 133ec6b71dfSLang Hames if (Layer.ReturnObjectBuffer && ObjBuffer) 134a98546ebSLang Hames Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 135a98546ebSLang Hames } 136a98546ebSLang Hames 13769091eb1SLang Hames JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 13811c8dfa5SLang Hames 139ef238923SStefan Gränitz void notifyMaterializing(LinkGraph &G) { 140ef238923SStefan Gränitz for (auto &P : Layer.Plugins) 141c42580bfSLang Hames P->notifyMaterializing(*MR, G, *this, 142c42580bfSLang Hames ObjBuffer ? ObjBuffer->getMemBufferRef() 143c42580bfSLang Hames : MemoryBufferRef()); 144ef238923SStefan Gränitz } 145ef238923SStefan Gränitz 14611c8dfa5SLang Hames void notifyFailed(Error Err) override { 1470aec49c8SLang Hames for (auto &P : Layer.Plugins) 1480aec49c8SLang Hames Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 14911c8dfa5SLang Hames Layer.getExecutionSession().reportError(std::move(Err)); 1507dcd0042SLang Hames MR->failMaterialization(); 15111c8dfa5SLang Hames } 15211c8dfa5SLang Hames 153674df13bSLang Hames void lookup(const LookupMap &Symbols, 1544e920e58SLang Hames std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 15511c8dfa5SLang Hames 156c66f8900SLang Hames JITDylibSearchOrder LinkOrder; 1577dcd0042SLang Hames MR->getTargetJITDylib().withLinkOrderDo( 158c66f8900SLang Hames [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 15911c8dfa5SLang Hames 16011c8dfa5SLang Hames auto &ES = Layer.getExecutionSession(); 16111c8dfa5SLang Hames 162674df13bSLang Hames SymbolLookupSet LookupSet; 163674df13bSLang Hames for (auto &KV : Symbols) { 164674df13bSLang Hames orc::SymbolLookupFlags LookupFlags; 165674df13bSLang Hames switch (KV.second) { 166674df13bSLang Hames case jitlink::SymbolLookupFlags::RequiredSymbol: 167674df13bSLang Hames LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 168674df13bSLang Hames break; 169674df13bSLang Hames case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 170674df13bSLang Hames LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 171674df13bSLang Hames break; 172674df13bSLang Hames } 173674df13bSLang Hames LookupSet.add(ES.intern(KV.first), LookupFlags); 174674df13bSLang Hames } 17511c8dfa5SLang Hames 17611c8dfa5SLang Hames // OnResolve -- De-intern the symbols and pass the result to the linker. 177b79e19e6SLang Hames auto OnResolve = [LookupContinuation = 178b79e19e6SLang Hames std::move(LC)](Expected<SymbolMap> Result) mutable { 17911c8dfa5SLang Hames if (!Result) 1804e920e58SLang Hames LookupContinuation->run(Result.takeError()); 18111c8dfa5SLang Hames else { 18211c8dfa5SLang Hames AsyncLookupResult LR; 18311c8dfa5SLang Hames for (auto &KV : *Result) 18411c8dfa5SLang Hames LR[*KV.first] = KV.second; 1854e920e58SLang Hames LookupContinuation->run(std::move(LR)); 18611c8dfa5SLang Hames } 18711c8dfa5SLang Hames }; 18811c8dfa5SLang Hames 189ca6f5848SLang Hames for (auto &KV : InternalNamedSymbolDeps) { 190ca6f5848SLang Hames SymbolDependenceMap InternalDeps; 1917dcd0042SLang Hames InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 1927dcd0042SLang Hames MR->addDependencies(KV.first, InternalDeps); 193ca6f5848SLang Hames } 194ca6f5848SLang Hames 195c66f8900SLang Hames ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 196674df13bSLang Hames SymbolState::Resolved, std::move(OnResolve), 197674df13bSLang Hames [this](const SymbolDependenceMap &Deps) { 19811c8dfa5SLang Hames registerDependencies(Deps); 19911c8dfa5SLang Hames }); 20011c8dfa5SLang Hames } 20111c8dfa5SLang Hames 2029f1dcdcaSLang Hames Error notifyResolved(LinkGraph &G) override { 20311c8dfa5SLang Hames auto &ES = Layer.getExecutionSession(); 20411c8dfa5SLang Hames 20511c8dfa5SLang Hames SymbolFlagsMap ExtraSymbolsToClaim; 20611c8dfa5SLang Hames bool AutoClaim = Layer.AutoClaimObjectSymbols; 20711c8dfa5SLang Hames 20811c8dfa5SLang Hames SymbolMap InternedResult; 2094e920e58SLang Hames for (auto *Sym : G.defined_symbols()) 2104e920e58SLang Hames if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2114e920e58SLang Hames auto InternedName = ES.intern(Sym->getName()); 21211c8dfa5SLang Hames JITSymbolFlags Flags; 21311c8dfa5SLang Hames 2144e920e58SLang Hames if (Sym->isCallable()) 21511c8dfa5SLang Hames Flags |= JITSymbolFlags::Callable; 2164e920e58SLang Hames if (Sym->getScope() == Scope::Default) 2174e920e58SLang Hames Flags |= JITSymbolFlags::Exported; 21811c8dfa5SLang Hames 21911c8dfa5SLang Hames InternedResult[InternedName] = 220118e953bSLang Hames JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags); 2217dcd0042SLang Hames if (AutoClaim && !MR->getSymbols().count(InternedName)) { 22211c8dfa5SLang Hames assert(!ExtraSymbolsToClaim.count(InternedName) && 22311c8dfa5SLang Hames "Duplicate symbol to claim?"); 22411c8dfa5SLang Hames ExtraSymbolsToClaim[InternedName] = Flags; 22511c8dfa5SLang Hames } 22611c8dfa5SLang Hames } 22711c8dfa5SLang Hames 2284e920e58SLang Hames for (auto *Sym : G.absolute_symbols()) 229*36f0dfd0SLang Hames if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2304e920e58SLang Hames auto InternedName = ES.intern(Sym->getName()); 23111c8dfa5SLang Hames JITSymbolFlags Flags; 2324e920e58SLang Hames if (Sym->isCallable()) 23311c8dfa5SLang Hames Flags |= JITSymbolFlags::Callable; 234*36f0dfd0SLang Hames if (Sym->getScope() == Scope::Default) 235*36f0dfd0SLang Hames Flags |= JITSymbolFlags::Exported; 2364e920e58SLang Hames if (Sym->getLinkage() == Linkage::Weak) 2374e920e58SLang Hames Flags |= JITSymbolFlags::Weak; 23811c8dfa5SLang Hames InternedResult[InternedName] = 239118e953bSLang Hames JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags); 2407dcd0042SLang Hames if (AutoClaim && !MR->getSymbols().count(InternedName)) { 24111c8dfa5SLang Hames assert(!ExtraSymbolsToClaim.count(InternedName) && 24211c8dfa5SLang Hames "Duplicate symbol to claim?"); 24311c8dfa5SLang Hames ExtraSymbolsToClaim[InternedName] = Flags; 24411c8dfa5SLang Hames } 24511c8dfa5SLang Hames } 24611c8dfa5SLang Hames 24711c8dfa5SLang Hames if (!ExtraSymbolsToClaim.empty()) 2487dcd0042SLang Hames if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 2499f1dcdcaSLang Hames return Err; 25085fb9976SLang Hames 25181726894SLang Hames { 252cb84e482SLang Hames 25302fc8d5cSLang Hames // Check that InternedResult matches up with MR->getSymbols(), overriding 25402fc8d5cSLang Hames // flags if requested. 25581726894SLang Hames // This guards against faulty transformations / compilers / object caches. 25681726894SLang Hames 257cb84e482SLang Hames // First check that there aren't any missing symbols. 258cb84e482SLang Hames size_t NumMaterializationSideEffectsOnlySymbols = 0; 25981726894SLang Hames SymbolNameVector ExtraSymbols; 260cb84e482SLang Hames SymbolNameVector MissingSymbols; 2617dcd0042SLang Hames for (auto &KV : MR->getSymbols()) { 262cb84e482SLang Hames 26302fc8d5cSLang Hames auto I = InternedResult.find(KV.first); 26402fc8d5cSLang Hames 265cb84e482SLang Hames // If this is a materialization-side-effects only symbol then bump 266cb84e482SLang Hames // the counter and make sure it's *not* defined, otherwise make 267cb84e482SLang Hames // sure that it is defined. 268cb84e482SLang Hames if (KV.second.hasMaterializationSideEffectsOnly()) { 269cb84e482SLang Hames ++NumMaterializationSideEffectsOnlySymbols; 27002fc8d5cSLang Hames if (I != InternedResult.end()) 27181726894SLang Hames ExtraSymbols.push_back(KV.first); 272cb84e482SLang Hames continue; 27302fc8d5cSLang Hames } else if (I == InternedResult.end()) 274cb84e482SLang Hames MissingSymbols.push_back(KV.first); 27502fc8d5cSLang Hames else if (Layer.OverrideObjectFlags) 27602fc8d5cSLang Hames I->second.setFlags(KV.second); 277cb84e482SLang Hames } 278cb84e482SLang Hames 279cb84e482SLang Hames // If there were missing symbols then report the error. 2809f1dcdcaSLang Hames if (!MissingSymbols.empty()) 2816fe2e9a9SLang Hames return make_error<MissingSymbolDefinitions>( 2826fe2e9a9SLang Hames Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 2839f1dcdcaSLang Hames std::move(MissingSymbols)); 28481726894SLang Hames 285cb84e482SLang Hames // If there are more definitions than expected, add them to the 286cb84e482SLang Hames // ExtraSymbols vector. 287cb84e482SLang Hames if (InternedResult.size() > 2887dcd0042SLang Hames MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 289cb84e482SLang Hames for (auto &KV : InternedResult) 2907dcd0042SLang Hames if (!MR->getSymbols().count(KV.first)) 291cb84e482SLang Hames ExtraSymbols.push_back(KV.first); 292cb84e482SLang Hames } 29381726894SLang Hames 294cb84e482SLang Hames // If there were extra definitions then report the error. 2959f1dcdcaSLang Hames if (!ExtraSymbols.empty()) 2966fe2e9a9SLang Hames return make_error<UnexpectedSymbolDefinitions>( 2976fe2e9a9SLang Hames Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 2989f1dcdcaSLang Hames std::move(ExtraSymbols)); 29981726894SLang Hames } 30081726894SLang Hames 3017dcd0042SLang Hames if (auto Err = MR->notifyResolved(InternedResult)) 3029f1dcdcaSLang Hames return Err; 3039f1dcdcaSLang Hames 3047dcd0042SLang Hames Layer.notifyLoaded(*MR); 3059f1dcdcaSLang Hames return Error::success(); 30611c8dfa5SLang Hames } 30711c8dfa5SLang Hames 308962a2479SLang Hames void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 3097dcd0042SLang Hames if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 31011c8dfa5SLang Hames Layer.getExecutionSession().reportError(std::move(Err)); 3117dcd0042SLang Hames MR->failMaterialization(); 31211c8dfa5SLang Hames return; 31311c8dfa5SLang Hames } 3147dcd0042SLang Hames if (auto Err = MR->notifyEmitted()) { 315e00585c7SLang Hames Layer.getExecutionSession().reportError(std::move(Err)); 3167dcd0042SLang Hames MR->failMaterialization(); 317e00585c7SLang Hames } 31811c8dfa5SLang Hames } 31911c8dfa5SLang Hames 3204e920e58SLang Hames LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 3214e920e58SLang Hames return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 32211c8dfa5SLang Hames } 32311c8dfa5SLang Hames 3244e30b20bSLang Hames Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 32511c8dfa5SLang Hames // Add passes to mark duplicate defs as should-discard, and to walk the 3264e920e58SLang Hames // link graph to build the symbol dependence graph. 3274dc110a4SLang Hames Config.PrePrunePasses.push_back([this](LinkGraph &G) { 3284dc110a4SLang Hames return claimOrExternalizeWeakAndCommonSymbols(G); 3294dc110a4SLang Hames }); 33011c8dfa5SLang Hames 3314e30b20bSLang Hames Layer.modifyPassConfig(*MR, LG, Config); 33211c8dfa5SLang Hames 333ca6f5848SLang Hames Config.PostPrunePasses.push_back( 334ca6f5848SLang Hames [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 335ca6f5848SLang Hames 33611c8dfa5SLang Hames return Error::success(); 33711c8dfa5SLang Hames } 33811c8dfa5SLang Hames 33911c8dfa5SLang Hames private: 340963378bdSLang Hames // Symbol name dependencies: 341963378bdSLang Hames // Internal: Defined in this graph. 342963378bdSLang Hames // External: Defined externally. 343963378bdSLang Hames struct BlockSymbolDependencies { 34485fb9976SLang Hames SymbolNameSet Internal, External; 34585fb9976SLang Hames }; 34685fb9976SLang Hames 347963378bdSLang Hames // Lazily populated map of blocks to BlockSymbolDependencies values. 348963378bdSLang Hames class BlockDependenciesMap { 349963378bdSLang Hames public: 350963378bdSLang Hames BlockDependenciesMap(ExecutionSession &ES, 351963378bdSLang Hames DenseMap<const Block *, DenseSet<Block *>> BlockDeps) 352963378bdSLang Hames : ES(ES), BlockDeps(std::move(BlockDeps)) {} 353963378bdSLang Hames 354963378bdSLang Hames const BlockSymbolDependencies &operator[](const Block &B) { 355963378bdSLang Hames // Check the cache first. 356963378bdSLang Hames auto I = BlockTransitiveDepsCache.find(&B); 357963378bdSLang Hames if (I != BlockTransitiveDepsCache.end()) 358963378bdSLang Hames return I->second; 359963378bdSLang Hames 360963378bdSLang Hames // No value. Populate the cache. 361963378bdSLang Hames BlockSymbolDependencies BTDCacheVal; 362963378bdSLang Hames auto BDI = BlockDeps.find(&B); 363963378bdSLang Hames assert(BDI != BlockDeps.end() && "No block dependencies"); 364963378bdSLang Hames 365963378bdSLang Hames for (auto *BDep : BDI->second) { 366963378bdSLang Hames auto &BID = getBlockImmediateDeps(*BDep); 367963378bdSLang Hames for (auto &ExternalDep : BID.External) 368963378bdSLang Hames BTDCacheVal.External.insert(ExternalDep); 369963378bdSLang Hames for (auto &InternalDep : BID.Internal) 370963378bdSLang Hames BTDCacheVal.Internal.insert(InternalDep); 371963378bdSLang Hames } 372963378bdSLang Hames 373963378bdSLang Hames return BlockTransitiveDepsCache 374963378bdSLang Hames .insert(std::make_pair(&B, std::move(BTDCacheVal))) 375963378bdSLang Hames .first->second; 376963378bdSLang Hames } 377963378bdSLang Hames 378963378bdSLang Hames SymbolStringPtr &getInternedName(Symbol &Sym) { 379963378bdSLang Hames auto I = NameCache.find(&Sym); 380963378bdSLang Hames if (I != NameCache.end()) 381963378bdSLang Hames return I->second; 382963378bdSLang Hames 383963378bdSLang Hames return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName()))) 384963378bdSLang Hames .first->second; 385963378bdSLang Hames } 386963378bdSLang Hames 387963378bdSLang Hames private: 388963378bdSLang Hames BlockSymbolDependencies &getBlockImmediateDeps(Block &B) { 389963378bdSLang Hames // Check the cache first. 390963378bdSLang Hames auto I = BlockImmediateDepsCache.find(&B); 391963378bdSLang Hames if (I != BlockImmediateDepsCache.end()) 392963378bdSLang Hames return I->second; 393963378bdSLang Hames 394963378bdSLang Hames BlockSymbolDependencies BIDCacheVal; 395963378bdSLang Hames for (auto &E : B.edges()) { 396963378bdSLang Hames auto &Tgt = E.getTarget(); 397963378bdSLang Hames if (Tgt.getScope() != Scope::Local) { 398963378bdSLang Hames if (Tgt.isExternal()) 399963378bdSLang Hames BIDCacheVal.External.insert(getInternedName(Tgt)); 400963378bdSLang Hames else 401963378bdSLang Hames BIDCacheVal.Internal.insert(getInternedName(Tgt)); 402963378bdSLang Hames } 403963378bdSLang Hames } 404963378bdSLang Hames 405963378bdSLang Hames return BlockImmediateDepsCache 406963378bdSLang Hames .insert(std::make_pair(&B, std::move(BIDCacheVal))) 407963378bdSLang Hames .first->second; 408963378bdSLang Hames } 409963378bdSLang Hames 410963378bdSLang Hames ExecutionSession &ES; 411963378bdSLang Hames DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 412963378bdSLang Hames DenseMap<const Symbol *, SymbolStringPtr> NameCache; 413963378bdSLang Hames DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache; 414963378bdSLang Hames DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache; 415963378bdSLang Hames }; 41611c8dfa5SLang Hames 4174dc110a4SLang Hames Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 41811c8dfa5SLang Hames auto &ES = Layer.getExecutionSession(); 41911c8dfa5SLang Hames 4204dc110a4SLang Hames SymbolFlagsMap NewSymbolsToClaim; 4214dc110a4SLang Hames std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 4224dc110a4SLang Hames 4234dc110a4SLang Hames auto ProcessSymbol = [&](Symbol *Sym) { 4244c94760fSBen Langmuir if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 4254c94760fSBen Langmuir Sym->getScope() != Scope::Local) { 4264dc110a4SLang Hames auto Name = ES.intern(Sym->getName()); 4274dc110a4SLang Hames if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 4284dc110a4SLang Hames JITSymbolFlags SF = JITSymbolFlags::Weak; 4294dc110a4SLang Hames if (Sym->getScope() == Scope::Default) 4304dc110a4SLang Hames SF |= JITSymbolFlags::Exported; 4314dc110a4SLang Hames NewSymbolsToClaim[Name] = SF; 4324dc110a4SLang Hames NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 43311c8dfa5SLang Hames } 4344dc110a4SLang Hames } 4354dc110a4SLang Hames }; 4364dc110a4SLang Hames 4374dc110a4SLang Hames for (auto *Sym : G.defined_symbols()) 4384dc110a4SLang Hames ProcessSymbol(Sym); 4394dc110a4SLang Hames for (auto *Sym : G.absolute_symbols()) 4404dc110a4SLang Hames ProcessSymbol(Sym); 4414dc110a4SLang Hames 4424dc110a4SLang Hames // Attempt to claim all weak defs that we're not already responsible for. 4434dc110a4SLang Hames // This cannot fail -- any clashes will just result in rejection of our 4444dc110a4SLang Hames // claim, at which point we'll externalize that symbol. 4454dc110a4SLang Hames cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim))); 4464dc110a4SLang Hames 4474dc110a4SLang Hames for (auto &KV : NameToSym) 4484dc110a4SLang Hames if (!MR->getSymbols().count(KV.first)) 4494dc110a4SLang Hames G.makeExternal(*KV.second); 45011c8dfa5SLang Hames 45111c8dfa5SLang Hames return Error::success(); 45211c8dfa5SLang Hames } 45311c8dfa5SLang Hames 4544e920e58SLang Hames Error markResponsibilitySymbolsLive(LinkGraph &G) const { 45511c8dfa5SLang Hames auto &ES = Layer.getExecutionSession(); 4564e920e58SLang Hames for (auto *Sym : G.defined_symbols()) 4577dcd0042SLang Hames if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 4584e920e58SLang Hames Sym->setLive(true); 45911c8dfa5SLang Hames return Error::success(); 46011c8dfa5SLang Hames } 46111c8dfa5SLang Hames 4624e920e58SLang Hames Error computeNamedSymbolDependencies(LinkGraph &G) { 4637dcd0042SLang Hames auto &ES = MR->getTargetJITDylib().getExecutionSession(); 464963378bdSLang Hames auto BlockDeps = computeBlockNonLocalDeps(G); 46511c8dfa5SLang Hames 46685fb9976SLang Hames // Compute dependencies for symbols defined in the JITLink graph. 4674e920e58SLang Hames for (auto *Sym : G.defined_symbols()) { 46811c8dfa5SLang Hames 469ca6f5848SLang Hames // Skip local symbols: we do not track dependencies for these. 4704e920e58SLang Hames if (Sym->getScope() == Scope::Local) 47111c8dfa5SLang Hames continue; 472ca6f5848SLang Hames assert(Sym->hasName() && 473ca6f5848SLang Hames "Defined non-local jitlink::Symbol should have a name"); 47411c8dfa5SLang Hames 475963378bdSLang Hames auto &SymDeps = BlockDeps[Sym->getBlock()]; 476963378bdSLang Hames if (SymDeps.External.empty() && SymDeps.Internal.empty()) 477ca6f5848SLang Hames continue; 478ca6f5848SLang Hames 479ca6f5848SLang Hames auto SymName = ES.intern(Sym->getName()); 480963378bdSLang Hames if (!SymDeps.External.empty()) 481963378bdSLang Hames ExternalNamedSymbolDeps[SymName] = SymDeps.External; 482963378bdSLang Hames if (!SymDeps.Internal.empty()) 483963378bdSLang Hames InternalNamedSymbolDeps[SymName] = SymDeps.Internal; 484ca6f5848SLang Hames } 485ca6f5848SLang Hames 48685fb9976SLang Hames for (auto &P : Layer.Plugins) { 487963378bdSLang Hames auto SynthDeps = P->getSyntheticSymbolDependencies(*MR); 488963378bdSLang Hames if (SynthDeps.empty()) 48985fb9976SLang Hames continue; 49085fb9976SLang Hames 491963378bdSLang Hames DenseSet<Block *> BlockVisited; 492963378bdSLang Hames for (auto &KV : SynthDeps) { 49385fb9976SLang Hames auto &Name = KV.first; 494963378bdSLang Hames auto &DepsForName = KV.second; 495963378bdSLang Hames for (auto *Sym : DepsForName) { 496963378bdSLang Hames if (Sym->getScope() == Scope::Local) { 497963378bdSLang Hames auto &BDeps = BlockDeps[Sym->getBlock()]; 498963378bdSLang Hames for (auto &S : BDeps.Internal) 49985fb9976SLang Hames InternalNamedSymbolDeps[Name].insert(S); 500963378bdSLang Hames for (auto &S : BDeps.External) 50185fb9976SLang Hames ExternalNamedSymbolDeps[Name].insert(S); 502963378bdSLang Hames } else { 503963378bdSLang Hames if (Sym->isExternal()) 504963378bdSLang Hames ExternalNamedSymbolDeps[Name].insert( 505963378bdSLang Hames BlockDeps.getInternedName(*Sym)); 506963378bdSLang Hames else 507963378bdSLang Hames InternalNamedSymbolDeps[Name].insert( 508963378bdSLang Hames BlockDeps.getInternedName(*Sym)); 509963378bdSLang Hames } 51085fb9976SLang Hames } 51185fb9976SLang Hames } 51285fb9976SLang Hames } 51385fb9976SLang Hames 51411c8dfa5SLang Hames return Error::success(); 51511c8dfa5SLang Hames } 51611c8dfa5SLang Hames 517963378bdSLang Hames BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) { 518963378bdSLang Hames // First calculate the reachable-via-non-local-symbol blocks for each block. 519963378bdSLang Hames struct BlockInfo { 520963378bdSLang Hames DenseSet<Block *> Dependencies; 521963378bdSLang Hames DenseSet<Block *> Dependants; 522963378bdSLang Hames bool DependenciesChanged = true; 52311c8dfa5SLang Hames }; 524963378bdSLang Hames DenseMap<Block *, BlockInfo> BlockInfos; 525963378bdSLang Hames SmallVector<Block *> WorkList; 52611c8dfa5SLang Hames 527963378bdSLang Hames // Pre-allocate map entries. This prevents any iterator/reference 528963378bdSLang Hames // invalidation in the next loop. 529963378bdSLang Hames for (auto *B : G.blocks()) 530963378bdSLang Hames (void)BlockInfos[B]; 531963378bdSLang Hames 532963378bdSLang Hames // Build initial worklist, record block dependencies/dependants and 533963378bdSLang Hames // non-local symbol dependencies. 534963378bdSLang Hames for (auto *B : G.blocks()) { 535963378bdSLang Hames auto &BI = BlockInfos[B]; 536963378bdSLang Hames for (auto &E : B->edges()) { 537963378bdSLang Hames if (E.getTarget().getScope() == Scope::Local) { 538963378bdSLang Hames auto &TgtB = E.getTarget().getBlock(); 539963378bdSLang Hames if (&TgtB != B) { 540963378bdSLang Hames BI.Dependencies.insert(&TgtB); 541963378bdSLang Hames BlockInfos[&TgtB].Dependants.insert(B); 542963378bdSLang Hames } 54311c8dfa5SLang Hames } 54411c8dfa5SLang Hames } 54511c8dfa5SLang Hames 546963378bdSLang Hames // If this node has both dependants and dependencies then add it to the 547963378bdSLang Hames // worklist to propagate the dependencies to the dependants. 548963378bdSLang Hames if (!BI.Dependants.empty() && !BI.Dependencies.empty()) 549963378bdSLang Hames WorkList.push_back(B); 55011c8dfa5SLang Hames } 55111c8dfa5SLang Hames 552963378bdSLang Hames // Propagate block-level dependencies through the block-dependence graph. 553963378bdSLang Hames while (!WorkList.empty()) { 55484b07c9bSKazu Hirata auto *B = WorkList.pop_back_val(); 55511c8dfa5SLang Hames 556963378bdSLang Hames auto &BI = BlockInfos[B]; 557963378bdSLang Hames assert(BI.DependenciesChanged && 558963378bdSLang Hames "Block in worklist has unchanged dependencies"); 559963378bdSLang Hames BI.DependenciesChanged = false; 560963378bdSLang Hames for (auto *Dependant : BI.Dependants) { 561963378bdSLang Hames auto &DependantBI = BlockInfos[Dependant]; 562963378bdSLang Hames for (auto *Dependency : BI.Dependencies) { 563963378bdSLang Hames if (Dependant != Dependency && 564963378bdSLang Hames DependantBI.Dependencies.insert(Dependency).second) 565963378bdSLang Hames if (!DependantBI.DependenciesChanged) { 566963378bdSLang Hames DependantBI.DependenciesChanged = true; 567963378bdSLang Hames WorkList.push_back(Dependant); 56811c8dfa5SLang Hames } 56911c8dfa5SLang Hames } 57085fb9976SLang Hames } 57185fb9976SLang Hames } 57285fb9976SLang Hames 573963378bdSLang Hames DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 574963378bdSLang Hames for (auto &KV : BlockInfos) 575963378bdSLang Hames BlockDeps[KV.first] = std::move(KV.second.Dependencies); 576963378bdSLang Hames 577963378bdSLang Hames return BlockDependenciesMap(Layer.getExecutionSession(), 578963378bdSLang Hames std::move(BlockDeps)); 57911c8dfa5SLang Hames } 58011c8dfa5SLang Hames 58111c8dfa5SLang Hames void registerDependencies(const SymbolDependenceMap &QueryDeps) { 582ca6f5848SLang Hames for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 58311c8dfa5SLang Hames auto &Name = NamedDepsEntry.first; 58411c8dfa5SLang Hames auto &NameDeps = NamedDepsEntry.second; 58511c8dfa5SLang Hames SymbolDependenceMap SymbolDeps; 58611c8dfa5SLang Hames 58711c8dfa5SLang Hames for (const auto &QueryDepsEntry : QueryDeps) { 58811c8dfa5SLang Hames JITDylib &SourceJD = *QueryDepsEntry.first; 58911c8dfa5SLang Hames const SymbolNameSet &Symbols = QueryDepsEntry.second; 59011c8dfa5SLang Hames auto &DepsForJD = SymbolDeps[&SourceJD]; 59111c8dfa5SLang Hames 59211c8dfa5SLang Hames for (const auto &S : Symbols) 59311c8dfa5SLang Hames if (NameDeps.count(S)) 59411c8dfa5SLang Hames DepsForJD.insert(S); 59511c8dfa5SLang Hames 59611c8dfa5SLang Hames if (DepsForJD.empty()) 59711c8dfa5SLang Hames SymbolDeps.erase(&SourceJD); 59811c8dfa5SLang Hames } 59911c8dfa5SLang Hames 6007dcd0042SLang Hames MR->addDependencies(Name, SymbolDeps); 60111c8dfa5SLang Hames } 60211c8dfa5SLang Hames } 60311c8dfa5SLang Hames 60411c8dfa5SLang Hames ObjectLinkingLayer &Layer; 6057dcd0042SLang Hames std::unique_ptr<MaterializationResponsibility> MR; 60611c8dfa5SLang Hames std::unique_ptr<MemoryBuffer> ObjBuffer; 607ca6f5848SLang Hames DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 608ca6f5848SLang Hames DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 60911c8dfa5SLang Hames }; 61011c8dfa5SLang Hames 6113a3cb929SKazu Hirata ObjectLinkingLayer::Plugin::~Plugin() = default; 612a9fdf375SLang Hames 613406ef36bSStefan Gränitz char ObjectLinkingLayer::ID; 614406ef36bSStefan Gränitz 615406ef36bSStefan Gränitz using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 616406ef36bSStefan Gränitz 6172487db1fSLang Hames ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 6182487db1fSLang Hames : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 6192487db1fSLang Hames ES.registerResourceManager(*this); 6202487db1fSLang Hames } 6212487db1fSLang Hames 62269091eb1SLang Hames ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 62369091eb1SLang Hames JITLinkMemoryManager &MemMgr) 624406ef36bSStefan Gränitz : BaseT(ES), MemMgr(MemMgr) { 6250aec49c8SLang Hames ES.registerResourceManager(*this); 6260aec49c8SLang Hames } 62769091eb1SLang Hames 628c0143f37SLang Hames ObjectLinkingLayer::ObjectLinkingLayer( 629c0143f37SLang Hames ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 630406ef36bSStefan Gränitz : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 6310aec49c8SLang Hames ES.registerResourceManager(*this); 6320aec49c8SLang Hames } 633a9fdf375SLang Hames 634a9fdf375SLang Hames ObjectLinkingLayer::~ObjectLinkingLayer() { 6350aec49c8SLang Hames assert(Allocs.empty() && "Layer destroyed with resources still attached"); 6360aec49c8SLang Hames getExecutionSession().deregisterResourceManager(*this); 637a9fdf375SLang Hames } 63811c8dfa5SLang Hames 6390fda4c47SLang Hames Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 6400fda4c47SLang Hames std::unique_ptr<LinkGraph> G) { 6410fda4c47SLang Hames auto &JD = RT->getJITDylib(); 6420fda4c47SLang Hames return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 6430fda4c47SLang Hames std::move(RT)); 6440fda4c47SLang Hames } 6450fda4c47SLang Hames 6467dcd0042SLang Hames void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 64711c8dfa5SLang Hames std::unique_ptr<MemoryBuffer> O) { 64811c8dfa5SLang Hames assert(O && "Object must not be null"); 649ef238923SStefan Gränitz MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 650ef238923SStefan Gränitz 651ec6b71dfSLang Hames auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 652ec6b71dfSLang Hames *this, std::move(R), std::move(O)); 653ef238923SStefan Gränitz if (auto G = createLinkGraphFromObject(ObjBuffer)) { 654ef238923SStefan Gränitz Ctx->notifyMaterializing(**G); 655ec6b71dfSLang Hames link(std::move(*G), std::move(Ctx)); 656ef238923SStefan Gränitz } else { 657ec6b71dfSLang Hames Ctx->notifyFailed(G.takeError()); 658ec6b71dfSLang Hames } 659ef238923SStefan Gränitz } 660ec6b71dfSLang Hames 661ec6b71dfSLang Hames void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 662ec6b71dfSLang Hames std::unique_ptr<LinkGraph> G) { 663ef238923SStefan Gränitz auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 664ef238923SStefan Gränitz *this, std::move(R), nullptr); 665ef238923SStefan Gränitz Ctx->notifyMaterializing(*G); 666ef238923SStefan Gränitz link(std::move(G), std::move(Ctx)); 66711c8dfa5SLang Hames } 66811c8dfa5SLang Hames 669a9fdf375SLang Hames void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 6704e30b20bSLang Hames LinkGraph &G, 671a9fdf375SLang Hames PassConfiguration &PassConfig) { 672a9fdf375SLang Hames for (auto &P : Plugins) 6734e30b20bSLang Hames P->modifyPassConfig(MR, G, PassConfig); 67411c8dfa5SLang Hames } 67511c8dfa5SLang Hames 676a9fdf375SLang Hames void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 677a9fdf375SLang Hames for (auto &P : Plugins) 678a9fdf375SLang Hames P->notifyLoaded(MR); 67911c8dfa5SLang Hames } 68011c8dfa5SLang Hames 681a9fdf375SLang Hames Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 682962a2479SLang Hames FinalizedAlloc FA) { 683a9fdf375SLang Hames Error Err = Error::success(); 684a9fdf375SLang Hames for (auto &P : Plugins) 685a9fdf375SLang Hames Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 68611c8dfa5SLang Hames 687a9fdf375SLang Hames if (Err) 688a9fdf375SLang Hames return Err; 68911c8dfa5SLang Hames 6900aec49c8SLang Hames return MR.withResourceKeyDo( 691962a2479SLang Hames [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 692a9fdf375SLang Hames } 69311c8dfa5SLang Hames 6940aec49c8SLang Hames Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) { 695a9fdf375SLang Hames 696962a2479SLang Hames { 697a9fdf375SLang Hames Error Err = Error::success(); 698a9fdf375SLang Hames for (auto &P : Plugins) 6990aec49c8SLang Hames Err = joinErrors(std::move(Err), P->notifyRemovingResources(K)); 700962a2479SLang Hames if (Err) 701962a2479SLang Hames return Err; 702962a2479SLang Hames } 703a9fdf375SLang Hames 704962a2479SLang Hames std::vector<FinalizedAlloc> AllocsToRemove; 7050aec49c8SLang Hames getExecutionSession().runSessionLocked([&] { 7060aec49c8SLang Hames auto I = Allocs.find(K); 7070aec49c8SLang Hames if (I != Allocs.end()) { 7080aec49c8SLang Hames std::swap(AllocsToRemove, I->second); 7090aec49c8SLang Hames Allocs.erase(I); 710a9fdf375SLang Hames } 7110aec49c8SLang Hames }); 712a9fdf375SLang Hames 713bfb40e83SLang Hames if (AllocsToRemove.empty()) 714bfb40e83SLang Hames return Error::success(); 715bfb40e83SLang Hames 716962a2479SLang Hames return MemMgr.deallocate(std::move(AllocsToRemove)); 717a9fdf375SLang Hames } 718a9fdf375SLang Hames 7190aec49c8SLang Hames void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey, 7200aec49c8SLang Hames ResourceKey SrcKey) { 7210aec49c8SLang Hames auto I = Allocs.find(SrcKey); 7220aec49c8SLang Hames if (I != Allocs.end()) { 7230aec49c8SLang Hames auto &SrcAllocs = I->second; 7240aec49c8SLang Hames auto &DstAllocs = Allocs[DstKey]; 7250aec49c8SLang Hames DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 7260aec49c8SLang Hames for (auto &Alloc : SrcAllocs) 7270aec49c8SLang Hames DstAllocs.push_back(std::move(Alloc)); 7280aec49c8SLang Hames 7290aec49c8SLang Hames // Erase SrcKey entry using value rather than iterator I: I may have been 7300aec49c8SLang Hames // invalidated when we looked up DstKey. 7310aec49c8SLang Hames Allocs.erase(SrcKey); 7320aec49c8SLang Hames } 7330aec49c8SLang Hames 7340aec49c8SLang Hames for (auto &P : Plugins) 7350aec49c8SLang Hames P->notifyTransferringResources(DstKey, SrcKey); 7360aec49c8SLang Hames } 7370aec49c8SLang Hames 738f5a885fdSLang Hames EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 7390aec49c8SLang Hames ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 7400aec49c8SLang Hames : ES(ES), Registrar(std::move(Registrar)) {} 741f5a885fdSLang Hames 742f5a885fdSLang Hames void EHFrameRegistrationPlugin::modifyPassConfig( 7434e30b20bSLang Hames MaterializationResponsibility &MR, LinkGraph &G, 744a9fdf375SLang Hames PassConfiguration &PassConfig) { 745a9fdf375SLang Hames 746214a9f0dSLang Hames PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 747118e953bSLang Hames G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) { 748214a9f0dSLang Hames if (Addr) { 749214a9f0dSLang Hames std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 750214a9f0dSLang Hames assert(!InProcessLinks.count(&MR) && 751214a9f0dSLang Hames "Link for MR already being tracked?"); 752c48f1f6dSLang Hames InProcessLinks[&MR] = {Addr, Size}; 753214a9f0dSLang Hames } 754a9fdf375SLang Hames })); 755a9fdf375SLang Hames } 756a9fdf375SLang Hames 757f5a885fdSLang Hames Error EHFrameRegistrationPlugin::notifyEmitted( 758a9fdf375SLang Hames MaterializationResponsibility &MR) { 7590aec49c8SLang Hames 760089acf25SLang Hames ExecutorAddrRange EmittedRange; 7610aec49c8SLang Hames { 762214a9f0dSLang Hames std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 763a9fdf375SLang Hames 764c48f1f6dSLang Hames auto EHFrameRangeItr = InProcessLinks.find(&MR); 765c48f1f6dSLang Hames if (EHFrameRangeItr == InProcessLinks.end()) 766a9fdf375SLang Hames return Error::success(); 767a9fdf375SLang Hames 7680aec49c8SLang Hames EmittedRange = EHFrameRangeItr->second; 769089acf25SLang Hames assert(EmittedRange.Start && "eh-frame addr to register can not be null"); 770c48f1f6dSLang Hames InProcessLinks.erase(EHFrameRangeItr); 771a9fdf375SLang Hames } 772a9fdf375SLang Hames 7730aec49c8SLang Hames if (auto Err = MR.withResourceKeyDo( 7740aec49c8SLang Hames [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 7750aec49c8SLang Hames return Err; 776214a9f0dSLang Hames 777089acf25SLang Hames return Registrar->registerEHFrames(EmittedRange); 7780aec49c8SLang Hames } 7790aec49c8SLang Hames 7800aec49c8SLang Hames Error EHFrameRegistrationPlugin::notifyFailed( 7810aec49c8SLang Hames MaterializationResponsibility &MR) { 7820aec49c8SLang Hames std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7830aec49c8SLang Hames InProcessLinks.erase(&MR); 784a9fdf375SLang Hames return Error::success(); 785a9fdf375SLang Hames } 786a9fdf375SLang Hames 7870aec49c8SLang Hames Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) { 788089acf25SLang Hames std::vector<ExecutorAddrRange> RangesToRemove; 789a9fdf375SLang Hames 7900aec49c8SLang Hames ES.runSessionLocked([&] { 7910aec49c8SLang Hames auto I = EHFrameRanges.find(K); 7920aec49c8SLang Hames if (I != EHFrameRanges.end()) { 7930aec49c8SLang Hames RangesToRemove = std::move(I->second); 7940aec49c8SLang Hames EHFrameRanges.erase(I); 7950aec49c8SLang Hames } 7960aec49c8SLang Hames }); 797a9fdf375SLang Hames 798a9fdf375SLang Hames Error Err = Error::success(); 7990aec49c8SLang Hames while (!RangesToRemove.empty()) { 8000aec49c8SLang Hames auto RangeToRemove = RangesToRemove.back(); 8010aec49c8SLang Hames RangesToRemove.pop_back(); 802089acf25SLang Hames assert(RangeToRemove.Start && "Untracked eh-frame range must not be null"); 803089acf25SLang Hames Err = joinErrors(std::move(Err), 804089acf25SLang Hames Registrar->deregisterEHFrames(RangeToRemove)); 805a9fdf375SLang Hames } 806a9fdf375SLang Hames 807a9fdf375SLang Hames return Err; 80811c8dfa5SLang Hames } 80911c8dfa5SLang Hames 8100aec49c8SLang Hames void EHFrameRegistrationPlugin::notifyTransferringResources( 8110aec49c8SLang Hames ResourceKey DstKey, ResourceKey SrcKey) { 8120aec49c8SLang Hames auto SI = EHFrameRanges.find(SrcKey); 813c1baf946SLang Hames if (SI == EHFrameRanges.end()) 814c1baf946SLang Hames return; 815c1baf946SLang Hames 816c1baf946SLang Hames auto DI = EHFrameRanges.find(DstKey); 817c1baf946SLang Hames if (DI != EHFrameRanges.end()) { 8180aec49c8SLang Hames auto &SrcRanges = SI->second; 819c1baf946SLang Hames auto &DstRanges = DI->second; 8200aec49c8SLang Hames DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 8210aec49c8SLang Hames for (auto &SrcRange : SrcRanges) 8220aec49c8SLang Hames DstRanges.push_back(std::move(SrcRange)); 8230aec49c8SLang Hames EHFrameRanges.erase(SI); 824c1baf946SLang Hames } else { 825c1baf946SLang Hames // We need to move SrcKey's ranges over without invalidating the SI 826c1baf946SLang Hames // iterator. 827c1baf946SLang Hames auto Tmp = std::move(SI->second); 828c1baf946SLang Hames EHFrameRanges.erase(SI); 829c1baf946SLang Hames EHFrameRanges[DstKey] = std::move(Tmp); 8300aec49c8SLang Hames } 8310aec49c8SLang Hames } 8320aec49c8SLang Hames 83311c8dfa5SLang Hames } // End namespace orc. 83411c8dfa5SLang Hames } // End namespace llvm. 835