xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
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 
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 
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>
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 
87fe6060f1SDimitry Andric   StringRef getName() const override { return G->getName(); }
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:
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 
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 
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 
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:
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 
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 
171e8d8bef9SDimitry Andric   JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
1720b57cec5SDimitry Andric 
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 
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 
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 
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 
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 
3398bcb0991SDimitry Andric   LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
3408bcb0991SDimitry Andric     return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
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 
359*0fca6ea1SDimitry Andric   void notifyLoaded() {
360*0fca6ea1SDimitry Andric     for (auto &P : Plugins)
361*0fca6ea1SDimitry Andric       P->notifyLoaded(*MR);
362*0fca6ea1SDimitry Andric   }
363*0fca6ea1SDimitry Andric 
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:
393fe6060f1SDimitry Andric     BlockDependenciesMap(ExecutionSession &ES,
394fe6060f1SDimitry Andric                          DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
395fe6060f1SDimitry Andric         : ES(ES), BlockDeps(std::move(BlockDeps)) {}
396fe6060f1SDimitry Andric 
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 
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:
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 
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 
5038bcb0991SDimitry 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 
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 
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 
683fe6060f1SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
684fe6060f1SDimitry Andric     : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
685fe6060f1SDimitry Andric   ES.registerResourceManager(*this);
686fe6060f1SDimitry Andric }
687fe6060f1SDimitry Andric 
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 
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 
700e8d8bef9SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() {
701e8d8bef9SDimitry Andric   assert(Allocs.empty() && "Layer destroyed with resources still attached");
702e8d8bef9SDimitry Andric   getExecutionSession().deregisterResourceManager(*this);
703e8d8bef9SDimitry Andric }
704e8d8bef9SDimitry Andric 
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 
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 
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 
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 
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 
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 
7910b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
792e8d8bef9SDimitry Andric     ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
793e8d8bef9SDimitry Andric     : ES(ES), Registrar(std::move(Registrar)) {}
7940b57cec5SDimitry Andric 
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 
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 
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 
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 
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