10b57cec5SDimitry Andric //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 100b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 1106c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch32.h" 12fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" 13*0fca6ea1SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 14bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 1506c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 16fe6060f1SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 17fe6060f1SDimitry Andric #include <string> 180b57cec5SDimitry Andric #include <vector> 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #define DEBUG_TYPE "orc" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric using namespace llvm::jitlink; 240b57cec5SDimitry Andric using namespace llvm::orc; 250b57cec5SDimitry Andric 26fe6060f1SDimitry Andric namespace { 27fe6060f1SDimitry Andric 2806c3fb27SDimitry Andric bool hasInitializerSection(jitlink::LinkGraph &G) { 2906c3fb27SDimitry Andric bool IsMachO = G.getTargetTriple().isOSBinFormatMachO(); 3006c3fb27SDimitry Andric bool IsElf = G.getTargetTriple().isOSBinFormatELF(); 3106c3fb27SDimitry Andric if (!IsMachO && !IsElf) 3206c3fb27SDimitry Andric return false; 3306c3fb27SDimitry Andric 3406c3fb27SDimitry Andric for (auto &Sec : G.sections()) { 3506c3fb27SDimitry Andric if (IsMachO && isMachOInitializerSection(Sec.getName())) 3606c3fb27SDimitry Andric return true; 3706c3fb27SDimitry Andric if (IsElf && isELFInitializerSection(Sec.getName())) 3806c3fb27SDimitry Andric return true; 3906c3fb27SDimitry Andric } 4006c3fb27SDimitry Andric 4106c3fb27SDimitry Andric return false; 4206c3fb27SDimitry Andric } 4306c3fb27SDimitry Andric 4406c3fb27SDimitry Andric ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) { 4506c3fb27SDimitry Andric switch (TT.getArch()) { 4606c3fb27SDimitry Andric case Triple::arm: 4706c3fb27SDimitry Andric case Triple::armeb: 4806c3fb27SDimitry Andric case Triple::thumb: 4906c3fb27SDimitry Andric case Triple::thumbeb: 505f757f3fSDimitry Andric if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) { 5106c3fb27SDimitry Andric // Set LSB to indicate thumb target 5206c3fb27SDimitry Andric assert(Sym.isCallable() && "Only callable symbols can have thumb flag"); 5306c3fb27SDimitry Andric assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear"); 5406c3fb27SDimitry Andric return Sym.getAddress() + 0x01; 5506c3fb27SDimitry Andric } 5606c3fb27SDimitry Andric return Sym.getAddress(); 5706c3fb27SDimitry Andric default: 5806c3fb27SDimitry Andric return Sym.getAddress(); 5906c3fb27SDimitry Andric } 6006c3fb27SDimitry Andric } 6106c3fb27SDimitry Andric 6206c3fb27SDimitry Andric JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) { 6306c3fb27SDimitry Andric JITSymbolFlags Flags; 6406c3fb27SDimitry Andric 6506c3fb27SDimitry Andric if (Sym.getLinkage() == Linkage::Weak) 6606c3fb27SDimitry Andric Flags |= JITSymbolFlags::Weak; 6706c3fb27SDimitry Andric 6806c3fb27SDimitry Andric if (Sym.getScope() == Scope::Default) 6906c3fb27SDimitry Andric Flags |= JITSymbolFlags::Exported; 7006c3fb27SDimitry Andric 7106c3fb27SDimitry Andric if (Sym.isCallable()) 7206c3fb27SDimitry Andric Flags |= JITSymbolFlags::Callable; 7306c3fb27SDimitry Andric 7406c3fb27SDimitry Andric return Flags; 7506c3fb27SDimitry Andric } 7606c3fb27SDimitry Andric 77fe6060f1SDimitry Andric class LinkGraphMaterializationUnit : public MaterializationUnit { 78fe6060f1SDimitry Andric public: 79fe6060f1SDimitry Andric static std::unique_ptr<LinkGraphMaterializationUnit> 80fe6060f1SDimitry Andric Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 81fe6060f1SDimitry Andric auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 82fe6060f1SDimitry Andric return std::unique_ptr<LinkGraphMaterializationUnit>( 83fe6060f1SDimitry Andric new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 84fe6060f1SDimitry Andric std::move(LGI))); 85fe6060f1SDimitry Andric } 86fe6060f1SDimitry Andric 87fe6060f1SDimitry Andric StringRef getName() const override { return G->getName(); } 88fe6060f1SDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 89fe6060f1SDimitry Andric ObjLinkingLayer.emit(std::move(MR), std::move(G)); 90fe6060f1SDimitry Andric } 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric private: 930eae32dcSDimitry Andric static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 94fe6060f1SDimitry Andric 950eae32dcSDimitry Andric Interface LGI; 96fe6060f1SDimitry Andric 971db9f3b2SDimitry Andric auto AddSymbol = [&](Symbol *Sym) { 98fe6060f1SDimitry Andric // Skip local symbols. 99fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) 1001db9f3b2SDimitry Andric return; 101fe6060f1SDimitry Andric assert(Sym->hasName() && "Anonymous non-local symbol?"); 102fe6060f1SDimitry Andric 10306c3fb27SDimitry Andric LGI.SymbolFlags[ES.intern(Sym->getName())] = 10406c3fb27SDimitry Andric getJITSymbolFlagsForSymbol(*Sym); 1051db9f3b2SDimitry Andric }; 1061db9f3b2SDimitry Andric 1071db9f3b2SDimitry Andric for (auto *Sym : G.defined_symbols()) 1081db9f3b2SDimitry Andric AddSymbol(Sym); 1091db9f3b2SDimitry Andric for (auto *Sym : G.absolute_symbols()) 1101db9f3b2SDimitry Andric AddSymbol(Sym); 111fe6060f1SDimitry Andric 112bdd1243dSDimitry Andric if (hasInitializerSection(G)) 113fe6060f1SDimitry Andric LGI.InitSymbol = makeInitSymbol(ES, G); 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric return LGI; 116fe6060f1SDimitry Andric } 117fe6060f1SDimitry Andric 118fe6060f1SDimitry Andric static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 119fe6060f1SDimitry Andric std::string InitSymString; 120fe6060f1SDimitry Andric raw_string_ostream(InitSymString) 121fe6060f1SDimitry Andric << "$." << G.getName() << ".__inits" << Counter++; 122fe6060f1SDimitry Andric return ES.intern(InitSymString); 123fe6060f1SDimitry Andric } 124fe6060f1SDimitry Andric 125fe6060f1SDimitry Andric LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 1260eae32dcSDimitry Andric std::unique_ptr<LinkGraph> G, Interface LGI) 1270eae32dcSDimitry Andric : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), 1280eae32dcSDimitry Andric G(std::move(G)) {} 129fe6060f1SDimitry Andric 130fe6060f1SDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 131fe6060f1SDimitry Andric for (auto *Sym : G->defined_symbols()) 132fe6060f1SDimitry Andric if (Sym->getName() == *Name) { 133fe6060f1SDimitry Andric assert(Sym->getLinkage() == Linkage::Weak && 134fe6060f1SDimitry Andric "Discarding non-weak definition"); 135fe6060f1SDimitry Andric G->makeExternal(*Sym); 136fe6060f1SDimitry Andric break; 137fe6060f1SDimitry Andric } 138fe6060f1SDimitry Andric } 139fe6060f1SDimitry Andric 140fe6060f1SDimitry Andric ObjectLinkingLayer &ObjLinkingLayer; 141fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G; 142fe6060f1SDimitry Andric static std::atomic<uint64_t> Counter; 143fe6060f1SDimitry Andric }; 144fe6060f1SDimitry Andric 145fe6060f1SDimitry Andric std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 146fe6060f1SDimitry Andric 147fe6060f1SDimitry Andric } // end anonymous namespace 148fe6060f1SDimitry Andric 1490b57cec5SDimitry Andric namespace llvm { 1500b57cec5SDimitry Andric namespace orc { 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 1530b57cec5SDimitry Andric public: 154e8d8bef9SDimitry Andric ObjectLinkingLayerJITLinkContext( 155e8d8bef9SDimitry Andric ObjectLinkingLayer &Layer, 156e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR, 1570b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer) 158e8d8bef9SDimitry Andric : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 159*0fca6ea1SDimitry Andric MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) { 160*0fca6ea1SDimitry Andric std::lock_guard<std::mutex> Lock(Layer.LayerMutex); 161*0fca6ea1SDimitry Andric Plugins = Layer.Plugins; 162*0fca6ea1SDimitry Andric } 1630b57cec5SDimitry Andric 1648bcb0991SDimitry Andric ~ObjectLinkingLayerJITLinkContext() { 1658bcb0991SDimitry Andric // If there is an object buffer return function then use it to 1668bcb0991SDimitry Andric // return ownership of the buffer. 167e8d8bef9SDimitry Andric if (Layer.ReturnObjectBuffer && ObjBuffer) 1688bcb0991SDimitry Andric Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 1698bcb0991SDimitry Andric } 1708bcb0991SDimitry Andric 171e8d8bef9SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 1720b57cec5SDimitry Andric 173fe6060f1SDimitry Andric void notifyMaterializing(LinkGraph &G) { 174*0fca6ea1SDimitry Andric for (auto &P : Plugins) 175fe6060f1SDimitry Andric P->notifyMaterializing(*MR, G, *this, 176fe6060f1SDimitry Andric ObjBuffer ? ObjBuffer->getMemBufferRef() 177fe6060f1SDimitry Andric : MemoryBufferRef()); 178fe6060f1SDimitry Andric } 179fe6060f1SDimitry Andric 1800b57cec5SDimitry Andric void notifyFailed(Error Err) override { 181*0fca6ea1SDimitry Andric for (auto &P : Plugins) 182e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 1830b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 184e8d8bef9SDimitry Andric MR->failMaterialization(); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 187480093f4SDimitry Andric void lookup(const LookupMap &Symbols, 1888bcb0991SDimitry Andric std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 1890b57cec5SDimitry Andric 1905ffd83dbSDimitry Andric JITDylibSearchOrder LinkOrder; 191e8d8bef9SDimitry Andric MR->getTargetJITDylib().withLinkOrderDo( 1925ffd83dbSDimitry Andric [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 1950b57cec5SDimitry Andric 196480093f4SDimitry Andric SymbolLookupSet LookupSet; 197480093f4SDimitry Andric for (auto &KV : Symbols) { 198480093f4SDimitry Andric orc::SymbolLookupFlags LookupFlags; 199480093f4SDimitry Andric switch (KV.second) { 200480093f4SDimitry Andric case jitlink::SymbolLookupFlags::RequiredSymbol: 201480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 202480093f4SDimitry Andric break; 203480093f4SDimitry Andric case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 204480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 205480093f4SDimitry Andric break; 206480093f4SDimitry Andric } 207480093f4SDimitry Andric LookupSet.add(ES.intern(KV.first), LookupFlags); 208480093f4SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker. 211e8d8bef9SDimitry Andric auto OnResolve = [LookupContinuation = 212e8d8bef9SDimitry Andric std::move(LC)](Expected<SymbolMap> Result) mutable { 2130b57cec5SDimitry Andric if (!Result) 2148bcb0991SDimitry Andric LookupContinuation->run(Result.takeError()); 2150b57cec5SDimitry Andric else { 2160b57cec5SDimitry Andric AsyncLookupResult LR; 2170b57cec5SDimitry Andric for (auto &KV : *Result) 2180b57cec5SDimitry Andric LR[*KV.first] = KV.second; 2198bcb0991SDimitry Andric LookupContinuation->run(std::move(LR)); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric }; 2220b57cec5SDimitry Andric 2235ffd83dbSDimitry Andric ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 224480093f4SDimitry Andric SymbolState::Resolved, std::move(OnResolve), 225480093f4SDimitry Andric [this](const SymbolDependenceMap &Deps) { 226*0fca6ea1SDimitry Andric // Translate LookupDeps map to SymbolSourceJD. 227*0fca6ea1SDimitry Andric for (auto &[DepJD, Deps] : Deps) 228*0fca6ea1SDimitry Andric for (auto &DepSym : Deps) 229*0fca6ea1SDimitry Andric SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD; 2300b57cec5SDimitry Andric }); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 233e8d8bef9SDimitry Andric Error notifyResolved(LinkGraph &G) override { 2340b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim; 2370b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric SymbolMap InternedResult; 2408bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 2418bcb0991SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2428bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 24306c3fb27SDimitry Andric auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 24406c3fb27SDimitry Andric auto Flags = getJITSymbolFlagsForSymbol(*Sym); 24506c3fb27SDimitry Andric InternedResult[InternedName] = {Ptr, Flags}; 246e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2470b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2480b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2490b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2538bcb0991SDimitry Andric for (auto *Sym : G.absolute_symbols()) 25481ad6265SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2558bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 25606c3fb27SDimitry Andric auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 25706c3fb27SDimitry Andric auto Flags = getJITSymbolFlagsForSymbol(*Sym); 25806c3fb27SDimitry Andric InternedResult[InternedName] = {Ptr, Flags}; 259e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2600b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2610b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2620b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty()) 267e8d8bef9SDimitry Andric if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 268e8d8bef9SDimitry Andric return Err; 2695ffd83dbSDimitry Andric 2705ffd83dbSDimitry Andric { 2715ffd83dbSDimitry Andric 2720eae32dcSDimitry Andric // Check that InternedResult matches up with MR->getSymbols(), overriding 2730eae32dcSDimitry Andric // flags if requested. 2745ffd83dbSDimitry Andric // This guards against faulty transformations / compilers / object caches. 2755ffd83dbSDimitry Andric 2765ffd83dbSDimitry Andric // First check that there aren't any missing symbols. 2775ffd83dbSDimitry Andric size_t NumMaterializationSideEffectsOnlySymbols = 0; 2785ffd83dbSDimitry Andric SymbolNameVector ExtraSymbols; 2795ffd83dbSDimitry Andric SymbolNameVector MissingSymbols; 280e8d8bef9SDimitry Andric for (auto &KV : MR->getSymbols()) { 2815ffd83dbSDimitry Andric 2820eae32dcSDimitry Andric auto I = InternedResult.find(KV.first); 2830eae32dcSDimitry Andric 2845ffd83dbSDimitry Andric // If this is a materialization-side-effects only symbol then bump 2855ffd83dbSDimitry Andric // the counter and make sure it's *not* defined, otherwise make 2865ffd83dbSDimitry Andric // sure that it is defined. 2875ffd83dbSDimitry Andric if (KV.second.hasMaterializationSideEffectsOnly()) { 2885ffd83dbSDimitry Andric ++NumMaterializationSideEffectsOnlySymbols; 2890eae32dcSDimitry Andric if (I != InternedResult.end()) 2905ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 2915ffd83dbSDimitry Andric continue; 2920eae32dcSDimitry Andric } else if (I == InternedResult.end()) 2935ffd83dbSDimitry Andric MissingSymbols.push_back(KV.first); 2940eae32dcSDimitry Andric else if (Layer.OverrideObjectFlags) 2950eae32dcSDimitry Andric I->second.setFlags(KV.second); 2965ffd83dbSDimitry Andric } 2975ffd83dbSDimitry Andric 2985ffd83dbSDimitry Andric // If there were missing symbols then report the error. 299e8d8bef9SDimitry Andric if (!MissingSymbols.empty()) 300349cc55cSDimitry Andric return make_error<MissingSymbolDefinitions>( 301349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 302e8d8bef9SDimitry Andric std::move(MissingSymbols)); 3035ffd83dbSDimitry Andric 3045ffd83dbSDimitry Andric // If there are more definitions than expected, add them to the 3055ffd83dbSDimitry Andric // ExtraSymbols vector. 3065ffd83dbSDimitry Andric if (InternedResult.size() > 307e8d8bef9SDimitry Andric MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 3085ffd83dbSDimitry Andric for (auto &KV : InternedResult) 309e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 3105ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 3115ffd83dbSDimitry Andric } 3125ffd83dbSDimitry Andric 3135ffd83dbSDimitry Andric // If there were extra definitions then report the error. 314e8d8bef9SDimitry Andric if (!ExtraSymbols.empty()) 315349cc55cSDimitry Andric return make_error<UnexpectedSymbolDefinitions>( 316349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 317e8d8bef9SDimitry Andric std::move(ExtraSymbols)); 3185ffd83dbSDimitry Andric } 3195ffd83dbSDimitry Andric 320e8d8bef9SDimitry Andric if (auto Err = MR->notifyResolved(InternedResult)) 321e8d8bef9SDimitry Andric return Err; 322e8d8bef9SDimitry Andric 323*0fca6ea1SDimitry Andric notifyLoaded(); 324e8d8bef9SDimitry Andric return Error::success(); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 327349cc55cSDimitry Andric void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 328*0fca6ea1SDimitry Andric if (auto Err = notifyEmitted(std::move(A))) { 3290b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 330e8d8bef9SDimitry Andric MR->failMaterialization(); 3310b57cec5SDimitry Andric return; 3320b57cec5SDimitry Andric } 333*0fca6ea1SDimitry Andric if (auto Err = MR->notifyEmitted(SymbolDepGroups)) { 3348bcb0991SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 335e8d8bef9SDimitry Andric MR->failMaterialization(); 3368bcb0991SDimitry Andric } 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3398bcb0991SDimitry Andric LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 3408bcb0991SDimitry Andric return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 343fe6060f1SDimitry Andric Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 3440b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the 3458bcb0991SDimitry Andric // link graph to build the symbol dependence graph. 346e8d8bef9SDimitry Andric Config.PrePrunePasses.push_back([this](LinkGraph &G) { 347e8d8bef9SDimitry Andric return claimOrExternalizeWeakAndCommonSymbols(G); 348e8d8bef9SDimitry Andric }); 3490b57cec5SDimitry Andric 350*0fca6ea1SDimitry Andric for (auto &P : Plugins) 351*0fca6ea1SDimitry Andric P->modifyPassConfig(*MR, LG, Config); 3520b57cec5SDimitry Andric 353*0fca6ea1SDimitry Andric Config.PreFixupPasses.push_back( 354*0fca6ea1SDimitry Andric [this](LinkGraph &G) { return registerDependencies(G); }); 355*0fca6ea1SDimitry Andric 356*0fca6ea1SDimitry Andric return Error::success(); 357*0fca6ea1SDimitry Andric } 358*0fca6ea1SDimitry Andric 359*0fca6ea1SDimitry Andric void notifyLoaded() { 360*0fca6ea1SDimitry Andric for (auto &P : Plugins) 361*0fca6ea1SDimitry Andric P->notifyLoaded(*MR); 362*0fca6ea1SDimitry Andric } 363*0fca6ea1SDimitry Andric 364*0fca6ea1SDimitry Andric Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) { 365*0fca6ea1SDimitry Andric Error Err = Error::success(); 366*0fca6ea1SDimitry Andric for (auto &P : Plugins) 367*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(*MR)); 368*0fca6ea1SDimitry Andric 369*0fca6ea1SDimitry Andric if (Err) { 370*0fca6ea1SDimitry Andric if (FA) 371*0fca6ea1SDimitry Andric Err = 372*0fca6ea1SDimitry Andric joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA))); 373*0fca6ea1SDimitry Andric return Err; 374*0fca6ea1SDimitry Andric } 375*0fca6ea1SDimitry Andric 376*0fca6ea1SDimitry Andric if (FA) 377*0fca6ea1SDimitry Andric return Layer.recordFinalizedAlloc(*MR, std::move(FA)); 3785ffd83dbSDimitry Andric 3790b57cec5SDimitry Andric return Error::success(); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric private: 383fe6060f1SDimitry Andric // Symbol name dependencies: 384fe6060f1SDimitry Andric // Internal: Defined in this graph. 385fe6060f1SDimitry Andric // External: Defined externally. 386fe6060f1SDimitry Andric struct BlockSymbolDependencies { 3875ffd83dbSDimitry Andric SymbolNameSet Internal, External; 3885ffd83dbSDimitry Andric }; 3895ffd83dbSDimitry Andric 390fe6060f1SDimitry Andric // Lazily populated map of blocks to BlockSymbolDependencies values. 391fe6060f1SDimitry Andric class BlockDependenciesMap { 392fe6060f1SDimitry Andric public: 393fe6060f1SDimitry Andric BlockDependenciesMap(ExecutionSession &ES, 394fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps) 395fe6060f1SDimitry Andric : ES(ES), BlockDeps(std::move(BlockDeps)) {} 396fe6060f1SDimitry Andric 397fe6060f1SDimitry Andric const BlockSymbolDependencies &operator[](const Block &B) { 398fe6060f1SDimitry Andric // Check the cache first. 399fe6060f1SDimitry Andric auto I = BlockTransitiveDepsCache.find(&B); 400fe6060f1SDimitry Andric if (I != BlockTransitiveDepsCache.end()) 401fe6060f1SDimitry Andric return I->second; 402fe6060f1SDimitry Andric 403fe6060f1SDimitry Andric // No value. Populate the cache. 404fe6060f1SDimitry Andric BlockSymbolDependencies BTDCacheVal; 405fe6060f1SDimitry Andric auto BDI = BlockDeps.find(&B); 406fe6060f1SDimitry Andric assert(BDI != BlockDeps.end() && "No block dependencies"); 407fe6060f1SDimitry Andric 408fe6060f1SDimitry Andric for (auto *BDep : BDI->second) { 409fe6060f1SDimitry Andric auto &BID = getBlockImmediateDeps(*BDep); 410fe6060f1SDimitry Andric for (auto &ExternalDep : BID.External) 411fe6060f1SDimitry Andric BTDCacheVal.External.insert(ExternalDep); 412fe6060f1SDimitry Andric for (auto &InternalDep : BID.Internal) 413fe6060f1SDimitry Andric BTDCacheVal.Internal.insert(InternalDep); 414fe6060f1SDimitry Andric } 415fe6060f1SDimitry Andric 416fe6060f1SDimitry Andric return BlockTransitiveDepsCache 417fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BTDCacheVal))) 418fe6060f1SDimitry Andric .first->second; 419fe6060f1SDimitry Andric } 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric SymbolStringPtr &getInternedName(Symbol &Sym) { 422fe6060f1SDimitry Andric auto I = NameCache.find(&Sym); 423fe6060f1SDimitry Andric if (I != NameCache.end()) 424fe6060f1SDimitry Andric return I->second; 425fe6060f1SDimitry Andric 426fe6060f1SDimitry Andric return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName()))) 427fe6060f1SDimitry Andric .first->second; 428fe6060f1SDimitry Andric } 429fe6060f1SDimitry Andric 430fe6060f1SDimitry Andric private: 431fe6060f1SDimitry Andric BlockSymbolDependencies &getBlockImmediateDeps(Block &B) { 432fe6060f1SDimitry Andric // Check the cache first. 433fe6060f1SDimitry Andric auto I = BlockImmediateDepsCache.find(&B); 434fe6060f1SDimitry Andric if (I != BlockImmediateDepsCache.end()) 435fe6060f1SDimitry Andric return I->second; 436fe6060f1SDimitry Andric 437fe6060f1SDimitry Andric BlockSymbolDependencies BIDCacheVal; 438fe6060f1SDimitry Andric for (auto &E : B.edges()) { 439fe6060f1SDimitry Andric auto &Tgt = E.getTarget(); 440fe6060f1SDimitry Andric if (Tgt.getScope() != Scope::Local) { 441*0fca6ea1SDimitry Andric if (Tgt.isExternal()) { 442*0fca6ea1SDimitry Andric if (Tgt.getAddress() || !Tgt.isWeaklyReferenced()) 443fe6060f1SDimitry Andric BIDCacheVal.External.insert(getInternedName(Tgt)); 444*0fca6ea1SDimitry Andric } else 445fe6060f1SDimitry Andric BIDCacheVal.Internal.insert(getInternedName(Tgt)); 446fe6060f1SDimitry Andric } 447fe6060f1SDimitry Andric } 448fe6060f1SDimitry Andric 449fe6060f1SDimitry Andric return BlockImmediateDepsCache 450fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BIDCacheVal))) 451fe6060f1SDimitry Andric .first->second; 452fe6060f1SDimitry Andric } 453fe6060f1SDimitry Andric 454fe6060f1SDimitry Andric ExecutionSession &ES; 455fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 456fe6060f1SDimitry Andric DenseMap<const Symbol *, SymbolStringPtr> NameCache; 457fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache; 458fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache; 459fe6060f1SDimitry Andric }; 4600b57cec5SDimitry Andric 461e8d8bef9SDimitry Andric Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 4620b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4630b57cec5SDimitry Andric 464e8d8bef9SDimitry Andric SymbolFlagsMap NewSymbolsToClaim; 465e8d8bef9SDimitry Andric std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 466e8d8bef9SDimitry Andric 467e8d8bef9SDimitry Andric auto ProcessSymbol = [&](Symbol *Sym) { 468349cc55cSDimitry Andric if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 469349cc55cSDimitry Andric Sym->getScope() != Scope::Local) { 470e8d8bef9SDimitry Andric auto Name = ES.intern(Sym->getName()); 471e8d8bef9SDimitry Andric if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 47206c3fb27SDimitry Andric NewSymbolsToClaim[Name] = 47306c3fb27SDimitry Andric getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 474e8d8bef9SDimitry Andric NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 4750b57cec5SDimitry Andric } 476e8d8bef9SDimitry Andric } 477e8d8bef9SDimitry Andric }; 478e8d8bef9SDimitry Andric 479e8d8bef9SDimitry Andric for (auto *Sym : G.defined_symbols()) 480e8d8bef9SDimitry Andric ProcessSymbol(Sym); 481e8d8bef9SDimitry Andric for (auto *Sym : G.absolute_symbols()) 482e8d8bef9SDimitry Andric ProcessSymbol(Sym); 483e8d8bef9SDimitry Andric 484e8d8bef9SDimitry Andric // Attempt to claim all weak defs that we're not already responsible for. 485*0fca6ea1SDimitry Andric // This may fail if the resource tracker has become defunct, but should 486*0fca6ea1SDimitry Andric // always succeed otherwise. 487*0fca6ea1SDimitry Andric if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim))) 488*0fca6ea1SDimitry Andric return Err; 489e8d8bef9SDimitry Andric 490bdd1243dSDimitry Andric // Walk the list of symbols that we just tried to claim. Symbols that we're 491bdd1243dSDimitry Andric // responsible for are marked live. Symbols that we're not responsible for 492bdd1243dSDimitry Andric // are turned into external references. 493bdd1243dSDimitry Andric for (auto &KV : NameToSym) { 494bdd1243dSDimitry Andric if (MR->getSymbols().count(KV.first)) 495bdd1243dSDimitry Andric KV.second->setLive(true); 496bdd1243dSDimitry Andric else 497e8d8bef9SDimitry Andric G.makeExternal(*KV.second); 498bdd1243dSDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric return Error::success(); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5038bcb0991SDimitry Andric Error markResponsibilitySymbolsLive(LinkGraph &G) const { 5040b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 5058bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 506e8d8bef9SDimitry Andric if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 5078bcb0991SDimitry Andric Sym->setLive(true); 5080b57cec5SDimitry Andric return Error::success(); 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 511*0fca6ea1SDimitry Andric Error registerDependencies(LinkGraph &G) { 512*0fca6ea1SDimitry Andric auto &TargetJD = MR->getTargetJITDylib(); 513*0fca6ea1SDimitry Andric auto &ES = TargetJD.getExecutionSession(); 514fe6060f1SDimitry Andric auto BlockDeps = computeBlockNonLocalDeps(G); 5150b57cec5SDimitry Andric 516*0fca6ea1SDimitry Andric DenseSet<Block *> BlockDepsProcessed; 517*0fca6ea1SDimitry Andric DenseMap<Block *, SymbolDependenceGroup> DepGroupForBlock; 518*0fca6ea1SDimitry Andric 5195ffd83dbSDimitry Andric // Compute dependencies for symbols defined in the JITLink graph. 5208bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) { 5210b57cec5SDimitry Andric 522*0fca6ea1SDimitry Andric // Skip local symbols. 5238bcb0991SDimitry Andric if (Sym->getScope() == Scope::Local) 5240b57cec5SDimitry Andric continue; 5255ffd83dbSDimitry Andric assert(Sym->hasName() && 5265ffd83dbSDimitry Andric "Defined non-local jitlink::Symbol should have a name"); 5270b57cec5SDimitry Andric 528*0fca6ea1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()]; 529*0fca6ea1SDimitry Andric 530*0fca6ea1SDimitry Andric // Skip symbols in blocks that don't depend on anything. 531*0fca6ea1SDimitry Andric if (BDeps.Internal.empty() && BDeps.External.empty()) 5325ffd83dbSDimitry Andric continue; 5335ffd83dbSDimitry Andric 534*0fca6ea1SDimitry Andric SymbolDependenceGroup &SDG = DepGroupForBlock[&Sym->getBlock()]; 535*0fca6ea1SDimitry Andric SDG.Symbols.insert(ES.intern(Sym->getName())); 536*0fca6ea1SDimitry Andric 537*0fca6ea1SDimitry Andric if (!BlockDepsProcessed.count(&Sym->getBlock())) { 538*0fca6ea1SDimitry Andric BlockDepsProcessed.insert(&Sym->getBlock()); 539*0fca6ea1SDimitry Andric 540*0fca6ea1SDimitry Andric if (!BDeps.Internal.empty()) 541*0fca6ea1SDimitry Andric SDG.Dependencies[&TargetJD] = BDeps.Internal; 542*0fca6ea1SDimitry Andric for (auto &Dep : BDeps.External) { 543*0fca6ea1SDimitry Andric auto DepSrcItr = SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep)); 544*0fca6ea1SDimitry Andric if (DepSrcItr != SymbolSourceJDs.end()) 545*0fca6ea1SDimitry Andric SDG.Dependencies[DepSrcItr->second].insert(Dep); 546*0fca6ea1SDimitry Andric } 547*0fca6ea1SDimitry Andric } 5485ffd83dbSDimitry Andric } 5495ffd83dbSDimitry Andric 550*0fca6ea1SDimitry Andric SymbolDependenceGroup SynthSDG; 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric for (auto &P : Plugins) { 553fe6060f1SDimitry Andric auto SynthDeps = P->getSyntheticSymbolDependencies(*MR); 554fe6060f1SDimitry Andric if (SynthDeps.empty()) 5555ffd83dbSDimitry Andric continue; 5565ffd83dbSDimitry Andric 557fe6060f1SDimitry Andric DenseSet<Block *> BlockVisited; 558*0fca6ea1SDimitry Andric for (auto &[Name, DepSyms] : SynthDeps) { 559*0fca6ea1SDimitry Andric SynthSDG.Symbols.insert(Name); 560*0fca6ea1SDimitry Andric for (auto *Sym : DepSyms) { 561fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) { 562fe6060f1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()]; 563fe6060f1SDimitry Andric for (auto &S : BDeps.Internal) 564*0fca6ea1SDimitry Andric SynthSDG.Dependencies[&TargetJD].insert(S); 565*0fca6ea1SDimitry Andric for (auto &S : BDeps.External) { 566*0fca6ea1SDimitry Andric auto DepSrcItr = 567*0fca6ea1SDimitry Andric SymbolSourceJDs.find(NonOwningSymbolStringPtr(S)); 568*0fca6ea1SDimitry Andric if (DepSrcItr != SymbolSourceJDs.end()) 569*0fca6ea1SDimitry Andric SynthSDG.Dependencies[DepSrcItr->second].insert(S); 570*0fca6ea1SDimitry Andric } 571fe6060f1SDimitry Andric } else { 572*0fca6ea1SDimitry Andric auto SymName = ES.intern(Sym->getName()); 573*0fca6ea1SDimitry Andric if (Sym->isExternal()) { 574*0fca6ea1SDimitry Andric assert(SymbolSourceJDs.count(NonOwningSymbolStringPtr(SymName)) && 575*0fca6ea1SDimitry Andric "External symbol source entry missing"); 576*0fca6ea1SDimitry Andric SynthSDG 577*0fca6ea1SDimitry Andric .Dependencies[SymbolSourceJDs[NonOwningSymbolStringPtr( 578*0fca6ea1SDimitry Andric SymName)]] 579*0fca6ea1SDimitry Andric .insert(SymName); 580*0fca6ea1SDimitry Andric } else 581*0fca6ea1SDimitry Andric SynthSDG.Dependencies[&TargetJD].insert(SymName); 582fe6060f1SDimitry Andric } 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 587*0fca6ea1SDimitry Andric // Transfer SDGs to SymbolDepGroups. 588*0fca6ea1SDimitry Andric DepGroupForBlock.reserve(DepGroupForBlock.size() + 1); 589*0fca6ea1SDimitry Andric for (auto &[B, SDG] : DepGroupForBlock) { 590*0fca6ea1SDimitry Andric assert(!SDG.Symbols.empty() && "SymbolDependenceGroup covers no symbols"); 591*0fca6ea1SDimitry Andric if (!SDG.Dependencies.empty()) 592*0fca6ea1SDimitry Andric SymbolDepGroups.push_back(std::move(SDG)); 593*0fca6ea1SDimitry Andric } 594*0fca6ea1SDimitry Andric if (!SynthSDG.Symbols.empty() && !SynthSDG.Dependencies.empty()) 595*0fca6ea1SDimitry Andric SymbolDepGroups.push_back(std::move(SynthSDG)); 596*0fca6ea1SDimitry Andric 5970b57cec5SDimitry Andric return Error::success(); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 600fe6060f1SDimitry Andric BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) { 601fe6060f1SDimitry Andric // First calculate the reachable-via-non-local-symbol blocks for each block. 602fe6060f1SDimitry Andric struct BlockInfo { 603fe6060f1SDimitry Andric DenseSet<Block *> Dependencies; 604fe6060f1SDimitry Andric DenseSet<Block *> Dependants; 605fe6060f1SDimitry Andric bool DependenciesChanged = true; 6060b57cec5SDimitry Andric }; 607fe6060f1SDimitry Andric DenseMap<Block *, BlockInfo> BlockInfos; 608fe6060f1SDimitry Andric SmallVector<Block *> WorkList; 6090b57cec5SDimitry Andric 610fe6060f1SDimitry Andric // Pre-allocate map entries. This prevents any iterator/reference 611fe6060f1SDimitry Andric // invalidation in the next loop. 612fe6060f1SDimitry Andric for (auto *B : G.blocks()) 613fe6060f1SDimitry Andric (void)BlockInfos[B]; 614fe6060f1SDimitry Andric 615fe6060f1SDimitry Andric // Build initial worklist, record block dependencies/dependants and 616fe6060f1SDimitry Andric // non-local symbol dependencies. 617fe6060f1SDimitry Andric for (auto *B : G.blocks()) { 618fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 619fe6060f1SDimitry Andric for (auto &E : B->edges()) { 620bdd1243dSDimitry Andric if (E.getTarget().getScope() == Scope::Local && 621bdd1243dSDimitry Andric !E.getTarget().isAbsolute()) { 622fe6060f1SDimitry Andric auto &TgtB = E.getTarget().getBlock(); 623fe6060f1SDimitry Andric if (&TgtB != B) { 624fe6060f1SDimitry Andric BI.Dependencies.insert(&TgtB); 625fe6060f1SDimitry Andric BlockInfos[&TgtB].Dependants.insert(B); 626fe6060f1SDimitry Andric } 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric } 629*0fca6ea1SDimitry Andric } 6300b57cec5SDimitry Andric 631*0fca6ea1SDimitry Andric // Add blocks with both dependants and dependencies to the worklist to 632*0fca6ea1SDimitry Andric // propagate dependencies to dependants. 633*0fca6ea1SDimitry Andric for (auto &[B, BI] : BlockInfos) { 634fe6060f1SDimitry Andric if (!BI.Dependants.empty() && !BI.Dependencies.empty()) 635fe6060f1SDimitry Andric WorkList.push_back(B); 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 638fe6060f1SDimitry Andric // Propagate block-level dependencies through the block-dependence graph. 639fe6060f1SDimitry Andric while (!WorkList.empty()) { 640349cc55cSDimitry Andric auto *B = WorkList.pop_back_val(); 6410b57cec5SDimitry Andric 642fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 643fe6060f1SDimitry Andric assert(BI.DependenciesChanged && 644fe6060f1SDimitry Andric "Block in worklist has unchanged dependencies"); 645fe6060f1SDimitry Andric BI.DependenciesChanged = false; 646fe6060f1SDimitry Andric for (auto *Dependant : BI.Dependants) { 647fe6060f1SDimitry Andric auto &DependantBI = BlockInfos[Dependant]; 648fe6060f1SDimitry Andric for (auto *Dependency : BI.Dependencies) { 649fe6060f1SDimitry Andric if (Dependant != Dependency && 650fe6060f1SDimitry Andric DependantBI.Dependencies.insert(Dependency).second) 651fe6060f1SDimitry Andric if (!DependantBI.DependenciesChanged) { 652fe6060f1SDimitry Andric DependantBI.DependenciesChanged = true; 653fe6060f1SDimitry Andric WorkList.push_back(Dependant); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric } 6565ffd83dbSDimitry Andric } 6575ffd83dbSDimitry Andric } 6585ffd83dbSDimitry Andric 659fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 660fe6060f1SDimitry Andric for (auto &KV : BlockInfos) 661fe6060f1SDimitry Andric BlockDeps[KV.first] = std::move(KV.second.Dependencies); 662fe6060f1SDimitry Andric 663fe6060f1SDimitry Andric return BlockDependenciesMap(Layer.getExecutionSession(), 664fe6060f1SDimitry Andric std::move(BlockDeps)); 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric ObjectLinkingLayer &Layer; 668*0fca6ea1SDimitry Andric std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins; 669e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR; 6700b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer; 671*0fca6ea1SDimitry Andric DenseMap<Block *, SymbolNameSet> ExternalBlockDeps; 672*0fca6ea1SDimitry Andric DenseMap<Block *, SymbolNameSet> InternalBlockDeps; 673*0fca6ea1SDimitry Andric DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs; 674*0fca6ea1SDimitry Andric std::vector<SymbolDependenceGroup> SymbolDepGroups; 6750b57cec5SDimitry Andric }; 6760b57cec5SDimitry Andric 67781ad6265SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() = default; 6780b57cec5SDimitry Andric 679fe6060f1SDimitry Andric char ObjectLinkingLayer::ID; 680fe6060f1SDimitry Andric 681fe6060f1SDimitry Andric using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 682fe6060f1SDimitry Andric 683fe6060f1SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 684fe6060f1SDimitry Andric : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 685fe6060f1SDimitry Andric ES.registerResourceManager(*this); 686fe6060f1SDimitry Andric } 687fe6060f1SDimitry Andric 688e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 689e8d8bef9SDimitry Andric JITLinkMemoryManager &MemMgr) 690fe6060f1SDimitry Andric : BaseT(ES), MemMgr(MemMgr) { 691e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric 694e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer( 695e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 696fe6060f1SDimitry Andric : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 697e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 698e8d8bef9SDimitry Andric } 699e8d8bef9SDimitry Andric 700e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() { 701e8d8bef9SDimitry Andric assert(Allocs.empty() && "Layer destroyed with resources still attached"); 702e8d8bef9SDimitry Andric getExecutionSession().deregisterResourceManager(*this); 703e8d8bef9SDimitry Andric } 704e8d8bef9SDimitry Andric 705fe6060f1SDimitry Andric Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 706fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G) { 707fe6060f1SDimitry Andric auto &JD = RT->getJITDylib(); 708fe6060f1SDimitry Andric return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 709fe6060f1SDimitry Andric std::move(RT)); 710fe6060f1SDimitry Andric } 711fe6060f1SDimitry Andric 712e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 7130b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 7140b57cec5SDimitry Andric assert(O && "Object must not be null"); 715fe6060f1SDimitry Andric MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 716fe6060f1SDimitry Andric 717e8d8bef9SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 718e8d8bef9SDimitry Andric *this, std::move(R), std::move(O)); 719fe6060f1SDimitry Andric if (auto G = createLinkGraphFromObject(ObjBuffer)) { 720fe6060f1SDimitry Andric Ctx->notifyMaterializing(**G); 721e8d8bef9SDimitry Andric link(std::move(*G), std::move(Ctx)); 722fe6060f1SDimitry Andric } else { 723e8d8bef9SDimitry Andric Ctx->notifyFailed(G.takeError()); 724e8d8bef9SDimitry Andric } 725fe6060f1SDimitry Andric } 726e8d8bef9SDimitry Andric 727e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 728e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G) { 729fe6060f1SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 730fe6060f1SDimitry Andric *this, std::move(R), nullptr); 731fe6060f1SDimitry Andric Ctx->notifyMaterializing(*G); 732fe6060f1SDimitry Andric link(std::move(G), std::move(Ctx)); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 735*0fca6ea1SDimitry Andric Error ObjectLinkingLayer::recordFinalizedAlloc( 736*0fca6ea1SDimitry Andric MaterializationResponsibility &MR, FinalizedAlloc FA) { 737*0fca6ea1SDimitry Andric auto Err = MR.withResourceKeyDo( 738*0fca6ea1SDimitry Andric [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric if (Err) 741*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA))); 742*0fca6ea1SDimitry Andric 7430b57cec5SDimitry Andric return Err; 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric 746bdd1243dSDimitry Andric Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) { 7470b57cec5SDimitry Andric 748349cc55cSDimitry Andric { 7490b57cec5SDimitry Andric Error Err = Error::success(); 7500b57cec5SDimitry Andric for (auto &P : Plugins) 751bdd1243dSDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 752349cc55cSDimitry Andric if (Err) 753349cc55cSDimitry Andric return Err; 754349cc55cSDimitry Andric } 7550b57cec5SDimitry Andric 756349cc55cSDimitry Andric std::vector<FinalizedAlloc> AllocsToRemove; 757e8d8bef9SDimitry Andric getExecutionSession().runSessionLocked([&] { 758e8d8bef9SDimitry Andric auto I = Allocs.find(K); 759e8d8bef9SDimitry Andric if (I != Allocs.end()) { 760e8d8bef9SDimitry Andric std::swap(AllocsToRemove, I->second); 761e8d8bef9SDimitry Andric Allocs.erase(I); 7620b57cec5SDimitry Andric } 763e8d8bef9SDimitry Andric }); 7640b57cec5SDimitry Andric 765349cc55cSDimitry Andric if (AllocsToRemove.empty()) 766349cc55cSDimitry Andric return Error::success(); 7670b57cec5SDimitry Andric 768349cc55cSDimitry Andric return MemMgr.deallocate(std::move(AllocsToRemove)); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 771bdd1243dSDimitry Andric void ObjectLinkingLayer::handleTransferResources(JITDylib &JD, 772bdd1243dSDimitry Andric ResourceKey DstKey, 773e8d8bef9SDimitry Andric ResourceKey SrcKey) { 774e8d8bef9SDimitry Andric auto I = Allocs.find(SrcKey); 775e8d8bef9SDimitry Andric if (I != Allocs.end()) { 776e8d8bef9SDimitry Andric auto &SrcAllocs = I->second; 777e8d8bef9SDimitry Andric auto &DstAllocs = Allocs[DstKey]; 778e8d8bef9SDimitry Andric DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 779e8d8bef9SDimitry Andric for (auto &Alloc : SrcAllocs) 780e8d8bef9SDimitry Andric DstAllocs.push_back(std::move(Alloc)); 781e8d8bef9SDimitry Andric 782e8d8bef9SDimitry Andric // Erase SrcKey entry using value rather than iterator I: I may have been 783e8d8bef9SDimitry Andric // invalidated when we looked up DstKey. 784e8d8bef9SDimitry Andric Allocs.erase(SrcKey); 785e8d8bef9SDimitry Andric } 786e8d8bef9SDimitry Andric 787e8d8bef9SDimitry Andric for (auto &P : Plugins) 788bdd1243dSDimitry Andric P->notifyTransferringResources(JD, DstKey, SrcKey); 789e8d8bef9SDimitry Andric } 790e8d8bef9SDimitry Andric 7910b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 792e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 793e8d8bef9SDimitry Andric : ES(ES), Registrar(std::move(Registrar)) {} 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig( 796fe6060f1SDimitry Andric MaterializationResponsibility &MR, LinkGraph &G, 7970b57cec5SDimitry Andric PassConfiguration &PassConfig) { 7980b57cec5SDimitry Andric 7995ffd83dbSDimitry Andric PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 80004eeddc0SDimitry Andric G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) { 8015ffd83dbSDimitry Andric if (Addr) { 8025ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 8035ffd83dbSDimitry Andric assert(!InProcessLinks.count(&MR) && 8045ffd83dbSDimitry Andric "Link for MR already being tracked?"); 8058bcb0991SDimitry Andric InProcessLinks[&MR] = {Addr, Size}; 8065ffd83dbSDimitry Andric } 8070b57cec5SDimitry Andric })); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted( 8110b57cec5SDimitry Andric MaterializationResponsibility &MR) { 812e8d8bef9SDimitry Andric 81304eeddc0SDimitry Andric ExecutorAddrRange EmittedRange; 814e8d8bef9SDimitry Andric { 8155ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 8160b57cec5SDimitry Andric 8178bcb0991SDimitry Andric auto EHFrameRangeItr = InProcessLinks.find(&MR); 8188bcb0991SDimitry Andric if (EHFrameRangeItr == InProcessLinks.end()) 8190b57cec5SDimitry Andric return Error::success(); 8200b57cec5SDimitry Andric 821e8d8bef9SDimitry Andric EmittedRange = EHFrameRangeItr->second; 82204eeddc0SDimitry Andric assert(EmittedRange.Start && "eh-frame addr to register can not be null"); 8238bcb0991SDimitry Andric InProcessLinks.erase(EHFrameRangeItr); 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 826e8d8bef9SDimitry Andric if (auto Err = MR.withResourceKeyDo( 827e8d8bef9SDimitry Andric [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 828e8d8bef9SDimitry Andric return Err; 8295ffd83dbSDimitry Andric 83004eeddc0SDimitry Andric return Registrar->registerEHFrames(EmittedRange); 831e8d8bef9SDimitry Andric } 832e8d8bef9SDimitry Andric 833e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyFailed( 834e8d8bef9SDimitry Andric MaterializationResponsibility &MR) { 835e8d8bef9SDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 836e8d8bef9SDimitry Andric InProcessLinks.erase(&MR); 8370b57cec5SDimitry Andric return Error::success(); 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric 840bdd1243dSDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD, 841bdd1243dSDimitry Andric ResourceKey K) { 84204eeddc0SDimitry Andric std::vector<ExecutorAddrRange> RangesToRemove; 8430b57cec5SDimitry Andric 844e8d8bef9SDimitry Andric ES.runSessionLocked([&] { 845e8d8bef9SDimitry Andric auto I = EHFrameRanges.find(K); 846e8d8bef9SDimitry Andric if (I != EHFrameRanges.end()) { 847e8d8bef9SDimitry Andric RangesToRemove = std::move(I->second); 848e8d8bef9SDimitry Andric EHFrameRanges.erase(I); 849e8d8bef9SDimitry Andric } 850e8d8bef9SDimitry Andric }); 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric Error Err = Error::success(); 853e8d8bef9SDimitry Andric while (!RangesToRemove.empty()) { 854e8d8bef9SDimitry Andric auto RangeToRemove = RangesToRemove.back(); 855e8d8bef9SDimitry Andric RangesToRemove.pop_back(); 85604eeddc0SDimitry Andric assert(RangeToRemove.Start && "Untracked eh-frame range must not be null"); 85704eeddc0SDimitry Andric Err = joinErrors(std::move(Err), 85804eeddc0SDimitry Andric Registrar->deregisterEHFrames(RangeToRemove)); 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric return Err; 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 864e8d8bef9SDimitry Andric void EHFrameRegistrationPlugin::notifyTransferringResources( 865bdd1243dSDimitry Andric JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) { 866e8d8bef9SDimitry Andric auto SI = EHFrameRanges.find(SrcKey); 867fe6060f1SDimitry Andric if (SI == EHFrameRanges.end()) 868fe6060f1SDimitry Andric return; 869fe6060f1SDimitry Andric 870fe6060f1SDimitry Andric auto DI = EHFrameRanges.find(DstKey); 871fe6060f1SDimitry Andric if (DI != EHFrameRanges.end()) { 872e8d8bef9SDimitry Andric auto &SrcRanges = SI->second; 873fe6060f1SDimitry Andric auto &DstRanges = DI->second; 874e8d8bef9SDimitry Andric DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 875e8d8bef9SDimitry Andric for (auto &SrcRange : SrcRanges) 876e8d8bef9SDimitry Andric DstRanges.push_back(std::move(SrcRange)); 877e8d8bef9SDimitry Andric EHFrameRanges.erase(SI); 878fe6060f1SDimitry Andric } else { 879fe6060f1SDimitry Andric // We need to move SrcKey's ranges over without invalidating the SI 880fe6060f1SDimitry Andric // iterator. 881fe6060f1SDimitry Andric auto Tmp = std::move(SI->second); 882fe6060f1SDimitry Andric EHFrameRanges.erase(SI); 883fe6060f1SDimitry Andric EHFrameRanges[DstKey] = std::move(Tmp); 884e8d8bef9SDimitry Andric } 885e8d8bef9SDimitry Andric } 886e8d8bef9SDimitry Andric 8870b57cec5SDimitry Andric } // End namespace orc. 8880b57cec5SDimitry Andric } // End namespace llvm. 889