10b57cec5SDimitry Andric //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
100b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
1106c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch32.h"
12fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
13*0fca6ea1SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
14bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
1506c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
16fe6060f1SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
17fe6060f1SDimitry Andric #include <string>
180b57cec5SDimitry Andric #include <vector>
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric #define DEBUG_TYPE "orc"
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric using namespace llvm::jitlink;
240b57cec5SDimitry Andric using namespace llvm::orc;
250b57cec5SDimitry Andric
26fe6060f1SDimitry Andric namespace {
27fe6060f1SDimitry Andric
hasInitializerSection(jitlink::LinkGraph & G)2806c3fb27SDimitry Andric bool hasInitializerSection(jitlink::LinkGraph &G) {
2906c3fb27SDimitry Andric bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
3006c3fb27SDimitry Andric bool IsElf = G.getTargetTriple().isOSBinFormatELF();
3106c3fb27SDimitry Andric if (!IsMachO && !IsElf)
3206c3fb27SDimitry Andric return false;
3306c3fb27SDimitry Andric
3406c3fb27SDimitry Andric for (auto &Sec : G.sections()) {
3506c3fb27SDimitry Andric if (IsMachO && isMachOInitializerSection(Sec.getName()))
3606c3fb27SDimitry Andric return true;
3706c3fb27SDimitry Andric if (IsElf && isELFInitializerSection(Sec.getName()))
3806c3fb27SDimitry Andric return true;
3906c3fb27SDimitry Andric }
4006c3fb27SDimitry Andric
4106c3fb27SDimitry Andric return false;
4206c3fb27SDimitry Andric }
4306c3fb27SDimitry Andric
getJITSymbolPtrForSymbol(Symbol & Sym,const Triple & TT)4406c3fb27SDimitry Andric ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
4506c3fb27SDimitry Andric switch (TT.getArch()) {
4606c3fb27SDimitry Andric case Triple::arm:
4706c3fb27SDimitry Andric case Triple::armeb:
4806c3fb27SDimitry Andric case Triple::thumb:
4906c3fb27SDimitry Andric case Triple::thumbeb:
505f757f3fSDimitry Andric if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
5106c3fb27SDimitry Andric // Set LSB to indicate thumb target
5206c3fb27SDimitry Andric assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
5306c3fb27SDimitry Andric assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
5406c3fb27SDimitry Andric return Sym.getAddress() + 0x01;
5506c3fb27SDimitry Andric }
5606c3fb27SDimitry Andric return Sym.getAddress();
5706c3fb27SDimitry Andric default:
5806c3fb27SDimitry Andric return Sym.getAddress();
5906c3fb27SDimitry Andric }
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric
getJITSymbolFlagsForSymbol(Symbol & Sym)6206c3fb27SDimitry Andric JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
6306c3fb27SDimitry Andric JITSymbolFlags Flags;
6406c3fb27SDimitry Andric
6506c3fb27SDimitry Andric if (Sym.getLinkage() == Linkage::Weak)
6606c3fb27SDimitry Andric Flags |= JITSymbolFlags::Weak;
6706c3fb27SDimitry Andric
6806c3fb27SDimitry Andric if (Sym.getScope() == Scope::Default)
6906c3fb27SDimitry Andric Flags |= JITSymbolFlags::Exported;
7006c3fb27SDimitry Andric
7106c3fb27SDimitry Andric if (Sym.isCallable())
7206c3fb27SDimitry Andric Flags |= JITSymbolFlags::Callable;
7306c3fb27SDimitry Andric
7406c3fb27SDimitry Andric return Flags;
7506c3fb27SDimitry Andric }
7606c3fb27SDimitry Andric
77fe6060f1SDimitry Andric class LinkGraphMaterializationUnit : public MaterializationUnit {
78fe6060f1SDimitry Andric public:
79fe6060f1SDimitry Andric static std::unique_ptr<LinkGraphMaterializationUnit>
Create(ObjectLinkingLayer & ObjLinkingLayer,std::unique_ptr<LinkGraph> G)80fe6060f1SDimitry Andric Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
81fe6060f1SDimitry Andric auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
82fe6060f1SDimitry Andric return std::unique_ptr<LinkGraphMaterializationUnit>(
83fe6060f1SDimitry Andric new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
84fe6060f1SDimitry Andric std::move(LGI)));
85fe6060f1SDimitry Andric }
86fe6060f1SDimitry Andric
getName() const87fe6060f1SDimitry Andric StringRef getName() const override { return G->getName(); }
materialize(std::unique_ptr<MaterializationResponsibility> MR)88fe6060f1SDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
89fe6060f1SDimitry Andric ObjLinkingLayer.emit(std::move(MR), std::move(G));
90fe6060f1SDimitry Andric }
91fe6060f1SDimitry Andric
92fe6060f1SDimitry Andric private:
scanLinkGraph(ExecutionSession & ES,LinkGraph & G)930eae32dcSDimitry Andric static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
94fe6060f1SDimitry Andric
950eae32dcSDimitry Andric Interface LGI;
96fe6060f1SDimitry Andric
971db9f3b2SDimitry Andric auto AddSymbol = [&](Symbol *Sym) {
98fe6060f1SDimitry Andric // Skip local symbols.
99fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local)
1001db9f3b2SDimitry Andric return;
101fe6060f1SDimitry Andric assert(Sym->hasName() && "Anonymous non-local symbol?");
102fe6060f1SDimitry Andric
10306c3fb27SDimitry Andric LGI.SymbolFlags[ES.intern(Sym->getName())] =
10406c3fb27SDimitry Andric getJITSymbolFlagsForSymbol(*Sym);
1051db9f3b2SDimitry Andric };
1061db9f3b2SDimitry Andric
1071db9f3b2SDimitry Andric for (auto *Sym : G.defined_symbols())
1081db9f3b2SDimitry Andric AddSymbol(Sym);
1091db9f3b2SDimitry Andric for (auto *Sym : G.absolute_symbols())
1101db9f3b2SDimitry Andric AddSymbol(Sym);
111fe6060f1SDimitry Andric
112bdd1243dSDimitry Andric if (hasInitializerSection(G))
113fe6060f1SDimitry Andric LGI.InitSymbol = makeInitSymbol(ES, G);
114fe6060f1SDimitry Andric
115fe6060f1SDimitry Andric return LGI;
116fe6060f1SDimitry Andric }
117fe6060f1SDimitry Andric
makeInitSymbol(ExecutionSession & ES,LinkGraph & G)118fe6060f1SDimitry Andric static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
119fe6060f1SDimitry Andric std::string InitSymString;
120fe6060f1SDimitry Andric raw_string_ostream(InitSymString)
121fe6060f1SDimitry Andric << "$." << G.getName() << ".__inits" << Counter++;
122fe6060f1SDimitry Andric return ES.intern(InitSymString);
123fe6060f1SDimitry Andric }
124fe6060f1SDimitry Andric
LinkGraphMaterializationUnit(ObjectLinkingLayer & ObjLinkingLayer,std::unique_ptr<LinkGraph> G,Interface LGI)125fe6060f1SDimitry Andric LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
1260eae32dcSDimitry Andric std::unique_ptr<LinkGraph> G, Interface LGI)
1270eae32dcSDimitry Andric : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
1280eae32dcSDimitry Andric G(std::move(G)) {}
129fe6060f1SDimitry Andric
discard(const JITDylib & JD,const SymbolStringPtr & Name)130fe6060f1SDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
131fe6060f1SDimitry Andric for (auto *Sym : G->defined_symbols())
132fe6060f1SDimitry Andric if (Sym->getName() == *Name) {
133fe6060f1SDimitry Andric assert(Sym->getLinkage() == Linkage::Weak &&
134fe6060f1SDimitry Andric "Discarding non-weak definition");
135fe6060f1SDimitry Andric G->makeExternal(*Sym);
136fe6060f1SDimitry Andric break;
137fe6060f1SDimitry Andric }
138fe6060f1SDimitry Andric }
139fe6060f1SDimitry Andric
140fe6060f1SDimitry Andric ObjectLinkingLayer &ObjLinkingLayer;
141fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G;
142fe6060f1SDimitry Andric static std::atomic<uint64_t> Counter;
143fe6060f1SDimitry Andric };
144fe6060f1SDimitry Andric
145fe6060f1SDimitry Andric std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
146fe6060f1SDimitry Andric
147fe6060f1SDimitry Andric } // end anonymous namespace
148fe6060f1SDimitry Andric
1490b57cec5SDimitry Andric namespace llvm {
1500b57cec5SDimitry Andric namespace orc {
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
1530b57cec5SDimitry Andric public:
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer & Layer,std::unique_ptr<MaterializationResponsibility> MR,std::unique_ptr<MemoryBuffer> ObjBuffer)154e8d8bef9SDimitry Andric ObjectLinkingLayerJITLinkContext(
155e8d8bef9SDimitry Andric ObjectLinkingLayer &Layer,
156e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR,
1570b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer)
158e8d8bef9SDimitry Andric : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
159*0fca6ea1SDimitry Andric MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {
160*0fca6ea1SDimitry Andric std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
161*0fca6ea1SDimitry Andric Plugins = Layer.Plugins;
162*0fca6ea1SDimitry Andric }
1630b57cec5SDimitry Andric
~ObjectLinkingLayerJITLinkContext()1648bcb0991SDimitry Andric ~ObjectLinkingLayerJITLinkContext() {
1658bcb0991SDimitry Andric // If there is an object buffer return function then use it to
1668bcb0991SDimitry Andric // return ownership of the buffer.
167e8d8bef9SDimitry Andric if (Layer.ReturnObjectBuffer && ObjBuffer)
1688bcb0991SDimitry Andric Layer.ReturnObjectBuffer(std::move(ObjBuffer));
1698bcb0991SDimitry Andric }
1708bcb0991SDimitry Andric
getMemoryManager()171e8d8bef9SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
1720b57cec5SDimitry Andric
notifyMaterializing(LinkGraph & G)173fe6060f1SDimitry Andric void notifyMaterializing(LinkGraph &G) {
174*0fca6ea1SDimitry Andric for (auto &P : Plugins)
175fe6060f1SDimitry Andric P->notifyMaterializing(*MR, G, *this,
176fe6060f1SDimitry Andric ObjBuffer ? ObjBuffer->getMemBufferRef()
177fe6060f1SDimitry Andric : MemoryBufferRef());
178fe6060f1SDimitry Andric }
179fe6060f1SDimitry Andric
notifyFailed(Error Err)1800b57cec5SDimitry Andric void notifyFailed(Error Err) override {
181*0fca6ea1SDimitry Andric for (auto &P : Plugins)
182e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
1830b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err));
184e8d8bef9SDimitry Andric MR->failMaterialization();
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
lookup(const LookupMap & Symbols,std::unique_ptr<JITLinkAsyncLookupContinuation> LC)187480093f4SDimitry Andric void lookup(const LookupMap &Symbols,
1888bcb0991SDimitry Andric std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
1890b57cec5SDimitry Andric
1905ffd83dbSDimitry Andric JITDylibSearchOrder LinkOrder;
191e8d8bef9SDimitry Andric MR->getTargetJITDylib().withLinkOrderDo(
1925ffd83dbSDimitry Andric [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession();
1950b57cec5SDimitry Andric
196480093f4SDimitry Andric SymbolLookupSet LookupSet;
197480093f4SDimitry Andric for (auto &KV : Symbols) {
198480093f4SDimitry Andric orc::SymbolLookupFlags LookupFlags;
199480093f4SDimitry Andric switch (KV.second) {
200480093f4SDimitry Andric case jitlink::SymbolLookupFlags::RequiredSymbol:
201480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;
202480093f4SDimitry Andric break;
203480093f4SDimitry Andric case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:
204480093f4SDimitry Andric LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;
205480093f4SDimitry Andric break;
206480093f4SDimitry Andric }
207480093f4SDimitry Andric LookupSet.add(ES.intern(KV.first), LookupFlags);
208480093f4SDimitry Andric }
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker.
211e8d8bef9SDimitry Andric auto OnResolve = [LookupContinuation =
212e8d8bef9SDimitry Andric std::move(LC)](Expected<SymbolMap> Result) mutable {
2130b57cec5SDimitry Andric if (!Result)
2148bcb0991SDimitry Andric LookupContinuation->run(Result.takeError());
2150b57cec5SDimitry Andric else {
2160b57cec5SDimitry Andric AsyncLookupResult LR;
2170b57cec5SDimitry Andric for (auto &KV : *Result)
2180b57cec5SDimitry Andric LR[*KV.first] = KV.second;
2198bcb0991SDimitry Andric LookupContinuation->run(std::move(LR));
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric };
2220b57cec5SDimitry Andric
2235ffd83dbSDimitry Andric ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
224480093f4SDimitry Andric SymbolState::Resolved, std::move(OnResolve),
225480093f4SDimitry Andric [this](const SymbolDependenceMap &Deps) {
226*0fca6ea1SDimitry Andric // Translate LookupDeps map to SymbolSourceJD.
227*0fca6ea1SDimitry Andric for (auto &[DepJD, Deps] : Deps)
228*0fca6ea1SDimitry Andric for (auto &DepSym : Deps)
229*0fca6ea1SDimitry Andric SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD;
2300b57cec5SDimitry Andric });
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric
notifyResolved(LinkGraph & G)233e8d8bef9SDimitry Andric Error notifyResolved(LinkGraph &G) override {
2340b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession();
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim;
2370b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols;
2380b57cec5SDimitry Andric
2390b57cec5SDimitry Andric SymbolMap InternedResult;
2408bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols())
2418bcb0991SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) {
2428bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName());
24306c3fb27SDimitry Andric auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
24406c3fb27SDimitry Andric auto Flags = getJITSymbolFlagsForSymbol(*Sym);
24506c3fb27SDimitry Andric InternedResult[InternedName] = {Ptr, Flags};
246e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) {
2470b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) &&
2480b57cec5SDimitry Andric "Duplicate symbol to claim?");
2490b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags;
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric
2538bcb0991SDimitry Andric for (auto *Sym : G.absolute_symbols())
25481ad6265SDimitry Andric if (Sym->hasName() && Sym->getScope() != Scope::Local) {
2558bcb0991SDimitry Andric auto InternedName = ES.intern(Sym->getName());
25606c3fb27SDimitry Andric auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
25706c3fb27SDimitry Andric auto Flags = getJITSymbolFlagsForSymbol(*Sym);
25806c3fb27SDimitry Andric InternedResult[InternedName] = {Ptr, Flags};
259e8d8bef9SDimitry Andric if (AutoClaim && !MR->getSymbols().count(InternedName)) {
2600b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) &&
2610b57cec5SDimitry Andric "Duplicate symbol to claim?");
2620b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty())
267e8d8bef9SDimitry Andric if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
268e8d8bef9SDimitry Andric return Err;
2695ffd83dbSDimitry Andric
2705ffd83dbSDimitry Andric {
2715ffd83dbSDimitry Andric
2720eae32dcSDimitry Andric // Check that InternedResult matches up with MR->getSymbols(), overriding
2730eae32dcSDimitry Andric // flags if requested.
2745ffd83dbSDimitry Andric // This guards against faulty transformations / compilers / object caches.
2755ffd83dbSDimitry Andric
2765ffd83dbSDimitry Andric // First check that there aren't any missing symbols.
2775ffd83dbSDimitry Andric size_t NumMaterializationSideEffectsOnlySymbols = 0;
2785ffd83dbSDimitry Andric SymbolNameVector ExtraSymbols;
2795ffd83dbSDimitry Andric SymbolNameVector MissingSymbols;
280e8d8bef9SDimitry Andric for (auto &KV : MR->getSymbols()) {
2815ffd83dbSDimitry Andric
2820eae32dcSDimitry Andric auto I = InternedResult.find(KV.first);
2830eae32dcSDimitry Andric
2845ffd83dbSDimitry Andric // If this is a materialization-side-effects only symbol then bump
2855ffd83dbSDimitry Andric // the counter and make sure it's *not* defined, otherwise make
2865ffd83dbSDimitry Andric // sure that it is defined.
2875ffd83dbSDimitry Andric if (KV.second.hasMaterializationSideEffectsOnly()) {
2885ffd83dbSDimitry Andric ++NumMaterializationSideEffectsOnlySymbols;
2890eae32dcSDimitry Andric if (I != InternedResult.end())
2905ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first);
2915ffd83dbSDimitry Andric continue;
2920eae32dcSDimitry Andric } else if (I == InternedResult.end())
2935ffd83dbSDimitry Andric MissingSymbols.push_back(KV.first);
2940eae32dcSDimitry Andric else if (Layer.OverrideObjectFlags)
2950eae32dcSDimitry Andric I->second.setFlags(KV.second);
2965ffd83dbSDimitry Andric }
2975ffd83dbSDimitry Andric
2985ffd83dbSDimitry Andric // If there were missing symbols then report the error.
299e8d8bef9SDimitry Andric if (!MissingSymbols.empty())
300349cc55cSDimitry Andric return make_error<MissingSymbolDefinitions>(
301349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
302e8d8bef9SDimitry Andric std::move(MissingSymbols));
3035ffd83dbSDimitry Andric
3045ffd83dbSDimitry Andric // If there are more definitions than expected, add them to the
3055ffd83dbSDimitry Andric // ExtraSymbols vector.
3065ffd83dbSDimitry Andric if (InternedResult.size() >
307e8d8bef9SDimitry Andric MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
3085ffd83dbSDimitry Andric for (auto &KV : InternedResult)
309e8d8bef9SDimitry Andric if (!MR->getSymbols().count(KV.first))
3105ffd83dbSDimitry Andric ExtraSymbols.push_back(KV.first);
3115ffd83dbSDimitry Andric }
3125ffd83dbSDimitry Andric
3135ffd83dbSDimitry Andric // If there were extra definitions then report the error.
314e8d8bef9SDimitry Andric if (!ExtraSymbols.empty())
315349cc55cSDimitry Andric return make_error<UnexpectedSymbolDefinitions>(
316349cc55cSDimitry Andric Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
317e8d8bef9SDimitry Andric std::move(ExtraSymbols));
3185ffd83dbSDimitry Andric }
3195ffd83dbSDimitry Andric
320e8d8bef9SDimitry Andric if (auto Err = MR->notifyResolved(InternedResult))
321e8d8bef9SDimitry Andric return Err;
322e8d8bef9SDimitry Andric
323*0fca6ea1SDimitry Andric notifyLoaded();
324e8d8bef9SDimitry Andric return Error::success();
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric
notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A)327349cc55cSDimitry Andric void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {
328*0fca6ea1SDimitry Andric if (auto Err = notifyEmitted(std::move(A))) {
3290b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err));
330e8d8bef9SDimitry Andric MR->failMaterialization();
3310b57cec5SDimitry Andric return;
3320b57cec5SDimitry Andric }
333*0fca6ea1SDimitry Andric if (auto Err = MR->notifyEmitted(SymbolDepGroups)) {
3348bcb0991SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err));
335e8d8bef9SDimitry Andric MR->failMaterialization();
3368bcb0991SDimitry Andric }
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric
getMarkLivePass(const Triple & TT) const3398bcb0991SDimitry Andric LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
3408bcb0991SDimitry Andric return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric
modifyPassConfig(LinkGraph & LG,PassConfiguration & Config)343fe6060f1SDimitry Andric Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override {
3440b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the
3458bcb0991SDimitry Andric // link graph to build the symbol dependence graph.
346e8d8bef9SDimitry Andric Config.PrePrunePasses.push_back([this](LinkGraph &G) {
347e8d8bef9SDimitry Andric return claimOrExternalizeWeakAndCommonSymbols(G);
348e8d8bef9SDimitry Andric });
3490b57cec5SDimitry Andric
350*0fca6ea1SDimitry Andric for (auto &P : Plugins)
351*0fca6ea1SDimitry Andric P->modifyPassConfig(*MR, LG, Config);
3520b57cec5SDimitry Andric
353*0fca6ea1SDimitry Andric Config.PreFixupPasses.push_back(
354*0fca6ea1SDimitry Andric [this](LinkGraph &G) { return registerDependencies(G); });
355*0fca6ea1SDimitry Andric
356*0fca6ea1SDimitry Andric return Error::success();
357*0fca6ea1SDimitry Andric }
358*0fca6ea1SDimitry Andric
notifyLoaded()359*0fca6ea1SDimitry Andric void notifyLoaded() {
360*0fca6ea1SDimitry Andric for (auto &P : Plugins)
361*0fca6ea1SDimitry Andric P->notifyLoaded(*MR);
362*0fca6ea1SDimitry Andric }
363*0fca6ea1SDimitry Andric
notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA)364*0fca6ea1SDimitry Andric Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) {
365*0fca6ea1SDimitry Andric Error Err = Error::success();
366*0fca6ea1SDimitry Andric for (auto &P : Plugins)
367*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(*MR));
368*0fca6ea1SDimitry Andric
369*0fca6ea1SDimitry Andric if (Err) {
370*0fca6ea1SDimitry Andric if (FA)
371*0fca6ea1SDimitry Andric Err =
372*0fca6ea1SDimitry Andric joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));
373*0fca6ea1SDimitry Andric return Err;
374*0fca6ea1SDimitry Andric }
375*0fca6ea1SDimitry Andric
376*0fca6ea1SDimitry Andric if (FA)
377*0fca6ea1SDimitry Andric return Layer.recordFinalizedAlloc(*MR, std::move(FA));
3785ffd83dbSDimitry Andric
3790b57cec5SDimitry Andric return Error::success();
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andric private:
383fe6060f1SDimitry Andric // Symbol name dependencies:
384fe6060f1SDimitry Andric // Internal: Defined in this graph.
385fe6060f1SDimitry Andric // External: Defined externally.
386fe6060f1SDimitry Andric struct BlockSymbolDependencies {
3875ffd83dbSDimitry Andric SymbolNameSet Internal, External;
3885ffd83dbSDimitry Andric };
3895ffd83dbSDimitry Andric
390fe6060f1SDimitry Andric // Lazily populated map of blocks to BlockSymbolDependencies values.
391fe6060f1SDimitry Andric class BlockDependenciesMap {
392fe6060f1SDimitry Andric public:
BlockDependenciesMap(ExecutionSession & ES,DenseMap<const Block *,DenseSet<Block * >> BlockDeps)393fe6060f1SDimitry Andric BlockDependenciesMap(ExecutionSession &ES,
394fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
395fe6060f1SDimitry Andric : ES(ES), BlockDeps(std::move(BlockDeps)) {}
396fe6060f1SDimitry Andric
operator [](const Block & B)397fe6060f1SDimitry Andric const BlockSymbolDependencies &operator[](const Block &B) {
398fe6060f1SDimitry Andric // Check the cache first.
399fe6060f1SDimitry Andric auto I = BlockTransitiveDepsCache.find(&B);
400fe6060f1SDimitry Andric if (I != BlockTransitiveDepsCache.end())
401fe6060f1SDimitry Andric return I->second;
402fe6060f1SDimitry Andric
403fe6060f1SDimitry Andric // No value. Populate the cache.
404fe6060f1SDimitry Andric BlockSymbolDependencies BTDCacheVal;
405fe6060f1SDimitry Andric auto BDI = BlockDeps.find(&B);
406fe6060f1SDimitry Andric assert(BDI != BlockDeps.end() && "No block dependencies");
407fe6060f1SDimitry Andric
408fe6060f1SDimitry Andric for (auto *BDep : BDI->second) {
409fe6060f1SDimitry Andric auto &BID = getBlockImmediateDeps(*BDep);
410fe6060f1SDimitry Andric for (auto &ExternalDep : BID.External)
411fe6060f1SDimitry Andric BTDCacheVal.External.insert(ExternalDep);
412fe6060f1SDimitry Andric for (auto &InternalDep : BID.Internal)
413fe6060f1SDimitry Andric BTDCacheVal.Internal.insert(InternalDep);
414fe6060f1SDimitry Andric }
415fe6060f1SDimitry Andric
416fe6060f1SDimitry Andric return BlockTransitiveDepsCache
417fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BTDCacheVal)))
418fe6060f1SDimitry Andric .first->second;
419fe6060f1SDimitry Andric }
420fe6060f1SDimitry Andric
getInternedName(Symbol & Sym)421fe6060f1SDimitry Andric SymbolStringPtr &getInternedName(Symbol &Sym) {
422fe6060f1SDimitry Andric auto I = NameCache.find(&Sym);
423fe6060f1SDimitry Andric if (I != NameCache.end())
424fe6060f1SDimitry Andric return I->second;
425fe6060f1SDimitry Andric
426fe6060f1SDimitry Andric return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
427fe6060f1SDimitry Andric .first->second;
428fe6060f1SDimitry Andric }
429fe6060f1SDimitry Andric
430fe6060f1SDimitry Andric private:
getBlockImmediateDeps(Block & B)431fe6060f1SDimitry Andric BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
432fe6060f1SDimitry Andric // Check the cache first.
433fe6060f1SDimitry Andric auto I = BlockImmediateDepsCache.find(&B);
434fe6060f1SDimitry Andric if (I != BlockImmediateDepsCache.end())
435fe6060f1SDimitry Andric return I->second;
436fe6060f1SDimitry Andric
437fe6060f1SDimitry Andric BlockSymbolDependencies BIDCacheVal;
438fe6060f1SDimitry Andric for (auto &E : B.edges()) {
439fe6060f1SDimitry Andric auto &Tgt = E.getTarget();
440fe6060f1SDimitry Andric if (Tgt.getScope() != Scope::Local) {
441*0fca6ea1SDimitry Andric if (Tgt.isExternal()) {
442*0fca6ea1SDimitry Andric if (Tgt.getAddress() || !Tgt.isWeaklyReferenced())
443fe6060f1SDimitry Andric BIDCacheVal.External.insert(getInternedName(Tgt));
444*0fca6ea1SDimitry Andric } else
445fe6060f1SDimitry Andric BIDCacheVal.Internal.insert(getInternedName(Tgt));
446fe6060f1SDimitry Andric }
447fe6060f1SDimitry Andric }
448fe6060f1SDimitry Andric
449fe6060f1SDimitry Andric return BlockImmediateDepsCache
450fe6060f1SDimitry Andric .insert(std::make_pair(&B, std::move(BIDCacheVal)))
451fe6060f1SDimitry Andric .first->second;
452fe6060f1SDimitry Andric }
453fe6060f1SDimitry Andric
454fe6060f1SDimitry Andric ExecutionSession &ES;
455fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
456fe6060f1SDimitry Andric DenseMap<const Symbol *, SymbolStringPtr> NameCache;
457fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
458fe6060f1SDimitry Andric DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
459fe6060f1SDimitry Andric };
4600b57cec5SDimitry Andric
claimOrExternalizeWeakAndCommonSymbols(LinkGraph & G)461e8d8bef9SDimitry Andric Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
4620b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession();
4630b57cec5SDimitry Andric
464e8d8bef9SDimitry Andric SymbolFlagsMap NewSymbolsToClaim;
465e8d8bef9SDimitry Andric std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
466e8d8bef9SDimitry Andric
467e8d8bef9SDimitry Andric auto ProcessSymbol = [&](Symbol *Sym) {
468349cc55cSDimitry Andric if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
469349cc55cSDimitry Andric Sym->getScope() != Scope::Local) {
470e8d8bef9SDimitry Andric auto Name = ES.intern(Sym->getName());
471e8d8bef9SDimitry Andric if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
47206c3fb27SDimitry Andric NewSymbolsToClaim[Name] =
47306c3fb27SDimitry Andric getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;
474e8d8bef9SDimitry Andric NameToSym.push_back(std::make_pair(std::move(Name), Sym));
4750b57cec5SDimitry Andric }
476e8d8bef9SDimitry Andric }
477e8d8bef9SDimitry Andric };
478e8d8bef9SDimitry Andric
479e8d8bef9SDimitry Andric for (auto *Sym : G.defined_symbols())
480e8d8bef9SDimitry Andric ProcessSymbol(Sym);
481e8d8bef9SDimitry Andric for (auto *Sym : G.absolute_symbols())
482e8d8bef9SDimitry Andric ProcessSymbol(Sym);
483e8d8bef9SDimitry Andric
484e8d8bef9SDimitry Andric // Attempt to claim all weak defs that we're not already responsible for.
485*0fca6ea1SDimitry Andric // This may fail if the resource tracker has become defunct, but should
486*0fca6ea1SDimitry Andric // always succeed otherwise.
487*0fca6ea1SDimitry Andric if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
488*0fca6ea1SDimitry Andric return Err;
489e8d8bef9SDimitry Andric
490bdd1243dSDimitry Andric // Walk the list of symbols that we just tried to claim. Symbols that we're
491bdd1243dSDimitry Andric // responsible for are marked live. Symbols that we're not responsible for
492bdd1243dSDimitry Andric // are turned into external references.
493bdd1243dSDimitry Andric for (auto &KV : NameToSym) {
494bdd1243dSDimitry Andric if (MR->getSymbols().count(KV.first))
495bdd1243dSDimitry Andric KV.second->setLive(true);
496bdd1243dSDimitry Andric else
497e8d8bef9SDimitry Andric G.makeExternal(*KV.second);
498bdd1243dSDimitry Andric }
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric return Error::success();
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric
markResponsibilitySymbolsLive(LinkGraph & G) const5038bcb0991SDimitry Andric Error markResponsibilitySymbolsLive(LinkGraph &G) const {
5040b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession();
5058bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols())
506e8d8bef9SDimitry Andric if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
5078bcb0991SDimitry Andric Sym->setLive(true);
5080b57cec5SDimitry Andric return Error::success();
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric
registerDependencies(LinkGraph & G)511*0fca6ea1SDimitry Andric Error registerDependencies(LinkGraph &G) {
512*0fca6ea1SDimitry Andric auto &TargetJD = MR->getTargetJITDylib();
513*0fca6ea1SDimitry Andric auto &ES = TargetJD.getExecutionSession();
514fe6060f1SDimitry Andric auto BlockDeps = computeBlockNonLocalDeps(G);
5150b57cec5SDimitry Andric
516*0fca6ea1SDimitry Andric DenseSet<Block *> BlockDepsProcessed;
517*0fca6ea1SDimitry Andric DenseMap<Block *, SymbolDependenceGroup> DepGroupForBlock;
518*0fca6ea1SDimitry Andric
5195ffd83dbSDimitry Andric // Compute dependencies for symbols defined in the JITLink graph.
5208bcb0991SDimitry Andric for (auto *Sym : G.defined_symbols()) {
5210b57cec5SDimitry Andric
522*0fca6ea1SDimitry Andric // Skip local symbols.
5238bcb0991SDimitry Andric if (Sym->getScope() == Scope::Local)
5240b57cec5SDimitry Andric continue;
5255ffd83dbSDimitry Andric assert(Sym->hasName() &&
5265ffd83dbSDimitry Andric "Defined non-local jitlink::Symbol should have a name");
5270b57cec5SDimitry Andric
528*0fca6ea1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()];
529*0fca6ea1SDimitry Andric
530*0fca6ea1SDimitry Andric // Skip symbols in blocks that don't depend on anything.
531*0fca6ea1SDimitry Andric if (BDeps.Internal.empty() && BDeps.External.empty())
5325ffd83dbSDimitry Andric continue;
5335ffd83dbSDimitry Andric
534*0fca6ea1SDimitry Andric SymbolDependenceGroup &SDG = DepGroupForBlock[&Sym->getBlock()];
535*0fca6ea1SDimitry Andric SDG.Symbols.insert(ES.intern(Sym->getName()));
536*0fca6ea1SDimitry Andric
537*0fca6ea1SDimitry Andric if (!BlockDepsProcessed.count(&Sym->getBlock())) {
538*0fca6ea1SDimitry Andric BlockDepsProcessed.insert(&Sym->getBlock());
539*0fca6ea1SDimitry Andric
540*0fca6ea1SDimitry Andric if (!BDeps.Internal.empty())
541*0fca6ea1SDimitry Andric SDG.Dependencies[&TargetJD] = BDeps.Internal;
542*0fca6ea1SDimitry Andric for (auto &Dep : BDeps.External) {
543*0fca6ea1SDimitry Andric auto DepSrcItr = SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep));
544*0fca6ea1SDimitry Andric if (DepSrcItr != SymbolSourceJDs.end())
545*0fca6ea1SDimitry Andric SDG.Dependencies[DepSrcItr->second].insert(Dep);
546*0fca6ea1SDimitry Andric }
547*0fca6ea1SDimitry Andric }
5485ffd83dbSDimitry Andric }
5495ffd83dbSDimitry Andric
550*0fca6ea1SDimitry Andric SymbolDependenceGroup SynthSDG;
551*0fca6ea1SDimitry Andric
552*0fca6ea1SDimitry Andric for (auto &P : Plugins) {
553fe6060f1SDimitry Andric auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
554fe6060f1SDimitry Andric if (SynthDeps.empty())
5555ffd83dbSDimitry Andric continue;
5565ffd83dbSDimitry Andric
557fe6060f1SDimitry Andric DenseSet<Block *> BlockVisited;
558*0fca6ea1SDimitry Andric for (auto &[Name, DepSyms] : SynthDeps) {
559*0fca6ea1SDimitry Andric SynthSDG.Symbols.insert(Name);
560*0fca6ea1SDimitry Andric for (auto *Sym : DepSyms) {
561fe6060f1SDimitry Andric if (Sym->getScope() == Scope::Local) {
562fe6060f1SDimitry Andric auto &BDeps = BlockDeps[Sym->getBlock()];
563fe6060f1SDimitry Andric for (auto &S : BDeps.Internal)
564*0fca6ea1SDimitry Andric SynthSDG.Dependencies[&TargetJD].insert(S);
565*0fca6ea1SDimitry Andric for (auto &S : BDeps.External) {
566*0fca6ea1SDimitry Andric auto DepSrcItr =
567*0fca6ea1SDimitry Andric SymbolSourceJDs.find(NonOwningSymbolStringPtr(S));
568*0fca6ea1SDimitry Andric if (DepSrcItr != SymbolSourceJDs.end())
569*0fca6ea1SDimitry Andric SynthSDG.Dependencies[DepSrcItr->second].insert(S);
570*0fca6ea1SDimitry Andric }
571fe6060f1SDimitry Andric } else {
572*0fca6ea1SDimitry Andric auto SymName = ES.intern(Sym->getName());
573*0fca6ea1SDimitry Andric if (Sym->isExternal()) {
574*0fca6ea1SDimitry Andric assert(SymbolSourceJDs.count(NonOwningSymbolStringPtr(SymName)) &&
575*0fca6ea1SDimitry Andric "External symbol source entry missing");
576*0fca6ea1SDimitry Andric SynthSDG
577*0fca6ea1SDimitry Andric .Dependencies[SymbolSourceJDs[NonOwningSymbolStringPtr(
578*0fca6ea1SDimitry Andric SymName)]]
579*0fca6ea1SDimitry Andric .insert(SymName);
580*0fca6ea1SDimitry Andric } else
581*0fca6ea1SDimitry Andric SynthSDG.Dependencies[&TargetJD].insert(SymName);
582fe6060f1SDimitry Andric }
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric
587*0fca6ea1SDimitry Andric // Transfer SDGs to SymbolDepGroups.
588*0fca6ea1SDimitry Andric DepGroupForBlock.reserve(DepGroupForBlock.size() + 1);
589*0fca6ea1SDimitry Andric for (auto &[B, SDG] : DepGroupForBlock) {
590*0fca6ea1SDimitry Andric assert(!SDG.Symbols.empty() && "SymbolDependenceGroup covers no symbols");
591*0fca6ea1SDimitry Andric if (!SDG.Dependencies.empty())
592*0fca6ea1SDimitry Andric SymbolDepGroups.push_back(std::move(SDG));
593*0fca6ea1SDimitry Andric }
594*0fca6ea1SDimitry Andric if (!SynthSDG.Symbols.empty() && !SynthSDG.Dependencies.empty())
595*0fca6ea1SDimitry Andric SymbolDepGroups.push_back(std::move(SynthSDG));
596*0fca6ea1SDimitry Andric
5970b57cec5SDimitry Andric return Error::success();
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric
computeBlockNonLocalDeps(LinkGraph & G)600fe6060f1SDimitry Andric BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
601fe6060f1SDimitry Andric // First calculate the reachable-via-non-local-symbol blocks for each block.
602fe6060f1SDimitry Andric struct BlockInfo {
603fe6060f1SDimitry Andric DenseSet<Block *> Dependencies;
604fe6060f1SDimitry Andric DenseSet<Block *> Dependants;
605fe6060f1SDimitry Andric bool DependenciesChanged = true;
6060b57cec5SDimitry Andric };
607fe6060f1SDimitry Andric DenseMap<Block *, BlockInfo> BlockInfos;
608fe6060f1SDimitry Andric SmallVector<Block *> WorkList;
6090b57cec5SDimitry Andric
610fe6060f1SDimitry Andric // Pre-allocate map entries. This prevents any iterator/reference
611fe6060f1SDimitry Andric // invalidation in the next loop.
612fe6060f1SDimitry Andric for (auto *B : G.blocks())
613fe6060f1SDimitry Andric (void)BlockInfos[B];
614fe6060f1SDimitry Andric
615fe6060f1SDimitry Andric // Build initial worklist, record block dependencies/dependants and
616fe6060f1SDimitry Andric // non-local symbol dependencies.
617fe6060f1SDimitry Andric for (auto *B : G.blocks()) {
618fe6060f1SDimitry Andric auto &BI = BlockInfos[B];
619fe6060f1SDimitry Andric for (auto &E : B->edges()) {
620bdd1243dSDimitry Andric if (E.getTarget().getScope() == Scope::Local &&
621bdd1243dSDimitry Andric !E.getTarget().isAbsolute()) {
622fe6060f1SDimitry Andric auto &TgtB = E.getTarget().getBlock();
623fe6060f1SDimitry Andric if (&TgtB != B) {
624fe6060f1SDimitry Andric BI.Dependencies.insert(&TgtB);
625fe6060f1SDimitry Andric BlockInfos[&TgtB].Dependants.insert(B);
626fe6060f1SDimitry Andric }
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric }
629*0fca6ea1SDimitry Andric }
6300b57cec5SDimitry Andric
631*0fca6ea1SDimitry Andric // Add blocks with both dependants and dependencies to the worklist to
632*0fca6ea1SDimitry Andric // propagate dependencies to dependants.
633*0fca6ea1SDimitry Andric for (auto &[B, BI] : BlockInfos) {
634fe6060f1SDimitry Andric if (!BI.Dependants.empty() && !BI.Dependencies.empty())
635fe6060f1SDimitry Andric WorkList.push_back(B);
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric
638fe6060f1SDimitry Andric // Propagate block-level dependencies through the block-dependence graph.
639fe6060f1SDimitry Andric while (!WorkList.empty()) {
640349cc55cSDimitry Andric auto *B = WorkList.pop_back_val();
6410b57cec5SDimitry Andric
642fe6060f1SDimitry Andric auto &BI = BlockInfos[B];
643fe6060f1SDimitry Andric assert(BI.DependenciesChanged &&
644fe6060f1SDimitry Andric "Block in worklist has unchanged dependencies");
645fe6060f1SDimitry Andric BI.DependenciesChanged = false;
646fe6060f1SDimitry Andric for (auto *Dependant : BI.Dependants) {
647fe6060f1SDimitry Andric auto &DependantBI = BlockInfos[Dependant];
648fe6060f1SDimitry Andric for (auto *Dependency : BI.Dependencies) {
649fe6060f1SDimitry Andric if (Dependant != Dependency &&
650fe6060f1SDimitry Andric DependantBI.Dependencies.insert(Dependency).second)
651fe6060f1SDimitry Andric if (!DependantBI.DependenciesChanged) {
652fe6060f1SDimitry Andric DependantBI.DependenciesChanged = true;
653fe6060f1SDimitry Andric WorkList.push_back(Dependant);
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric }
6565ffd83dbSDimitry Andric }
6575ffd83dbSDimitry Andric }
6585ffd83dbSDimitry Andric
659fe6060f1SDimitry Andric DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
660fe6060f1SDimitry Andric for (auto &KV : BlockInfos)
661fe6060f1SDimitry Andric BlockDeps[KV.first] = std::move(KV.second.Dependencies);
662fe6060f1SDimitry Andric
663fe6060f1SDimitry Andric return BlockDependenciesMap(Layer.getExecutionSession(),
664fe6060f1SDimitry Andric std::move(BlockDeps));
6650b57cec5SDimitry Andric }
6660b57cec5SDimitry Andric
6670b57cec5SDimitry Andric ObjectLinkingLayer &Layer;
668*0fca6ea1SDimitry Andric std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins;
669e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> MR;
6700b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer;
671*0fca6ea1SDimitry Andric DenseMap<Block *, SymbolNameSet> ExternalBlockDeps;
672*0fca6ea1SDimitry Andric DenseMap<Block *, SymbolNameSet> InternalBlockDeps;
673*0fca6ea1SDimitry Andric DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
674*0fca6ea1SDimitry Andric std::vector<SymbolDependenceGroup> SymbolDepGroups;
6750b57cec5SDimitry Andric };
6760b57cec5SDimitry Andric
67781ad6265SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() = default;
6780b57cec5SDimitry Andric
679fe6060f1SDimitry Andric char ObjectLinkingLayer::ID;
680fe6060f1SDimitry Andric
681fe6060f1SDimitry Andric using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
682fe6060f1SDimitry Andric
ObjectLinkingLayer(ExecutionSession & ES)683fe6060f1SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
684fe6060f1SDimitry Andric : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
685fe6060f1SDimitry Andric ES.registerResourceManager(*this);
686fe6060f1SDimitry Andric }
687fe6060f1SDimitry Andric
ObjectLinkingLayer(ExecutionSession & ES,JITLinkMemoryManager & MemMgr)688e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
689e8d8bef9SDimitry Andric JITLinkMemoryManager &MemMgr)
690fe6060f1SDimitry Andric : BaseT(ES), MemMgr(MemMgr) {
691e8d8bef9SDimitry Andric ES.registerResourceManager(*this);
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric
ObjectLinkingLayer(ExecutionSession & ES,std::unique_ptr<JITLinkMemoryManager> MemMgr)694e8d8bef9SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(
695e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
696fe6060f1SDimitry Andric : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
697e8d8bef9SDimitry Andric ES.registerResourceManager(*this);
698e8d8bef9SDimitry Andric }
699e8d8bef9SDimitry Andric
~ObjectLinkingLayer()700e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() {
701e8d8bef9SDimitry Andric assert(Allocs.empty() && "Layer destroyed with resources still attached");
702e8d8bef9SDimitry Andric getExecutionSession().deregisterResourceManager(*this);
703e8d8bef9SDimitry Andric }
704e8d8bef9SDimitry Andric
add(ResourceTrackerSP RT,std::unique_ptr<LinkGraph> G)705fe6060f1SDimitry Andric Error ObjectLinkingLayer::add(ResourceTrackerSP RT,
706fe6060f1SDimitry Andric std::unique_ptr<LinkGraph> G) {
707fe6060f1SDimitry Andric auto &JD = RT->getJITDylib();
708fe6060f1SDimitry Andric return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
709fe6060f1SDimitry Andric std::move(RT));
710fe6060f1SDimitry Andric }
711fe6060f1SDimitry Andric
emit(std::unique_ptr<MaterializationResponsibility> R,std::unique_ptr<MemoryBuffer> O)712e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
7130b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) {
7140b57cec5SDimitry Andric assert(O && "Object must not be null");
715fe6060f1SDimitry Andric MemoryBufferRef ObjBuffer = O->getMemBufferRef();
716fe6060f1SDimitry Andric
717e8d8bef9SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
718e8d8bef9SDimitry Andric *this, std::move(R), std::move(O));
719fe6060f1SDimitry Andric if (auto G = createLinkGraphFromObject(ObjBuffer)) {
720fe6060f1SDimitry Andric Ctx->notifyMaterializing(**G);
721e8d8bef9SDimitry Andric link(std::move(*G), std::move(Ctx));
722fe6060f1SDimitry Andric } else {
723e8d8bef9SDimitry Andric Ctx->notifyFailed(G.takeError());
724e8d8bef9SDimitry Andric }
725fe6060f1SDimitry Andric }
726e8d8bef9SDimitry Andric
emit(std::unique_ptr<MaterializationResponsibility> R,std::unique_ptr<LinkGraph> G)727e8d8bef9SDimitry Andric void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
728e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G) {
729fe6060f1SDimitry Andric auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
730fe6060f1SDimitry Andric *this, std::move(R), nullptr);
731fe6060f1SDimitry Andric Ctx->notifyMaterializing(*G);
732fe6060f1SDimitry Andric link(std::move(G), std::move(Ctx));
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric
recordFinalizedAlloc(MaterializationResponsibility & MR,FinalizedAlloc FA)735*0fca6ea1SDimitry Andric Error ObjectLinkingLayer::recordFinalizedAlloc(
736*0fca6ea1SDimitry Andric MaterializationResponsibility &MR, FinalizedAlloc FA) {
737*0fca6ea1SDimitry Andric auto Err = MR.withResourceKeyDo(
738*0fca6ea1SDimitry Andric [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric if (Err)
741*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
742*0fca6ea1SDimitry Andric
7430b57cec5SDimitry Andric return Err;
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric
handleRemoveResources(JITDylib & JD,ResourceKey K)746bdd1243dSDimitry Andric Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
7470b57cec5SDimitry Andric
748349cc55cSDimitry Andric {
7490b57cec5SDimitry Andric Error Err = Error::success();
7500b57cec5SDimitry Andric for (auto &P : Plugins)
751bdd1243dSDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
752349cc55cSDimitry Andric if (Err)
753349cc55cSDimitry Andric return Err;
754349cc55cSDimitry Andric }
7550b57cec5SDimitry Andric
756349cc55cSDimitry Andric std::vector<FinalizedAlloc> AllocsToRemove;
757e8d8bef9SDimitry Andric getExecutionSession().runSessionLocked([&] {
758e8d8bef9SDimitry Andric auto I = Allocs.find(K);
759e8d8bef9SDimitry Andric if (I != Allocs.end()) {
760e8d8bef9SDimitry Andric std::swap(AllocsToRemove, I->second);
761e8d8bef9SDimitry Andric Allocs.erase(I);
7620b57cec5SDimitry Andric }
763e8d8bef9SDimitry Andric });
7640b57cec5SDimitry Andric
765349cc55cSDimitry Andric if (AllocsToRemove.empty())
766349cc55cSDimitry Andric return Error::success();
7670b57cec5SDimitry Andric
768349cc55cSDimitry Andric return MemMgr.deallocate(std::move(AllocsToRemove));
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric
handleTransferResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)771bdd1243dSDimitry Andric void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,
772bdd1243dSDimitry Andric ResourceKey DstKey,
773e8d8bef9SDimitry Andric ResourceKey SrcKey) {
774e8d8bef9SDimitry Andric auto I = Allocs.find(SrcKey);
775e8d8bef9SDimitry Andric if (I != Allocs.end()) {
776e8d8bef9SDimitry Andric auto &SrcAllocs = I->second;
777e8d8bef9SDimitry Andric auto &DstAllocs = Allocs[DstKey];
778e8d8bef9SDimitry Andric DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
779e8d8bef9SDimitry Andric for (auto &Alloc : SrcAllocs)
780e8d8bef9SDimitry Andric DstAllocs.push_back(std::move(Alloc));
781e8d8bef9SDimitry Andric
782e8d8bef9SDimitry Andric // Erase SrcKey entry using value rather than iterator I: I may have been
783e8d8bef9SDimitry Andric // invalidated when we looked up DstKey.
784e8d8bef9SDimitry Andric Allocs.erase(SrcKey);
785e8d8bef9SDimitry Andric }
786e8d8bef9SDimitry Andric
787e8d8bef9SDimitry Andric for (auto &P : Plugins)
788bdd1243dSDimitry Andric P->notifyTransferringResources(JD, DstKey, SrcKey);
789e8d8bef9SDimitry Andric }
790e8d8bef9SDimitry Andric
EHFrameRegistrationPlugin(ExecutionSession & ES,std::unique_ptr<EHFrameRegistrar> Registrar)7910b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
792e8d8bef9SDimitry Andric ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
793e8d8bef9SDimitry Andric : ES(ES), Registrar(std::move(Registrar)) {}
7940b57cec5SDimitry Andric
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)7950b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig(
796fe6060f1SDimitry Andric MaterializationResponsibility &MR, LinkGraph &G,
7970b57cec5SDimitry Andric PassConfiguration &PassConfig) {
7980b57cec5SDimitry Andric
7995ffd83dbSDimitry Andric PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
80004eeddc0SDimitry Andric G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
8015ffd83dbSDimitry Andric if (Addr) {
8025ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
8035ffd83dbSDimitry Andric assert(!InProcessLinks.count(&MR) &&
8045ffd83dbSDimitry Andric "Link for MR already being tracked?");
8058bcb0991SDimitry Andric InProcessLinks[&MR] = {Addr, Size};
8065ffd83dbSDimitry Andric }
8070b57cec5SDimitry Andric }));
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric
notifyEmitted(MaterializationResponsibility & MR)8100b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted(
8110b57cec5SDimitry Andric MaterializationResponsibility &MR) {
812e8d8bef9SDimitry Andric
81304eeddc0SDimitry Andric ExecutorAddrRange EmittedRange;
814e8d8bef9SDimitry Andric {
8155ffd83dbSDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
8160b57cec5SDimitry Andric
8178bcb0991SDimitry Andric auto EHFrameRangeItr = InProcessLinks.find(&MR);
8188bcb0991SDimitry Andric if (EHFrameRangeItr == InProcessLinks.end())
8190b57cec5SDimitry Andric return Error::success();
8200b57cec5SDimitry Andric
821e8d8bef9SDimitry Andric EmittedRange = EHFrameRangeItr->second;
82204eeddc0SDimitry Andric assert(EmittedRange.Start && "eh-frame addr to register can not be null");
8238bcb0991SDimitry Andric InProcessLinks.erase(EHFrameRangeItr);
8240b57cec5SDimitry Andric }
8250b57cec5SDimitry Andric
826e8d8bef9SDimitry Andric if (auto Err = MR.withResourceKeyDo(
827e8d8bef9SDimitry Andric [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
828e8d8bef9SDimitry Andric return Err;
8295ffd83dbSDimitry Andric
83004eeddc0SDimitry Andric return Registrar->registerEHFrames(EmittedRange);
831e8d8bef9SDimitry Andric }
832e8d8bef9SDimitry Andric
notifyFailed(MaterializationResponsibility & MR)833e8d8bef9SDimitry Andric Error EHFrameRegistrationPlugin::notifyFailed(
834e8d8bef9SDimitry Andric MaterializationResponsibility &MR) {
835e8d8bef9SDimitry Andric std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
836e8d8bef9SDimitry Andric InProcessLinks.erase(&MR);
8370b57cec5SDimitry Andric return Error::success();
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric
notifyRemovingResources(JITDylib & JD,ResourceKey K)840bdd1243dSDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
841bdd1243dSDimitry Andric ResourceKey K) {
84204eeddc0SDimitry Andric std::vector<ExecutorAddrRange> RangesToRemove;
8430b57cec5SDimitry Andric
844e8d8bef9SDimitry Andric ES.runSessionLocked([&] {
845e8d8bef9SDimitry Andric auto I = EHFrameRanges.find(K);
846e8d8bef9SDimitry Andric if (I != EHFrameRanges.end()) {
847e8d8bef9SDimitry Andric RangesToRemove = std::move(I->second);
848e8d8bef9SDimitry Andric EHFrameRanges.erase(I);
849e8d8bef9SDimitry Andric }
850e8d8bef9SDimitry Andric });
8510b57cec5SDimitry Andric
8520b57cec5SDimitry Andric Error Err = Error::success();
853e8d8bef9SDimitry Andric while (!RangesToRemove.empty()) {
854e8d8bef9SDimitry Andric auto RangeToRemove = RangesToRemove.back();
855e8d8bef9SDimitry Andric RangesToRemove.pop_back();
85604eeddc0SDimitry Andric assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
85704eeddc0SDimitry Andric Err = joinErrors(std::move(Err),
85804eeddc0SDimitry Andric Registrar->deregisterEHFrames(RangeToRemove));
8590b57cec5SDimitry Andric }
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric return Err;
8620b57cec5SDimitry Andric }
8630b57cec5SDimitry Andric
notifyTransferringResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)864e8d8bef9SDimitry Andric void EHFrameRegistrationPlugin::notifyTransferringResources(
865bdd1243dSDimitry Andric JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
866e8d8bef9SDimitry Andric auto SI = EHFrameRanges.find(SrcKey);
867fe6060f1SDimitry Andric if (SI == EHFrameRanges.end())
868fe6060f1SDimitry Andric return;
869fe6060f1SDimitry Andric
870fe6060f1SDimitry Andric auto DI = EHFrameRanges.find(DstKey);
871fe6060f1SDimitry Andric if (DI != EHFrameRanges.end()) {
872e8d8bef9SDimitry Andric auto &SrcRanges = SI->second;
873fe6060f1SDimitry Andric auto &DstRanges = DI->second;
874e8d8bef9SDimitry Andric DstRanges.reserve(DstRanges.size() + SrcRanges.size());
875e8d8bef9SDimitry Andric for (auto &SrcRange : SrcRanges)
876e8d8bef9SDimitry Andric DstRanges.push_back(std::move(SrcRange));
877e8d8bef9SDimitry Andric EHFrameRanges.erase(SI);
878fe6060f1SDimitry Andric } else {
879fe6060f1SDimitry Andric // We need to move SrcKey's ranges over without invalidating the SI
880fe6060f1SDimitry Andric // iterator.
881fe6060f1SDimitry Andric auto Tmp = std::move(SI->second);
882fe6060f1SDimitry Andric EHFrameRanges.erase(SI);
883fe6060f1SDimitry Andric EHFrameRanges[DstKey] = std::move(Tmp);
884e8d8bef9SDimitry Andric }
885e8d8bef9SDimitry Andric }
886e8d8bef9SDimitry Andric
8870b57cec5SDimitry Andric } // End namespace orc.
8880b57cec5SDimitry Andric } // End namespace llvm.
889