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/ADT/Optional.h" 110b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 12*fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" 13*fe6060f1SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 14*fe6060f1SDimitry Andric #include <string> 150b57cec5SDimitry Andric #include <vector> 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #define DEBUG_TYPE "orc" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric using namespace llvm::jitlink; 210b57cec5SDimitry Andric using namespace llvm::orc; 220b57cec5SDimitry Andric 23*fe6060f1SDimitry Andric namespace { 24*fe6060f1SDimitry Andric 25*fe6060f1SDimitry Andric class LinkGraphMaterializationUnit : public MaterializationUnit { 26*fe6060f1SDimitry Andric private: 27*fe6060f1SDimitry Andric struct LinkGraphInterface { 28*fe6060f1SDimitry Andric SymbolFlagsMap SymbolFlags; 29*fe6060f1SDimitry Andric SymbolStringPtr InitSymbol; 30*fe6060f1SDimitry Andric }; 31*fe6060f1SDimitry Andric 32*fe6060f1SDimitry Andric public: 33*fe6060f1SDimitry Andric static std::unique_ptr<LinkGraphMaterializationUnit> 34*fe6060f1SDimitry Andric Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 35*fe6060f1SDimitry Andric auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 36*fe6060f1SDimitry Andric return std::unique_ptr<LinkGraphMaterializationUnit>( 37*fe6060f1SDimitry Andric new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 38*fe6060f1SDimitry Andric std::move(LGI))); 39*fe6060f1SDimitry Andric } 40*fe6060f1SDimitry Andric 41*fe6060f1SDimitry Andric StringRef getName() const override { return G->getName(); } 42*fe6060f1SDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 43*fe6060f1SDimitry Andric ObjLinkingLayer.emit(std::move(MR), std::move(G)); 44*fe6060f1SDimitry Andric } 45*fe6060f1SDimitry Andric 46*fe6060f1SDimitry Andric private: 47*fe6060f1SDimitry Andric static LinkGraphInterface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 48*fe6060f1SDimitry Andric 49*fe6060f1SDimitry Andric LinkGraphInterface LGI; 50*fe6060f1SDimitry Andric 51*fe6060f1SDimitry Andric for (auto *Sym : G.defined_symbols()) { 52*fe6060f1SDimitry Andric // Skip local symbols. 53*fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) 54*fe6060f1SDimitry Andric continue; 55*fe6060f1SDimitry Andric assert(Sym->hasName() && "Anonymous non-local symbol?"); 56*fe6060f1SDimitry Andric 57*fe6060f1SDimitry Andric JITSymbolFlags Flags; 58*fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Default) 59*fe6060f1SDimitry Andric Flags |= JITSymbolFlags::Exported; 60*fe6060f1SDimitry Andric 61*fe6060f1SDimitry Andric if (Sym->isCallable()) 62*fe6060f1SDimitry Andric Flags |= JITSymbolFlags::Callable; 63*fe6060f1SDimitry Andric 64*fe6060f1SDimitry Andric LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags; 65*fe6060f1SDimitry Andric } 66*fe6060f1SDimitry Andric 67*fe6060f1SDimitry Andric if (G.getTargetTriple().isOSBinFormatMachO()) 68*fe6060f1SDimitry Andric if (hasMachOInitSection(G)) 69*fe6060f1SDimitry Andric LGI.InitSymbol = makeInitSymbol(ES, G); 70*fe6060f1SDimitry Andric 71*fe6060f1SDimitry Andric return LGI; 72*fe6060f1SDimitry Andric } 73*fe6060f1SDimitry Andric 74*fe6060f1SDimitry Andric static bool hasMachOInitSection(LinkGraph &G) { 75*fe6060f1SDimitry Andric for (auto &Sec : G.sections()) 76*fe6060f1SDimitry Andric if (Sec.getName() == "__DATA,__obj_selrefs" || 77*fe6060f1SDimitry Andric Sec.getName() == "__DATA,__objc_classlist" || 78*fe6060f1SDimitry Andric Sec.getName() == "__TEXT,__swift5_protos" || 79*fe6060f1SDimitry Andric Sec.getName() == "__TEXT,__swift5_proto" || 80*fe6060f1SDimitry Andric Sec.getName() == "__DATA,__mod_init_func") 81*fe6060f1SDimitry Andric return true; 82*fe6060f1SDimitry Andric return false; 83*fe6060f1SDimitry Andric } 84*fe6060f1SDimitry Andric 85*fe6060f1SDimitry Andric static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 86*fe6060f1SDimitry Andric std::string InitSymString; 87*fe6060f1SDimitry Andric raw_string_ostream(InitSymString) 88*fe6060f1SDimitry Andric << "$." << G.getName() << ".__inits" << Counter++; 89*fe6060f1SDimitry Andric return ES.intern(InitSymString); 90*fe6060f1SDimitry Andric } 91*fe6060f1SDimitry Andric 92*fe6060f1SDimitry Andric LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 93*fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G, 94*fe6060f1SDimitry Andric LinkGraphInterface LGI) 95*fe6060f1SDimitry Andric : MaterializationUnit(std::move(LGI.SymbolFlags), 96*fe6060f1SDimitry Andric std::move(LGI.InitSymbol)), 97*fe6060f1SDimitry Andric ObjLinkingLayer(ObjLinkingLayer), G(std::move(G)) {} 98*fe6060f1SDimitry Andric 99*fe6060f1SDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 100*fe6060f1SDimitry Andric for (auto *Sym : G->defined_symbols()) 101*fe6060f1SDimitry Andric if (Sym->getName() == *Name) { 102*fe6060f1SDimitry Andric assert(Sym->getLinkage() == Linkage::Weak && 103*fe6060f1SDimitry Andric "Discarding non-weak definition"); 104*fe6060f1SDimitry Andric G->makeExternal(*Sym); 105*fe6060f1SDimitry Andric break; 106*fe6060f1SDimitry Andric } 107*fe6060f1SDimitry Andric } 108*fe6060f1SDimitry Andric 109*fe6060f1SDimitry Andric ObjectLinkingLayer &ObjLinkingLayer; 110*fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G; 111*fe6060f1SDimitry Andric static std::atomic<uint64_t> Counter; 112*fe6060f1SDimitry Andric }; 113*fe6060f1SDimitry Andric 114*fe6060f1SDimitry Andric std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 115*fe6060f1SDimitry Andric 116*fe6060f1SDimitry Andric } // end anonymous namespace 117*fe6060f1SDimitry Andric 1180b57cec5SDimitry Andric namespace llvm { 1190b57cec5SDimitry Andric namespace orc { 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 1220b57cec5SDimitry Andric public: 123e8d8bef9SDimitry Andric ObjectLinkingLayerJITLinkContext( 124e8d8bef9SDimitry Andric ObjectLinkingLayer &Layer, 125e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR, 1260b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer) 127e8d8bef9SDimitry Andric : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 128e8d8bef9SDimitry Andric MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 1290b57cec5SDimitry Andric 1308bcb0991SDimitry Andric ~ObjectLinkingLayerJITLinkContext() { 1318bcb0991SDimitry Andric // If there is an object buffer return function then use it to 1328bcb0991SDimitry Andric // return ownership of the buffer. 133e8d8bef9SDimitry Andric if (Layer.ReturnObjectBuffer && ObjBuffer) 1348bcb0991SDimitry Andric Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 1358bcb0991SDimitry Andric } 1368bcb0991SDimitry Andric 137e8d8bef9SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 1380b57cec5SDimitry Andric 139*fe6060f1SDimitry Andric void notifyMaterializing(LinkGraph &G) { 140*fe6060f1SDimitry Andric for (auto &P : Layer.Plugins) 141*fe6060f1SDimitry Andric P->notifyMaterializing(*MR, G, *this, 142*fe6060f1SDimitry Andric ObjBuffer ? ObjBuffer->getMemBufferRef() 143*fe6060f1SDimitry Andric : MemoryBufferRef()); 144*fe6060f1SDimitry Andric } 145*fe6060f1SDimitry Andric 1460b57cec5SDimitry Andric void notifyFailed(Error Err) override { 147e8d8bef9SDimitry Andric for (auto &P : Layer.Plugins) 148e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 1490b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 150e8d8bef9SDimitry Andric MR->failMaterialization(); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 153480093f4SDimitry Andric void lookup(const LookupMap &Symbols, 1548bcb0991SDimitry Andric std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 1550b57cec5SDimitry Andric 1565ffd83dbSDimitry Andric JITDylibSearchOrder LinkOrder; 157e8d8bef9SDimitry Andric MR->getTargetJITDylib().withLinkOrderDo( 1585ffd83dbSDimitry Andric [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 1610b57cec5SDimitry Andric 162480093f4SDimitry Andric SymbolLookupSet LookupSet; 163480093f4SDimitry Andric for (auto &KV : Symbols) { 164480093f4SDimitry Andric orc::SymbolLookupFlags LookupFlags; 165480093f4SDimitry Andric switch (KV.second) { 166480093f4SDimitry Andric case jitlink::SymbolLookupFlags::RequiredSymbol: 167480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 168480093f4SDimitry Andric break; 169480093f4SDimitry Andric case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 170480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 171480093f4SDimitry Andric break; 172480093f4SDimitry Andric } 173480093f4SDimitry Andric LookupSet.add(ES.intern(KV.first), LookupFlags); 174480093f4SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker. 177e8d8bef9SDimitry Andric auto OnResolve = [LookupContinuation = 178e8d8bef9SDimitry Andric std::move(LC)](Expected<SymbolMap> Result) mutable { 1790b57cec5SDimitry Andric if (!Result) 1808bcb0991SDimitry Andric LookupContinuation->run(Result.takeError()); 1810b57cec5SDimitry Andric else { 1820b57cec5SDimitry Andric AsyncLookupResult LR; 1830b57cec5SDimitry Andric for (auto &KV : *Result) 1840b57cec5SDimitry Andric LR[*KV.first] = KV.second; 1858bcb0991SDimitry Andric LookupContinuation->run(std::move(LR)); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric }; 1880b57cec5SDimitry Andric 1895ffd83dbSDimitry Andric for (auto &KV : InternalNamedSymbolDeps) { 1905ffd83dbSDimitry Andric SymbolDependenceMap InternalDeps; 191e8d8bef9SDimitry Andric InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 192e8d8bef9SDimitry Andric MR->addDependencies(KV.first, InternalDeps); 1935ffd83dbSDimitry Andric } 1945ffd83dbSDimitry Andric 1955ffd83dbSDimitry Andric ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 196480093f4SDimitry Andric SymbolState::Resolved, std::move(OnResolve), 197480093f4SDimitry Andric [this](const SymbolDependenceMap &Deps) { 1980b57cec5SDimitry Andric registerDependencies(Deps); 1990b57cec5SDimitry Andric }); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 202e8d8bef9SDimitry Andric Error notifyResolved(LinkGraph &G) override { 2030b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim; 2060b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric SymbolMap InternedResult; 2098bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 2108bcb0991SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2118bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 2120b57cec5SDimitry Andric JITSymbolFlags Flags; 2130b57cec5SDimitry Andric 2148bcb0991SDimitry Andric if (Sym->isCallable()) 2150b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 2168bcb0991SDimitry Andric if (Sym->getScope() == Scope::Default) 2178bcb0991SDimitry Andric Flags |= JITSymbolFlags::Exported; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric InternedResult[InternedName] = 2208bcb0991SDimitry Andric JITEvaluatedSymbol(Sym->getAddress(), Flags); 221e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2220b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2230b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2240b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2288bcb0991SDimitry Andric for (auto *Sym : G.absolute_symbols()) 2298bcb0991SDimitry Andric if (Sym->hasName()) { 2308bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 2310b57cec5SDimitry Andric JITSymbolFlags Flags; 2320b57cec5SDimitry Andric Flags |= JITSymbolFlags::Absolute; 2338bcb0991SDimitry Andric if (Sym->isCallable()) 2340b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 2358bcb0991SDimitry Andric if (Sym->getLinkage() == Linkage::Weak) 2368bcb0991SDimitry Andric Flags |= JITSymbolFlags::Weak; 2370b57cec5SDimitry Andric InternedResult[InternedName] = 2388bcb0991SDimitry Andric JITEvaluatedSymbol(Sym->getAddress(), Flags); 239e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2400b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2410b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2420b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty()) 247e8d8bef9SDimitry Andric if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 248e8d8bef9SDimitry Andric return Err; 2495ffd83dbSDimitry Andric 2505ffd83dbSDimitry Andric { 2515ffd83dbSDimitry Andric 252e8d8bef9SDimitry Andric // Check that InternedResult matches up with MR->getSymbols(). 2535ffd83dbSDimitry Andric // This guards against faulty transformations / compilers / object caches. 2545ffd83dbSDimitry Andric 2555ffd83dbSDimitry Andric // First check that there aren't any missing symbols. 2565ffd83dbSDimitry Andric size_t NumMaterializationSideEffectsOnlySymbols = 0; 2575ffd83dbSDimitry Andric SymbolNameVector ExtraSymbols; 2585ffd83dbSDimitry Andric SymbolNameVector MissingSymbols; 259e8d8bef9SDimitry Andric for (auto &KV : MR->getSymbols()) { 2605ffd83dbSDimitry Andric 2615ffd83dbSDimitry Andric // If this is a materialization-side-effects only symbol then bump 2625ffd83dbSDimitry Andric // the counter and make sure it's *not* defined, otherwise make 2635ffd83dbSDimitry Andric // sure that it is defined. 2645ffd83dbSDimitry Andric if (KV.second.hasMaterializationSideEffectsOnly()) { 2655ffd83dbSDimitry Andric ++NumMaterializationSideEffectsOnlySymbols; 2665ffd83dbSDimitry Andric if (InternedResult.count(KV.first)) 2675ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 2685ffd83dbSDimitry Andric continue; 2695ffd83dbSDimitry Andric } else if (!InternedResult.count(KV.first)) 2705ffd83dbSDimitry Andric MissingSymbols.push_back(KV.first); 2715ffd83dbSDimitry Andric } 2725ffd83dbSDimitry Andric 2735ffd83dbSDimitry Andric // If there were missing symbols then report the error. 274e8d8bef9SDimitry Andric if (!MissingSymbols.empty()) 275e8d8bef9SDimitry Andric return make_error<MissingSymbolDefinitions>(G.getName(), 276e8d8bef9SDimitry Andric std::move(MissingSymbols)); 2775ffd83dbSDimitry Andric 2785ffd83dbSDimitry Andric // If there are more definitions than expected, add them to the 2795ffd83dbSDimitry Andric // ExtraSymbols vector. 2805ffd83dbSDimitry Andric if (InternedResult.size() > 281e8d8bef9SDimitry Andric MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 2825ffd83dbSDimitry Andric for (auto &KV : InternedResult) 283e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 2845ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 2855ffd83dbSDimitry Andric } 2865ffd83dbSDimitry Andric 2875ffd83dbSDimitry Andric // If there were extra definitions then report the error. 288e8d8bef9SDimitry Andric if (!ExtraSymbols.empty()) 289e8d8bef9SDimitry Andric return make_error<UnexpectedSymbolDefinitions>(G.getName(), 290e8d8bef9SDimitry Andric std::move(ExtraSymbols)); 2915ffd83dbSDimitry Andric } 2925ffd83dbSDimitry Andric 293e8d8bef9SDimitry Andric if (auto Err = MR->notifyResolved(InternedResult)) 294e8d8bef9SDimitry Andric return Err; 295e8d8bef9SDimitry Andric 296e8d8bef9SDimitry Andric Layer.notifyLoaded(*MR); 297e8d8bef9SDimitry Andric return Error::success(); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric void notifyFinalized( 3010b57cec5SDimitry Andric std::unique_ptr<JITLinkMemoryManager::Allocation> A) override { 302e8d8bef9SDimitry Andric if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 3030b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 304e8d8bef9SDimitry Andric MR->failMaterialization(); 3050b57cec5SDimitry Andric return; 3060b57cec5SDimitry Andric } 307e8d8bef9SDimitry Andric if (auto Err = MR->notifyEmitted()) { 3088bcb0991SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 309e8d8bef9SDimitry Andric MR->failMaterialization(); 3108bcb0991SDimitry Andric } 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3138bcb0991SDimitry Andric LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 3148bcb0991SDimitry Andric return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 317*fe6060f1SDimitry Andric Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 3180b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the 3198bcb0991SDimitry Andric // link graph to build the symbol dependence graph. 320e8d8bef9SDimitry Andric Config.PrePrunePasses.push_back([this](LinkGraph &G) { 321e8d8bef9SDimitry Andric return claimOrExternalizeWeakAndCommonSymbols(G); 322e8d8bef9SDimitry Andric }); 3230b57cec5SDimitry Andric 324*fe6060f1SDimitry Andric Layer.modifyPassConfig(*MR, LG, Config); 3250b57cec5SDimitry Andric 3265ffd83dbSDimitry Andric Config.PostPrunePasses.push_back( 3275ffd83dbSDimitry Andric [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 3285ffd83dbSDimitry Andric 3290b57cec5SDimitry Andric return Error::success(); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric private: 333*fe6060f1SDimitry Andric // Symbol name dependencies: 334*fe6060f1SDimitry Andric // Internal: Defined in this graph. 335*fe6060f1SDimitry Andric // External: Defined externally. 336*fe6060f1SDimitry Andric struct BlockSymbolDependencies { 3375ffd83dbSDimitry Andric SymbolNameSet Internal, External; 3385ffd83dbSDimitry Andric }; 3395ffd83dbSDimitry Andric 340*fe6060f1SDimitry Andric // Lazily populated map of blocks to BlockSymbolDependencies values. 341*fe6060f1SDimitry Andric class BlockDependenciesMap { 342*fe6060f1SDimitry Andric public: 343*fe6060f1SDimitry Andric BlockDependenciesMap(ExecutionSession &ES, 344*fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps) 345*fe6060f1SDimitry Andric : ES(ES), BlockDeps(std::move(BlockDeps)) {} 346*fe6060f1SDimitry Andric 347*fe6060f1SDimitry Andric const BlockSymbolDependencies &operator[](const Block &B) { 348*fe6060f1SDimitry Andric // Check the cache first. 349*fe6060f1SDimitry Andric auto I = BlockTransitiveDepsCache.find(&B); 350*fe6060f1SDimitry Andric if (I != BlockTransitiveDepsCache.end()) 351*fe6060f1SDimitry Andric return I->second; 352*fe6060f1SDimitry Andric 353*fe6060f1SDimitry Andric // No value. Populate the cache. 354*fe6060f1SDimitry Andric BlockSymbolDependencies BTDCacheVal; 355*fe6060f1SDimitry Andric auto BDI = BlockDeps.find(&B); 356*fe6060f1SDimitry Andric assert(BDI != BlockDeps.end() && "No block dependencies"); 357*fe6060f1SDimitry Andric 358*fe6060f1SDimitry Andric for (auto *BDep : BDI->second) { 359*fe6060f1SDimitry Andric auto &BID = getBlockImmediateDeps(*BDep); 360*fe6060f1SDimitry Andric for (auto &ExternalDep : BID.External) 361*fe6060f1SDimitry Andric BTDCacheVal.External.insert(ExternalDep); 362*fe6060f1SDimitry Andric for (auto &InternalDep : BID.Internal) 363*fe6060f1SDimitry Andric BTDCacheVal.Internal.insert(InternalDep); 364*fe6060f1SDimitry Andric } 365*fe6060f1SDimitry Andric 366*fe6060f1SDimitry Andric return BlockTransitiveDepsCache 367*fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BTDCacheVal))) 368*fe6060f1SDimitry Andric .first->second; 369*fe6060f1SDimitry Andric } 370*fe6060f1SDimitry Andric 371*fe6060f1SDimitry Andric SymbolStringPtr &getInternedName(Symbol &Sym) { 372*fe6060f1SDimitry Andric auto I = NameCache.find(&Sym); 373*fe6060f1SDimitry Andric if (I != NameCache.end()) 374*fe6060f1SDimitry Andric return I->second; 375*fe6060f1SDimitry Andric 376*fe6060f1SDimitry Andric return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName()))) 377*fe6060f1SDimitry Andric .first->second; 378*fe6060f1SDimitry Andric } 379*fe6060f1SDimitry Andric 380*fe6060f1SDimitry Andric private: 381*fe6060f1SDimitry Andric BlockSymbolDependencies &getBlockImmediateDeps(Block &B) { 382*fe6060f1SDimitry Andric // Check the cache first. 383*fe6060f1SDimitry Andric auto I = BlockImmediateDepsCache.find(&B); 384*fe6060f1SDimitry Andric if (I != BlockImmediateDepsCache.end()) 385*fe6060f1SDimitry Andric return I->second; 386*fe6060f1SDimitry Andric 387*fe6060f1SDimitry Andric BlockSymbolDependencies BIDCacheVal; 388*fe6060f1SDimitry Andric for (auto &E : B.edges()) { 389*fe6060f1SDimitry Andric auto &Tgt = E.getTarget(); 390*fe6060f1SDimitry Andric if (Tgt.getScope() != Scope::Local) { 391*fe6060f1SDimitry Andric if (Tgt.isExternal()) 392*fe6060f1SDimitry Andric BIDCacheVal.External.insert(getInternedName(Tgt)); 393*fe6060f1SDimitry Andric else 394*fe6060f1SDimitry Andric BIDCacheVal.Internal.insert(getInternedName(Tgt)); 395*fe6060f1SDimitry Andric } 396*fe6060f1SDimitry Andric } 397*fe6060f1SDimitry Andric 398*fe6060f1SDimitry Andric return BlockImmediateDepsCache 399*fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BIDCacheVal))) 400*fe6060f1SDimitry Andric .first->second; 401*fe6060f1SDimitry Andric } 402*fe6060f1SDimitry Andric 403*fe6060f1SDimitry Andric ExecutionSession &ES; 404*fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 405*fe6060f1SDimitry Andric DenseMap<const Symbol *, SymbolStringPtr> NameCache; 406*fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache; 407*fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache; 408*fe6060f1SDimitry Andric }; 4090b57cec5SDimitry Andric 410e8d8bef9SDimitry Andric Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 4110b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4120b57cec5SDimitry Andric 413e8d8bef9SDimitry Andric SymbolFlagsMap NewSymbolsToClaim; 414e8d8bef9SDimitry Andric std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 415e8d8bef9SDimitry Andric 416e8d8bef9SDimitry Andric auto ProcessSymbol = [&](Symbol *Sym) { 4178bcb0991SDimitry Andric if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) { 418e8d8bef9SDimitry Andric auto Name = ES.intern(Sym->getName()); 419e8d8bef9SDimitry Andric if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 420e8d8bef9SDimitry Andric JITSymbolFlags SF = JITSymbolFlags::Weak; 421e8d8bef9SDimitry Andric if (Sym->getScope() == Scope::Default) 422e8d8bef9SDimitry Andric SF |= JITSymbolFlags::Exported; 423e8d8bef9SDimitry Andric NewSymbolsToClaim[Name] = SF; 424e8d8bef9SDimitry Andric NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 4250b57cec5SDimitry Andric } 426e8d8bef9SDimitry Andric } 427e8d8bef9SDimitry Andric }; 428e8d8bef9SDimitry Andric 429e8d8bef9SDimitry Andric for (auto *Sym : G.defined_symbols()) 430e8d8bef9SDimitry Andric ProcessSymbol(Sym); 431e8d8bef9SDimitry Andric for (auto *Sym : G.absolute_symbols()) 432e8d8bef9SDimitry Andric ProcessSymbol(Sym); 433e8d8bef9SDimitry Andric 434e8d8bef9SDimitry Andric // Attempt to claim all weak defs that we're not already responsible for. 435e8d8bef9SDimitry Andric // This cannot fail -- any clashes will just result in rejection of our 436e8d8bef9SDimitry Andric // claim, at which point we'll externalize that symbol. 437e8d8bef9SDimitry Andric cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim))); 438e8d8bef9SDimitry Andric 439e8d8bef9SDimitry Andric for (auto &KV : NameToSym) 440e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 441e8d8bef9SDimitry Andric G.makeExternal(*KV.second); 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric return Error::success(); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4468bcb0991SDimitry Andric Error markResponsibilitySymbolsLive(LinkGraph &G) const { 4470b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4488bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 449e8d8bef9SDimitry Andric if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 4508bcb0991SDimitry Andric Sym->setLive(true); 4510b57cec5SDimitry Andric return Error::success(); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4548bcb0991SDimitry Andric Error computeNamedSymbolDependencies(LinkGraph &G) { 455e8d8bef9SDimitry Andric auto &ES = MR->getTargetJITDylib().getExecutionSession(); 456*fe6060f1SDimitry Andric auto BlockDeps = computeBlockNonLocalDeps(G); 4570b57cec5SDimitry Andric 4585ffd83dbSDimitry Andric // Compute dependencies for symbols defined in the JITLink graph. 4598bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) { 4600b57cec5SDimitry Andric 4615ffd83dbSDimitry Andric // Skip local symbols: we do not track dependencies for these. 4628bcb0991SDimitry Andric if (Sym->getScope() == Scope::Local) 4630b57cec5SDimitry Andric continue; 4645ffd83dbSDimitry Andric assert(Sym->hasName() && 4655ffd83dbSDimitry Andric "Defined non-local jitlink::Symbol should have a name"); 4660b57cec5SDimitry Andric 467*fe6060f1SDimitry Andric auto &SymDeps = BlockDeps[Sym->getBlock()]; 468*fe6060f1SDimitry Andric if (SymDeps.External.empty() && SymDeps.Internal.empty()) 4695ffd83dbSDimitry Andric continue; 4705ffd83dbSDimitry Andric 4715ffd83dbSDimitry Andric auto SymName = ES.intern(Sym->getName()); 472*fe6060f1SDimitry Andric if (!SymDeps.External.empty()) 473*fe6060f1SDimitry Andric ExternalNamedSymbolDeps[SymName] = SymDeps.External; 474*fe6060f1SDimitry Andric if (!SymDeps.Internal.empty()) 475*fe6060f1SDimitry Andric InternalNamedSymbolDeps[SymName] = SymDeps.Internal; 4765ffd83dbSDimitry Andric } 4775ffd83dbSDimitry Andric 4785ffd83dbSDimitry Andric for (auto &P : Layer.Plugins) { 479*fe6060f1SDimitry Andric auto SynthDeps = P->getSyntheticSymbolDependencies(*MR); 480*fe6060f1SDimitry Andric if (SynthDeps.empty()) 4815ffd83dbSDimitry Andric continue; 4825ffd83dbSDimitry Andric 483*fe6060f1SDimitry Andric DenseSet<Block *> BlockVisited; 484*fe6060f1SDimitry Andric for (auto &KV : SynthDeps) { 4855ffd83dbSDimitry Andric auto &Name = KV.first; 486*fe6060f1SDimitry Andric auto &DepsForName = KV.second; 487*fe6060f1SDimitry Andric for (auto *Sym : DepsForName) { 488*fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) { 489*fe6060f1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()]; 490*fe6060f1SDimitry Andric for (auto &S : BDeps.Internal) 4915ffd83dbSDimitry Andric InternalNamedSymbolDeps[Name].insert(S); 492*fe6060f1SDimitry Andric for (auto &S : BDeps.External) 4935ffd83dbSDimitry Andric ExternalNamedSymbolDeps[Name].insert(S); 494*fe6060f1SDimitry Andric } else { 495*fe6060f1SDimitry Andric if (Sym->isExternal()) 496*fe6060f1SDimitry Andric ExternalNamedSymbolDeps[Name].insert( 497*fe6060f1SDimitry Andric BlockDeps.getInternedName(*Sym)); 498*fe6060f1SDimitry Andric else 499*fe6060f1SDimitry Andric InternalNamedSymbolDeps[Name].insert( 500*fe6060f1SDimitry Andric BlockDeps.getInternedName(*Sym)); 501*fe6060f1SDimitry Andric } 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric return Error::success(); 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 509*fe6060f1SDimitry Andric BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) { 510*fe6060f1SDimitry Andric // First calculate the reachable-via-non-local-symbol blocks for each block. 511*fe6060f1SDimitry Andric struct BlockInfo { 512*fe6060f1SDimitry Andric DenseSet<Block *> Dependencies; 513*fe6060f1SDimitry Andric DenseSet<Block *> Dependants; 514*fe6060f1SDimitry Andric bool DependenciesChanged = true; 5150b57cec5SDimitry Andric }; 516*fe6060f1SDimitry Andric DenseMap<Block *, BlockInfo> BlockInfos; 517*fe6060f1SDimitry Andric SmallVector<Block *> WorkList; 5180b57cec5SDimitry Andric 519*fe6060f1SDimitry Andric // Pre-allocate map entries. This prevents any iterator/reference 520*fe6060f1SDimitry Andric // invalidation in the next loop. 521*fe6060f1SDimitry Andric for (auto *B : G.blocks()) 522*fe6060f1SDimitry Andric (void)BlockInfos[B]; 523*fe6060f1SDimitry Andric 524*fe6060f1SDimitry Andric // Build initial worklist, record block dependencies/dependants and 525*fe6060f1SDimitry Andric // non-local symbol dependencies. 526*fe6060f1SDimitry Andric for (auto *B : G.blocks()) { 527*fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 528*fe6060f1SDimitry Andric for (auto &E : B->edges()) { 529*fe6060f1SDimitry Andric if (E.getTarget().getScope() == Scope::Local) { 530*fe6060f1SDimitry Andric auto &TgtB = E.getTarget().getBlock(); 531*fe6060f1SDimitry Andric if (&TgtB != B) { 532*fe6060f1SDimitry Andric BI.Dependencies.insert(&TgtB); 533*fe6060f1SDimitry Andric BlockInfos[&TgtB].Dependants.insert(B); 534*fe6060f1SDimitry Andric } 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 538*fe6060f1SDimitry Andric // If this node has both dependants and dependencies then add it to the 539*fe6060f1SDimitry Andric // worklist to propagate the dependencies to the dependants. 540*fe6060f1SDimitry Andric if (!BI.Dependants.empty() && !BI.Dependencies.empty()) 541*fe6060f1SDimitry Andric WorkList.push_back(B); 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 544*fe6060f1SDimitry Andric // Propagate block-level dependencies through the block-dependence graph. 545*fe6060f1SDimitry Andric while (!WorkList.empty()) { 546*fe6060f1SDimitry Andric auto *B = WorkList.back(); 547*fe6060f1SDimitry Andric WorkList.pop_back(); 5480b57cec5SDimitry Andric 549*fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 550*fe6060f1SDimitry Andric assert(BI.DependenciesChanged && 551*fe6060f1SDimitry Andric "Block in worklist has unchanged dependencies"); 552*fe6060f1SDimitry Andric BI.DependenciesChanged = false; 553*fe6060f1SDimitry Andric for (auto *Dependant : BI.Dependants) { 554*fe6060f1SDimitry Andric auto &DependantBI = BlockInfos[Dependant]; 555*fe6060f1SDimitry Andric for (auto *Dependency : BI.Dependencies) { 556*fe6060f1SDimitry Andric if (Dependant != Dependency && 557*fe6060f1SDimitry Andric DependantBI.Dependencies.insert(Dependency).second) 558*fe6060f1SDimitry Andric if (!DependantBI.DependenciesChanged) { 559*fe6060f1SDimitry Andric DependantBI.DependenciesChanged = true; 560*fe6060f1SDimitry Andric WorkList.push_back(Dependant); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric } 5635ffd83dbSDimitry Andric } 5645ffd83dbSDimitry Andric } 5655ffd83dbSDimitry Andric 566*fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 567*fe6060f1SDimitry Andric for (auto &KV : BlockInfos) 568*fe6060f1SDimitry Andric BlockDeps[KV.first] = std::move(KV.second.Dependencies); 569*fe6060f1SDimitry Andric 570*fe6060f1SDimitry Andric return BlockDependenciesMap(Layer.getExecutionSession(), 571*fe6060f1SDimitry Andric std::move(BlockDeps)); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric void registerDependencies(const SymbolDependenceMap &QueryDeps) { 5755ffd83dbSDimitry Andric for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 5760b57cec5SDimitry Andric auto &Name = NamedDepsEntry.first; 5770b57cec5SDimitry Andric auto &NameDeps = NamedDepsEntry.second; 5780b57cec5SDimitry Andric SymbolDependenceMap SymbolDeps; 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric for (const auto &QueryDepsEntry : QueryDeps) { 5810b57cec5SDimitry Andric JITDylib &SourceJD = *QueryDepsEntry.first; 5820b57cec5SDimitry Andric const SymbolNameSet &Symbols = QueryDepsEntry.second; 5830b57cec5SDimitry Andric auto &DepsForJD = SymbolDeps[&SourceJD]; 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric for (const auto &S : Symbols) 5860b57cec5SDimitry Andric if (NameDeps.count(S)) 5870b57cec5SDimitry Andric DepsForJD.insert(S); 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric if (DepsForJD.empty()) 5900b57cec5SDimitry Andric SymbolDeps.erase(&SourceJD); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 593e8d8bef9SDimitry Andric MR->addDependencies(Name, SymbolDeps); 5940b57cec5SDimitry Andric } 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric ObjectLinkingLayer &Layer; 598e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR; 5990b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer; 6005ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 6015ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 6020b57cec5SDimitry Andric }; 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() {} 6050b57cec5SDimitry Andric 606*fe6060f1SDimitry Andric char ObjectLinkingLayer::ID; 607*fe6060f1SDimitry Andric 608*fe6060f1SDimitry Andric using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 609*fe6060f1SDimitry Andric 610*fe6060f1SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 611*fe6060f1SDimitry Andric : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 612*fe6060f1SDimitry Andric ES.registerResourceManager(*this); 613*fe6060f1SDimitry Andric } 614*fe6060f1SDimitry Andric 615e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 616e8d8bef9SDimitry Andric JITLinkMemoryManager &MemMgr) 617*fe6060f1SDimitry Andric : BaseT(ES), MemMgr(MemMgr) { 618e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 621e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer( 622e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 623*fe6060f1SDimitry Andric : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 624e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 625e8d8bef9SDimitry Andric } 626e8d8bef9SDimitry Andric 627e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() { 628e8d8bef9SDimitry Andric assert(Allocs.empty() && "Layer destroyed with resources still attached"); 629e8d8bef9SDimitry Andric getExecutionSession().deregisterResourceManager(*this); 630e8d8bef9SDimitry Andric } 631e8d8bef9SDimitry Andric 632*fe6060f1SDimitry Andric Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 633*fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G) { 634*fe6060f1SDimitry Andric auto &JD = RT->getJITDylib(); 635*fe6060f1SDimitry Andric return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 636*fe6060f1SDimitry Andric std::move(RT)); 637*fe6060f1SDimitry Andric } 638*fe6060f1SDimitry Andric 639e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 6400b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 6410b57cec5SDimitry Andric assert(O && "Object must not be null"); 642*fe6060f1SDimitry Andric MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 643*fe6060f1SDimitry Andric 644e8d8bef9SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 645e8d8bef9SDimitry Andric *this, std::move(R), std::move(O)); 646*fe6060f1SDimitry Andric if (auto G = createLinkGraphFromObject(ObjBuffer)) { 647*fe6060f1SDimitry Andric Ctx->notifyMaterializing(**G); 648e8d8bef9SDimitry Andric link(std::move(*G), std::move(Ctx)); 649*fe6060f1SDimitry Andric } else { 650e8d8bef9SDimitry Andric Ctx->notifyFailed(G.takeError()); 651e8d8bef9SDimitry Andric } 652*fe6060f1SDimitry Andric } 653e8d8bef9SDimitry Andric 654e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 655e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G) { 656*fe6060f1SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 657*fe6060f1SDimitry Andric *this, std::move(R), nullptr); 658*fe6060f1SDimitry Andric Ctx->notifyMaterializing(*G); 659*fe6060f1SDimitry Andric link(std::move(G), std::move(Ctx)); 6600b57cec5SDimitry Andric } 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 663*fe6060f1SDimitry Andric LinkGraph &G, 6640b57cec5SDimitry Andric PassConfiguration &PassConfig) { 6650b57cec5SDimitry Andric for (auto &P : Plugins) 666*fe6060f1SDimitry Andric P->modifyPassConfig(MR, G, PassConfig); 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 6700b57cec5SDimitry Andric for (auto &P : Plugins) 6710b57cec5SDimitry Andric P->notifyLoaded(MR); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 6750b57cec5SDimitry Andric AllocPtr Alloc) { 6760b57cec5SDimitry Andric Error Err = Error::success(); 6770b57cec5SDimitry Andric for (auto &P : Plugins) 6780b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric if (Err) 6810b57cec5SDimitry Andric return Err; 6820b57cec5SDimitry Andric 683e8d8bef9SDimitry Andric return MR.withResourceKeyDo( 684e8d8bef9SDimitry Andric [&](ResourceKey K) { Allocs[K].push_back(std::move(Alloc)); }); 6850b57cec5SDimitry Andric } 6860b57cec5SDimitry Andric 687e8d8bef9SDimitry Andric Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) { 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric Error Err = Error::success(); 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric for (auto &P : Plugins) 692e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingResources(K)); 6930b57cec5SDimitry Andric 694e8d8bef9SDimitry Andric std::vector<AllocPtr> AllocsToRemove; 695e8d8bef9SDimitry Andric getExecutionSession().runSessionLocked([&] { 696e8d8bef9SDimitry Andric auto I = Allocs.find(K); 697e8d8bef9SDimitry Andric if (I != Allocs.end()) { 698e8d8bef9SDimitry Andric std::swap(AllocsToRemove, I->second); 699e8d8bef9SDimitry Andric Allocs.erase(I); 7000b57cec5SDimitry Andric } 701e8d8bef9SDimitry Andric }); 7020b57cec5SDimitry Andric 703e8d8bef9SDimitry Andric while (!AllocsToRemove.empty()) { 704e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), AllocsToRemove.back()->deallocate()); 705e8d8bef9SDimitry Andric AllocsToRemove.pop_back(); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric return Err; 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric 711e8d8bef9SDimitry Andric void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey, 712e8d8bef9SDimitry Andric ResourceKey SrcKey) { 713e8d8bef9SDimitry Andric auto I = Allocs.find(SrcKey); 714e8d8bef9SDimitry Andric if (I != Allocs.end()) { 715e8d8bef9SDimitry Andric auto &SrcAllocs = I->second; 716e8d8bef9SDimitry Andric auto &DstAllocs = Allocs[DstKey]; 717e8d8bef9SDimitry Andric DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 718e8d8bef9SDimitry Andric for (auto &Alloc : SrcAllocs) 719e8d8bef9SDimitry Andric DstAllocs.push_back(std::move(Alloc)); 720e8d8bef9SDimitry Andric 721e8d8bef9SDimitry Andric // Erase SrcKey entry using value rather than iterator I: I may have been 722e8d8bef9SDimitry Andric // invalidated when we looked up DstKey. 723e8d8bef9SDimitry Andric Allocs.erase(SrcKey); 724e8d8bef9SDimitry Andric } 725e8d8bef9SDimitry Andric 726e8d8bef9SDimitry Andric for (auto &P : Plugins) 727e8d8bef9SDimitry Andric P->notifyTransferringResources(DstKey, SrcKey); 728e8d8bef9SDimitry Andric } 729e8d8bef9SDimitry Andric 7300b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 731e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 732e8d8bef9SDimitry Andric : ES(ES), Registrar(std::move(Registrar)) {} 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig( 735*fe6060f1SDimitry Andric MaterializationResponsibility &MR, LinkGraph &G, 7360b57cec5SDimitry Andric PassConfiguration &PassConfig) { 7370b57cec5SDimitry Andric 7385ffd83dbSDimitry Andric PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 739*fe6060f1SDimitry Andric G.getTargetTriple(), [this, &MR](JITTargetAddress Addr, size_t Size) { 7405ffd83dbSDimitry Andric if (Addr) { 7415ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7425ffd83dbSDimitry Andric assert(!InProcessLinks.count(&MR) && 7435ffd83dbSDimitry Andric "Link for MR already being tracked?"); 7448bcb0991SDimitry Andric InProcessLinks[&MR] = {Addr, Size}; 7455ffd83dbSDimitry Andric } 7460b57cec5SDimitry Andric })); 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted( 7500b57cec5SDimitry Andric MaterializationResponsibility &MR) { 751e8d8bef9SDimitry Andric 752e8d8bef9SDimitry Andric EHFrameRange EmittedRange; 753e8d8bef9SDimitry Andric { 7545ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7550b57cec5SDimitry Andric 7568bcb0991SDimitry Andric auto EHFrameRangeItr = InProcessLinks.find(&MR); 7578bcb0991SDimitry Andric if (EHFrameRangeItr == InProcessLinks.end()) 7580b57cec5SDimitry Andric return Error::success(); 7590b57cec5SDimitry Andric 760e8d8bef9SDimitry Andric EmittedRange = EHFrameRangeItr->second; 761e8d8bef9SDimitry Andric assert(EmittedRange.Addr && "eh-frame addr to register can not be null"); 7628bcb0991SDimitry Andric InProcessLinks.erase(EHFrameRangeItr); 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric 765e8d8bef9SDimitry Andric if (auto Err = MR.withResourceKeyDo( 766e8d8bef9SDimitry Andric [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 767e8d8bef9SDimitry Andric return Err; 7685ffd83dbSDimitry Andric 769e8d8bef9SDimitry Andric return Registrar->registerEHFrames(EmittedRange.Addr, EmittedRange.Size); 770e8d8bef9SDimitry Andric } 771e8d8bef9SDimitry Andric 772e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyFailed( 773e8d8bef9SDimitry Andric MaterializationResponsibility &MR) { 774e8d8bef9SDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 775e8d8bef9SDimitry Andric InProcessLinks.erase(&MR); 7760b57cec5SDimitry Andric return Error::success(); 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 779e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) { 780e8d8bef9SDimitry Andric std::vector<EHFrameRange> RangesToRemove; 7810b57cec5SDimitry Andric 782e8d8bef9SDimitry Andric ES.runSessionLocked([&] { 783e8d8bef9SDimitry Andric auto I = EHFrameRanges.find(K); 784e8d8bef9SDimitry Andric if (I != EHFrameRanges.end()) { 785e8d8bef9SDimitry Andric RangesToRemove = std::move(I->second); 786e8d8bef9SDimitry Andric EHFrameRanges.erase(I); 787e8d8bef9SDimitry Andric } 788e8d8bef9SDimitry Andric }); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric Error Err = Error::success(); 791e8d8bef9SDimitry Andric while (!RangesToRemove.empty()) { 792e8d8bef9SDimitry Andric auto RangeToRemove = RangesToRemove.back(); 793e8d8bef9SDimitry Andric RangesToRemove.pop_back(); 794e8d8bef9SDimitry Andric assert(RangeToRemove.Addr && "Untracked eh-frame range must not be null"); 795e8d8bef9SDimitry Andric Err = joinErrors( 796e8d8bef9SDimitry Andric std::move(Err), 797e8d8bef9SDimitry Andric Registrar->deregisterEHFrames(RangeToRemove.Addr, RangeToRemove.Size)); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric return Err; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 803e8d8bef9SDimitry Andric void EHFrameRegistrationPlugin::notifyTransferringResources( 804e8d8bef9SDimitry Andric ResourceKey DstKey, ResourceKey SrcKey) { 805e8d8bef9SDimitry Andric auto SI = EHFrameRanges.find(SrcKey); 806*fe6060f1SDimitry Andric if (SI == EHFrameRanges.end()) 807*fe6060f1SDimitry Andric return; 808*fe6060f1SDimitry Andric 809*fe6060f1SDimitry Andric auto DI = EHFrameRanges.find(DstKey); 810*fe6060f1SDimitry Andric if (DI != EHFrameRanges.end()) { 811e8d8bef9SDimitry Andric auto &SrcRanges = SI->second; 812*fe6060f1SDimitry Andric auto &DstRanges = DI->second; 813e8d8bef9SDimitry Andric DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 814e8d8bef9SDimitry Andric for (auto &SrcRange : SrcRanges) 815e8d8bef9SDimitry Andric DstRanges.push_back(std::move(SrcRange)); 816e8d8bef9SDimitry Andric EHFrameRanges.erase(SI); 817*fe6060f1SDimitry Andric } else { 818*fe6060f1SDimitry Andric // We need to move SrcKey's ranges over without invalidating the SI 819*fe6060f1SDimitry Andric // iterator. 820*fe6060f1SDimitry Andric auto Tmp = std::move(SI->second); 821*fe6060f1SDimitry Andric EHFrameRanges.erase(SI); 822*fe6060f1SDimitry Andric EHFrameRanges[DstKey] = std::move(Tmp); 823e8d8bef9SDimitry Andric } 824e8d8bef9SDimitry Andric } 825e8d8bef9SDimitry Andric 8260b57cec5SDimitry Andric } // End namespace orc. 8270b57cec5SDimitry Andric } // End namespace llvm. 828