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" 12fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" 13fe6060f1SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 14fe6060f1SDimitry 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 23fe6060f1SDimitry Andric namespace { 24fe6060f1SDimitry Andric 25fe6060f1SDimitry Andric class LinkGraphMaterializationUnit : public MaterializationUnit { 26fe6060f1SDimitry Andric private: 27fe6060f1SDimitry Andric struct LinkGraphInterface { 28fe6060f1SDimitry Andric SymbolFlagsMap SymbolFlags; 29fe6060f1SDimitry Andric SymbolStringPtr InitSymbol; 30fe6060f1SDimitry Andric }; 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric public: 33fe6060f1SDimitry Andric static std::unique_ptr<LinkGraphMaterializationUnit> 34fe6060f1SDimitry Andric Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 35fe6060f1SDimitry Andric auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 36fe6060f1SDimitry Andric return std::unique_ptr<LinkGraphMaterializationUnit>( 37fe6060f1SDimitry Andric new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 38fe6060f1SDimitry Andric std::move(LGI))); 39fe6060f1SDimitry Andric } 40fe6060f1SDimitry Andric 41fe6060f1SDimitry Andric StringRef getName() const override { return G->getName(); } 42fe6060f1SDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 43fe6060f1SDimitry Andric ObjLinkingLayer.emit(std::move(MR), std::move(G)); 44fe6060f1SDimitry Andric } 45fe6060f1SDimitry Andric 46fe6060f1SDimitry Andric private: 47fe6060f1SDimitry Andric static LinkGraphInterface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric LinkGraphInterface LGI; 50fe6060f1SDimitry Andric 51fe6060f1SDimitry Andric for (auto *Sym : G.defined_symbols()) { 52fe6060f1SDimitry Andric // Skip local symbols. 53fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) 54fe6060f1SDimitry Andric continue; 55fe6060f1SDimitry Andric assert(Sym->hasName() && "Anonymous non-local symbol?"); 56fe6060f1SDimitry Andric 57fe6060f1SDimitry Andric JITSymbolFlags Flags; 58fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Default) 59fe6060f1SDimitry Andric Flags |= JITSymbolFlags::Exported; 60fe6060f1SDimitry Andric 61fe6060f1SDimitry Andric if (Sym->isCallable()) 62fe6060f1SDimitry Andric Flags |= JITSymbolFlags::Callable; 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags; 65fe6060f1SDimitry Andric } 66fe6060f1SDimitry Andric 67*349cc55cSDimitry Andric if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) || 68*349cc55cSDimitry Andric (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G))) 69fe6060f1SDimitry Andric LGI.InitSymbol = makeInitSymbol(ES, G); 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric return LGI; 72fe6060f1SDimitry Andric } 73fe6060f1SDimitry Andric 74fe6060f1SDimitry Andric static bool hasMachOInitSection(LinkGraph &G) { 75fe6060f1SDimitry Andric for (auto &Sec : G.sections()) 76fe6060f1SDimitry Andric if (Sec.getName() == "__DATA,__obj_selrefs" || 77fe6060f1SDimitry Andric Sec.getName() == "__DATA,__objc_classlist" || 78fe6060f1SDimitry Andric Sec.getName() == "__TEXT,__swift5_protos" || 79fe6060f1SDimitry Andric Sec.getName() == "__TEXT,__swift5_proto" || 80*349cc55cSDimitry Andric Sec.getName() == "__TEXT,__swift5_types" || 81fe6060f1SDimitry Andric Sec.getName() == "__DATA,__mod_init_func") 82fe6060f1SDimitry Andric return true; 83fe6060f1SDimitry Andric return false; 84fe6060f1SDimitry Andric } 85fe6060f1SDimitry Andric 86*349cc55cSDimitry Andric static bool hasELFInitSection(LinkGraph &G) { 87*349cc55cSDimitry Andric for (auto &Sec : G.sections()) 88*349cc55cSDimitry Andric if (Sec.getName() == ".init_array") 89*349cc55cSDimitry Andric return true; 90*349cc55cSDimitry Andric return false; 91*349cc55cSDimitry Andric } 92*349cc55cSDimitry Andric 93fe6060f1SDimitry Andric static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 94fe6060f1SDimitry Andric std::string InitSymString; 95fe6060f1SDimitry Andric raw_string_ostream(InitSymString) 96fe6060f1SDimitry Andric << "$." << G.getName() << ".__inits" << Counter++; 97fe6060f1SDimitry Andric return ES.intern(InitSymString); 98fe6060f1SDimitry Andric } 99fe6060f1SDimitry Andric 100fe6060f1SDimitry Andric LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 101fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G, 102fe6060f1SDimitry Andric LinkGraphInterface LGI) 103fe6060f1SDimitry Andric : MaterializationUnit(std::move(LGI.SymbolFlags), 104fe6060f1SDimitry Andric std::move(LGI.InitSymbol)), 105fe6060f1SDimitry Andric ObjLinkingLayer(ObjLinkingLayer), G(std::move(G)) {} 106fe6060f1SDimitry Andric 107fe6060f1SDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 108fe6060f1SDimitry Andric for (auto *Sym : G->defined_symbols()) 109fe6060f1SDimitry Andric if (Sym->getName() == *Name) { 110fe6060f1SDimitry Andric assert(Sym->getLinkage() == Linkage::Weak && 111fe6060f1SDimitry Andric "Discarding non-weak definition"); 112fe6060f1SDimitry Andric G->makeExternal(*Sym); 113fe6060f1SDimitry Andric break; 114fe6060f1SDimitry Andric } 115fe6060f1SDimitry Andric } 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric ObjectLinkingLayer &ObjLinkingLayer; 118fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G; 119fe6060f1SDimitry Andric static std::atomic<uint64_t> Counter; 120fe6060f1SDimitry Andric }; 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 123fe6060f1SDimitry Andric 124fe6060f1SDimitry Andric } // end anonymous namespace 125fe6060f1SDimitry Andric 1260b57cec5SDimitry Andric namespace llvm { 1270b57cec5SDimitry Andric namespace orc { 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 1300b57cec5SDimitry Andric public: 131e8d8bef9SDimitry Andric ObjectLinkingLayerJITLinkContext( 132e8d8bef9SDimitry Andric ObjectLinkingLayer &Layer, 133e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR, 1340b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer) 135e8d8bef9SDimitry Andric : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 136e8d8bef9SDimitry Andric MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 1370b57cec5SDimitry Andric 1388bcb0991SDimitry Andric ~ObjectLinkingLayerJITLinkContext() { 1398bcb0991SDimitry Andric // If there is an object buffer return function then use it to 1408bcb0991SDimitry Andric // return ownership of the buffer. 141e8d8bef9SDimitry Andric if (Layer.ReturnObjectBuffer && ObjBuffer) 1428bcb0991SDimitry Andric Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 1438bcb0991SDimitry Andric } 1448bcb0991SDimitry Andric 145e8d8bef9SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 1460b57cec5SDimitry Andric 147fe6060f1SDimitry Andric void notifyMaterializing(LinkGraph &G) { 148fe6060f1SDimitry Andric for (auto &P : Layer.Plugins) 149fe6060f1SDimitry Andric P->notifyMaterializing(*MR, G, *this, 150fe6060f1SDimitry Andric ObjBuffer ? ObjBuffer->getMemBufferRef() 151fe6060f1SDimitry Andric : MemoryBufferRef()); 152fe6060f1SDimitry Andric } 153fe6060f1SDimitry Andric 1540b57cec5SDimitry Andric void notifyFailed(Error Err) override { 155e8d8bef9SDimitry Andric for (auto &P : Layer.Plugins) 156e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 1570b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 158e8d8bef9SDimitry Andric MR->failMaterialization(); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 161480093f4SDimitry Andric void lookup(const LookupMap &Symbols, 1628bcb0991SDimitry Andric std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 1630b57cec5SDimitry Andric 1645ffd83dbSDimitry Andric JITDylibSearchOrder LinkOrder; 165e8d8bef9SDimitry Andric MR->getTargetJITDylib().withLinkOrderDo( 1665ffd83dbSDimitry Andric [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 1690b57cec5SDimitry Andric 170480093f4SDimitry Andric SymbolLookupSet LookupSet; 171480093f4SDimitry Andric for (auto &KV : Symbols) { 172480093f4SDimitry Andric orc::SymbolLookupFlags LookupFlags; 173480093f4SDimitry Andric switch (KV.second) { 174480093f4SDimitry Andric case jitlink::SymbolLookupFlags::RequiredSymbol: 175480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 176480093f4SDimitry Andric break; 177480093f4SDimitry Andric case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 178480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 179480093f4SDimitry Andric break; 180480093f4SDimitry Andric } 181480093f4SDimitry Andric LookupSet.add(ES.intern(KV.first), LookupFlags); 182480093f4SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker. 185e8d8bef9SDimitry Andric auto OnResolve = [LookupContinuation = 186e8d8bef9SDimitry Andric std::move(LC)](Expected<SymbolMap> Result) mutable { 1870b57cec5SDimitry Andric if (!Result) 1888bcb0991SDimitry Andric LookupContinuation->run(Result.takeError()); 1890b57cec5SDimitry Andric else { 1900b57cec5SDimitry Andric AsyncLookupResult LR; 1910b57cec5SDimitry Andric for (auto &KV : *Result) 1920b57cec5SDimitry Andric LR[*KV.first] = KV.second; 1938bcb0991SDimitry Andric LookupContinuation->run(std::move(LR)); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric }; 1960b57cec5SDimitry Andric 1975ffd83dbSDimitry Andric for (auto &KV : InternalNamedSymbolDeps) { 1985ffd83dbSDimitry Andric SymbolDependenceMap InternalDeps; 199e8d8bef9SDimitry Andric InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 200e8d8bef9SDimitry Andric MR->addDependencies(KV.first, InternalDeps); 2015ffd83dbSDimitry Andric } 2025ffd83dbSDimitry Andric 2035ffd83dbSDimitry Andric ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 204480093f4SDimitry Andric SymbolState::Resolved, std::move(OnResolve), 205480093f4SDimitry Andric [this](const SymbolDependenceMap &Deps) { 2060b57cec5SDimitry Andric registerDependencies(Deps); 2070b57cec5SDimitry Andric }); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 210e8d8bef9SDimitry Andric Error notifyResolved(LinkGraph &G) override { 2110b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim; 2140b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric SymbolMap InternedResult; 2178bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 2188bcb0991SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 2198bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 2200b57cec5SDimitry Andric JITSymbolFlags Flags; 2210b57cec5SDimitry Andric 2228bcb0991SDimitry Andric if (Sym->isCallable()) 2230b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 2248bcb0991SDimitry Andric if (Sym->getScope() == Scope::Default) 2258bcb0991SDimitry Andric Flags |= JITSymbolFlags::Exported; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric InternedResult[InternedName] = 2288bcb0991SDimitry Andric JITEvaluatedSymbol(Sym->getAddress(), Flags); 229e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2300b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2310b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2320b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2368bcb0991SDimitry Andric for (auto *Sym : G.absolute_symbols()) 2378bcb0991SDimitry Andric if (Sym->hasName()) { 2388bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 2390b57cec5SDimitry Andric JITSymbolFlags Flags; 2400b57cec5SDimitry Andric Flags |= JITSymbolFlags::Absolute; 2418bcb0991SDimitry Andric if (Sym->isCallable()) 2420b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 2438bcb0991SDimitry Andric if (Sym->getLinkage() == Linkage::Weak) 2448bcb0991SDimitry Andric Flags |= JITSymbolFlags::Weak; 2450b57cec5SDimitry Andric InternedResult[InternedName] = 2468bcb0991SDimitry Andric JITEvaluatedSymbol(Sym->getAddress(), Flags); 247e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 2480b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 2490b57cec5SDimitry Andric "Duplicate symbol to claim?"); 2500b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty()) 255e8d8bef9SDimitry Andric if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 256e8d8bef9SDimitry Andric return Err; 2575ffd83dbSDimitry Andric 2585ffd83dbSDimitry Andric { 2595ffd83dbSDimitry Andric 260e8d8bef9SDimitry Andric // Check that InternedResult matches up with MR->getSymbols(). 2615ffd83dbSDimitry Andric // This guards against faulty transformations / compilers / object caches. 2625ffd83dbSDimitry Andric 2635ffd83dbSDimitry Andric // First check that there aren't any missing symbols. 2645ffd83dbSDimitry Andric size_t NumMaterializationSideEffectsOnlySymbols = 0; 2655ffd83dbSDimitry Andric SymbolNameVector ExtraSymbols; 2665ffd83dbSDimitry Andric SymbolNameVector MissingSymbols; 267e8d8bef9SDimitry Andric for (auto &KV : MR->getSymbols()) { 2685ffd83dbSDimitry Andric 2695ffd83dbSDimitry Andric // If this is a materialization-side-effects only symbol then bump 2705ffd83dbSDimitry Andric // the counter and make sure it's *not* defined, otherwise make 2715ffd83dbSDimitry Andric // sure that it is defined. 2725ffd83dbSDimitry Andric if (KV.second.hasMaterializationSideEffectsOnly()) { 2735ffd83dbSDimitry Andric ++NumMaterializationSideEffectsOnlySymbols; 2745ffd83dbSDimitry Andric if (InternedResult.count(KV.first)) 2755ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 2765ffd83dbSDimitry Andric continue; 2775ffd83dbSDimitry Andric } else if (!InternedResult.count(KV.first)) 2785ffd83dbSDimitry Andric MissingSymbols.push_back(KV.first); 2795ffd83dbSDimitry Andric } 2805ffd83dbSDimitry Andric 2815ffd83dbSDimitry Andric // If there were missing symbols then report the error. 282e8d8bef9SDimitry Andric if (!MissingSymbols.empty()) 283*349cc55cSDimitry Andric return make_error<MissingSymbolDefinitions>( 284*349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 285e8d8bef9SDimitry Andric std::move(MissingSymbols)); 2865ffd83dbSDimitry Andric 2875ffd83dbSDimitry Andric // If there are more definitions than expected, add them to the 2885ffd83dbSDimitry Andric // ExtraSymbols vector. 2895ffd83dbSDimitry Andric if (InternedResult.size() > 290e8d8bef9SDimitry Andric MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 2915ffd83dbSDimitry Andric for (auto &KV : InternedResult) 292e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 2935ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 2945ffd83dbSDimitry Andric } 2955ffd83dbSDimitry Andric 2965ffd83dbSDimitry Andric // If there were extra definitions then report the error. 297e8d8bef9SDimitry Andric if (!ExtraSymbols.empty()) 298*349cc55cSDimitry Andric return make_error<UnexpectedSymbolDefinitions>( 299*349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 300e8d8bef9SDimitry Andric std::move(ExtraSymbols)); 3015ffd83dbSDimitry Andric } 3025ffd83dbSDimitry Andric 303e8d8bef9SDimitry Andric if (auto Err = MR->notifyResolved(InternedResult)) 304e8d8bef9SDimitry Andric return Err; 305e8d8bef9SDimitry Andric 306e8d8bef9SDimitry Andric Layer.notifyLoaded(*MR); 307e8d8bef9SDimitry Andric return Error::success(); 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 310*349cc55cSDimitry Andric void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 311e8d8bef9SDimitry Andric if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 3120b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 313e8d8bef9SDimitry Andric MR->failMaterialization(); 3140b57cec5SDimitry Andric return; 3150b57cec5SDimitry Andric } 316e8d8bef9SDimitry Andric if (auto Err = MR->notifyEmitted()) { 3178bcb0991SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 318e8d8bef9SDimitry Andric MR->failMaterialization(); 3198bcb0991SDimitry Andric } 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3228bcb0991SDimitry Andric LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 3238bcb0991SDimitry Andric return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 326fe6060f1SDimitry Andric Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 3270b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the 3288bcb0991SDimitry Andric // link graph to build the symbol dependence graph. 329e8d8bef9SDimitry Andric Config.PrePrunePasses.push_back([this](LinkGraph &G) { 330e8d8bef9SDimitry Andric return claimOrExternalizeWeakAndCommonSymbols(G); 331e8d8bef9SDimitry Andric }); 3320b57cec5SDimitry Andric 333fe6060f1SDimitry Andric Layer.modifyPassConfig(*MR, LG, Config); 3340b57cec5SDimitry Andric 3355ffd83dbSDimitry Andric Config.PostPrunePasses.push_back( 3365ffd83dbSDimitry Andric [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 3375ffd83dbSDimitry Andric 3380b57cec5SDimitry Andric return Error::success(); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric private: 342fe6060f1SDimitry Andric // Symbol name dependencies: 343fe6060f1SDimitry Andric // Internal: Defined in this graph. 344fe6060f1SDimitry Andric // External: Defined externally. 345fe6060f1SDimitry Andric struct BlockSymbolDependencies { 3465ffd83dbSDimitry Andric SymbolNameSet Internal, External; 3475ffd83dbSDimitry Andric }; 3485ffd83dbSDimitry Andric 349fe6060f1SDimitry Andric // Lazily populated map of blocks to BlockSymbolDependencies values. 350fe6060f1SDimitry Andric class BlockDependenciesMap { 351fe6060f1SDimitry Andric public: 352fe6060f1SDimitry Andric BlockDependenciesMap(ExecutionSession &ES, 353fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps) 354fe6060f1SDimitry Andric : ES(ES), BlockDeps(std::move(BlockDeps)) {} 355fe6060f1SDimitry Andric 356fe6060f1SDimitry Andric const BlockSymbolDependencies &operator[](const Block &B) { 357fe6060f1SDimitry Andric // Check the cache first. 358fe6060f1SDimitry Andric auto I = BlockTransitiveDepsCache.find(&B); 359fe6060f1SDimitry Andric if (I != BlockTransitiveDepsCache.end()) 360fe6060f1SDimitry Andric return I->second; 361fe6060f1SDimitry Andric 362fe6060f1SDimitry Andric // No value. Populate the cache. 363fe6060f1SDimitry Andric BlockSymbolDependencies BTDCacheVal; 364fe6060f1SDimitry Andric auto BDI = BlockDeps.find(&B); 365fe6060f1SDimitry Andric assert(BDI != BlockDeps.end() && "No block dependencies"); 366fe6060f1SDimitry Andric 367fe6060f1SDimitry Andric for (auto *BDep : BDI->second) { 368fe6060f1SDimitry Andric auto &BID = getBlockImmediateDeps(*BDep); 369fe6060f1SDimitry Andric for (auto &ExternalDep : BID.External) 370fe6060f1SDimitry Andric BTDCacheVal.External.insert(ExternalDep); 371fe6060f1SDimitry Andric for (auto &InternalDep : BID.Internal) 372fe6060f1SDimitry Andric BTDCacheVal.Internal.insert(InternalDep); 373fe6060f1SDimitry Andric } 374fe6060f1SDimitry Andric 375fe6060f1SDimitry Andric return BlockTransitiveDepsCache 376fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BTDCacheVal))) 377fe6060f1SDimitry Andric .first->second; 378fe6060f1SDimitry Andric } 379fe6060f1SDimitry Andric 380fe6060f1SDimitry Andric SymbolStringPtr &getInternedName(Symbol &Sym) { 381fe6060f1SDimitry Andric auto I = NameCache.find(&Sym); 382fe6060f1SDimitry Andric if (I != NameCache.end()) 383fe6060f1SDimitry Andric return I->second; 384fe6060f1SDimitry Andric 385fe6060f1SDimitry Andric return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName()))) 386fe6060f1SDimitry Andric .first->second; 387fe6060f1SDimitry Andric } 388fe6060f1SDimitry Andric 389fe6060f1SDimitry Andric private: 390fe6060f1SDimitry Andric BlockSymbolDependencies &getBlockImmediateDeps(Block &B) { 391fe6060f1SDimitry Andric // Check the cache first. 392fe6060f1SDimitry Andric auto I = BlockImmediateDepsCache.find(&B); 393fe6060f1SDimitry Andric if (I != BlockImmediateDepsCache.end()) 394fe6060f1SDimitry Andric return I->second; 395fe6060f1SDimitry Andric 396fe6060f1SDimitry Andric BlockSymbolDependencies BIDCacheVal; 397fe6060f1SDimitry Andric for (auto &E : B.edges()) { 398fe6060f1SDimitry Andric auto &Tgt = E.getTarget(); 399fe6060f1SDimitry Andric if (Tgt.getScope() != Scope::Local) { 400fe6060f1SDimitry Andric if (Tgt.isExternal()) 401fe6060f1SDimitry Andric BIDCacheVal.External.insert(getInternedName(Tgt)); 402fe6060f1SDimitry Andric else 403fe6060f1SDimitry Andric BIDCacheVal.Internal.insert(getInternedName(Tgt)); 404fe6060f1SDimitry Andric } 405fe6060f1SDimitry Andric } 406fe6060f1SDimitry Andric 407fe6060f1SDimitry Andric return BlockImmediateDepsCache 408fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BIDCacheVal))) 409fe6060f1SDimitry Andric .first->second; 410fe6060f1SDimitry Andric } 411fe6060f1SDimitry Andric 412fe6060f1SDimitry Andric ExecutionSession &ES; 413fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 414fe6060f1SDimitry Andric DenseMap<const Symbol *, SymbolStringPtr> NameCache; 415fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache; 416fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache; 417fe6060f1SDimitry Andric }; 4180b57cec5SDimitry Andric 419e8d8bef9SDimitry Andric Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 4200b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4210b57cec5SDimitry Andric 422e8d8bef9SDimitry Andric SymbolFlagsMap NewSymbolsToClaim; 423e8d8bef9SDimitry Andric std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 424e8d8bef9SDimitry Andric 425e8d8bef9SDimitry Andric auto ProcessSymbol = [&](Symbol *Sym) { 426*349cc55cSDimitry Andric if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 427*349cc55cSDimitry Andric Sym->getScope() != Scope::Local) { 428e8d8bef9SDimitry Andric auto Name = ES.intern(Sym->getName()); 429e8d8bef9SDimitry Andric if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 430e8d8bef9SDimitry Andric JITSymbolFlags SF = JITSymbolFlags::Weak; 431e8d8bef9SDimitry Andric if (Sym->getScope() == Scope::Default) 432e8d8bef9SDimitry Andric SF |= JITSymbolFlags::Exported; 433e8d8bef9SDimitry Andric NewSymbolsToClaim[Name] = SF; 434e8d8bef9SDimitry Andric NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 4350b57cec5SDimitry Andric } 436e8d8bef9SDimitry Andric } 437e8d8bef9SDimitry Andric }; 438e8d8bef9SDimitry Andric 439e8d8bef9SDimitry Andric for (auto *Sym : G.defined_symbols()) 440e8d8bef9SDimitry Andric ProcessSymbol(Sym); 441e8d8bef9SDimitry Andric for (auto *Sym : G.absolute_symbols()) 442e8d8bef9SDimitry Andric ProcessSymbol(Sym); 443e8d8bef9SDimitry Andric 444e8d8bef9SDimitry Andric // Attempt to claim all weak defs that we're not already responsible for. 445e8d8bef9SDimitry Andric // This cannot fail -- any clashes will just result in rejection of our 446e8d8bef9SDimitry Andric // claim, at which point we'll externalize that symbol. 447e8d8bef9SDimitry Andric cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim))); 448e8d8bef9SDimitry Andric 449e8d8bef9SDimitry Andric for (auto &KV : NameToSym) 450e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 451e8d8bef9SDimitry Andric G.makeExternal(*KV.second); 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric return Error::success(); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4568bcb0991SDimitry Andric Error markResponsibilitySymbolsLive(LinkGraph &G) const { 4570b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 4588bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 459e8d8bef9SDimitry Andric if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 4608bcb0991SDimitry Andric Sym->setLive(true); 4610b57cec5SDimitry Andric return Error::success(); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4648bcb0991SDimitry Andric Error computeNamedSymbolDependencies(LinkGraph &G) { 465e8d8bef9SDimitry Andric auto &ES = MR->getTargetJITDylib().getExecutionSession(); 466fe6060f1SDimitry Andric auto BlockDeps = computeBlockNonLocalDeps(G); 4670b57cec5SDimitry Andric 4685ffd83dbSDimitry Andric // Compute dependencies for symbols defined in the JITLink graph. 4698bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) { 4700b57cec5SDimitry Andric 4715ffd83dbSDimitry Andric // Skip local symbols: we do not track dependencies for these. 4728bcb0991SDimitry Andric if (Sym->getScope() == Scope::Local) 4730b57cec5SDimitry Andric continue; 4745ffd83dbSDimitry Andric assert(Sym->hasName() && 4755ffd83dbSDimitry Andric "Defined non-local jitlink::Symbol should have a name"); 4760b57cec5SDimitry Andric 477fe6060f1SDimitry Andric auto &SymDeps = BlockDeps[Sym->getBlock()]; 478fe6060f1SDimitry Andric if (SymDeps.External.empty() && SymDeps.Internal.empty()) 4795ffd83dbSDimitry Andric continue; 4805ffd83dbSDimitry Andric 4815ffd83dbSDimitry Andric auto SymName = ES.intern(Sym->getName()); 482fe6060f1SDimitry Andric if (!SymDeps.External.empty()) 483fe6060f1SDimitry Andric ExternalNamedSymbolDeps[SymName] = SymDeps.External; 484fe6060f1SDimitry Andric if (!SymDeps.Internal.empty()) 485fe6060f1SDimitry Andric InternalNamedSymbolDeps[SymName] = SymDeps.Internal; 4865ffd83dbSDimitry Andric } 4875ffd83dbSDimitry Andric 4885ffd83dbSDimitry Andric for (auto &P : Layer.Plugins) { 489fe6060f1SDimitry Andric auto SynthDeps = P->getSyntheticSymbolDependencies(*MR); 490fe6060f1SDimitry Andric if (SynthDeps.empty()) 4915ffd83dbSDimitry Andric continue; 4925ffd83dbSDimitry Andric 493fe6060f1SDimitry Andric DenseSet<Block *> BlockVisited; 494fe6060f1SDimitry Andric for (auto &KV : SynthDeps) { 4955ffd83dbSDimitry Andric auto &Name = KV.first; 496fe6060f1SDimitry Andric auto &DepsForName = KV.second; 497fe6060f1SDimitry Andric for (auto *Sym : DepsForName) { 498fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) { 499fe6060f1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()]; 500fe6060f1SDimitry Andric for (auto &S : BDeps.Internal) 5015ffd83dbSDimitry Andric InternalNamedSymbolDeps[Name].insert(S); 502fe6060f1SDimitry Andric for (auto &S : BDeps.External) 5035ffd83dbSDimitry Andric ExternalNamedSymbolDeps[Name].insert(S); 504fe6060f1SDimitry Andric } else { 505fe6060f1SDimitry Andric if (Sym->isExternal()) 506fe6060f1SDimitry Andric ExternalNamedSymbolDeps[Name].insert( 507fe6060f1SDimitry Andric BlockDeps.getInternedName(*Sym)); 508fe6060f1SDimitry Andric else 509fe6060f1SDimitry Andric InternalNamedSymbolDeps[Name].insert( 510fe6060f1SDimitry Andric BlockDeps.getInternedName(*Sym)); 511fe6060f1SDimitry Andric } 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric return Error::success(); 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric 519fe6060f1SDimitry Andric BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) { 520fe6060f1SDimitry Andric // First calculate the reachable-via-non-local-symbol blocks for each block. 521fe6060f1SDimitry Andric struct BlockInfo { 522fe6060f1SDimitry Andric DenseSet<Block *> Dependencies; 523fe6060f1SDimitry Andric DenseSet<Block *> Dependants; 524fe6060f1SDimitry Andric bool DependenciesChanged = true; 5250b57cec5SDimitry Andric }; 526fe6060f1SDimitry Andric DenseMap<Block *, BlockInfo> BlockInfos; 527fe6060f1SDimitry Andric SmallVector<Block *> WorkList; 5280b57cec5SDimitry Andric 529fe6060f1SDimitry Andric // Pre-allocate map entries. This prevents any iterator/reference 530fe6060f1SDimitry Andric // invalidation in the next loop. 531fe6060f1SDimitry Andric for (auto *B : G.blocks()) 532fe6060f1SDimitry Andric (void)BlockInfos[B]; 533fe6060f1SDimitry Andric 534fe6060f1SDimitry Andric // Build initial worklist, record block dependencies/dependants and 535fe6060f1SDimitry Andric // non-local symbol dependencies. 536fe6060f1SDimitry Andric for (auto *B : G.blocks()) { 537fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 538fe6060f1SDimitry Andric for (auto &E : B->edges()) { 539fe6060f1SDimitry Andric if (E.getTarget().getScope() == Scope::Local) { 540fe6060f1SDimitry Andric auto &TgtB = E.getTarget().getBlock(); 541fe6060f1SDimitry Andric if (&TgtB != B) { 542fe6060f1SDimitry Andric BI.Dependencies.insert(&TgtB); 543fe6060f1SDimitry Andric BlockInfos[&TgtB].Dependants.insert(B); 544fe6060f1SDimitry Andric } 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 548fe6060f1SDimitry Andric // If this node has both dependants and dependencies then add it to the 549fe6060f1SDimitry Andric // worklist to propagate the dependencies to the dependants. 550fe6060f1SDimitry Andric if (!BI.Dependants.empty() && !BI.Dependencies.empty()) 551fe6060f1SDimitry Andric WorkList.push_back(B); 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 554fe6060f1SDimitry Andric // Propagate block-level dependencies through the block-dependence graph. 555fe6060f1SDimitry Andric while (!WorkList.empty()) { 556*349cc55cSDimitry Andric auto *B = WorkList.pop_back_val(); 5570b57cec5SDimitry Andric 558fe6060f1SDimitry Andric auto &BI = BlockInfos[B]; 559fe6060f1SDimitry Andric assert(BI.DependenciesChanged && 560fe6060f1SDimitry Andric "Block in worklist has unchanged dependencies"); 561fe6060f1SDimitry Andric BI.DependenciesChanged = false; 562fe6060f1SDimitry Andric for (auto *Dependant : BI.Dependants) { 563fe6060f1SDimitry Andric auto &DependantBI = BlockInfos[Dependant]; 564fe6060f1SDimitry Andric for (auto *Dependency : BI.Dependencies) { 565fe6060f1SDimitry Andric if (Dependant != Dependency && 566fe6060f1SDimitry Andric DependantBI.Dependencies.insert(Dependency).second) 567fe6060f1SDimitry Andric if (!DependantBI.DependenciesChanged) { 568fe6060f1SDimitry Andric DependantBI.DependenciesChanged = true; 569fe6060f1SDimitry Andric WorkList.push_back(Dependant); 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric } 5725ffd83dbSDimitry Andric } 5735ffd83dbSDimitry Andric } 5745ffd83dbSDimitry Andric 575fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 576fe6060f1SDimitry Andric for (auto &KV : BlockInfos) 577fe6060f1SDimitry Andric BlockDeps[KV.first] = std::move(KV.second.Dependencies); 578fe6060f1SDimitry Andric 579fe6060f1SDimitry Andric return BlockDependenciesMap(Layer.getExecutionSession(), 580fe6060f1SDimitry Andric std::move(BlockDeps)); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric void registerDependencies(const SymbolDependenceMap &QueryDeps) { 5845ffd83dbSDimitry Andric for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 5850b57cec5SDimitry Andric auto &Name = NamedDepsEntry.first; 5860b57cec5SDimitry Andric auto &NameDeps = NamedDepsEntry.second; 5870b57cec5SDimitry Andric SymbolDependenceMap SymbolDeps; 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric for (const auto &QueryDepsEntry : QueryDeps) { 5900b57cec5SDimitry Andric JITDylib &SourceJD = *QueryDepsEntry.first; 5910b57cec5SDimitry Andric const SymbolNameSet &Symbols = QueryDepsEntry.second; 5920b57cec5SDimitry Andric auto &DepsForJD = SymbolDeps[&SourceJD]; 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric for (const auto &S : Symbols) 5950b57cec5SDimitry Andric if (NameDeps.count(S)) 5960b57cec5SDimitry Andric DepsForJD.insert(S); 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric if (DepsForJD.empty()) 5990b57cec5SDimitry Andric SymbolDeps.erase(&SourceJD); 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 602e8d8bef9SDimitry Andric MR->addDependencies(Name, SymbolDeps); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric ObjectLinkingLayer &Layer; 607e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR; 6080b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer; 6095ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 6105ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 6110b57cec5SDimitry Andric }; 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() {} 6140b57cec5SDimitry Andric 615fe6060f1SDimitry Andric char ObjectLinkingLayer::ID; 616fe6060f1SDimitry Andric 617fe6060f1SDimitry Andric using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 618fe6060f1SDimitry Andric 619fe6060f1SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 620fe6060f1SDimitry Andric : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 621fe6060f1SDimitry Andric ES.registerResourceManager(*this); 622fe6060f1SDimitry Andric } 623fe6060f1SDimitry Andric 624e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 625e8d8bef9SDimitry Andric JITLinkMemoryManager &MemMgr) 626fe6060f1SDimitry Andric : BaseT(ES), MemMgr(MemMgr) { 627e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 630e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer( 631e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 632fe6060f1SDimitry Andric : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 633e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 634e8d8bef9SDimitry Andric } 635e8d8bef9SDimitry Andric 636e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() { 637e8d8bef9SDimitry Andric assert(Allocs.empty() && "Layer destroyed with resources still attached"); 638e8d8bef9SDimitry Andric getExecutionSession().deregisterResourceManager(*this); 639e8d8bef9SDimitry Andric } 640e8d8bef9SDimitry Andric 641fe6060f1SDimitry Andric Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 642fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G) { 643fe6060f1SDimitry Andric auto &JD = RT->getJITDylib(); 644fe6060f1SDimitry Andric return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 645fe6060f1SDimitry Andric std::move(RT)); 646fe6060f1SDimitry Andric } 647fe6060f1SDimitry Andric 648e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 6490b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 6500b57cec5SDimitry Andric assert(O && "Object must not be null"); 651fe6060f1SDimitry Andric MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 652fe6060f1SDimitry Andric 653e8d8bef9SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 654e8d8bef9SDimitry Andric *this, std::move(R), std::move(O)); 655fe6060f1SDimitry Andric if (auto G = createLinkGraphFromObject(ObjBuffer)) { 656fe6060f1SDimitry Andric Ctx->notifyMaterializing(**G); 657e8d8bef9SDimitry Andric link(std::move(*G), std::move(Ctx)); 658fe6060f1SDimitry Andric } else { 659e8d8bef9SDimitry Andric Ctx->notifyFailed(G.takeError()); 660e8d8bef9SDimitry Andric } 661fe6060f1SDimitry Andric } 662e8d8bef9SDimitry Andric 663e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 664e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G) { 665fe6060f1SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 666fe6060f1SDimitry Andric *this, std::move(R), nullptr); 667fe6060f1SDimitry Andric Ctx->notifyMaterializing(*G); 668fe6060f1SDimitry Andric link(std::move(G), std::move(Ctx)); 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 672fe6060f1SDimitry Andric LinkGraph &G, 6730b57cec5SDimitry Andric PassConfiguration &PassConfig) { 6740b57cec5SDimitry Andric for (auto &P : Plugins) 675fe6060f1SDimitry Andric P->modifyPassConfig(MR, G, PassConfig); 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 6790b57cec5SDimitry Andric for (auto &P : Plugins) 6800b57cec5SDimitry Andric P->notifyLoaded(MR); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 684*349cc55cSDimitry Andric FinalizedAlloc FA) { 6850b57cec5SDimitry Andric Error Err = Error::success(); 6860b57cec5SDimitry Andric for (auto &P : Plugins) 6870b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric if (Err) 6900b57cec5SDimitry Andric return Err; 6910b57cec5SDimitry Andric 692e8d8bef9SDimitry Andric return MR.withResourceKeyDo( 693*349cc55cSDimitry Andric [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 696e8d8bef9SDimitry Andric Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) { 6970b57cec5SDimitry Andric 698*349cc55cSDimitry Andric { 6990b57cec5SDimitry Andric Error Err = Error::success(); 7000b57cec5SDimitry Andric for (auto &P : Plugins) 701e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingResources(K)); 702*349cc55cSDimitry Andric if (Err) 703*349cc55cSDimitry Andric return Err; 704*349cc55cSDimitry Andric } 7050b57cec5SDimitry Andric 706*349cc55cSDimitry Andric std::vector<FinalizedAlloc> AllocsToRemove; 707e8d8bef9SDimitry Andric getExecutionSession().runSessionLocked([&] { 708e8d8bef9SDimitry Andric auto I = Allocs.find(K); 709e8d8bef9SDimitry Andric if (I != Allocs.end()) { 710e8d8bef9SDimitry Andric std::swap(AllocsToRemove, I->second); 711e8d8bef9SDimitry Andric Allocs.erase(I); 7120b57cec5SDimitry Andric } 713e8d8bef9SDimitry Andric }); 7140b57cec5SDimitry Andric 715*349cc55cSDimitry Andric if (AllocsToRemove.empty()) 716*349cc55cSDimitry Andric return Error::success(); 7170b57cec5SDimitry Andric 718*349cc55cSDimitry Andric return MemMgr.deallocate(std::move(AllocsToRemove)); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 721e8d8bef9SDimitry Andric void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey, 722e8d8bef9SDimitry Andric ResourceKey SrcKey) { 723e8d8bef9SDimitry Andric auto I = Allocs.find(SrcKey); 724e8d8bef9SDimitry Andric if (I != Allocs.end()) { 725e8d8bef9SDimitry Andric auto &SrcAllocs = I->second; 726e8d8bef9SDimitry Andric auto &DstAllocs = Allocs[DstKey]; 727e8d8bef9SDimitry Andric DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 728e8d8bef9SDimitry Andric for (auto &Alloc : SrcAllocs) 729e8d8bef9SDimitry Andric DstAllocs.push_back(std::move(Alloc)); 730e8d8bef9SDimitry Andric 731e8d8bef9SDimitry Andric // Erase SrcKey entry using value rather than iterator I: I may have been 732e8d8bef9SDimitry Andric // invalidated when we looked up DstKey. 733e8d8bef9SDimitry Andric Allocs.erase(SrcKey); 734e8d8bef9SDimitry Andric } 735e8d8bef9SDimitry Andric 736e8d8bef9SDimitry Andric for (auto &P : Plugins) 737e8d8bef9SDimitry Andric P->notifyTransferringResources(DstKey, SrcKey); 738e8d8bef9SDimitry Andric } 739e8d8bef9SDimitry Andric 7400b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 741e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 742e8d8bef9SDimitry Andric : ES(ES), Registrar(std::move(Registrar)) {} 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig( 745fe6060f1SDimitry Andric MaterializationResponsibility &MR, LinkGraph &G, 7460b57cec5SDimitry Andric PassConfiguration &PassConfig) { 7470b57cec5SDimitry Andric 7485ffd83dbSDimitry Andric PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 749fe6060f1SDimitry Andric G.getTargetTriple(), [this, &MR](JITTargetAddress Addr, size_t Size) { 7505ffd83dbSDimitry Andric if (Addr) { 7515ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7525ffd83dbSDimitry Andric assert(!InProcessLinks.count(&MR) && 7535ffd83dbSDimitry Andric "Link for MR already being tracked?"); 7548bcb0991SDimitry Andric InProcessLinks[&MR] = {Addr, Size}; 7555ffd83dbSDimitry Andric } 7560b57cec5SDimitry Andric })); 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted( 7600b57cec5SDimitry Andric MaterializationResponsibility &MR) { 761e8d8bef9SDimitry Andric 762e8d8bef9SDimitry Andric EHFrameRange EmittedRange; 763e8d8bef9SDimitry Andric { 7645ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 7650b57cec5SDimitry Andric 7668bcb0991SDimitry Andric auto EHFrameRangeItr = InProcessLinks.find(&MR); 7678bcb0991SDimitry Andric if (EHFrameRangeItr == InProcessLinks.end()) 7680b57cec5SDimitry Andric return Error::success(); 7690b57cec5SDimitry Andric 770e8d8bef9SDimitry Andric EmittedRange = EHFrameRangeItr->second; 771e8d8bef9SDimitry Andric assert(EmittedRange.Addr && "eh-frame addr to register can not be null"); 7728bcb0991SDimitry Andric InProcessLinks.erase(EHFrameRangeItr); 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 775e8d8bef9SDimitry Andric if (auto Err = MR.withResourceKeyDo( 776e8d8bef9SDimitry Andric [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 777e8d8bef9SDimitry Andric return Err; 7785ffd83dbSDimitry Andric 779e8d8bef9SDimitry Andric return Registrar->registerEHFrames(EmittedRange.Addr, EmittedRange.Size); 780e8d8bef9SDimitry Andric } 781e8d8bef9SDimitry Andric 782e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyFailed( 783e8d8bef9SDimitry Andric MaterializationResponsibility &MR) { 784e8d8bef9SDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 785e8d8bef9SDimitry Andric InProcessLinks.erase(&MR); 7860b57cec5SDimitry Andric return Error::success(); 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric 789e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) { 790e8d8bef9SDimitry Andric std::vector<EHFrameRange> RangesToRemove; 7910b57cec5SDimitry Andric 792e8d8bef9SDimitry Andric ES.runSessionLocked([&] { 793e8d8bef9SDimitry Andric auto I = EHFrameRanges.find(K); 794e8d8bef9SDimitry Andric if (I != EHFrameRanges.end()) { 795e8d8bef9SDimitry Andric RangesToRemove = std::move(I->second); 796e8d8bef9SDimitry Andric EHFrameRanges.erase(I); 797e8d8bef9SDimitry Andric } 798e8d8bef9SDimitry Andric }); 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric Error Err = Error::success(); 801e8d8bef9SDimitry Andric while (!RangesToRemove.empty()) { 802e8d8bef9SDimitry Andric auto RangeToRemove = RangesToRemove.back(); 803e8d8bef9SDimitry Andric RangesToRemove.pop_back(); 804e8d8bef9SDimitry Andric assert(RangeToRemove.Addr && "Untracked eh-frame range must not be null"); 805e8d8bef9SDimitry Andric Err = joinErrors( 806e8d8bef9SDimitry Andric std::move(Err), 807e8d8bef9SDimitry Andric Registrar->deregisterEHFrames(RangeToRemove.Addr, RangeToRemove.Size)); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric return Err; 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 813e8d8bef9SDimitry Andric void EHFrameRegistrationPlugin::notifyTransferringResources( 814e8d8bef9SDimitry Andric ResourceKey DstKey, ResourceKey SrcKey) { 815e8d8bef9SDimitry Andric auto SI = EHFrameRanges.find(SrcKey); 816fe6060f1SDimitry Andric if (SI == EHFrameRanges.end()) 817fe6060f1SDimitry Andric return; 818fe6060f1SDimitry Andric 819fe6060f1SDimitry Andric auto DI = EHFrameRanges.find(DstKey); 820fe6060f1SDimitry Andric if (DI != EHFrameRanges.end()) { 821e8d8bef9SDimitry Andric auto &SrcRanges = SI->second; 822fe6060f1SDimitry Andric auto &DstRanges = DI->second; 823e8d8bef9SDimitry Andric DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 824e8d8bef9SDimitry Andric for (auto &SrcRange : SrcRanges) 825e8d8bef9SDimitry Andric DstRanges.push_back(std::move(SrcRange)); 826e8d8bef9SDimitry Andric EHFrameRanges.erase(SI); 827fe6060f1SDimitry Andric } else { 828fe6060f1SDimitry Andric // We need to move SrcKey's ranges over without invalidating the SI 829fe6060f1SDimitry Andric // iterator. 830fe6060f1SDimitry Andric auto Tmp = std::move(SI->second); 831fe6060f1SDimitry Andric EHFrameRanges.erase(SI); 832fe6060f1SDimitry Andric EHFrameRanges[DstKey] = std::move(Tmp); 833e8d8bef9SDimitry Andric } 834e8d8bef9SDimitry Andric } 835e8d8bef9SDimitry Andric 8360b57cec5SDimitry Andric } // End namespace orc. 8370b57cec5SDimitry Andric } // End namespace llvm. 838