1*7bf8190aSLang Hames //===------ LinkGraphLinkingLayer.cpp - Link LinkGraphs with JITLink ------===// 2b3d2548dSLang Hames // 3b3d2548dSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b3d2548dSLang Hames // See https://llvm.org/LICENSE.txt for license information. 5b3d2548dSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b3d2548dSLang Hames // 7b3d2548dSLang Hames //===----------------------------------------------------------------------===// 8b3d2548dSLang Hames 9b3d2548dSLang Hames #include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h" 10b3d2548dSLang Hames #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 11b3d2548dSLang Hames #include "llvm/ExecutionEngine/JITLink/aarch32.h" 12b3d2548dSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 13b3d2548dSLang Hames #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 14b3d2548dSLang Hames #include "llvm/Support/MemoryBuffer.h" 15b3d2548dSLang Hames 16b3d2548dSLang Hames #define DEBUG_TYPE "orc" 17b3d2548dSLang Hames 18b3d2548dSLang Hames using namespace llvm; 19b3d2548dSLang Hames using namespace llvm::jitlink; 20b3d2548dSLang Hames using namespace llvm::orc; 21b3d2548dSLang Hames 22b3d2548dSLang Hames namespace { 23b3d2548dSLang Hames 24b3d2548dSLang Hames ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) { 25b3d2548dSLang Hames switch (TT.getArch()) { 26b3d2548dSLang Hames case Triple::arm: 27b3d2548dSLang Hames case Triple::armeb: 28b3d2548dSLang Hames case Triple::thumb: 29b3d2548dSLang Hames case Triple::thumbeb: 30b3d2548dSLang Hames if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) { 31b3d2548dSLang Hames // Set LSB to indicate thumb target 32b3d2548dSLang Hames assert(Sym.isCallable() && "Only callable symbols can have thumb flag"); 33b3d2548dSLang Hames assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear"); 34b3d2548dSLang Hames return Sym.getAddress() + 0x01; 35b3d2548dSLang Hames } 36b3d2548dSLang Hames return Sym.getAddress(); 37b3d2548dSLang Hames default: 38b3d2548dSLang Hames return Sym.getAddress(); 39b3d2548dSLang Hames } 40b3d2548dSLang Hames } 41b3d2548dSLang Hames 42b3d2548dSLang Hames } // end anonymous namespace 43b3d2548dSLang Hames 44b3d2548dSLang Hames namespace llvm { 45b3d2548dSLang Hames namespace orc { 46b3d2548dSLang Hames 47b3d2548dSLang Hames class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext { 48b3d2548dSLang Hames public: 49b3d2548dSLang Hames JITLinkCtx(LinkGraphLinkingLayer &Layer, 50b3d2548dSLang Hames std::unique_ptr<MaterializationResponsibility> MR, 51b3d2548dSLang Hames std::unique_ptr<MemoryBuffer> ObjBuffer) 52b3d2548dSLang Hames : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 53b3d2548dSLang Hames MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) { 54b3d2548dSLang Hames std::lock_guard<std::mutex> Lock(Layer.LayerMutex); 55b3d2548dSLang Hames Plugins = Layer.Plugins; 56b3d2548dSLang Hames } 57b3d2548dSLang Hames 58b3d2548dSLang Hames ~JITLinkCtx() { 59b3d2548dSLang Hames // If there is an object buffer return function then use it to 60b3d2548dSLang Hames // return ownership of the buffer. 61b3d2548dSLang Hames if (Layer.ReturnObjectBuffer && ObjBuffer) 62b3d2548dSLang Hames Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 63b3d2548dSLang Hames } 64b3d2548dSLang Hames 65b3d2548dSLang Hames JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 66b3d2548dSLang Hames 67b3d2548dSLang Hames void notifyMaterializing(LinkGraph &G) { 68b3d2548dSLang Hames for (auto &P : Plugins) 69b3d2548dSLang Hames P->notifyMaterializing(*MR, G, *this, 70b3d2548dSLang Hames ObjBuffer ? ObjBuffer->getMemBufferRef() 71b3d2548dSLang Hames : MemoryBufferRef()); 72b3d2548dSLang Hames } 73b3d2548dSLang Hames 74b3d2548dSLang Hames void notifyFailed(Error Err) override { 75b3d2548dSLang Hames for (auto &P : Plugins) 76b3d2548dSLang Hames Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 77b3d2548dSLang Hames Layer.getExecutionSession().reportError(std::move(Err)); 78b3d2548dSLang Hames MR->failMaterialization(); 79b3d2548dSLang Hames } 80b3d2548dSLang Hames 81b3d2548dSLang Hames void lookup(const LookupMap &Symbols, 82b3d2548dSLang Hames std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 83b3d2548dSLang Hames 84b3d2548dSLang Hames JITDylibSearchOrder LinkOrder; 85b3d2548dSLang Hames MR->getTargetJITDylib().withLinkOrderDo( 86b3d2548dSLang Hames [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 87b3d2548dSLang Hames 88b3d2548dSLang Hames auto &ES = Layer.getExecutionSession(); 89b3d2548dSLang Hames 90b3d2548dSLang Hames SymbolLookupSet LookupSet; 91b3d2548dSLang Hames for (auto &KV : Symbols) { 92b3d2548dSLang Hames orc::SymbolLookupFlags LookupFlags; 93b3d2548dSLang Hames switch (KV.second) { 94b3d2548dSLang Hames case jitlink::SymbolLookupFlags::RequiredSymbol: 95b3d2548dSLang Hames LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 96b3d2548dSLang Hames break; 97b3d2548dSLang Hames case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 98b3d2548dSLang Hames LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 99b3d2548dSLang Hames break; 100b3d2548dSLang Hames } 101b3d2548dSLang Hames LookupSet.add(KV.first, LookupFlags); 102b3d2548dSLang Hames } 103b3d2548dSLang Hames 104b3d2548dSLang Hames // OnResolve -- De-intern the symbols and pass the result to the linker. 105b3d2548dSLang Hames auto OnResolve = [LookupContinuation = 106b3d2548dSLang Hames std::move(LC)](Expected<SymbolMap> Result) mutable { 107b3d2548dSLang Hames if (!Result) 108b3d2548dSLang Hames LookupContinuation->run(Result.takeError()); 109b3d2548dSLang Hames else { 110b3d2548dSLang Hames AsyncLookupResult LR; 111b3d2548dSLang Hames for (auto &KV : *Result) 112b3d2548dSLang Hames LR[KV.first] = KV.second; 113b3d2548dSLang Hames LookupContinuation->run(std::move(LR)); 114b3d2548dSLang Hames } 115b3d2548dSLang Hames }; 116b3d2548dSLang Hames 117b3d2548dSLang Hames ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 118b3d2548dSLang Hames SymbolState::Resolved, std::move(OnResolve), 119b3d2548dSLang Hames [this](const SymbolDependenceMap &Deps) { 120b3d2548dSLang Hames // Translate LookupDeps map to SymbolSourceJD. 121b3d2548dSLang Hames for (auto &[DepJD, Deps] : Deps) 122b3d2548dSLang Hames for (auto &DepSym : Deps) 123b3d2548dSLang Hames SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD; 124b3d2548dSLang Hames }); 125b3d2548dSLang Hames } 126b3d2548dSLang Hames 127b3d2548dSLang Hames Error notifyResolved(LinkGraph &G) override { 128b3d2548dSLang Hames 129b3d2548dSLang Hames SymbolFlagsMap ExtraSymbolsToClaim; 130b3d2548dSLang Hames bool AutoClaim = Layer.AutoClaimObjectSymbols; 131b3d2548dSLang Hames 132b3d2548dSLang Hames SymbolMap InternedResult; 133b3d2548dSLang Hames for (auto *Sym : G.defined_symbols()) 134b3d2548dSLang Hames if (Sym->getScope() < Scope::SideEffectsOnly) { 135b3d2548dSLang Hames auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 136b3d2548dSLang Hames auto Flags = getJITSymbolFlagsForSymbol(*Sym); 137b3d2548dSLang Hames InternedResult[Sym->getName()] = {Ptr, Flags}; 138b3d2548dSLang Hames if (AutoClaim && !MR->getSymbols().count(Sym->getName())) { 139b3d2548dSLang Hames assert(!ExtraSymbolsToClaim.count(Sym->getName()) && 140b3d2548dSLang Hames "Duplicate symbol to claim?"); 141b3d2548dSLang Hames ExtraSymbolsToClaim[Sym->getName()] = Flags; 142b3d2548dSLang Hames } 143b3d2548dSLang Hames } 144b3d2548dSLang Hames 145b3d2548dSLang Hames for (auto *Sym : G.absolute_symbols()) 146b3d2548dSLang Hames if (Sym->getScope() < Scope::SideEffectsOnly) { 147b3d2548dSLang Hames auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 148b3d2548dSLang Hames auto Flags = getJITSymbolFlagsForSymbol(*Sym); 149b3d2548dSLang Hames InternedResult[Sym->getName()] = {Ptr, Flags}; 150b3d2548dSLang Hames if (AutoClaim && !MR->getSymbols().count(Sym->getName())) { 151b3d2548dSLang Hames assert(!ExtraSymbolsToClaim.count(Sym->getName()) && 152b3d2548dSLang Hames "Duplicate symbol to claim?"); 153b3d2548dSLang Hames ExtraSymbolsToClaim[Sym->getName()] = Flags; 154b3d2548dSLang Hames } 155b3d2548dSLang Hames } 156b3d2548dSLang Hames 157b3d2548dSLang Hames if (!ExtraSymbolsToClaim.empty()) 158b3d2548dSLang Hames if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 159b3d2548dSLang Hames return Err; 160b3d2548dSLang Hames 161b3d2548dSLang Hames { 162b3d2548dSLang Hames 163b3d2548dSLang Hames // Check that InternedResult matches up with MR->getSymbols(), overriding 164b3d2548dSLang Hames // flags if requested. 165b3d2548dSLang Hames // This guards against faulty transformations / compilers / object caches. 166b3d2548dSLang Hames 167b3d2548dSLang Hames // First check that there aren't any missing symbols. 168b3d2548dSLang Hames size_t NumMaterializationSideEffectsOnlySymbols = 0; 169b3d2548dSLang Hames SymbolNameVector MissingSymbols; 170b3d2548dSLang Hames for (auto &[Sym, Flags] : MR->getSymbols()) { 171b3d2548dSLang Hames 172b3d2548dSLang Hames auto I = InternedResult.find(Sym); 173b3d2548dSLang Hames 174b3d2548dSLang Hames // If this is a materialization-side-effects only symbol then bump 175b3d2548dSLang Hames // the counter and remove in from the result, otherwise make sure that 176b3d2548dSLang Hames // it's defined. 177b3d2548dSLang Hames if (Flags.hasMaterializationSideEffectsOnly()) 178b3d2548dSLang Hames ++NumMaterializationSideEffectsOnlySymbols; 179b3d2548dSLang Hames else if (I == InternedResult.end()) 180b3d2548dSLang Hames MissingSymbols.push_back(Sym); 181b3d2548dSLang Hames else if (Layer.OverrideObjectFlags) 182b3d2548dSLang Hames I->second.setFlags(Flags); 183b3d2548dSLang Hames } 184b3d2548dSLang Hames 185b3d2548dSLang Hames // If there were missing symbols then report the error. 186b3d2548dSLang Hames if (!MissingSymbols.empty()) 187b3d2548dSLang Hames return make_error<MissingSymbolDefinitions>( 188b3d2548dSLang Hames Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 189b3d2548dSLang Hames std::move(MissingSymbols)); 190b3d2548dSLang Hames 191b3d2548dSLang Hames // If there are more definitions than expected, add them to the 192b3d2548dSLang Hames // ExtraSymbols vector. 193b3d2548dSLang Hames SymbolNameVector ExtraSymbols; 194b3d2548dSLang Hames if (InternedResult.size() > 195b3d2548dSLang Hames MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 196b3d2548dSLang Hames for (auto &KV : InternedResult) 197b3d2548dSLang Hames if (!MR->getSymbols().count(KV.first)) 198b3d2548dSLang Hames ExtraSymbols.push_back(KV.first); 199b3d2548dSLang Hames } 200b3d2548dSLang Hames 201b3d2548dSLang Hames // If there were extra definitions then report the error. 202b3d2548dSLang Hames if (!ExtraSymbols.empty()) 203b3d2548dSLang Hames return make_error<UnexpectedSymbolDefinitions>( 204b3d2548dSLang Hames Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 205b3d2548dSLang Hames std::move(ExtraSymbols)); 206b3d2548dSLang Hames } 207b3d2548dSLang Hames 208b3d2548dSLang Hames if (auto Err = MR->notifyResolved(InternedResult)) 209b3d2548dSLang Hames return Err; 210b3d2548dSLang Hames 211b3d2548dSLang Hames notifyLoaded(); 212b3d2548dSLang Hames return Error::success(); 213b3d2548dSLang Hames } 214b3d2548dSLang Hames 215b3d2548dSLang Hames void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 216b3d2548dSLang Hames if (auto Err = notifyEmitted(std::move(A))) { 217b3d2548dSLang Hames Layer.getExecutionSession().reportError(std::move(Err)); 218b3d2548dSLang Hames MR->failMaterialization(); 219b3d2548dSLang Hames return; 220b3d2548dSLang Hames } 221b3d2548dSLang Hames 222b3d2548dSLang Hames if (auto Err = MR->notifyEmitted(SymbolDepGroups)) { 223b3d2548dSLang Hames Layer.getExecutionSession().reportError(std::move(Err)); 224b3d2548dSLang Hames MR->failMaterialization(); 225b3d2548dSLang Hames } 226b3d2548dSLang Hames } 227b3d2548dSLang Hames 228b3d2548dSLang Hames LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 229b3d2548dSLang Hames return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 230b3d2548dSLang Hames } 231b3d2548dSLang Hames 232b3d2548dSLang Hames Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 233b3d2548dSLang Hames // Add passes to mark duplicate defs as should-discard, and to walk the 234b3d2548dSLang Hames // link graph to build the symbol dependence graph. 235b3d2548dSLang Hames Config.PrePrunePasses.push_back([this](LinkGraph &G) { 236b3d2548dSLang Hames return claimOrExternalizeWeakAndCommonSymbols(G); 237b3d2548dSLang Hames }); 238b3d2548dSLang Hames 239b3d2548dSLang Hames for (auto &P : Plugins) 240b3d2548dSLang Hames P->modifyPassConfig(*MR, LG, Config); 241b3d2548dSLang Hames 242b3d2548dSLang Hames Config.PreFixupPasses.push_back( 243b3d2548dSLang Hames [this](LinkGraph &G) { return registerDependencies(G); }); 244b3d2548dSLang Hames 245b3d2548dSLang Hames return Error::success(); 246b3d2548dSLang Hames } 247b3d2548dSLang Hames 248b3d2548dSLang Hames void notifyLoaded() { 249b3d2548dSLang Hames for (auto &P : Plugins) 250b3d2548dSLang Hames P->notifyLoaded(*MR); 251b3d2548dSLang Hames } 252b3d2548dSLang Hames 253b3d2548dSLang Hames Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) { 254b3d2548dSLang Hames Error Err = Error::success(); 255b3d2548dSLang Hames for (auto &P : Plugins) 256b3d2548dSLang Hames Err = joinErrors(std::move(Err), P->notifyEmitted(*MR)); 257b3d2548dSLang Hames 258b3d2548dSLang Hames if (Err) { 259b3d2548dSLang Hames if (FA) 260b3d2548dSLang Hames Err = 261b3d2548dSLang Hames joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA))); 262b3d2548dSLang Hames return Err; 263b3d2548dSLang Hames } 264b3d2548dSLang Hames 265b3d2548dSLang Hames if (FA) 266b3d2548dSLang Hames return Layer.recordFinalizedAlloc(*MR, std::move(FA)); 267b3d2548dSLang Hames 268b3d2548dSLang Hames return Error::success(); 269b3d2548dSLang Hames } 270b3d2548dSLang Hames 271b3d2548dSLang Hames private: 272b3d2548dSLang Hames Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 273b3d2548dSLang Hames SymbolFlagsMap NewSymbolsToClaim; 274b3d2548dSLang Hames std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 275b3d2548dSLang Hames 276b3d2548dSLang Hames auto ProcessSymbol = [&](Symbol *Sym) { 277b3d2548dSLang Hames if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 278b3d2548dSLang Hames Sym->getScope() != Scope::Local) { 279b3d2548dSLang Hames if (!MR->getSymbols().count(Sym->getName())) { 280b3d2548dSLang Hames NewSymbolsToClaim[Sym->getName()] = 281b3d2548dSLang Hames getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 282b3d2548dSLang Hames NameToSym.push_back(std::make_pair(Sym->getName(), Sym)); 283b3d2548dSLang Hames } 284b3d2548dSLang Hames } 285b3d2548dSLang Hames }; 286b3d2548dSLang Hames 287b3d2548dSLang Hames for (auto *Sym : G.defined_symbols()) 288b3d2548dSLang Hames ProcessSymbol(Sym); 289b3d2548dSLang Hames for (auto *Sym : G.absolute_symbols()) 290b3d2548dSLang Hames ProcessSymbol(Sym); 291b3d2548dSLang Hames 292b3d2548dSLang Hames // Attempt to claim all weak defs that we're not already responsible for. 293b3d2548dSLang Hames // This may fail if the resource tracker has become defunct, but should 294b3d2548dSLang Hames // always succeed otherwise. 295b3d2548dSLang Hames if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim))) 296b3d2548dSLang Hames return Err; 297b3d2548dSLang Hames 298b3d2548dSLang Hames // Walk the list of symbols that we just tried to claim. Symbols that we're 299b3d2548dSLang Hames // responsible for are marked live. Symbols that we're not responsible for 300b3d2548dSLang Hames // are turned into external references. 301b3d2548dSLang Hames for (auto &KV : NameToSym) { 302b3d2548dSLang Hames if (MR->getSymbols().count(KV.first)) 303b3d2548dSLang Hames KV.second->setLive(true); 304b3d2548dSLang Hames else 305b3d2548dSLang Hames G.makeExternal(*KV.second); 306b3d2548dSLang Hames } 307b3d2548dSLang Hames 308b3d2548dSLang Hames return Error::success(); 309b3d2548dSLang Hames } 310b3d2548dSLang Hames 311b3d2548dSLang Hames Error markResponsibilitySymbolsLive(LinkGraph &G) const { 312b3d2548dSLang Hames for (auto *Sym : G.defined_symbols()) 313b3d2548dSLang Hames if (Sym->hasName() && MR->getSymbols().count(Sym->getName())) 314b3d2548dSLang Hames Sym->setLive(true); 315b3d2548dSLang Hames return Error::success(); 316b3d2548dSLang Hames } 317b3d2548dSLang Hames 318b3d2548dSLang Hames Error registerDependencies(LinkGraph &G) { 319b3d2548dSLang Hames 320b3d2548dSLang Hames struct BlockInfo { 321b3d2548dSLang Hames bool InWorklist = false; 322b3d2548dSLang Hames DenseSet<Symbol *> Defs; 323b3d2548dSLang Hames DenseSet<Symbol *> SymbolDeps; 324b3d2548dSLang Hames DenseSet<Block *> AnonEdges, AnonBackEdges; 325b3d2548dSLang Hames }; 326b3d2548dSLang Hames 327b3d2548dSLang Hames DenseMap<Block *, BlockInfo> BlockInfos; 328b3d2548dSLang Hames 329b3d2548dSLang Hames // Reserve space so that BlockInfos doesn't need to resize. This is 330b3d2548dSLang Hames // essential to avoid invalidating pointers to entries below. 331b3d2548dSLang Hames { 332b3d2548dSLang Hames size_t NumBlocks = 0; 333b3d2548dSLang Hames for (auto &Sec : G.sections()) 334b3d2548dSLang Hames NumBlocks += Sec.blocks_size(); 335b3d2548dSLang Hames BlockInfos.reserve(NumBlocks); 336b3d2548dSLang Hames } 337b3d2548dSLang Hames 338b3d2548dSLang Hames // Identify non-locally-scoped symbols defined by each block. 339b3d2548dSLang Hames for (auto *Sym : G.defined_symbols()) { 340b3d2548dSLang Hames if (Sym->getScope() != Scope::Local) 341b3d2548dSLang Hames BlockInfos[&Sym->getBlock()].Defs.insert(Sym); 342b3d2548dSLang Hames } 343b3d2548dSLang Hames 344b3d2548dSLang Hames // Identify the symbolic and anonymous-block dependencies for each block. 345b3d2548dSLang Hames for (auto *B : G.blocks()) { 346b3d2548dSLang Hames auto &BI = BlockInfos[B]; 347b3d2548dSLang Hames 348b3d2548dSLang Hames for (auto &E : B->edges()) { 349b3d2548dSLang Hames 350b3d2548dSLang Hames // External symbols are trivially depended on. 351b3d2548dSLang Hames if (E.getTarget().isExternal()) { 352b3d2548dSLang Hames BI.SymbolDeps.insert(&E.getTarget()); 353b3d2548dSLang Hames continue; 354b3d2548dSLang Hames } 355b3d2548dSLang Hames 356b3d2548dSLang Hames // Anonymous symbols aren't depended on at all (they're assumed to be 357b3d2548dSLang Hames // already available). 358b3d2548dSLang Hames if (E.getTarget().isAbsolute()) 359b3d2548dSLang Hames continue; 360b3d2548dSLang Hames 361b3d2548dSLang Hames // If we get here then we depend on a symbol defined by some other 362b3d2548dSLang Hames // block. 363b3d2548dSLang Hames auto &TgtBI = BlockInfos[&E.getTarget().getBlock()]; 364b3d2548dSLang Hames 365b3d2548dSLang Hames // If that block has any definitions then use the first one as the 366b3d2548dSLang Hames // "effective" dependence here (all symbols in TgtBI will become 367b3d2548dSLang Hames // ready at the same time, and chosing a single symbol to represent 368b3d2548dSLang Hames // the block keeps the SymbolDepGroup size small). 369b3d2548dSLang Hames if (!TgtBI.Defs.empty()) { 370b3d2548dSLang Hames BI.SymbolDeps.insert(*TgtBI.Defs.begin()); 371b3d2548dSLang Hames continue; 372b3d2548dSLang Hames } 373b3d2548dSLang Hames 374b3d2548dSLang Hames // Otherwise we've got a dependence on an anonymous block. Record it 375b3d2548dSLang Hames // here for back-propagating symbol dependencies below. 376b3d2548dSLang Hames BI.AnonEdges.insert(&E.getTarget().getBlock()); 377b3d2548dSLang Hames TgtBI.AnonBackEdges.insert(B); 378b3d2548dSLang Hames } 379b3d2548dSLang Hames } 380b3d2548dSLang Hames 381b3d2548dSLang Hames // Prune anonymous blocks. 382b3d2548dSLang Hames { 383b3d2548dSLang Hames std::vector<Block *> BlocksToRemove; 384b3d2548dSLang Hames for (auto &[B, BI] : BlockInfos) { 385b3d2548dSLang Hames // Skip blocks with defs. We only care about anonyous blocks. 386b3d2548dSLang Hames if (!BI.Defs.empty()) 387b3d2548dSLang Hames continue; 388b3d2548dSLang Hames 389b3d2548dSLang Hames BlocksToRemove.push_back(B); 390b3d2548dSLang Hames 391b3d2548dSLang Hames for (auto *FB : BI.AnonEdges) 392b3d2548dSLang Hames BlockInfos[FB].AnonBackEdges.erase(B); 393b3d2548dSLang Hames 394b3d2548dSLang Hames for (auto *BB : BI.AnonBackEdges) 395b3d2548dSLang Hames BlockInfos[BB].AnonEdges.erase(B); 396b3d2548dSLang Hames 397b3d2548dSLang Hames for (auto *FB : BI.AnonEdges) { 398b3d2548dSLang Hames auto &FBI = BlockInfos[FB]; 399b3d2548dSLang Hames for (auto *BB : BI.AnonBackEdges) 400b3d2548dSLang Hames FBI.AnonBackEdges.insert(BB); 401b3d2548dSLang Hames } 402b3d2548dSLang Hames 403b3d2548dSLang Hames for (auto *BB : BI.AnonBackEdges) { 404b3d2548dSLang Hames auto &BBI = BlockInfos[BB]; 405b3d2548dSLang Hames for (auto *SD : BI.SymbolDeps) 406b3d2548dSLang Hames BBI.SymbolDeps.insert(SD); 407b3d2548dSLang Hames for (auto *FB : BI.AnonEdges) 408b3d2548dSLang Hames BBI.AnonEdges.insert(FB); 409b3d2548dSLang Hames } 410b3d2548dSLang Hames } 411b3d2548dSLang Hames 412b3d2548dSLang Hames for (auto *B : BlocksToRemove) 413b3d2548dSLang Hames BlockInfos.erase(B); 414b3d2548dSLang Hames } 415b3d2548dSLang Hames 416b3d2548dSLang Hames // Build the initial dependence propagation worklist. 417b3d2548dSLang Hames std::deque<Block *> Worklist; 418b3d2548dSLang Hames for (auto &[B, BI] : BlockInfos) { 419b3d2548dSLang Hames if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) { 420b3d2548dSLang Hames Worklist.push_back(B); 421b3d2548dSLang Hames BI.InWorklist = true; 422b3d2548dSLang Hames } 423b3d2548dSLang Hames } 424b3d2548dSLang Hames 425b3d2548dSLang Hames // Propagate symbol deps through the graph. 426b3d2548dSLang Hames while (!Worklist.empty()) { 427b3d2548dSLang Hames auto *B = Worklist.front(); 428b3d2548dSLang Hames Worklist.pop_front(); 429b3d2548dSLang Hames 430b3d2548dSLang Hames auto &BI = BlockInfos[B]; 431b3d2548dSLang Hames BI.InWorklist = false; 432b3d2548dSLang Hames 433b3d2548dSLang Hames for (auto *DB : BI.AnonBackEdges) { 434b3d2548dSLang Hames auto &DBI = BlockInfos[DB]; 435b3d2548dSLang Hames for (auto *Sym : BI.SymbolDeps) { 436b3d2548dSLang Hames if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) { 437b3d2548dSLang Hames Worklist.push_back(DB); 438b3d2548dSLang Hames DBI.InWorklist = true; 439b3d2548dSLang Hames } 440b3d2548dSLang Hames } 441b3d2548dSLang Hames } 442b3d2548dSLang Hames } 443b3d2548dSLang Hames 444b3d2548dSLang Hames // Transform our local dependence information into a list of 445b3d2548dSLang Hames // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in 446b3d2548dSLang Hames // the upcoming notifyFinalized call. 447b3d2548dSLang Hames auto &TargetJD = MR->getTargetJITDylib(); 448b3d2548dSLang Hames 449b3d2548dSLang Hames for (auto &[B, BI] : BlockInfos) { 450b3d2548dSLang Hames if (!BI.Defs.empty()) { 451b3d2548dSLang Hames SymbolDepGroups.push_back(SymbolDependenceGroup()); 452b3d2548dSLang Hames auto &SDG = SymbolDepGroups.back(); 453b3d2548dSLang Hames 454b3d2548dSLang Hames for (auto *Def : BI.Defs) 455b3d2548dSLang Hames SDG.Symbols.insert(Def->getName()); 456b3d2548dSLang Hames 457b3d2548dSLang Hames for (auto *Dep : BI.SymbolDeps) { 458b3d2548dSLang Hames auto DepName = Dep->getName(); 459b3d2548dSLang Hames if (Dep->isDefined()) 460b3d2548dSLang Hames SDG.Dependencies[&TargetJD].insert(std::move(DepName)); 461b3d2548dSLang Hames else { 462b3d2548dSLang Hames auto SourceJDItr = 463b3d2548dSLang Hames SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName)); 464b3d2548dSLang Hames if (SourceJDItr != SymbolSourceJDs.end()) 465b3d2548dSLang Hames SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName)); 466b3d2548dSLang Hames } 467b3d2548dSLang Hames } 468b3d2548dSLang Hames } 469b3d2548dSLang Hames } 470b3d2548dSLang Hames 471b3d2548dSLang Hames return Error::success(); 472b3d2548dSLang Hames } 473b3d2548dSLang Hames 474b3d2548dSLang Hames LinkGraphLinkingLayer &Layer; 475b3d2548dSLang Hames std::vector<std::shared_ptr<LinkGraphLinkingLayer::Plugin>> Plugins; 476b3d2548dSLang Hames std::unique_ptr<MaterializationResponsibility> MR; 477b3d2548dSLang Hames std::unique_ptr<MemoryBuffer> ObjBuffer; 478b3d2548dSLang Hames DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs; 479b3d2548dSLang Hames std::vector<SymbolDependenceGroup> SymbolDepGroups; 480b3d2548dSLang Hames }; 481b3d2548dSLang Hames 482b3d2548dSLang Hames LinkGraphLinkingLayer::Plugin::~Plugin() = default; 483b3d2548dSLang Hames 484b3d2548dSLang Hames LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES) 485b3d2548dSLang Hames : LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 486b3d2548dSLang Hames ES.registerResourceManager(*this); 487b3d2548dSLang Hames } 488b3d2548dSLang Hames 489b3d2548dSLang Hames LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES, 490b3d2548dSLang Hames JITLinkMemoryManager &MemMgr) 491b3d2548dSLang Hames : LinkGraphLayer(ES), MemMgr(MemMgr) { 492b3d2548dSLang Hames ES.registerResourceManager(*this); 493b3d2548dSLang Hames } 494b3d2548dSLang Hames 495b3d2548dSLang Hames LinkGraphLinkingLayer::LinkGraphLinkingLayer( 496b3d2548dSLang Hames ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 497b3d2548dSLang Hames : LinkGraphLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 498b3d2548dSLang Hames ES.registerResourceManager(*this); 499b3d2548dSLang Hames } 500b3d2548dSLang Hames 501b3d2548dSLang Hames LinkGraphLinkingLayer::~LinkGraphLinkingLayer() { 502b3d2548dSLang Hames assert(Allocs.empty() && "Layer destroyed with resources still attached"); 503b3d2548dSLang Hames getExecutionSession().deregisterResourceManager(*this); 504b3d2548dSLang Hames } 505b3d2548dSLang Hames 506b3d2548dSLang Hames void LinkGraphLinkingLayer::emit( 507b3d2548dSLang Hames std::unique_ptr<MaterializationResponsibility> R, 508b3d2548dSLang Hames std::unique_ptr<LinkGraph> G) { 509b3d2548dSLang Hames assert(R && "R must not be null"); 510b3d2548dSLang Hames assert(G && "G must not be null"); 511b3d2548dSLang Hames auto Ctx = std::make_unique<JITLinkCtx>(*this, std::move(R), nullptr); 512b3d2548dSLang Hames Ctx->notifyMaterializing(*G); 513b3d2548dSLang Hames link(std::move(G), std::move(Ctx)); 514b3d2548dSLang Hames } 515b3d2548dSLang Hames 516b3d2548dSLang Hames void LinkGraphLinkingLayer::emit( 517b3d2548dSLang Hames std::unique_ptr<MaterializationResponsibility> R, 518b3d2548dSLang Hames std::unique_ptr<LinkGraph> G, std::unique_ptr<MemoryBuffer> ObjBuf) { 519b3d2548dSLang Hames assert(R && "R must not be null"); 520b3d2548dSLang Hames assert(G && "G must not be null"); 521b3d2548dSLang Hames assert(ObjBuf && "Object must not be null"); 522b3d2548dSLang Hames auto Ctx = 523b3d2548dSLang Hames std::make_unique<JITLinkCtx>(*this, std::move(R), std::move(ObjBuf)); 524b3d2548dSLang Hames Ctx->notifyMaterializing(*G); 525b3d2548dSLang Hames link(std::move(G), std::move(Ctx)); 526b3d2548dSLang Hames } 527b3d2548dSLang Hames 528b3d2548dSLang Hames Error LinkGraphLinkingLayer::recordFinalizedAlloc( 529b3d2548dSLang Hames MaterializationResponsibility &MR, FinalizedAlloc FA) { 530b3d2548dSLang Hames auto Err = MR.withResourceKeyDo( 531b3d2548dSLang Hames [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 532b3d2548dSLang Hames 533b3d2548dSLang Hames if (Err) 534b3d2548dSLang Hames Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA))); 535b3d2548dSLang Hames 536b3d2548dSLang Hames return Err; 537b3d2548dSLang Hames } 538b3d2548dSLang Hames 539b3d2548dSLang Hames Error LinkGraphLinkingLayer::handleRemoveResources(JITDylib &JD, 540b3d2548dSLang Hames ResourceKey K) { 541b3d2548dSLang Hames 542b3d2548dSLang Hames { 543b3d2548dSLang Hames Error Err = Error::success(); 544b3d2548dSLang Hames for (auto &P : Plugins) 545b3d2548dSLang Hames Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 546b3d2548dSLang Hames if (Err) 547b3d2548dSLang Hames return Err; 548b3d2548dSLang Hames } 549b3d2548dSLang Hames 550b3d2548dSLang Hames std::vector<FinalizedAlloc> AllocsToRemove; 551b3d2548dSLang Hames getExecutionSession().runSessionLocked([&] { 552b3d2548dSLang Hames auto I = Allocs.find(K); 553b3d2548dSLang Hames if (I != Allocs.end()) { 554b3d2548dSLang Hames std::swap(AllocsToRemove, I->second); 555b3d2548dSLang Hames Allocs.erase(I); 556b3d2548dSLang Hames } 557b3d2548dSLang Hames }); 558b3d2548dSLang Hames 559b3d2548dSLang Hames if (AllocsToRemove.empty()) 560b3d2548dSLang Hames return Error::success(); 561b3d2548dSLang Hames 562b3d2548dSLang Hames return MemMgr.deallocate(std::move(AllocsToRemove)); 563b3d2548dSLang Hames } 564b3d2548dSLang Hames 565b3d2548dSLang Hames void LinkGraphLinkingLayer::handleTransferResources(JITDylib &JD, 566b3d2548dSLang Hames ResourceKey DstKey, 567b3d2548dSLang Hames ResourceKey SrcKey) { 568b3d2548dSLang Hames if (Allocs.contains(SrcKey)) { 569b3d2548dSLang Hames // DstKey may not be in the DenseMap yet, so the following line may resize 570b3d2548dSLang Hames // the container and invalidate iterators and value references. 571b3d2548dSLang Hames auto &DstAllocs = Allocs[DstKey]; 572b3d2548dSLang Hames auto &SrcAllocs = Allocs[SrcKey]; 573b3d2548dSLang Hames DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 574b3d2548dSLang Hames for (auto &Alloc : SrcAllocs) 575b3d2548dSLang Hames DstAllocs.push_back(std::move(Alloc)); 576b3d2548dSLang Hames 577b3d2548dSLang Hames Allocs.erase(SrcKey); 578b3d2548dSLang Hames } 579b3d2548dSLang Hames 580b3d2548dSLang Hames for (auto &P : Plugins) 581b3d2548dSLang Hames P->notifyTransferringResources(JD, DstKey, SrcKey); 582b3d2548dSLang Hames } 583b3d2548dSLang Hames 584b3d2548dSLang Hames } // End namespace orc. 585b3d2548dSLang Hames } // End namespace llvm. 586