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 110b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 120b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include <vector> 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #define DEBUG_TYPE "orc" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric using namespace llvm::jitlink; 200b57cec5SDimitry Andric using namespace llvm::orc; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace llvm { 230b57cec5SDimitry Andric namespace orc { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 260b57cec5SDimitry Andric public: 27*e8d8bef9SDimitry Andric ObjectLinkingLayerJITLinkContext( 28*e8d8bef9SDimitry Andric ObjectLinkingLayer &Layer, 29*e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR, 300b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer) 31*e8d8bef9SDimitry Andric : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 32*e8d8bef9SDimitry Andric MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 330b57cec5SDimitry Andric 348bcb0991SDimitry Andric ~ObjectLinkingLayerJITLinkContext() { 358bcb0991SDimitry Andric // If there is an object buffer return function then use it to 368bcb0991SDimitry Andric // return ownership of the buffer. 37*e8d8bef9SDimitry Andric if (Layer.ReturnObjectBuffer && ObjBuffer) 388bcb0991SDimitry Andric Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 398bcb0991SDimitry Andric } 408bcb0991SDimitry Andric 41*e8d8bef9SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric void notifyFailed(Error Err) override { 44*e8d8bef9SDimitry Andric for (auto &P : Layer.Plugins) 45*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 460b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 47*e8d8bef9SDimitry Andric MR->failMaterialization(); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 50480093f4SDimitry Andric void lookup(const LookupMap &Symbols, 518bcb0991SDimitry Andric std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 520b57cec5SDimitry Andric 535ffd83dbSDimitry Andric JITDylibSearchOrder LinkOrder; 54*e8d8bef9SDimitry Andric MR->getTargetJITDylib().withLinkOrderDo( 555ffd83dbSDimitry Andric [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 580b57cec5SDimitry Andric 59480093f4SDimitry Andric SymbolLookupSet LookupSet; 60480093f4SDimitry Andric for (auto &KV : Symbols) { 61480093f4SDimitry Andric orc::SymbolLookupFlags LookupFlags; 62480093f4SDimitry Andric switch (KV.second) { 63480093f4SDimitry Andric case jitlink::SymbolLookupFlags::RequiredSymbol: 64480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 65480093f4SDimitry Andric break; 66480093f4SDimitry Andric case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 67480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 68480093f4SDimitry Andric break; 69480093f4SDimitry Andric } 70480093f4SDimitry Andric LookupSet.add(ES.intern(KV.first), LookupFlags); 71480093f4SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker. 74*e8d8bef9SDimitry Andric auto OnResolve = [LookupContinuation = 75*e8d8bef9SDimitry Andric std::move(LC)](Expected<SymbolMap> Result) mutable { 760b57cec5SDimitry Andric if (!Result) 778bcb0991SDimitry Andric LookupContinuation->run(Result.takeError()); 780b57cec5SDimitry Andric else { 790b57cec5SDimitry Andric AsyncLookupResult LR; 800b57cec5SDimitry Andric for (auto &KV : *Result) 810b57cec5SDimitry Andric LR[*KV.first] = KV.second; 828bcb0991SDimitry Andric LookupContinuation->run(std::move(LR)); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric }; 850b57cec5SDimitry Andric 865ffd83dbSDimitry Andric for (auto &KV : InternalNamedSymbolDeps) { 875ffd83dbSDimitry Andric SymbolDependenceMap InternalDeps; 88*e8d8bef9SDimitry Andric InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 89*e8d8bef9SDimitry Andric MR->addDependencies(KV.first, InternalDeps); 905ffd83dbSDimitry Andric } 915ffd83dbSDimitry Andric 925ffd83dbSDimitry Andric ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 93480093f4SDimitry Andric SymbolState::Resolved, std::move(OnResolve), 94480093f4SDimitry Andric [this](const SymbolDependenceMap &Deps) { 950b57cec5SDimitry Andric registerDependencies(Deps); 960b57cec5SDimitry Andric }); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 99*e8d8bef9SDimitry Andric Error notifyResolved(LinkGraph &G) override { 1000b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim; 1030b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric SymbolMap InternedResult; 1068bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 1078bcb0991SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) { 1088bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 1090b57cec5SDimitry Andric JITSymbolFlags Flags; 1100b57cec5SDimitry Andric 1118bcb0991SDimitry Andric if (Sym->isCallable()) 1120b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 1138bcb0991SDimitry Andric if (Sym->getScope() == Scope::Default) 1148bcb0991SDimitry Andric Flags |= JITSymbolFlags::Exported; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric InternedResult[InternedName] = 1178bcb0991SDimitry Andric JITEvaluatedSymbol(Sym->getAddress(), Flags); 118*e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 1190b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 1200b57cec5SDimitry Andric "Duplicate symbol to claim?"); 1210b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1258bcb0991SDimitry Andric for (auto *Sym : G.absolute_symbols()) 1268bcb0991SDimitry Andric if (Sym->hasName()) { 1278bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName()); 1280b57cec5SDimitry Andric JITSymbolFlags Flags; 1290b57cec5SDimitry Andric Flags |= JITSymbolFlags::Absolute; 1308bcb0991SDimitry Andric if (Sym->isCallable()) 1310b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 1328bcb0991SDimitry Andric if (Sym->getLinkage() == Linkage::Weak) 1338bcb0991SDimitry Andric Flags |= JITSymbolFlags::Weak; 1340b57cec5SDimitry Andric InternedResult[InternedName] = 1358bcb0991SDimitry Andric JITEvaluatedSymbol(Sym->getAddress(), Flags); 136*e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) { 1370b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 1380b57cec5SDimitry Andric "Duplicate symbol to claim?"); 1390b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty()) 144*e8d8bef9SDimitry Andric if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 145*e8d8bef9SDimitry Andric return Err; 1465ffd83dbSDimitry Andric 1475ffd83dbSDimitry Andric { 1485ffd83dbSDimitry Andric 149*e8d8bef9SDimitry Andric // Check that InternedResult matches up with MR->getSymbols(). 1505ffd83dbSDimitry Andric // This guards against faulty transformations / compilers / object caches. 1515ffd83dbSDimitry Andric 1525ffd83dbSDimitry Andric // First check that there aren't any missing symbols. 1535ffd83dbSDimitry Andric size_t NumMaterializationSideEffectsOnlySymbols = 0; 1545ffd83dbSDimitry Andric SymbolNameVector ExtraSymbols; 1555ffd83dbSDimitry Andric SymbolNameVector MissingSymbols; 156*e8d8bef9SDimitry Andric for (auto &KV : MR->getSymbols()) { 1575ffd83dbSDimitry Andric 1585ffd83dbSDimitry Andric // If this is a materialization-side-effects only symbol then bump 1595ffd83dbSDimitry Andric // the counter and make sure it's *not* defined, otherwise make 1605ffd83dbSDimitry Andric // sure that it is defined. 1615ffd83dbSDimitry Andric if (KV.second.hasMaterializationSideEffectsOnly()) { 1625ffd83dbSDimitry Andric ++NumMaterializationSideEffectsOnlySymbols; 1635ffd83dbSDimitry Andric if (InternedResult.count(KV.first)) 1645ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 1655ffd83dbSDimitry Andric continue; 1665ffd83dbSDimitry Andric } else if (!InternedResult.count(KV.first)) 1675ffd83dbSDimitry Andric MissingSymbols.push_back(KV.first); 1685ffd83dbSDimitry Andric } 1695ffd83dbSDimitry Andric 1705ffd83dbSDimitry Andric // If there were missing symbols then report the error. 171*e8d8bef9SDimitry Andric if (!MissingSymbols.empty()) 172*e8d8bef9SDimitry Andric return make_error<MissingSymbolDefinitions>(G.getName(), 173*e8d8bef9SDimitry Andric std::move(MissingSymbols)); 1745ffd83dbSDimitry Andric 1755ffd83dbSDimitry Andric // If there are more definitions than expected, add them to the 1765ffd83dbSDimitry Andric // ExtraSymbols vector. 1775ffd83dbSDimitry Andric if (InternedResult.size() > 178*e8d8bef9SDimitry Andric MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 1795ffd83dbSDimitry Andric for (auto &KV : InternedResult) 180*e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 1815ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first); 1825ffd83dbSDimitry Andric } 1835ffd83dbSDimitry Andric 1845ffd83dbSDimitry Andric // If there were extra definitions then report the error. 185*e8d8bef9SDimitry Andric if (!ExtraSymbols.empty()) 186*e8d8bef9SDimitry Andric return make_error<UnexpectedSymbolDefinitions>(G.getName(), 187*e8d8bef9SDimitry Andric std::move(ExtraSymbols)); 1885ffd83dbSDimitry Andric } 1895ffd83dbSDimitry Andric 190*e8d8bef9SDimitry Andric if (auto Err = MR->notifyResolved(InternedResult)) 191*e8d8bef9SDimitry Andric return Err; 192*e8d8bef9SDimitry Andric 193*e8d8bef9SDimitry Andric Layer.notifyLoaded(*MR); 194*e8d8bef9SDimitry Andric return Error::success(); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric void notifyFinalized( 1980b57cec5SDimitry Andric std::unique_ptr<JITLinkMemoryManager::Allocation> A) override { 199*e8d8bef9SDimitry Andric if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 2000b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 201*e8d8bef9SDimitry Andric MR->failMaterialization(); 2020b57cec5SDimitry Andric return; 2030b57cec5SDimitry Andric } 204*e8d8bef9SDimitry Andric if (auto Err = MR->notifyEmitted()) { 2058bcb0991SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 206*e8d8bef9SDimitry Andric MR->failMaterialization(); 2078bcb0991SDimitry Andric } 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2108bcb0991SDimitry Andric LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 2118bcb0991SDimitry Andric return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override { 2150b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the 2168bcb0991SDimitry Andric // link graph to build the symbol dependence graph. 217*e8d8bef9SDimitry Andric Config.PrePrunePasses.push_back([this](LinkGraph &G) { 218*e8d8bef9SDimitry Andric return claimOrExternalizeWeakAndCommonSymbols(G); 219*e8d8bef9SDimitry Andric }); 2200b57cec5SDimitry Andric 221*e8d8bef9SDimitry Andric Layer.modifyPassConfig(*MR, TT, Config); 2220b57cec5SDimitry Andric 2235ffd83dbSDimitry Andric Config.PostPrunePasses.push_back( 2245ffd83dbSDimitry Andric [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 2255ffd83dbSDimitry Andric 2260b57cec5SDimitry Andric return Error::success(); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric private: 2305ffd83dbSDimitry Andric struct LocalSymbolNamedDependencies { 2315ffd83dbSDimitry Andric SymbolNameSet Internal, External; 2325ffd83dbSDimitry Andric }; 2335ffd83dbSDimitry Andric 2345ffd83dbSDimitry Andric using LocalSymbolNamedDependenciesMap = 2355ffd83dbSDimitry Andric DenseMap<const Symbol *, LocalSymbolNamedDependencies>; 2360b57cec5SDimitry Andric 237*e8d8bef9SDimitry Andric Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 2380b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 2390b57cec5SDimitry Andric 240*e8d8bef9SDimitry Andric SymbolFlagsMap NewSymbolsToClaim; 241*e8d8bef9SDimitry Andric std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 242*e8d8bef9SDimitry Andric 243*e8d8bef9SDimitry Andric auto ProcessSymbol = [&](Symbol *Sym) { 2448bcb0991SDimitry Andric if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) { 245*e8d8bef9SDimitry Andric auto Name = ES.intern(Sym->getName()); 246*e8d8bef9SDimitry Andric if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 247*e8d8bef9SDimitry Andric JITSymbolFlags SF = JITSymbolFlags::Weak; 248*e8d8bef9SDimitry Andric if (Sym->getScope() == Scope::Default) 249*e8d8bef9SDimitry Andric SF |= JITSymbolFlags::Exported; 250*e8d8bef9SDimitry Andric NewSymbolsToClaim[Name] = SF; 251*e8d8bef9SDimitry Andric NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 2520b57cec5SDimitry Andric } 253*e8d8bef9SDimitry Andric } 254*e8d8bef9SDimitry Andric }; 255*e8d8bef9SDimitry Andric 256*e8d8bef9SDimitry Andric for (auto *Sym : G.defined_symbols()) 257*e8d8bef9SDimitry Andric ProcessSymbol(Sym); 258*e8d8bef9SDimitry Andric for (auto *Sym : G.absolute_symbols()) 259*e8d8bef9SDimitry Andric ProcessSymbol(Sym); 260*e8d8bef9SDimitry Andric 261*e8d8bef9SDimitry Andric // Attempt to claim all weak defs that we're not already responsible for. 262*e8d8bef9SDimitry Andric // This cannot fail -- any clashes will just result in rejection of our 263*e8d8bef9SDimitry Andric // claim, at which point we'll externalize that symbol. 264*e8d8bef9SDimitry Andric cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim))); 265*e8d8bef9SDimitry Andric 266*e8d8bef9SDimitry Andric for (auto &KV : NameToSym) 267*e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first)) 268*e8d8bef9SDimitry Andric G.makeExternal(*KV.second); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric return Error::success(); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2738bcb0991SDimitry Andric Error markResponsibilitySymbolsLive(LinkGraph &G) const { 2740b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 2758bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 276*e8d8bef9SDimitry Andric if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 2778bcb0991SDimitry Andric Sym->setLive(true); 2780b57cec5SDimitry Andric return Error::success(); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2818bcb0991SDimitry Andric Error computeNamedSymbolDependencies(LinkGraph &G) { 282*e8d8bef9SDimitry Andric auto &ES = MR->getTargetJITDylib().getExecutionSession(); 2835ffd83dbSDimitry Andric auto LocalDeps = computeLocalDeps(G); 2840b57cec5SDimitry Andric 2855ffd83dbSDimitry Andric // Compute dependencies for symbols defined in the JITLink graph. 2868bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) { 2870b57cec5SDimitry Andric 2885ffd83dbSDimitry Andric // Skip local symbols: we do not track dependencies for these. 2898bcb0991SDimitry Andric if (Sym->getScope() == Scope::Local) 2900b57cec5SDimitry Andric continue; 2915ffd83dbSDimitry Andric assert(Sym->hasName() && 2925ffd83dbSDimitry Andric "Defined non-local jitlink::Symbol should have a name"); 2930b57cec5SDimitry Andric 2945ffd83dbSDimitry Andric SymbolNameSet ExternalSymDeps, InternalSymDeps; 2950b57cec5SDimitry Andric 2965ffd83dbSDimitry Andric // Find internal and external named symbol dependencies. 2978bcb0991SDimitry Andric for (auto &E : Sym->getBlock().edges()) { 2988bcb0991SDimitry Andric auto &TargetSym = E.getTarget(); 2990b57cec5SDimitry Andric 3005ffd83dbSDimitry Andric if (TargetSym.getScope() != Scope::Local) { 3015ffd83dbSDimitry Andric if (TargetSym.isExternal()) 3025ffd83dbSDimitry Andric ExternalSymDeps.insert(ES.intern(TargetSym.getName())); 3035ffd83dbSDimitry Andric else if (&TargetSym != Sym) 3045ffd83dbSDimitry Andric InternalSymDeps.insert(ES.intern(TargetSym.getName())); 3055ffd83dbSDimitry Andric } else { 3068bcb0991SDimitry Andric assert(TargetSym.isDefined() && 3075ffd83dbSDimitry Andric "local symbols must be defined"); 3085ffd83dbSDimitry Andric auto I = LocalDeps.find(&TargetSym); 3095ffd83dbSDimitry Andric if (I != LocalDeps.end()) { 3105ffd83dbSDimitry Andric for (auto &S : I->second.External) 3115ffd83dbSDimitry Andric ExternalSymDeps.insert(S); 3125ffd83dbSDimitry Andric for (auto &S : I->second.Internal) 3135ffd83dbSDimitry Andric InternalSymDeps.insert(S); 3145ffd83dbSDimitry Andric } 3155ffd83dbSDimitry Andric } 3165ffd83dbSDimitry Andric } 3175ffd83dbSDimitry Andric 3185ffd83dbSDimitry Andric if (ExternalSymDeps.empty() && InternalSymDeps.empty()) 3195ffd83dbSDimitry Andric continue; 3205ffd83dbSDimitry Andric 3215ffd83dbSDimitry Andric auto SymName = ES.intern(Sym->getName()); 3225ffd83dbSDimitry Andric if (!ExternalSymDeps.empty()) 3235ffd83dbSDimitry Andric ExternalNamedSymbolDeps[SymName] = std::move(ExternalSymDeps); 3245ffd83dbSDimitry Andric if (!InternalSymDeps.empty()) 3255ffd83dbSDimitry Andric InternalNamedSymbolDeps[SymName] = std::move(InternalSymDeps); 3265ffd83dbSDimitry Andric } 3275ffd83dbSDimitry Andric 3285ffd83dbSDimitry Andric for (auto &P : Layer.Plugins) { 329*e8d8bef9SDimitry Andric auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(*MR); 3305ffd83dbSDimitry Andric if (SyntheticLocalDeps.empty()) 3315ffd83dbSDimitry Andric continue; 3325ffd83dbSDimitry Andric 3335ffd83dbSDimitry Andric for (auto &KV : SyntheticLocalDeps) { 3345ffd83dbSDimitry Andric auto &Name = KV.first; 3355ffd83dbSDimitry Andric auto &LocalDepsForName = KV.second; 3365ffd83dbSDimitry Andric for (auto *Local : LocalDepsForName) { 3375ffd83dbSDimitry Andric assert(Local->getScope() == Scope::Local && 3385ffd83dbSDimitry Andric "Dependence on non-local symbol"); 3395ffd83dbSDimitry Andric auto LocalNamedDepsItr = LocalDeps.find(Local); 3405ffd83dbSDimitry Andric if (LocalNamedDepsItr == LocalDeps.end()) 3415ffd83dbSDimitry Andric continue; 3425ffd83dbSDimitry Andric for (auto &S : LocalNamedDepsItr->second.Internal) 3435ffd83dbSDimitry Andric InternalNamedSymbolDeps[Name].insert(S); 3445ffd83dbSDimitry Andric for (auto &S : LocalNamedDepsItr->second.External) 3455ffd83dbSDimitry Andric ExternalNamedSymbolDeps[Name].insert(S); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric return Error::success(); 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3535ffd83dbSDimitry Andric LocalSymbolNamedDependenciesMap computeLocalDeps(LinkGraph &G) { 3545ffd83dbSDimitry Andric DenseMap<jitlink::Symbol *, DenseSet<jitlink::Symbol *>> DepMap; 3550b57cec5SDimitry Andric 3565ffd83dbSDimitry Andric // For all local symbols: 3570b57cec5SDimitry Andric // (1) Add their named dependencies. 3580b57cec5SDimitry Andric // (2) Add them to the worklist for further iteration if they have any 3595ffd83dbSDimitry Andric // depend on any other local symbols. 3600b57cec5SDimitry Andric struct WorklistEntry { 3615ffd83dbSDimitry Andric WorklistEntry(Symbol *Sym, DenseSet<Symbol *> LocalDeps) 3625ffd83dbSDimitry Andric : Sym(Sym), LocalDeps(std::move(LocalDeps)) {} 3630b57cec5SDimitry Andric 3648bcb0991SDimitry Andric Symbol *Sym = nullptr; 3655ffd83dbSDimitry Andric DenseSet<Symbol *> LocalDeps; 3660b57cec5SDimitry Andric }; 3670b57cec5SDimitry Andric std::vector<WorklistEntry> Worklist; 3688bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) 3695ffd83dbSDimitry Andric if (Sym->getScope() == Scope::Local) { 3708bcb0991SDimitry Andric auto &SymNamedDeps = DepMap[Sym]; 3715ffd83dbSDimitry Andric DenseSet<Symbol *> LocalDeps; 3720b57cec5SDimitry Andric 3738bcb0991SDimitry Andric for (auto &E : Sym->getBlock().edges()) { 3748bcb0991SDimitry Andric auto &TargetSym = E.getTarget(); 3755ffd83dbSDimitry Andric if (TargetSym.getScope() != Scope::Local) 3765ffd83dbSDimitry Andric SymNamedDeps.insert(&TargetSym); 3770b57cec5SDimitry Andric else { 3788bcb0991SDimitry Andric assert(TargetSym.isDefined() && 3795ffd83dbSDimitry Andric "local symbols must be defined"); 3805ffd83dbSDimitry Andric LocalDeps.insert(&TargetSym); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3845ffd83dbSDimitry Andric if (!LocalDeps.empty()) 3855ffd83dbSDimitry Andric Worklist.push_back(WorklistEntry(Sym, std::move(LocalDeps))); 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3885ffd83dbSDimitry Andric // Loop over all local symbols with local dependencies, propagating 3895ffd83dbSDimitry Andric // their respective non-local dependencies. Iterate until we hit a stable 3900b57cec5SDimitry Andric // state. 3910b57cec5SDimitry Andric bool Changed; 3920b57cec5SDimitry Andric do { 3930b57cec5SDimitry Andric Changed = false; 3940b57cec5SDimitry Andric for (auto &WLEntry : Worklist) { 3958bcb0991SDimitry Andric auto *Sym = WLEntry.Sym; 3965ffd83dbSDimitry Andric auto &NamedDeps = DepMap[Sym]; 3975ffd83dbSDimitry Andric auto &LocalDeps = WLEntry.LocalDeps; 3980b57cec5SDimitry Andric 3995ffd83dbSDimitry Andric for (auto *TargetSym : LocalDeps) { 4008bcb0991SDimitry Andric auto I = DepMap.find(TargetSym); 4010b57cec5SDimitry Andric if (I != DepMap.end()) 4020b57cec5SDimitry Andric for (const auto &S : I->second) 4035ffd83dbSDimitry Andric Changed |= NamedDeps.insert(S).second; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric } while (Changed); 4070b57cec5SDimitry Andric 4085ffd83dbSDimitry Andric // Intern the results to produce a mapping of jitlink::Symbol* to internal 4095ffd83dbSDimitry Andric // and external symbol names. 4105ffd83dbSDimitry Andric auto &ES = Layer.getExecutionSession(); 4115ffd83dbSDimitry Andric LocalSymbolNamedDependenciesMap Result; 4125ffd83dbSDimitry Andric for (auto &KV : DepMap) { 4135ffd83dbSDimitry Andric auto *Local = KV.first; 4145ffd83dbSDimitry Andric assert(Local->getScope() == Scope::Local && 4155ffd83dbSDimitry Andric "DepMap keys should all be local symbols"); 4165ffd83dbSDimitry Andric auto &LocalNamedDeps = Result[Local]; 4175ffd83dbSDimitry Andric for (auto *Named : KV.second) { 4185ffd83dbSDimitry Andric assert(Named->getScope() != Scope::Local && 4195ffd83dbSDimitry Andric "DepMap values should all be non-local symbol sets"); 4205ffd83dbSDimitry Andric if (Named->isExternal()) 4215ffd83dbSDimitry Andric LocalNamedDeps.External.insert(ES.intern(Named->getName())); 4225ffd83dbSDimitry Andric else 4235ffd83dbSDimitry Andric LocalNamedDeps.Internal.insert(ES.intern(Named->getName())); 4245ffd83dbSDimitry Andric } 4255ffd83dbSDimitry Andric } 4265ffd83dbSDimitry Andric 4275ffd83dbSDimitry Andric return Result; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric void registerDependencies(const SymbolDependenceMap &QueryDeps) { 4315ffd83dbSDimitry Andric for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 4320b57cec5SDimitry Andric auto &Name = NamedDepsEntry.first; 4330b57cec5SDimitry Andric auto &NameDeps = NamedDepsEntry.second; 4340b57cec5SDimitry Andric SymbolDependenceMap SymbolDeps; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric for (const auto &QueryDepsEntry : QueryDeps) { 4370b57cec5SDimitry Andric JITDylib &SourceJD = *QueryDepsEntry.first; 4380b57cec5SDimitry Andric const SymbolNameSet &Symbols = QueryDepsEntry.second; 4390b57cec5SDimitry Andric auto &DepsForJD = SymbolDeps[&SourceJD]; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric for (const auto &S : Symbols) 4420b57cec5SDimitry Andric if (NameDeps.count(S)) 4430b57cec5SDimitry Andric DepsForJD.insert(S); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric if (DepsForJD.empty()) 4460b57cec5SDimitry Andric SymbolDeps.erase(&SourceJD); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric 449*e8d8bef9SDimitry Andric MR->addDependencies(Name, SymbolDeps); 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric ObjectLinkingLayer &Layer; 454*e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR; 4550b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer; 4565ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 4575ffd83dbSDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 4580b57cec5SDimitry Andric }; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() {} 4610b57cec5SDimitry Andric 462*e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 463*e8d8bef9SDimitry Andric JITLinkMemoryManager &MemMgr) 464*e8d8bef9SDimitry Andric : ObjectLayer(ES), MemMgr(MemMgr) { 465*e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 468*e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer( 469*e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 470*e8d8bef9SDimitry Andric : ObjectLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 471*e8d8bef9SDimitry Andric ES.registerResourceManager(*this); 472*e8d8bef9SDimitry Andric } 473*e8d8bef9SDimitry Andric 474*e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() { 475*e8d8bef9SDimitry Andric assert(Allocs.empty() && "Layer destroyed with resources still attached"); 476*e8d8bef9SDimitry Andric getExecutionSession().deregisterResourceManager(*this); 477*e8d8bef9SDimitry Andric } 478*e8d8bef9SDimitry Andric 479*e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 4800b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 4810b57cec5SDimitry Andric assert(O && "Object must not be null"); 482*e8d8bef9SDimitry Andric auto ObjBuffer = O->getMemBufferRef(); 483*e8d8bef9SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 484*e8d8bef9SDimitry Andric *this, std::move(R), std::move(O)); 485*e8d8bef9SDimitry Andric if (auto G = createLinkGraphFromObject(std::move(ObjBuffer))) 486*e8d8bef9SDimitry Andric link(std::move(*G), std::move(Ctx)); 487*e8d8bef9SDimitry Andric else 488*e8d8bef9SDimitry Andric Ctx->notifyFailed(G.takeError()); 489*e8d8bef9SDimitry Andric } 490*e8d8bef9SDimitry Andric 491*e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 492*e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G) { 493*e8d8bef9SDimitry Andric link(std::move(G), std::make_unique<ObjectLinkingLayerJITLinkContext>( 494*e8d8bef9SDimitry Andric *this, std::move(R), nullptr)); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 4980b57cec5SDimitry Andric const Triple &TT, 4990b57cec5SDimitry Andric PassConfiguration &PassConfig) { 5000b57cec5SDimitry Andric for (auto &P : Plugins) 5010b57cec5SDimitry Andric P->modifyPassConfig(MR, TT, PassConfig); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 5050b57cec5SDimitry Andric for (auto &P : Plugins) 5060b57cec5SDimitry Andric P->notifyLoaded(MR); 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 5100b57cec5SDimitry Andric AllocPtr Alloc) { 5110b57cec5SDimitry Andric Error Err = Error::success(); 5120b57cec5SDimitry Andric for (auto &P : Plugins) 5130b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric if (Err) 5160b57cec5SDimitry Andric return Err; 5170b57cec5SDimitry Andric 518*e8d8bef9SDimitry Andric return MR.withResourceKeyDo( 519*e8d8bef9SDimitry Andric [&](ResourceKey K) { Allocs[K].push_back(std::move(Alloc)); }); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 522*e8d8bef9SDimitry Andric Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) { 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric Error Err = Error::success(); 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric for (auto &P : Plugins) 527*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingResources(K)); 5280b57cec5SDimitry Andric 529*e8d8bef9SDimitry Andric std::vector<AllocPtr> AllocsToRemove; 530*e8d8bef9SDimitry Andric getExecutionSession().runSessionLocked([&] { 531*e8d8bef9SDimitry Andric auto I = Allocs.find(K); 532*e8d8bef9SDimitry Andric if (I != Allocs.end()) { 533*e8d8bef9SDimitry Andric std::swap(AllocsToRemove, I->second); 534*e8d8bef9SDimitry Andric Allocs.erase(I); 5350b57cec5SDimitry Andric } 536*e8d8bef9SDimitry Andric }); 5370b57cec5SDimitry Andric 538*e8d8bef9SDimitry Andric while (!AllocsToRemove.empty()) { 539*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), AllocsToRemove.back()->deallocate()); 540*e8d8bef9SDimitry Andric AllocsToRemove.pop_back(); 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric return Err; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 546*e8d8bef9SDimitry Andric void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey, 547*e8d8bef9SDimitry Andric ResourceKey SrcKey) { 548*e8d8bef9SDimitry Andric auto I = Allocs.find(SrcKey); 549*e8d8bef9SDimitry Andric if (I != Allocs.end()) { 550*e8d8bef9SDimitry Andric auto &SrcAllocs = I->second; 551*e8d8bef9SDimitry Andric auto &DstAllocs = Allocs[DstKey]; 552*e8d8bef9SDimitry Andric DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 553*e8d8bef9SDimitry Andric for (auto &Alloc : SrcAllocs) 554*e8d8bef9SDimitry Andric DstAllocs.push_back(std::move(Alloc)); 555*e8d8bef9SDimitry Andric 556*e8d8bef9SDimitry Andric // Erase SrcKey entry using value rather than iterator I: I may have been 557*e8d8bef9SDimitry Andric // invalidated when we looked up DstKey. 558*e8d8bef9SDimitry Andric Allocs.erase(SrcKey); 559*e8d8bef9SDimitry Andric } 560*e8d8bef9SDimitry Andric 561*e8d8bef9SDimitry Andric for (auto &P : Plugins) 562*e8d8bef9SDimitry Andric P->notifyTransferringResources(DstKey, SrcKey); 563*e8d8bef9SDimitry Andric } 564*e8d8bef9SDimitry Andric 5650b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 566*e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 567*e8d8bef9SDimitry Andric : ES(ES), Registrar(std::move(Registrar)) {} 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig( 5700b57cec5SDimitry Andric MaterializationResponsibility &MR, const Triple &TT, 5710b57cec5SDimitry Andric PassConfiguration &PassConfig) { 5720b57cec5SDimitry Andric 5735ffd83dbSDimitry Andric PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 5745ffd83dbSDimitry Andric TT, [this, &MR](JITTargetAddress Addr, size_t Size) { 5755ffd83dbSDimitry Andric if (Addr) { 5765ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 5775ffd83dbSDimitry Andric assert(!InProcessLinks.count(&MR) && 5785ffd83dbSDimitry Andric "Link for MR already being tracked?"); 5798bcb0991SDimitry Andric InProcessLinks[&MR] = {Addr, Size}; 5805ffd83dbSDimitry Andric } 5810b57cec5SDimitry Andric })); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted( 5850b57cec5SDimitry Andric MaterializationResponsibility &MR) { 586*e8d8bef9SDimitry Andric 587*e8d8bef9SDimitry Andric EHFrameRange EmittedRange; 588*e8d8bef9SDimitry Andric { 5895ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 5900b57cec5SDimitry Andric 5918bcb0991SDimitry Andric auto EHFrameRangeItr = InProcessLinks.find(&MR); 5928bcb0991SDimitry Andric if (EHFrameRangeItr == InProcessLinks.end()) 5930b57cec5SDimitry Andric return Error::success(); 5940b57cec5SDimitry Andric 595*e8d8bef9SDimitry Andric EmittedRange = EHFrameRangeItr->second; 596*e8d8bef9SDimitry Andric assert(EmittedRange.Addr && "eh-frame addr to register can not be null"); 5978bcb0991SDimitry Andric InProcessLinks.erase(EHFrameRangeItr); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 600*e8d8bef9SDimitry Andric if (auto Err = MR.withResourceKeyDo( 601*e8d8bef9SDimitry Andric [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 602*e8d8bef9SDimitry Andric return Err; 6035ffd83dbSDimitry Andric 604*e8d8bef9SDimitry Andric return Registrar->registerEHFrames(EmittedRange.Addr, EmittedRange.Size); 605*e8d8bef9SDimitry Andric } 606*e8d8bef9SDimitry Andric 607*e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyFailed( 608*e8d8bef9SDimitry Andric MaterializationResponsibility &MR) { 609*e8d8bef9SDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 610*e8d8bef9SDimitry Andric InProcessLinks.erase(&MR); 6110b57cec5SDimitry Andric return Error::success(); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 614*e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) { 615*e8d8bef9SDimitry Andric std::vector<EHFrameRange> RangesToRemove; 6160b57cec5SDimitry Andric 617*e8d8bef9SDimitry Andric ES.runSessionLocked([&] { 618*e8d8bef9SDimitry Andric auto I = EHFrameRanges.find(K); 619*e8d8bef9SDimitry Andric if (I != EHFrameRanges.end()) { 620*e8d8bef9SDimitry Andric RangesToRemove = std::move(I->second); 621*e8d8bef9SDimitry Andric EHFrameRanges.erase(I); 622*e8d8bef9SDimitry Andric } 623*e8d8bef9SDimitry Andric }); 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric Error Err = Error::success(); 626*e8d8bef9SDimitry Andric while (!RangesToRemove.empty()) { 627*e8d8bef9SDimitry Andric auto RangeToRemove = RangesToRemove.back(); 628*e8d8bef9SDimitry Andric RangesToRemove.pop_back(); 629*e8d8bef9SDimitry Andric assert(RangeToRemove.Addr && "Untracked eh-frame range must not be null"); 630*e8d8bef9SDimitry Andric Err = joinErrors( 631*e8d8bef9SDimitry Andric std::move(Err), 632*e8d8bef9SDimitry Andric Registrar->deregisterEHFrames(RangeToRemove.Addr, RangeToRemove.Size)); 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric return Err; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 638*e8d8bef9SDimitry Andric void EHFrameRegistrationPlugin::notifyTransferringResources( 639*e8d8bef9SDimitry Andric ResourceKey DstKey, ResourceKey SrcKey) { 640*e8d8bef9SDimitry Andric auto SI = EHFrameRanges.find(SrcKey); 641*e8d8bef9SDimitry Andric if (SI != EHFrameRanges.end()) { 642*e8d8bef9SDimitry Andric auto &SrcRanges = SI->second; 643*e8d8bef9SDimitry Andric auto &DstRanges = EHFrameRanges[DstKey]; 644*e8d8bef9SDimitry Andric DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 645*e8d8bef9SDimitry Andric for (auto &SrcRange : SrcRanges) 646*e8d8bef9SDimitry Andric DstRanges.push_back(std::move(SrcRange)); 647*e8d8bef9SDimitry Andric EHFrameRanges.erase(SI); 648*e8d8bef9SDimitry Andric } 649*e8d8bef9SDimitry Andric } 650*e8d8bef9SDimitry Andric 6510b57cec5SDimitry Andric } // End namespace orc. 6520b57cec5SDimitry Andric } // End namespace llvm. 653