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" 13bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 1406c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 15fe6060f1SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 16fe6060f1SDimitry Andric #include <string> 170b57cec5SDimitry Andric #include <vector> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #define DEBUG_TYPE "orc" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric using namespace llvm; 220b57cec5SDimitry Andric using namespace llvm::jitlink; 230b57cec5SDimitry Andric using namespace llvm::orc; 240b57cec5SDimitry Andric 25fe6060f1SDimitry Andric namespace { 26fe6060f1SDimitry Andric 2706c3fb27SDimitry Andric bool hasInitializerSection(jitlink::LinkGraph &G) { 2806c3fb27SDimitry Andric bool IsMachO = G.getTargetTriple().isOSBinFormatMachO(); 2906c3fb27SDimitry Andric bool IsElf = G.getTargetTriple().isOSBinFormatELF(); 3006c3fb27SDimitry Andric if (!IsMachO && !IsElf) 3106c3fb27SDimitry Andric return false; 3206c3fb27SDimitry Andric 3306c3fb27SDimitry Andric for (auto &Sec : G.sections()) { 3406c3fb27SDimitry Andric if (IsMachO && isMachOInitializerSection(Sec.getName())) 3506c3fb27SDimitry Andric return true; 3606c3fb27SDimitry Andric if (IsElf && isELFInitializerSection(Sec.getName())) 3706c3fb27SDimitry Andric return true; 3806c3fb27SDimitry Andric } 3906c3fb27SDimitry Andric 4006c3fb27SDimitry Andric return false; 4106c3fb27SDimitry Andric } 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) { 4406c3fb27SDimitry Andric switch (TT.getArch()) { 4506c3fb27SDimitry Andric case Triple::arm: 4606c3fb27SDimitry Andric case Triple::armeb: 4706c3fb27SDimitry Andric case Triple::thumb: 4806c3fb27SDimitry Andric case Triple::thumbeb: 495f757f3fSDimitry Andric if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) { 5006c3fb27SDimitry Andric // Set LSB to indicate thumb target 5106c3fb27SDimitry Andric assert(Sym.isCallable() && "Only callable symbols can have thumb flag"); 5206c3fb27SDimitry Andric assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear"); 5306c3fb27SDimitry Andric return Sym.getAddress() + 0x01; 5406c3fb27SDimitry Andric } 5506c3fb27SDimitry Andric return Sym.getAddress(); 5606c3fb27SDimitry Andric default: 5706c3fb27SDimitry Andric return Sym.getAddress(); 5806c3fb27SDimitry Andric } 5906c3fb27SDimitry Andric } 6006c3fb27SDimitry Andric 6106c3fb27SDimitry Andric JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) { 6206c3fb27SDimitry Andric JITSymbolFlags Flags; 6306c3fb27SDimitry Andric 6406c3fb27SDimitry Andric if (Sym.getLinkage() == Linkage::Weak) 6506c3fb27SDimitry Andric Flags |= JITSymbolFlags::Weak; 6606c3fb27SDimitry Andric 6706c3fb27SDimitry Andric if (Sym.getScope() == Scope::Default) 6806c3fb27SDimitry Andric Flags |= JITSymbolFlags::Exported; 6906c3fb27SDimitry Andric 7006c3fb27SDimitry Andric if (Sym.isCallable()) 7106c3fb27SDimitry Andric Flags |= JITSymbolFlags::Callable; 7206c3fb27SDimitry Andric 7306c3fb27SDimitry Andric return Flags; 7406c3fb27SDimitry Andric } 7506c3fb27SDimitry Andric 76fe6060f1SDimitry Andric class LinkGraphMaterializationUnit : public MaterializationUnit { 77fe6060f1SDimitry Andric public: 78fe6060f1SDimitry Andric static std::unique_ptr<LinkGraphMaterializationUnit> 79fe6060f1SDimitry Andric Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 80fe6060f1SDimitry Andric auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 81fe6060f1SDimitry Andric return std::unique_ptr<LinkGraphMaterializationUnit>( 82fe6060f1SDimitry Andric new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 83fe6060f1SDimitry Andric std::move(LGI))); 84fe6060f1SDimitry Andric } 85fe6060f1SDimitry Andric 86fe6060f1SDimitry Andric StringRef getName() const override { return G->getName(); } 87fe6060f1SDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 88fe6060f1SDimitry Andric ObjLinkingLayer.emit(std::move(MR), std::move(G)); 89fe6060f1SDimitry Andric } 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric private: 920eae32dcSDimitry Andric static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 93fe6060f1SDimitry Andric 940eae32dcSDimitry Andric Interface LGI; 95fe6060f1SDimitry Andric 96*1db9f3b2SDimitry Andric auto AddSymbol = [&](Symbol *Sym) { 97fe6060f1SDimitry Andric // Skip local symbols. 98fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) 99*1db9f3b2SDimitry Andric return; 100fe6060f1SDimitry Andric assert(Sym->hasName() && "Anonymous non-local symbol?"); 101fe6060f1SDimitry Andric 10206c3fb27SDimitry Andric LGI.SymbolFlags[ES.intern(Sym->getName())] = 10306c3fb27SDimitry Andric getJITSymbolFlagsForSymbol(*Sym); 104*1db9f3b2SDimitry Andric }; 105*1db9f3b2SDimitry Andric 106*1db9f3b2SDimitry Andric for (auto *Sym : G.defined_symbols()) 107*1db9f3b2SDimitry Andric AddSymbol(Sym); 108*1db9f3b2SDimitry Andric for (auto *Sym : G.absolute_symbols()) 109*1db9f3b2SDimitry Andric AddSymbol(Sym); 110fe6060f1SDimitry Andric 111bdd1243dSDimitry Andric if (hasInitializerSection(G)) 112fe6060f1SDimitry Andric LGI.InitSymbol = makeInitSymbol(ES, G); 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric return LGI; 115fe6060f1SDimitry Andric } 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 118fe6060f1SDimitry Andric std::string InitSymString; 119fe6060f1SDimitry Andric raw_string_ostream(InitSymString) 120fe6060f1SDimitry Andric << "$." << G.getName() << ".__inits" << Counter++; 121fe6060f1SDimitry Andric return ES.intern(InitSymString); 122fe6060f1SDimitry Andric } 123fe6060f1SDimitry Andric 124fe6060f1SDimitry Andric LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 1250eae32dcSDimitry Andric std::unique_ptr<LinkGraph> G, Interface LGI) 1260eae32dcSDimitry Andric : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), 1270eae32dcSDimitry Andric G(std::move(G)) {} 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 130fe6060f1SDimitry Andric for (auto *Sym : G->defined_symbols()) 131fe6060f1SDimitry Andric if (Sym->getName() == *Name) { 132fe6060f1SDimitry Andric assert(Sym->getLinkage() == Linkage::Weak && 133fe6060f1SDimitry Andric "Discarding non-weak definition"); 134fe6060f1SDimitry Andric G->makeExternal(*Sym); 135fe6060f1SDimitry Andric break; 136fe6060f1SDimitry Andric } 137fe6060f1SDimitry Andric } 138fe6060f1SDimitry Andric 139fe6060f1SDimitry Andric ObjectLinkingLayer &ObjLinkingLayer; 140fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G; 141fe6060f1SDimitry Andric static std::atomic<uint64_t> Counter; 142fe6060f1SDimitry Andric }; 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 145fe6060f1SDimitry Andric 146fe6060f1SDimitry Andric } // end anonymous namespace 147fe6060f1SDimitry Andric 1480b57cec5SDimitry Andric namespace llvm { 1490b57cec5SDimitry Andric namespace orc { 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 1520b57cec5SDimitry Andric public: 153e8d8bef9SDimitry Andric ObjectLinkingLayerJITLinkContext( 154e8d8bef9SDimitry Andric ObjectLinkingLayer &Layer, 155e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR, 1560b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer) 157e8d8bef9SDimitry Andric : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 158e8d8bef9SDimitry Andric MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 1590b57cec5SDimitry Andric 1608bcb0991SDimitry Andric ~ObjectLinkingLayerJITLinkContext() { 1618bcb0991SDimitry Andric // If there is an object buffer return function then use it to 1628bcb0991SDimitry Andric // return ownership of the buffer. 163e8d8bef9SDimitry Andric if (Layer.ReturnObjectBuffer && ObjBuffer) 1648bcb0991SDimitry Andric Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 1658bcb0991SDimitry Andric } 1668bcb0991SDimitry Andric 167e8d8bef9SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 1680b57cec5SDimitry Andric 169fe6060f1SDimitry Andric void notifyMaterializing(LinkGraph &G) { 170fe6060f1SDimitry Andric for (auto &P : Layer.Plugins) 171fe6060f1SDimitry Andric P->notifyMaterializing(*MR, G, *this, 172fe6060f1SDimitry Andric ObjBuffer ? ObjBuffer->getMemBufferRef() 173fe6060f1SDimitry Andric : MemoryBufferRef()); 174fe6060f1SDimitry Andric } 175fe6060f1SDimitry Andric 1760b57cec5SDimitry Andric void notifyFailed(Error Err) override { 177e8d8bef9SDimitry Andric for (auto &P : Layer.Plugins) 178e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 1790b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 180e8d8bef9SDimitry Andric MR->failMaterialization(); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 183480093f4SDimitry Andric void lookup(const LookupMap &Symbols, 1848bcb0991SDimitry Andric std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 1850b57cec5SDimitry Andric 1865ffd83dbSDimitry Andric JITDylibSearchOrder LinkOrder; 187e8d8bef9SDimitry Andric MR->getTargetJITDylib().withLinkOrderDo( 1885ffd83dbSDimitry Andric [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 1910b57cec5SDimitry Andric 192480093f4SDimitry Andric SymbolLookupSet LookupSet; 193480093f4SDimitry Andric for (auto &KV : Symbols) { 194480093f4SDimitry Andric orc::SymbolLookupFlags LookupFlags; 195480093f4SDimitry Andric switch (KV.second) { 196480093f4SDimitry Andric case jitlink::SymbolLookupFlags::RequiredSymbol: 197480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 198480093f4SDimitry Andric break; 199480093f4SDimitry Andric case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 200480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 201480093f4SDimitry Andric break; 202480093f4SDimitry Andric } 203480093f4SDimitry Andric LookupSet.add(ES.intern(KV.first), LookupFlags); 204480093f4SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker. 207e8d8bef9SDimitry Andric auto OnResolve = [LookupContinuation = 208e8d8bef9SDimitry Andric std::move(LC)](Expected<SymbolMap> Result) mutable { 2090b57cec5SDimitry Andric if (!Result) 2108bcb0991SDimitry Andric LookupContinuation->run(Result.takeError()); 2110b57cec5SDimitry Andric else { 2120b57cec5SDimitry Andric AsyncLookupResult LR; 2130b57cec5SDimitry Andric for (auto &KV : *Result) 2140b57cec5SDimitry Andric LR[*KV.first] = KV.second; 2158bcb0991SDimitry Andric LookupContinuation->run(std::move(LR)); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric }; 2180b57cec5SDimitry Andric 2195ffd83dbSDimitry Andric for (auto &KV : InternalNamedSymbolDeps) { 2205ffd83dbSDimitry Andric SymbolDependenceMap InternalDeps; 221e8d8bef9SDimitry Andric InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 222e8d8bef9SDimitry Andric MR->addDependencies(KV.first, InternalDeps); 2235ffd83dbSDimitry Andric } 2245ffd83dbSDimitry Andric 2255ffd83dbSDimitry Andric ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 226480093f4SDimitry Andric SymbolState::Resolved, std::move(OnResolve), 227480093f4SDimitry Andric [this](const SymbolDependenceMap &Deps) { 2280b57cec5SDimitry Andric registerDependencies(Deps); 2290b57cec5SDimitry Andric }); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 232e8d8bef9SDimitry Andric Error notifyResolved(LinkGraph &G) override { 2330b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim; 2360b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric SymbolMap InternedResult; 2398bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 2408bcb0991SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2418bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 24206c3fb27SDimitry Andric auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 24306c3fb27SDimitry Andric auto Flags = getJITSymbolFlagsForSymbol(*Sym); 24406c3fb27SDimitry Andric InternedResult[InternedName] = {Ptr, Flags}; 245e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2460b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2470b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2480b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2528bcb0991SDimitry Andric for (auto *Sym : G.absolute_symbols()) 25381ad6265SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2548bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 25506c3fb27SDimitry Andric auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 25606c3fb27SDimitry Andric auto Flags = getJITSymbolFlagsForSymbol(*Sym); 25706c3fb27SDimitry Andric InternedResult[InternedName] = {Ptr, Flags}; 258e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2590b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2600b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2610b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty()) 266e8d8bef9SDimitry Andric if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 267e8d8bef9SDimitry Andric return Err; 2685ffd83dbSDimitry Andric 2695ffd83dbSDimitry Andric { 2705ffd83dbSDimitry Andric 2710eae32dcSDimitry Andric // Check that InternedResult matches up with MR->getSymbols(), overriding 2720eae32dcSDimitry Andric // flags if requested. 2735ffd83dbSDimitry Andric // This guards against faulty transformations / compilers / object caches. 2745ffd83dbSDimitry Andric 2755ffd83dbSDimitry Andric // First check that there aren't any missing symbols. 2765ffd83dbSDimitry Andric size_t NumMaterializationSideEffectsOnlySymbols = 0; 2775ffd83dbSDimitry Andric SymbolNameVector ExtraSymbols; 2785ffd83dbSDimitry Andric SymbolNameVector MissingSymbols; 279e8d8bef9SDimitry Andric for (auto &KV : MR->getSymbols()) { 2805ffd83dbSDimitry Andric 2810eae32dcSDimitry Andric auto I = InternedResult.find(KV.first); 2820eae32dcSDimitry Andric 2835ffd83dbSDimitry Andric // If this is a materialization-side-effects only symbol then bump 2845ffd83dbSDimitry Andric // the counter and make sure it's *not* defined, otherwise make 2855ffd83dbSDimitry Andric // sure that it is defined. 2865ffd83dbSDimitry Andric if (KV.second.hasMaterializationSideEffectsOnly()) { 2875ffd83dbSDimitry Andric ++NumMaterializationSideEffectsOnlySymbols; 2880eae32dcSDimitry Andric if (I != InternedResult.end()) 2895ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 2905ffd83dbSDimitry Andric continue; 2910eae32dcSDimitry Andric } else if (I == InternedResult.end()) 2925ffd83dbSDimitry Andric MissingSymbols.push_back(KV.first); 2930eae32dcSDimitry Andric else if (Layer.OverrideObjectFlags) 2940eae32dcSDimitry Andric I->second.setFlags(KV.second); 2955ffd83dbSDimitry Andric } 2965ffd83dbSDimitry Andric 2975ffd83dbSDimitry Andric // If there were missing symbols then report the error. 298e8d8bef9SDimitry Andric if (!MissingSymbols.empty()) 299349cc55cSDimitry Andric return make_error<MissingSymbolDefinitions>( 300349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 301e8d8bef9SDimitry Andric std::move(MissingSymbols)); 3025ffd83dbSDimitry Andric 3035ffd83dbSDimitry Andric // If there are more definitions than expected, add them to the 3045ffd83dbSDimitry Andric // ExtraSymbols vector. 3055ffd83dbSDimitry Andric if (InternedResult.size() > 306e8d8bef9SDimitry Andric MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 3075ffd83dbSDimitry Andric for (auto &KV : InternedResult) 308e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 3095ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 3105ffd83dbSDimitry Andric } 3115ffd83dbSDimitry Andric 3125ffd83dbSDimitry Andric // If there were extra definitions then report the error. 313e8d8bef9SDimitry Andric if (!ExtraSymbols.empty()) 314349cc55cSDimitry Andric return make_error<UnexpectedSymbolDefinitions>( 315349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 316e8d8bef9SDimitry Andric std::move(ExtraSymbols)); 3175ffd83dbSDimitry Andric } 3185ffd83dbSDimitry Andric 319e8d8bef9SDimitry Andric if (auto Err = MR->notifyResolved(InternedResult)) 320e8d8bef9SDimitry Andric return Err; 321e8d8bef9SDimitry Andric 322e8d8bef9SDimitry Andric Layer.notifyLoaded(*MR); 323e8d8bef9SDimitry Andric return Error::success(); 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 326349cc55cSDimitry Andric void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 327e8d8bef9SDimitry Andric if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 3280b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 329e8d8bef9SDimitry Andric MR->failMaterialization(); 3300b57cec5SDimitry Andric return; 3310b57cec5SDimitry Andric } 332e8d8bef9SDimitry Andric if (auto Err = MR->notifyEmitted()) { 3338bcb0991SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 334e8d8bef9SDimitry Andric MR->failMaterialization(); 3358bcb0991SDimitry Andric } 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 3388bcb0991SDimitry Andric LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 3398bcb0991SDimitry Andric return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 342fe6060f1SDimitry Andric Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 3430b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the 3448bcb0991SDimitry Andric // link graph to build the symbol dependence graph. 345e8d8bef9SDimitry Andric Config.PrePrunePasses.push_back([this](LinkGraph &G) { 346e8d8bef9SDimitry Andric return claimOrExternalizeWeakAndCommonSymbols(G); 347e8d8bef9SDimitry Andric }); 3480b57cec5SDimitry Andric 349fe6060f1SDimitry Andric Layer.modifyPassConfig(*MR, LG, Config); 3500b57cec5SDimitry Andric 3515ffd83dbSDimitry Andric Config.PostPrunePasses.push_back( 3525ffd83dbSDimitry Andric [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 3535ffd83dbSDimitry Andric 3540b57cec5SDimitry Andric return Error::success(); 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric private: 358fe6060f1SDimitry Andric // Symbol name dependencies: 359fe6060f1SDimitry Andric // Internal: Defined in this graph. 360fe6060f1SDimitry Andric // External: Defined externally. 361fe6060f1SDimitry Andric struct BlockSymbolDependencies { 3625ffd83dbSDimitry Andric SymbolNameSet Internal, External; 3635ffd83dbSDimitry Andric }; 3645ffd83dbSDimitry Andric 365fe6060f1SDimitry Andric // Lazily populated map of blocks to BlockSymbolDependencies values. 366fe6060f1SDimitry Andric class BlockDependenciesMap { 367fe6060f1SDimitry Andric public: 368fe6060f1SDimitry Andric BlockDependenciesMap(ExecutionSession &ES, 369fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps) 370fe6060f1SDimitry Andric : ES(ES), BlockDeps(std::move(BlockDeps)) {} 371fe6060f1SDimitry Andric 372fe6060f1SDimitry Andric const BlockSymbolDependencies &operator[](const Block &B) { 373fe6060f1SDimitry Andric // Check the cache first. 374fe6060f1SDimitry Andric auto I = BlockTransitiveDepsCache.find(&B); 375fe6060f1SDimitry Andric if (I != BlockTransitiveDepsCache.end()) 376fe6060f1SDimitry Andric return I->second; 377fe6060f1SDimitry Andric 378fe6060f1SDimitry Andric // No value. Populate the cache. 379fe6060f1SDimitry Andric BlockSymbolDependencies BTDCacheVal; 380fe6060f1SDimitry Andric auto BDI = BlockDeps.find(&B); 381fe6060f1SDimitry Andric assert(BDI != BlockDeps.end() && "No block dependencies"); 382fe6060f1SDimitry Andric 383fe6060f1SDimitry Andric for (auto *BDep : BDI->second) { 384fe6060f1SDimitry Andric auto &BID = getBlockImmediateDeps(*BDep); 385fe6060f1SDimitry Andric for (auto &ExternalDep : BID.External) 386fe6060f1SDimitry Andric BTDCacheVal.External.insert(ExternalDep); 387fe6060f1SDimitry Andric for (auto &InternalDep : BID.Internal) 388fe6060f1SDimitry Andric BTDCacheVal.Internal.insert(InternalDep); 389fe6060f1SDimitry Andric } 390fe6060f1SDimitry Andric 391fe6060f1SDimitry Andric return BlockTransitiveDepsCache 392fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BTDCacheVal))) 393fe6060f1SDimitry Andric .first->second; 394fe6060f1SDimitry Andric } 395fe6060f1SDimitry Andric 396fe6060f1SDimitry Andric SymbolStringPtr &getInternedName(Symbol &Sym) { 397fe6060f1SDimitry Andric auto I = NameCache.find(&Sym); 398fe6060f1SDimitry Andric if (I != NameCache.end()) 399fe6060f1SDimitry Andric return I->second; 400fe6060f1SDimitry Andric 401fe6060f1SDimitry Andric return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName()))) 402fe6060f1SDimitry Andric .first->second; 403fe6060f1SDimitry Andric } 404fe6060f1SDimitry Andric 405fe6060f1SDimitry Andric private: 406fe6060f1SDimitry Andric BlockSymbolDependencies &getBlockImmediateDeps(Block &B) { 407fe6060f1SDimitry Andric // Check the cache first. 408fe6060f1SDimitry Andric auto I = BlockImmediateDepsCache.find(&B); 409fe6060f1SDimitry Andric if (I != BlockImmediateDepsCache.end()) 410fe6060f1SDimitry Andric return I->second; 411fe6060f1SDimitry Andric 412fe6060f1SDimitry Andric BlockSymbolDependencies BIDCacheVal; 413fe6060f1SDimitry Andric for (auto &E : B.edges()) { 414fe6060f1SDimitry Andric auto &Tgt = E.getTarget(); 415fe6060f1SDimitry Andric if (Tgt.getScope() != Scope::Local) { 416fe6060f1SDimitry Andric if (Tgt.isExternal()) 417fe6060f1SDimitry Andric BIDCacheVal.External.insert(getInternedName(Tgt)); 418fe6060f1SDimitry Andric else 419fe6060f1SDimitry Andric BIDCacheVal.Internal.insert(getInternedName(Tgt)); 420fe6060f1SDimitry Andric } 421fe6060f1SDimitry Andric } 422fe6060f1SDimitry Andric 423fe6060f1SDimitry Andric return BlockImmediateDepsCache 424fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BIDCacheVal))) 425fe6060f1SDimitry Andric .first->second; 426fe6060f1SDimitry Andric } 427fe6060f1SDimitry Andric 428fe6060f1SDimitry Andric ExecutionSession &ES; 429fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 430fe6060f1SDimitry Andric DenseMap<const Symbol *, SymbolStringPtr> NameCache; 431fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache; 432fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache; 433fe6060f1SDimitry Andric }; 4340b57cec5SDimitry Andric 435e8d8bef9SDimitry Andric Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 4360b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4370b57cec5SDimitry Andric 438e8d8bef9SDimitry Andric SymbolFlagsMap NewSymbolsToClaim; 439e8d8bef9SDimitry Andric std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 440e8d8bef9SDimitry Andric 441e8d8bef9SDimitry Andric auto ProcessSymbol = [&](Symbol *Sym) { 442349cc55cSDimitry Andric if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 443349cc55cSDimitry Andric Sym->getScope() != Scope::Local) { 444e8d8bef9SDimitry Andric auto Name = ES.intern(Sym->getName()); 445e8d8bef9SDimitry Andric if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 44606c3fb27SDimitry Andric NewSymbolsToClaim[Name] = 44706c3fb27SDimitry Andric getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 448e8d8bef9SDimitry Andric NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 4490b57cec5SDimitry Andric } 450e8d8bef9SDimitry Andric } 451e8d8bef9SDimitry Andric }; 452e8d8bef9SDimitry Andric 453e8d8bef9SDimitry Andric for (auto *Sym : G.defined_symbols()) 454e8d8bef9SDimitry Andric ProcessSymbol(Sym); 455e8d8bef9SDimitry Andric for (auto *Sym : G.absolute_symbols()) 456e8d8bef9SDimitry Andric ProcessSymbol(Sym); 457e8d8bef9SDimitry Andric 458e8d8bef9SDimitry Andric // Attempt to claim all weak defs that we're not already responsible for. 459e8d8bef9SDimitry Andric // This cannot fail -- any clashes will just result in rejection of our 460e8d8bef9SDimitry Andric // claim, at which point we'll externalize that symbol. 461e8d8bef9SDimitry Andric cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim))); 462e8d8bef9SDimitry Andric 463bdd1243dSDimitry Andric // Walk the list of symbols that we just tried to claim. Symbols that we're 464bdd1243dSDimitry Andric // responsible for are marked live. Symbols that we're not responsible for 465bdd1243dSDimitry Andric // are turned into external references. 466bdd1243dSDimitry Andric for (auto &KV : NameToSym) { 467bdd1243dSDimitry Andric if (MR->getSymbols().count(KV.first)) 468bdd1243dSDimitry Andric KV.second->setLive(true); 469bdd1243dSDimitry Andric else 470e8d8bef9SDimitry Andric G.makeExternal(*KV.second); 471bdd1243dSDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric return Error::success(); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4768bcb0991SDimitry Andric Error markResponsibilitySymbolsLive(LinkGraph &G) const { 4770b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4788bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 479e8d8bef9SDimitry Andric if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 4808bcb0991SDimitry Andric Sym->setLive(true); 4810b57cec5SDimitry Andric return Error::success(); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4848bcb0991SDimitry Andric Error computeNamedSymbolDependencies(LinkGraph &G) { 485e8d8bef9SDimitry Andric auto &ES = MR->getTargetJITDylib().getExecutionSession(); 486fe6060f1SDimitry Andric auto BlockDeps = computeBlockNonLocalDeps(G); 4870b57cec5SDimitry Andric 4885ffd83dbSDimitry Andric // Compute dependencies for symbols defined in the JITLink graph. 4898bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) { 4900b57cec5SDimitry Andric 4915ffd83dbSDimitry Andric // Skip local symbols: we do not track dependencies for these. 4928bcb0991SDimitry Andric if (Sym->getScope() == Scope::Local) 4930b57cec5SDimitry Andric continue; 4945ffd83dbSDimitry Andric assert(Sym->hasName() && 4955ffd83dbSDimitry Andric "Defined non-local jitlink::Symbol should have a name"); 4960b57cec5SDimitry Andric 497fe6060f1SDimitry Andric auto &SymDeps = BlockDeps[Sym->getBlock()]; 498fe6060f1SDimitry Andric if (SymDeps.External.empty() && SymDeps.Internal.empty()) 4995ffd83dbSDimitry Andric continue; 5005ffd83dbSDimitry Andric 5015ffd83dbSDimitry Andric auto SymName = ES.intern(Sym->getName()); 502fe6060f1SDimitry Andric if (!SymDeps.External.empty()) 503fe6060f1SDimitry Andric ExternalNamedSymbolDeps[SymName] = SymDeps.External; 504fe6060f1SDimitry Andric if (!SymDeps.Internal.empty()) 505fe6060f1SDimitry Andric InternalNamedSymbolDeps[SymName] = SymDeps.Internal; 5065ffd83dbSDimitry Andric } 5075ffd83dbSDimitry Andric 5085ffd83dbSDimitry Andric for (auto &P : Layer.Plugins) { 509fe6060f1SDimitry Andric auto SynthDeps = P->getSyntheticSymbolDependencies(*MR); 510fe6060f1SDimitry Andric if (SynthDeps.empty()) 5115ffd83dbSDimitry Andric continue; 5125ffd83dbSDimitry Andric 513fe6060f1SDimitry Andric DenseSet<Block *> BlockVisited; 514fe6060f1SDimitry Andric for (auto &KV : SynthDeps) { 5155ffd83dbSDimitry Andric auto &Name = KV.first; 516fe6060f1SDimitry Andric auto &DepsForName = KV.second; 517fe6060f1SDimitry Andric for (auto *Sym : DepsForName) { 518fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) { 519fe6060f1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()]; 520fe6060f1SDimitry Andric for (auto &S : BDeps.Internal) 5215ffd83dbSDimitry Andric InternalNamedSymbolDeps[Name].insert(S); 522fe6060f1SDimitry Andric for (auto &S : BDeps.External) 5235ffd83dbSDimitry Andric ExternalNamedSymbolDeps[Name].insert(S); 524fe6060f1SDimitry Andric } else { 525fe6060f1SDimitry Andric if (Sym->isExternal()) 526fe6060f1SDimitry Andric ExternalNamedSymbolDeps[Name].insert( 527fe6060f1SDimitry Andric BlockDeps.getInternedName(*Sym)); 528fe6060f1SDimitry Andric else 529fe6060f1SDimitry Andric InternalNamedSymbolDeps[Name].insert( 530fe6060f1SDimitry Andric BlockDeps.getInternedName(*Sym)); 531fe6060f1SDimitry Andric } 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric return Error::success(); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 539fe6060f1SDimitry Andric BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) { 540fe6060f1SDimitry Andric // First calculate the reachable-via-non-local-symbol blocks for each block. 541fe6060f1SDimitry Andric struct BlockInfo { 542fe6060f1SDimitry Andric DenseSet<Block *> Dependencies; 543fe6060f1SDimitry Andric DenseSet<Block *> Dependants; 544fe6060f1SDimitry Andric bool DependenciesChanged = true; 5450b57cec5SDimitry Andric }; 546fe6060f1SDimitry Andric DenseMap<Block *, BlockInfo> BlockInfos; 547fe6060f1SDimitry Andric SmallVector<Block *> WorkList; 5480b57cec5SDimitry Andric 549fe6060f1SDimitry Andric // Pre-allocate map entries. This prevents any iterator/reference 550fe6060f1SDimitry Andric // invalidation in the next loop. 551fe6060f1SDimitry Andric for (auto *B : G.blocks()) 552fe6060f1SDimitry Andric (void)BlockInfos[B]; 553fe6060f1SDimitry Andric 554fe6060f1SDimitry Andric // Build initial worklist, record block dependencies/dependants and 555fe6060f1SDimitry Andric // non-local symbol dependencies. 556fe6060f1SDimitry Andric for (auto *B : G.blocks()) { 557fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 558fe6060f1SDimitry Andric for (auto &E : B->edges()) { 559bdd1243dSDimitry Andric if (E.getTarget().getScope() == Scope::Local && 560bdd1243dSDimitry Andric !E.getTarget().isAbsolute()) { 561fe6060f1SDimitry Andric auto &TgtB = E.getTarget().getBlock(); 562fe6060f1SDimitry Andric if (&TgtB != B) { 563fe6060f1SDimitry Andric BI.Dependencies.insert(&TgtB); 564fe6060f1SDimitry Andric BlockInfos[&TgtB].Dependants.insert(B); 565fe6060f1SDimitry Andric } 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 569fe6060f1SDimitry Andric // If this node has both dependants and dependencies then add it to the 570fe6060f1SDimitry Andric // worklist to propagate the dependencies to the dependants. 571fe6060f1SDimitry Andric if (!BI.Dependants.empty() && !BI.Dependencies.empty()) 572fe6060f1SDimitry Andric WorkList.push_back(B); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 575fe6060f1SDimitry Andric // Propagate block-level dependencies through the block-dependence graph. 576fe6060f1SDimitry Andric while (!WorkList.empty()) { 577349cc55cSDimitry Andric auto *B = WorkList.pop_back_val(); 5780b57cec5SDimitry Andric 579fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 580fe6060f1SDimitry Andric assert(BI.DependenciesChanged && 581fe6060f1SDimitry Andric "Block in worklist has unchanged dependencies"); 582fe6060f1SDimitry Andric BI.DependenciesChanged = false; 583fe6060f1SDimitry Andric for (auto *Dependant : BI.Dependants) { 584fe6060f1SDimitry Andric auto &DependantBI = BlockInfos[Dependant]; 585fe6060f1SDimitry Andric for (auto *Dependency : BI.Dependencies) { 586fe6060f1SDimitry Andric if (Dependant != Dependency && 587fe6060f1SDimitry Andric DependantBI.Dependencies.insert(Dependency).second) 588fe6060f1SDimitry Andric if (!DependantBI.DependenciesChanged) { 589fe6060f1SDimitry Andric DependantBI.DependenciesChanged = true; 590fe6060f1SDimitry Andric WorkList.push_back(Dependant); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric } 5935ffd83dbSDimitry Andric } 5945ffd83dbSDimitry Andric } 5955ffd83dbSDimitry Andric 596fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 597fe6060f1SDimitry Andric for (auto &KV : BlockInfos) 598fe6060f1SDimitry Andric BlockDeps[KV.first] = std::move(KV.second.Dependencies); 599fe6060f1SDimitry Andric 600fe6060f1SDimitry Andric return BlockDependenciesMap(Layer.getExecutionSession(), 601fe6060f1SDimitry Andric std::move(BlockDeps)); 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric void registerDependencies(const SymbolDependenceMap &QueryDeps) { 6055ffd83dbSDimitry Andric for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 6060b57cec5SDimitry Andric auto &Name = NamedDepsEntry.first; 6070b57cec5SDimitry Andric auto &NameDeps = NamedDepsEntry.second; 6080b57cec5SDimitry Andric SymbolDependenceMap SymbolDeps; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric for (const auto &QueryDepsEntry : QueryDeps) { 6110b57cec5SDimitry Andric JITDylib &SourceJD = *QueryDepsEntry.first; 6120b57cec5SDimitry Andric const SymbolNameSet &Symbols = QueryDepsEntry.second; 6130b57cec5SDimitry Andric auto &DepsForJD = SymbolDeps[&SourceJD]; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric for (const auto &S : Symbols) 6160b57cec5SDimitry Andric if (NameDeps.count(S)) 6170b57cec5SDimitry Andric DepsForJD.insert(S); 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric if (DepsForJD.empty()) 6200b57cec5SDimitry Andric SymbolDeps.erase(&SourceJD); 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 623e8d8bef9SDimitry Andric MR->addDependencies(Name, SymbolDeps); 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric ObjectLinkingLayer &Layer; 628e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR; 6290b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer; 6305ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 6315ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 6320b57cec5SDimitry Andric }; 6330b57cec5SDimitry Andric 63481ad6265SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() = default; 6350b57cec5SDimitry Andric 636fe6060f1SDimitry Andric char ObjectLinkingLayer::ID; 637fe6060f1SDimitry Andric 638fe6060f1SDimitry Andric using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 639fe6060f1SDimitry Andric 640fe6060f1SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 641fe6060f1SDimitry Andric : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 642fe6060f1SDimitry Andric ES.registerResourceManager(*this); 643fe6060f1SDimitry Andric } 644fe6060f1SDimitry Andric 645e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 646e8d8bef9SDimitry Andric JITLinkMemoryManager &MemMgr) 647fe6060f1SDimitry Andric : BaseT(ES), MemMgr(MemMgr) { 648e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 651e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer( 652e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 653fe6060f1SDimitry Andric : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 654e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 655e8d8bef9SDimitry Andric } 656e8d8bef9SDimitry Andric 657e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() { 658e8d8bef9SDimitry Andric assert(Allocs.empty() && "Layer destroyed with resources still attached"); 659e8d8bef9SDimitry Andric getExecutionSession().deregisterResourceManager(*this); 660e8d8bef9SDimitry Andric } 661e8d8bef9SDimitry Andric 662fe6060f1SDimitry Andric Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 663fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G) { 664fe6060f1SDimitry Andric auto &JD = RT->getJITDylib(); 665fe6060f1SDimitry Andric return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 666fe6060f1SDimitry Andric std::move(RT)); 667fe6060f1SDimitry Andric } 668fe6060f1SDimitry Andric 669e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 6700b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 6710b57cec5SDimitry Andric assert(O && "Object must not be null"); 672fe6060f1SDimitry Andric MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 673fe6060f1SDimitry Andric 674e8d8bef9SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 675e8d8bef9SDimitry Andric *this, std::move(R), std::move(O)); 676fe6060f1SDimitry Andric if (auto G = createLinkGraphFromObject(ObjBuffer)) { 677fe6060f1SDimitry Andric Ctx->notifyMaterializing(**G); 678e8d8bef9SDimitry Andric link(std::move(*G), std::move(Ctx)); 679fe6060f1SDimitry Andric } else { 680e8d8bef9SDimitry Andric Ctx->notifyFailed(G.takeError()); 681e8d8bef9SDimitry Andric } 682fe6060f1SDimitry Andric } 683e8d8bef9SDimitry Andric 684e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 685e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G) { 686fe6060f1SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 687fe6060f1SDimitry Andric *this, std::move(R), nullptr); 688fe6060f1SDimitry Andric Ctx->notifyMaterializing(*G); 689fe6060f1SDimitry Andric link(std::move(G), std::move(Ctx)); 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 693fe6060f1SDimitry Andric LinkGraph &G, 6940b57cec5SDimitry Andric PassConfiguration &PassConfig) { 6950b57cec5SDimitry Andric for (auto &P : Plugins) 696fe6060f1SDimitry Andric P->modifyPassConfig(MR, G, PassConfig); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 7000b57cec5SDimitry Andric for (auto &P : Plugins) 7010b57cec5SDimitry Andric P->notifyLoaded(MR); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 705349cc55cSDimitry Andric FinalizedAlloc FA) { 7060b57cec5SDimitry Andric Error Err = Error::success(); 7070b57cec5SDimitry Andric for (auto &P : Plugins) 7080b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric if (Err) 7110b57cec5SDimitry Andric return Err; 7120b57cec5SDimitry Andric 713*1db9f3b2SDimitry Andric if (!FA) 714*1db9f3b2SDimitry Andric return Error::success(); 715*1db9f3b2SDimitry Andric 716e8d8bef9SDimitry Andric return MR.withResourceKeyDo( 717349cc55cSDimitry Andric [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric 720bdd1243dSDimitry Andric Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) { 7210b57cec5SDimitry Andric 722349cc55cSDimitry Andric { 7230b57cec5SDimitry Andric Error Err = Error::success(); 7240b57cec5SDimitry Andric for (auto &P : Plugins) 725bdd1243dSDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 726349cc55cSDimitry Andric if (Err) 727349cc55cSDimitry Andric return Err; 728349cc55cSDimitry Andric } 7290b57cec5SDimitry Andric 730349cc55cSDimitry Andric std::vector<FinalizedAlloc> AllocsToRemove; 731e8d8bef9SDimitry Andric getExecutionSession().runSessionLocked([&] { 732e8d8bef9SDimitry Andric auto I = Allocs.find(K); 733e8d8bef9SDimitry Andric if (I != Allocs.end()) { 734e8d8bef9SDimitry Andric std::swap(AllocsToRemove, I->second); 735e8d8bef9SDimitry Andric Allocs.erase(I); 7360b57cec5SDimitry Andric } 737e8d8bef9SDimitry Andric }); 7380b57cec5SDimitry Andric 739349cc55cSDimitry Andric if (AllocsToRemove.empty()) 740349cc55cSDimitry Andric return Error::success(); 7410b57cec5SDimitry Andric 742349cc55cSDimitry Andric return MemMgr.deallocate(std::move(AllocsToRemove)); 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric 745bdd1243dSDimitry Andric void ObjectLinkingLayer::handleTransferResources(JITDylib &JD, 746bdd1243dSDimitry Andric ResourceKey DstKey, 747e8d8bef9SDimitry Andric ResourceKey SrcKey) { 748e8d8bef9SDimitry Andric auto I = Allocs.find(SrcKey); 749e8d8bef9SDimitry Andric if (I != Allocs.end()) { 750e8d8bef9SDimitry Andric auto &SrcAllocs = I->second; 751e8d8bef9SDimitry Andric auto &DstAllocs = Allocs[DstKey]; 752e8d8bef9SDimitry Andric DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 753e8d8bef9SDimitry Andric for (auto &Alloc : SrcAllocs) 754e8d8bef9SDimitry Andric DstAllocs.push_back(std::move(Alloc)); 755e8d8bef9SDimitry Andric 756e8d8bef9SDimitry Andric // Erase SrcKey entry using value rather than iterator I: I may have been 757e8d8bef9SDimitry Andric // invalidated when we looked up DstKey. 758e8d8bef9SDimitry Andric Allocs.erase(SrcKey); 759e8d8bef9SDimitry Andric } 760e8d8bef9SDimitry Andric 761e8d8bef9SDimitry Andric for (auto &P : Plugins) 762bdd1243dSDimitry Andric P->notifyTransferringResources(JD, DstKey, SrcKey); 763e8d8bef9SDimitry Andric } 764e8d8bef9SDimitry Andric 7650b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 766e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 767e8d8bef9SDimitry Andric : ES(ES), Registrar(std::move(Registrar)) {} 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig( 770fe6060f1SDimitry Andric MaterializationResponsibility &MR, LinkGraph &G, 7710b57cec5SDimitry Andric PassConfiguration &PassConfig) { 7720b57cec5SDimitry Andric 7735ffd83dbSDimitry Andric PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 77404eeddc0SDimitry Andric G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) { 7755ffd83dbSDimitry Andric if (Addr) { 7765ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7775ffd83dbSDimitry Andric assert(!InProcessLinks.count(&MR) && 7785ffd83dbSDimitry Andric "Link for MR already being tracked?"); 7798bcb0991SDimitry Andric InProcessLinks[&MR] = {Addr, Size}; 7805ffd83dbSDimitry Andric } 7810b57cec5SDimitry Andric })); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted( 7850b57cec5SDimitry Andric MaterializationResponsibility &MR) { 786e8d8bef9SDimitry Andric 78704eeddc0SDimitry Andric ExecutorAddrRange EmittedRange; 788e8d8bef9SDimitry Andric { 7895ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7900b57cec5SDimitry Andric 7918bcb0991SDimitry Andric auto EHFrameRangeItr = InProcessLinks.find(&MR); 7928bcb0991SDimitry Andric if (EHFrameRangeItr == InProcessLinks.end()) 7930b57cec5SDimitry Andric return Error::success(); 7940b57cec5SDimitry Andric 795e8d8bef9SDimitry Andric EmittedRange = EHFrameRangeItr->second; 79604eeddc0SDimitry Andric assert(EmittedRange.Start && "eh-frame addr to register can not be null"); 7978bcb0991SDimitry Andric InProcessLinks.erase(EHFrameRangeItr); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 800e8d8bef9SDimitry Andric if (auto Err = MR.withResourceKeyDo( 801e8d8bef9SDimitry Andric [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 802e8d8bef9SDimitry Andric return Err; 8035ffd83dbSDimitry Andric 80404eeddc0SDimitry Andric return Registrar->registerEHFrames(EmittedRange); 805e8d8bef9SDimitry Andric } 806e8d8bef9SDimitry Andric 807e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyFailed( 808e8d8bef9SDimitry Andric MaterializationResponsibility &MR) { 809e8d8bef9SDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 810e8d8bef9SDimitry Andric InProcessLinks.erase(&MR); 8110b57cec5SDimitry Andric return Error::success(); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 814bdd1243dSDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD, 815bdd1243dSDimitry Andric ResourceKey K) { 81604eeddc0SDimitry Andric std::vector<ExecutorAddrRange> RangesToRemove; 8170b57cec5SDimitry Andric 818e8d8bef9SDimitry Andric ES.runSessionLocked([&] { 819e8d8bef9SDimitry Andric auto I = EHFrameRanges.find(K); 820e8d8bef9SDimitry Andric if (I != EHFrameRanges.end()) { 821e8d8bef9SDimitry Andric RangesToRemove = std::move(I->second); 822e8d8bef9SDimitry Andric EHFrameRanges.erase(I); 823e8d8bef9SDimitry Andric } 824e8d8bef9SDimitry Andric }); 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric Error Err = Error::success(); 827e8d8bef9SDimitry Andric while (!RangesToRemove.empty()) { 828e8d8bef9SDimitry Andric auto RangeToRemove = RangesToRemove.back(); 829e8d8bef9SDimitry Andric RangesToRemove.pop_back(); 83004eeddc0SDimitry Andric assert(RangeToRemove.Start && "Untracked eh-frame range must not be null"); 83104eeddc0SDimitry Andric Err = joinErrors(std::move(Err), 83204eeddc0SDimitry Andric Registrar->deregisterEHFrames(RangeToRemove)); 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric return Err; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 838e8d8bef9SDimitry Andric void EHFrameRegistrationPlugin::notifyTransferringResources( 839bdd1243dSDimitry Andric JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) { 840e8d8bef9SDimitry Andric auto SI = EHFrameRanges.find(SrcKey); 841fe6060f1SDimitry Andric if (SI == EHFrameRanges.end()) 842fe6060f1SDimitry Andric return; 843fe6060f1SDimitry Andric 844fe6060f1SDimitry Andric auto DI = EHFrameRanges.find(DstKey); 845fe6060f1SDimitry Andric if (DI != EHFrameRanges.end()) { 846e8d8bef9SDimitry Andric auto &SrcRanges = SI->second; 847fe6060f1SDimitry Andric auto &DstRanges = DI->second; 848e8d8bef9SDimitry Andric DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 849e8d8bef9SDimitry Andric for (auto &SrcRange : SrcRanges) 850e8d8bef9SDimitry Andric DstRanges.push_back(std::move(SrcRange)); 851e8d8bef9SDimitry Andric EHFrameRanges.erase(SI); 852fe6060f1SDimitry Andric } else { 853fe6060f1SDimitry Andric // We need to move SrcKey's ranges over without invalidating the SI 854fe6060f1SDimitry Andric // iterator. 855fe6060f1SDimitry Andric auto Tmp = std::move(SI->second); 856fe6060f1SDimitry Andric EHFrameRanges.erase(SI); 857fe6060f1SDimitry Andric EHFrameRanges[DstKey] = std::move(Tmp); 858e8d8bef9SDimitry Andric } 859e8d8bef9SDimitry Andric } 860e8d8bef9SDimitry Andric 8610b57cec5SDimitry Andric } // End namespace orc. 8620b57cec5SDimitry Andric } // End namespace llvm. 863