111c8dfa5SLang Hames //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
211c8dfa5SLang Hames //
311c8dfa5SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
411c8dfa5SLang Hames // See https://llvm.org/LICENSE.txt for license information.
511c8dfa5SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
611c8dfa5SLang Hames //
711c8dfa5SLang Hames //===----------------------------------------------------------------------===//
811c8dfa5SLang Hames
911c8dfa5SLang Hames #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
1011c8dfa5SLang Hames #include "llvm/ADT/Optional.h"
111233c15bSLang Hames #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
12ef238923SStefan Gränitz #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
13ef238923SStefan Gränitz #include "llvm/Support/MemoryBuffer.h"
14367ec775SSimon Pilgrim #include <string>
1511c8dfa5SLang Hames #include <vector>
1611c8dfa5SLang Hames
1711c8dfa5SLang Hames #define DEBUG_TYPE "orc"
1811c8dfa5SLang Hames
1911c8dfa5SLang Hames using namespace llvm;
2011c8dfa5SLang Hames using namespace llvm::jitlink;
2111c8dfa5SLang Hames using namespace llvm::orc;
2211c8dfa5SLang Hames
230fda4c47SLang Hames namespace {
240fda4c47SLang Hames
250fda4c47SLang Hames class LinkGraphMaterializationUnit : public MaterializationUnit {
260fda4c47SLang Hames public:
270fda4c47SLang Hames static std::unique_ptr<LinkGraphMaterializationUnit>
Create(ObjectLinkingLayer & ObjLinkingLayer,std::unique_ptr<LinkGraph> G)280fda4c47SLang Hames Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
290fda4c47SLang Hames auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
300fda4c47SLang Hames return std::unique_ptr<LinkGraphMaterializationUnit>(
310fda4c47SLang Hames new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
320fda4c47SLang Hames std::move(LGI)));
330fda4c47SLang Hames }
340fda4c47SLang Hames
getName() const350fda4c47SLang Hames StringRef getName() const override { return G->getName(); }
materialize(std::unique_ptr<MaterializationResponsibility> MR)360fda4c47SLang Hames void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
370fda4c47SLang Hames ObjLinkingLayer.emit(std::move(MR), std::move(G));
380fda4c47SLang Hames }
390fda4c47SLang Hames
400fda4c47SLang Hames private:
scanLinkGraph(ExecutionSession & ES,LinkGraph & G)41ae73f3fdSLang Hames static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
420fda4c47SLang Hames
43ae73f3fdSLang Hames Interface LGI;
440fda4c47SLang Hames
450fda4c47SLang Hames for (auto *Sym : G.defined_symbols()) {
460fda4c47SLang Hames // Skip local symbols.
470fda4c47SLang Hames if (Sym->getScope() == Scope::Local)
480fda4c47SLang Hames continue;
490fda4c47SLang Hames assert(Sym->hasName() && "Anonymous non-local symbol?");
500fda4c47SLang Hames
510fda4c47SLang Hames JITSymbolFlags Flags;
520fda4c47SLang Hames if (Sym->getScope() == Scope::Default)
530fda4c47SLang Hames Flags |= JITSymbolFlags::Exported;
540fda4c47SLang Hames
550fda4c47SLang Hames if (Sym->isCallable())
560fda4c47SLang Hames Flags |= JITSymbolFlags::Callable;
570fda4c47SLang Hames
580fda4c47SLang Hames LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags;
590fda4c47SLang Hames }
600fda4c47SLang Hames
61b749ef9eSLang Hames if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) ||
62b749ef9eSLang Hames (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G)))
630fda4c47SLang Hames LGI.InitSymbol = makeInitSymbol(ES, G);
640fda4c47SLang Hames
650fda4c47SLang Hames return LGI;
660fda4c47SLang Hames }
670fda4c47SLang Hames
hasMachOInitSection(LinkGraph & G)680fda4c47SLang Hames static bool hasMachOInitSection(LinkGraph &G) {
690fda4c47SLang Hames for (auto &Sec : G.sections())
700fda4c47SLang Hames if (Sec.getName() == "__DATA,__obj_selrefs" ||
710fda4c47SLang Hames Sec.getName() == "__DATA,__objc_classlist" ||
720fda4c47SLang Hames Sec.getName() == "__TEXT,__swift5_protos" ||
730fda4c47SLang Hames Sec.getName() == "__TEXT,__swift5_proto" ||
742a739f27SBen Langmuir Sec.getName() == "__TEXT,__swift5_types" ||
750fda4c47SLang Hames Sec.getName() == "__DATA,__mod_init_func")
760fda4c47SLang Hames return true;
770fda4c47SLang Hames return false;
780fda4c47SLang Hames }
790fda4c47SLang Hames
hasELFInitSection(LinkGraph & G)80b749ef9eSLang Hames static bool hasELFInitSection(LinkGraph &G) {
81*2be5abb7SPeter S. Housel for (auto &Sec : G.sections()) {
82*2be5abb7SPeter S. Housel auto SecName = Sec.getName();
83*2be5abb7SPeter S. Housel if (SecName.consume_front(".init_array") &&
84*2be5abb7SPeter S. Housel (SecName.empty() || SecName[0] == '.'))
85b749ef9eSLang Hames return true;
86*2be5abb7SPeter S. Housel }
87b749ef9eSLang Hames return false;
88b749ef9eSLang Hames }
89b749ef9eSLang Hames
makeInitSymbol(ExecutionSession & ES,LinkGraph & G)900fda4c47SLang Hames static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
910fda4c47SLang Hames std::string InitSymString;
920fda4c47SLang Hames raw_string_ostream(InitSymString)
930fda4c47SLang Hames << "$." << G.getName() << ".__inits" << Counter++;
940fda4c47SLang Hames return ES.intern(InitSymString);
950fda4c47SLang Hames }
960fda4c47SLang Hames
LinkGraphMaterializationUnit(ObjectLinkingLayer & ObjLinkingLayer,std::unique_ptr<LinkGraph> G,Interface LGI)970fda4c47SLang Hames LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
98ae73f3fdSLang Hames std::unique_ptr<LinkGraph> G, Interface LGI)
99ae73f3fdSLang Hames : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
100ae73f3fdSLang Hames G(std::move(G)) {}
1010fda4c47SLang Hames
discard(const JITDylib & JD,const SymbolStringPtr & Name)1020fda4c47SLang Hames void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
1030fda4c47SLang Hames for (auto *Sym : G->defined_symbols())
1040fda4c47SLang Hames if (Sym->getName() == *Name) {
1050fda4c47SLang Hames assert(Sym->getLinkage() == Linkage::Weak &&
1060fda4c47SLang Hames "Discarding non-weak definition");
1070fda4c47SLang Hames G->makeExternal(*Sym);
1080fda4c47SLang Hames break;
1090fda4c47SLang Hames }
1100fda4c47SLang Hames }
1110fda4c47SLang Hames
1120fda4c47SLang Hames ObjectLinkingLayer &ObjLinkingLayer;
1130fda4c47SLang Hames std::unique_ptr<LinkGraph> G;
1140fda4c47SLang Hames static std::atomic<uint64_t> Counter;
1150fda4c47SLang Hames };
1160fda4c47SLang Hames
1170fda4c47SLang Hames std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
1180fda4c47SLang Hames
1190fda4c47SLang Hames } // end anonymous namespace
1200fda4c47SLang Hames
12111c8dfa5SLang Hames namespace llvm {
12211c8dfa5SLang Hames namespace orc {
12311c8dfa5SLang Hames
12411c8dfa5SLang Hames class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
12511c8dfa5SLang Hames public:
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer & Layer,std::unique_ptr<MaterializationResponsibility> MR,std::unique_ptr<MemoryBuffer> ObjBuffer)1267dcd0042SLang Hames ObjectLinkingLayerJITLinkContext(
1277dcd0042SLang Hames ObjectLinkingLayer &Layer,
1287dcd0042SLang Hames std::unique_ptr<MaterializationResponsibility> MR,
12911c8dfa5SLang Hames std::unique_ptr<MemoryBuffer> ObjBuffer)
13004795ab8SLang Hames : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
13104795ab8SLang Hames MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
13211c8dfa5SLang Hames
~ObjectLinkingLayerJITLinkContext()133a98546ebSLang Hames ~ObjectLinkingLayerJITLinkContext() {
134a98546ebSLang Hames // If there is an object buffer return function then use it to
135a98546ebSLang Hames // return ownership of the buffer.
136ec6b71dfSLang Hames if (Layer.ReturnObjectBuffer && ObjBuffer)
137a98546ebSLang Hames Layer.ReturnObjectBuffer(std::move(ObjBuffer));
138a98546ebSLang Hames }
139a98546ebSLang Hames
getMemoryManager()14069091eb1SLang Hames JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
14111c8dfa5SLang Hames
notifyMaterializing(LinkGraph & G)142ef238923SStefan Gränitz void notifyMaterializing(LinkGraph &G) {
143ef238923SStefan Gränitz for (auto &P : Layer.Plugins)
144c42580bfSLang Hames P->notifyMaterializing(*MR, G, *this,
145c42580bfSLang Hames ObjBuffer ? ObjBuffer->getMemBufferRef()
146c42580bfSLang Hames : MemoryBufferRef());
147ef238923SStefan Gränitz }
148ef238923SStefan Gränitz
notifyFailed(Error Err)14911c8dfa5SLang Hames void notifyFailed(Error Err) override {
1500aec49c8SLang Hames for (auto &P : Layer.Plugins)
1510aec49c8SLang Hames Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
15211c8dfa5SLang Hames Layer.getExecutionSession().reportError(std::move(Err));
1537dcd0042SLang Hames MR->failMaterialization();
15411c8dfa5SLang Hames }
15511c8dfa5SLang Hames
lookup(const LookupMap & Symbols,std::unique_ptr<JITLinkAsyncLookupContinuation> LC)156674df13bSLang Hames void lookup(const LookupMap &Symbols,
1574e920e58SLang Hames std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
15811c8dfa5SLang Hames
159c66f8900SLang Hames JITDylibSearchOrder LinkOrder;
1607dcd0042SLang Hames MR->getTargetJITDylib().withLinkOrderDo(
161c66f8900SLang Hames [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
16211c8dfa5SLang Hames
16311c8dfa5SLang Hames auto &ES = Layer.getExecutionSession();
16411c8dfa5SLang Hames
165674df13bSLang Hames SymbolLookupSet LookupSet;
166674df13bSLang Hames for (auto &KV : Symbols) {
167674df13bSLang Hames orc::SymbolLookupFlags LookupFlags;
168674df13bSLang Hames switch (KV.second) {
169674df13bSLang Hames case jitlink::SymbolLookupFlags::RequiredSymbol:
170674df13bSLang Hames LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;
171674df13bSLang Hames break;
172674df13bSLang Hames case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:
173674df13bSLang Hames LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;
174674df13bSLang Hames break;
175674df13bSLang Hames }
176674df13bSLang Hames LookupSet.add(ES.intern(KV.first), LookupFlags);
177674df13bSLang Hames }
17811c8dfa5SLang Hames
17911c8dfa5SLang Hames // OnResolve -- De-intern the symbols and pass the result to the linker.
180b79e19e6SLang Hames auto OnResolve = [LookupContinuation =
181b79e19e6SLang Hames std::move(LC)](Expected<SymbolMap> Result) mutable {
18211c8dfa5SLang Hames if (!Result)
1834e920e58SLang Hames LookupContinuation->run(Result.takeError());
18411c8dfa5SLang Hames else {
18511c8dfa5SLang Hames AsyncLookupResult LR;
18611c8dfa5SLang Hames for (auto &KV : *Result)
18711c8dfa5SLang Hames LR[*KV.first] = KV.second;
1884e920e58SLang Hames LookupContinuation->run(std::move(LR));
18911c8dfa5SLang Hames }
19011c8dfa5SLang Hames };
19111c8dfa5SLang Hames
192ca6f5848SLang Hames for (auto &KV : InternalNamedSymbolDeps) {
193ca6f5848SLang Hames SymbolDependenceMap InternalDeps;
1947dcd0042SLang Hames InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second);
1957dcd0042SLang Hames MR->addDependencies(KV.first, InternalDeps);
196ca6f5848SLang Hames }
197ca6f5848SLang Hames
198c66f8900SLang Hames ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
199674df13bSLang Hames SymbolState::Resolved, std::move(OnResolve),
200674df13bSLang Hames [this](const SymbolDependenceMap &Deps) {
20111c8dfa5SLang Hames registerDependencies(Deps);
20211c8dfa5SLang Hames });
20311c8dfa5SLang Hames }
20411c8dfa5SLang Hames
notifyResolved(LinkGraph & G)2059f1dcdcaSLang Hames Error notifyResolved(LinkGraph &G) override {
20611c8dfa5SLang Hames auto &ES = Layer.getExecutionSession();
20711c8dfa5SLang Hames
20811c8dfa5SLang Hames SymbolFlagsMap ExtraSymbolsToClaim;
20911c8dfa5SLang Hames bool AutoClaim = Layer.AutoClaimObjectSymbols;
21011c8dfa5SLang Hames
21111c8dfa5SLang Hames SymbolMap InternedResult;
2124e920e58SLang Hames for (auto *Sym : G.defined_symbols())
2134e920e58SLang Hames if (Sym->hasName() && Sym->getScope() != Scope::Local) {
2144e920e58SLang Hames auto InternedName = ES.intern(Sym->getName());
21511c8dfa5SLang Hames JITSymbolFlags Flags;
21611c8dfa5SLang Hames
2174e920e58SLang Hames if (Sym->isCallable())
21811c8dfa5SLang Hames Flags |= JITSymbolFlags::Callable;
2194e920e58SLang Hames if (Sym->getScope() == Scope::Default)
2204e920e58SLang Hames Flags |= JITSymbolFlags::Exported;
22111c8dfa5SLang Hames
22211c8dfa5SLang Hames InternedResult[InternedName] =
223118e953bSLang Hames JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
2247dcd0042SLang Hames if (AutoClaim && !MR->getSymbols().count(InternedName)) {
22511c8dfa5SLang Hames assert(!ExtraSymbolsToClaim.count(InternedName) &&
22611c8dfa5SLang Hames "Duplicate symbol to claim?");
22711c8dfa5SLang Hames ExtraSymbolsToClaim[InternedName] = Flags;
22811c8dfa5SLang Hames }
22911c8dfa5SLang Hames }
23011c8dfa5SLang Hames
2314e920e58SLang Hames for (auto *Sym : G.absolute_symbols())
23236f0dfd0SLang Hames if (Sym->hasName() && Sym->getScope() != Scope::Local) {
2334e920e58SLang Hames auto InternedName = ES.intern(Sym->getName());
23411c8dfa5SLang Hames JITSymbolFlags Flags;
2354e920e58SLang Hames if (Sym->isCallable())
23611c8dfa5SLang Hames Flags |= JITSymbolFlags::Callable;
23736f0dfd0SLang Hames if (Sym->getScope() == Scope::Default)
23836f0dfd0SLang Hames Flags |= JITSymbolFlags::Exported;
2394e920e58SLang Hames if (Sym->getLinkage() == Linkage::Weak)
2404e920e58SLang Hames Flags |= JITSymbolFlags::Weak;
24111c8dfa5SLang Hames InternedResult[InternedName] =
242118e953bSLang Hames JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
2437dcd0042SLang Hames if (AutoClaim && !MR->getSymbols().count(InternedName)) {
24411c8dfa5SLang Hames assert(!ExtraSymbolsToClaim.count(InternedName) &&
24511c8dfa5SLang Hames "Duplicate symbol to claim?");
24611c8dfa5SLang Hames ExtraSymbolsToClaim[InternedName] = Flags;
24711c8dfa5SLang Hames }
24811c8dfa5SLang Hames }
24911c8dfa5SLang Hames
25011c8dfa5SLang Hames if (!ExtraSymbolsToClaim.empty())
2517dcd0042SLang Hames if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
2529f1dcdcaSLang Hames return Err;
25385fb9976SLang Hames
25481726894SLang Hames {
255cb84e482SLang Hames
25602fc8d5cSLang Hames // Check that InternedResult matches up with MR->getSymbols(), overriding
25702fc8d5cSLang Hames // flags if requested.
25881726894SLang Hames // This guards against faulty transformations / compilers / object caches.
25981726894SLang Hames
260cb84e482SLang Hames // First check that there aren't any missing symbols.
261cb84e482SLang Hames size_t NumMaterializationSideEffectsOnlySymbols = 0;
26281726894SLang Hames SymbolNameVector ExtraSymbols;
263cb84e482SLang Hames SymbolNameVector MissingSymbols;
2647dcd0042SLang Hames for (auto &KV : MR->getSymbols()) {
265cb84e482SLang Hames
26602fc8d5cSLang Hames auto I = InternedResult.find(KV.first);
26702fc8d5cSLang Hames
268cb84e482SLang Hames // If this is a materialization-side-effects only symbol then bump
269cb84e482SLang Hames // the counter and make sure it's *not* defined, otherwise make
270cb84e482SLang Hames // sure that it is defined.
271cb84e482SLang Hames if (KV.second.hasMaterializationSideEffectsOnly()) {
272cb84e482SLang Hames ++NumMaterializationSideEffectsOnlySymbols;
27302fc8d5cSLang Hames if (I != InternedResult.end())
27481726894SLang Hames ExtraSymbols.push_back(KV.first);
275cb84e482SLang Hames continue;
27602fc8d5cSLang Hames } else if (I == InternedResult.end())
277cb84e482SLang Hames MissingSymbols.push_back(KV.first);
27802fc8d5cSLang Hames else if (Layer.OverrideObjectFlags)
27902fc8d5cSLang Hames I->second.setFlags(KV.second);
280cb84e482SLang Hames }
281cb84e482SLang Hames
282cb84e482SLang Hames // If there were missing symbols then report the error.
2839f1dcdcaSLang Hames if (!MissingSymbols.empty())
2846fe2e9a9SLang Hames return make_error<MissingSymbolDefinitions>(
2856fe2e9a9SLang Hames Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
2869f1dcdcaSLang Hames std::move(MissingSymbols));
28781726894SLang Hames
288cb84e482SLang Hames // If there are more definitions than expected, add them to the
289cb84e482SLang Hames // ExtraSymbols vector.
290cb84e482SLang Hames if (InternedResult.size() >
2917dcd0042SLang Hames MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
292cb84e482SLang Hames for (auto &KV : InternedResult)
2937dcd0042SLang Hames if (!MR->getSymbols().count(KV.first))
294cb84e482SLang Hames ExtraSymbols.push_back(KV.first);
295cb84e482SLang Hames }
29681726894SLang Hames
297cb84e482SLang Hames // If there were extra definitions then report the error.
2989f1dcdcaSLang Hames if (!ExtraSymbols.empty())
2996fe2e9a9SLang Hames return make_error<UnexpectedSymbolDefinitions>(
3006fe2e9a9SLang Hames Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
3019f1dcdcaSLang Hames std::move(ExtraSymbols));
30281726894SLang Hames }
30381726894SLang Hames
3047dcd0042SLang Hames if (auto Err = MR->notifyResolved(InternedResult))
3059f1dcdcaSLang Hames return Err;
3069f1dcdcaSLang Hames
3077dcd0042SLang Hames Layer.notifyLoaded(*MR);
3089f1dcdcaSLang Hames return Error::success();
30911c8dfa5SLang Hames }
31011c8dfa5SLang Hames
notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A)311962a2479SLang Hames void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {
3127dcd0042SLang Hames if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
31311c8dfa5SLang Hames Layer.getExecutionSession().reportError(std::move(Err));
3147dcd0042SLang Hames MR->failMaterialization();
31511c8dfa5SLang Hames return;
31611c8dfa5SLang Hames }
3177dcd0042SLang Hames if (auto Err = MR->notifyEmitted()) {
318e00585c7SLang Hames Layer.getExecutionSession().reportError(std::move(Err));
3197dcd0042SLang Hames MR->failMaterialization();
320e00585c7SLang Hames }
32111c8dfa5SLang Hames }
32211c8dfa5SLang Hames
getMarkLivePass(const Triple & TT) const3234e920e58SLang Hames LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
3244e920e58SLang Hames return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
32511c8dfa5SLang Hames }
32611c8dfa5SLang Hames
modifyPassConfig(LinkGraph & LG,PassConfiguration & Config)3274e30b20bSLang Hames Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override {
32811c8dfa5SLang Hames // Add passes to mark duplicate defs as should-discard, and to walk the
3294e920e58SLang Hames // link graph to build the symbol dependence graph.
3304dc110a4SLang Hames Config.PrePrunePasses.push_back([this](LinkGraph &G) {
3314dc110a4SLang Hames return claimOrExternalizeWeakAndCommonSymbols(G);
3324dc110a4SLang Hames });
33311c8dfa5SLang Hames
3344e30b20bSLang Hames Layer.modifyPassConfig(*MR, LG, Config);
33511c8dfa5SLang Hames
336ca6f5848SLang Hames Config.PostPrunePasses.push_back(
337ca6f5848SLang Hames [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
338ca6f5848SLang Hames
33911c8dfa5SLang Hames return Error::success();
34011c8dfa5SLang Hames }
34111c8dfa5SLang Hames
34211c8dfa5SLang Hames private:
343963378bdSLang Hames // Symbol name dependencies:
344963378bdSLang Hames // Internal: Defined in this graph.
345963378bdSLang Hames // External: Defined externally.
346963378bdSLang Hames struct BlockSymbolDependencies {
34785fb9976SLang Hames SymbolNameSet Internal, External;
34885fb9976SLang Hames };
34985fb9976SLang Hames
350963378bdSLang Hames // Lazily populated map of blocks to BlockSymbolDependencies values.
351963378bdSLang Hames class BlockDependenciesMap {
352963378bdSLang Hames public:
BlockDependenciesMap(ExecutionSession & ES,DenseMap<const Block *,DenseSet<Block * >> BlockDeps)353963378bdSLang Hames BlockDependenciesMap(ExecutionSession &ES,
354963378bdSLang Hames DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
355963378bdSLang Hames : ES(ES), BlockDeps(std::move(BlockDeps)) {}
356963378bdSLang Hames
operator [](const Block & B)357963378bdSLang Hames const BlockSymbolDependencies &operator[](const Block &B) {
358963378bdSLang Hames // Check the cache first.
359963378bdSLang Hames auto I = BlockTransitiveDepsCache.find(&B);
360963378bdSLang Hames if (I != BlockTransitiveDepsCache.end())
361963378bdSLang Hames return I->second;
362963378bdSLang Hames
363963378bdSLang Hames // No value. Populate the cache.
364963378bdSLang Hames BlockSymbolDependencies BTDCacheVal;
365963378bdSLang Hames auto BDI = BlockDeps.find(&B);
366963378bdSLang Hames assert(BDI != BlockDeps.end() && "No block dependencies");
367963378bdSLang Hames
368963378bdSLang Hames for (auto *BDep : BDI->second) {
369963378bdSLang Hames auto &BID = getBlockImmediateDeps(*BDep);
370963378bdSLang Hames for (auto &ExternalDep : BID.External)
371963378bdSLang Hames BTDCacheVal.External.insert(ExternalDep);
372963378bdSLang Hames for (auto &InternalDep : BID.Internal)
373963378bdSLang Hames BTDCacheVal.Internal.insert(InternalDep);
374963378bdSLang Hames }
375963378bdSLang Hames
376963378bdSLang Hames return BlockTransitiveDepsCache
377963378bdSLang Hames .insert(std::make_pair(&B, std::move(BTDCacheVal)))
378963378bdSLang Hames .first->second;
379963378bdSLang Hames }
380963378bdSLang Hames
getInternedName(Symbol & Sym)381963378bdSLang Hames SymbolStringPtr &getInternedName(Symbol &Sym) {
382963378bdSLang Hames auto I = NameCache.find(&Sym);
383963378bdSLang Hames if (I != NameCache.end())
384963378bdSLang Hames return I->second;
385963378bdSLang Hames
386963378bdSLang Hames return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
387963378bdSLang Hames .first->second;
388963378bdSLang Hames }
389963378bdSLang Hames
390963378bdSLang Hames private:
getBlockImmediateDeps(Block & B)391963378bdSLang Hames BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
392963378bdSLang Hames // Check the cache first.
393963378bdSLang Hames auto I = BlockImmediateDepsCache.find(&B);
394963378bdSLang Hames if (I != BlockImmediateDepsCache.end())
395963378bdSLang Hames return I->second;
396963378bdSLang Hames
397963378bdSLang Hames BlockSymbolDependencies BIDCacheVal;
398963378bdSLang Hames for (auto &E : B.edges()) {
399963378bdSLang Hames auto &Tgt = E.getTarget();
400963378bdSLang Hames if (Tgt.getScope() != Scope::Local) {
401963378bdSLang Hames if (Tgt.isExternal())
402963378bdSLang Hames BIDCacheVal.External.insert(getInternedName(Tgt));
403963378bdSLang Hames else
404963378bdSLang Hames BIDCacheVal.Internal.insert(getInternedName(Tgt));
405963378bdSLang Hames }
406963378bdSLang Hames }
407963378bdSLang Hames
408963378bdSLang Hames return BlockImmediateDepsCache
409963378bdSLang Hames .insert(std::make_pair(&B, std::move(BIDCacheVal)))
410963378bdSLang Hames .first->second;
411963378bdSLang Hames }
412963378bdSLang Hames
413963378bdSLang Hames ExecutionSession &ES;
414963378bdSLang Hames DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
415963378bdSLang Hames DenseMap<const Symbol *, SymbolStringPtr> NameCache;
416963378bdSLang Hames DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
417963378bdSLang Hames DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
418963378bdSLang Hames };
41911c8dfa5SLang Hames
claimOrExternalizeWeakAndCommonSymbols(LinkGraph & G)4204dc110a4SLang Hames Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
42111c8dfa5SLang Hames auto &ES = Layer.getExecutionSession();
42211c8dfa5SLang Hames
4234dc110a4SLang Hames SymbolFlagsMap NewSymbolsToClaim;
4244dc110a4SLang Hames std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
4254dc110a4SLang Hames
4264dc110a4SLang Hames auto ProcessSymbol = [&](Symbol *Sym) {
4274c94760fSBen Langmuir if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
4284c94760fSBen Langmuir Sym->getScope() != Scope::Local) {
4294dc110a4SLang Hames auto Name = ES.intern(Sym->getName());
4304dc110a4SLang Hames if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
4314dc110a4SLang Hames JITSymbolFlags SF = JITSymbolFlags::Weak;
4324dc110a4SLang Hames if (Sym->getScope() == Scope::Default)
4334dc110a4SLang Hames SF |= JITSymbolFlags::Exported;
4344dc110a4SLang Hames NewSymbolsToClaim[Name] = SF;
4354dc110a4SLang Hames NameToSym.push_back(std::make_pair(std::move(Name), Sym));
43611c8dfa5SLang Hames }
4374dc110a4SLang Hames }
4384dc110a4SLang Hames };
4394dc110a4SLang Hames
4404dc110a4SLang Hames for (auto *Sym : G.defined_symbols())
4414dc110a4SLang Hames ProcessSymbol(Sym);
4424dc110a4SLang Hames for (auto *Sym : G.absolute_symbols())
4434dc110a4SLang Hames ProcessSymbol(Sym);
4444dc110a4SLang Hames
4454dc110a4SLang Hames // Attempt to claim all weak defs that we're not already responsible for.
4464dc110a4SLang Hames // This cannot fail -- any clashes will just result in rejection of our
4474dc110a4SLang Hames // claim, at which point we'll externalize that symbol.
4484dc110a4SLang Hames cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
4494dc110a4SLang Hames
4504dc110a4SLang Hames for (auto &KV : NameToSym)
4514dc110a4SLang Hames if (!MR->getSymbols().count(KV.first))
4524dc110a4SLang Hames G.makeExternal(*KV.second);
45311c8dfa5SLang Hames
45411c8dfa5SLang Hames return Error::success();
45511c8dfa5SLang Hames }
45611c8dfa5SLang Hames
markResponsibilitySymbolsLive(LinkGraph & G) const4574e920e58SLang Hames Error markResponsibilitySymbolsLive(LinkGraph &G) const {
45811c8dfa5SLang Hames auto &ES = Layer.getExecutionSession();
4594e920e58SLang Hames for (auto *Sym : G.defined_symbols())
4607dcd0042SLang Hames if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
4614e920e58SLang Hames Sym->setLive(true);
46211c8dfa5SLang Hames return Error::success();
46311c8dfa5SLang Hames }
46411c8dfa5SLang Hames
computeNamedSymbolDependencies(LinkGraph & G)4654e920e58SLang Hames Error computeNamedSymbolDependencies(LinkGraph &G) {
4667dcd0042SLang Hames auto &ES = MR->getTargetJITDylib().getExecutionSession();
467963378bdSLang Hames auto BlockDeps = computeBlockNonLocalDeps(G);
46811c8dfa5SLang Hames
46985fb9976SLang Hames // Compute dependencies for symbols defined in the JITLink graph.
4704e920e58SLang Hames for (auto *Sym : G.defined_symbols()) {
47111c8dfa5SLang Hames
472ca6f5848SLang Hames // Skip local symbols: we do not track dependencies for these.
4734e920e58SLang Hames if (Sym->getScope() == Scope::Local)
47411c8dfa5SLang Hames continue;
475ca6f5848SLang Hames assert(Sym->hasName() &&
476ca6f5848SLang Hames "Defined non-local jitlink::Symbol should have a name");
47711c8dfa5SLang Hames
478963378bdSLang Hames auto &SymDeps = BlockDeps[Sym->getBlock()];
479963378bdSLang Hames if (SymDeps.External.empty() && SymDeps.Internal.empty())
480ca6f5848SLang Hames continue;
481ca6f5848SLang Hames
482ca6f5848SLang Hames auto SymName = ES.intern(Sym->getName());
483963378bdSLang Hames if (!SymDeps.External.empty())
484963378bdSLang Hames ExternalNamedSymbolDeps[SymName] = SymDeps.External;
485963378bdSLang Hames if (!SymDeps.Internal.empty())
486963378bdSLang Hames InternalNamedSymbolDeps[SymName] = SymDeps.Internal;
487ca6f5848SLang Hames }
488ca6f5848SLang Hames
48985fb9976SLang Hames for (auto &P : Layer.Plugins) {
490963378bdSLang Hames auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
491963378bdSLang Hames if (SynthDeps.empty())
49285fb9976SLang Hames continue;
49385fb9976SLang Hames
494963378bdSLang Hames DenseSet<Block *> BlockVisited;
495963378bdSLang Hames for (auto &KV : SynthDeps) {
49685fb9976SLang Hames auto &Name = KV.first;
497963378bdSLang Hames auto &DepsForName = KV.second;
498963378bdSLang Hames for (auto *Sym : DepsForName) {
499963378bdSLang Hames if (Sym->getScope() == Scope::Local) {
500963378bdSLang Hames auto &BDeps = BlockDeps[Sym->getBlock()];
501963378bdSLang Hames for (auto &S : BDeps.Internal)
50285fb9976SLang Hames InternalNamedSymbolDeps[Name].insert(S);
503963378bdSLang Hames for (auto &S : BDeps.External)
50485fb9976SLang Hames ExternalNamedSymbolDeps[Name].insert(S);
505963378bdSLang Hames } else {
506963378bdSLang Hames if (Sym->isExternal())
507963378bdSLang Hames ExternalNamedSymbolDeps[Name].insert(
508963378bdSLang Hames BlockDeps.getInternedName(*Sym));
509963378bdSLang Hames else
510963378bdSLang Hames InternalNamedSymbolDeps[Name].insert(
511963378bdSLang Hames BlockDeps.getInternedName(*Sym));
512963378bdSLang Hames }
51385fb9976SLang Hames }
51485fb9976SLang Hames }
51585fb9976SLang Hames }
51685fb9976SLang Hames
51711c8dfa5SLang Hames return Error::success();
51811c8dfa5SLang Hames }
51911c8dfa5SLang Hames
computeBlockNonLocalDeps(LinkGraph & G)520963378bdSLang Hames BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
521963378bdSLang Hames // First calculate the reachable-via-non-local-symbol blocks for each block.
522963378bdSLang Hames struct BlockInfo {
523963378bdSLang Hames DenseSet<Block *> Dependencies;
524963378bdSLang Hames DenseSet<Block *> Dependants;
525963378bdSLang Hames bool DependenciesChanged = true;
52611c8dfa5SLang Hames };
527963378bdSLang Hames DenseMap<Block *, BlockInfo> BlockInfos;
528963378bdSLang Hames SmallVector<Block *> WorkList;
52911c8dfa5SLang Hames
530963378bdSLang Hames // Pre-allocate map entries. This prevents any iterator/reference
531963378bdSLang Hames // invalidation in the next loop.
532963378bdSLang Hames for (auto *B : G.blocks())
533963378bdSLang Hames (void)BlockInfos[B];
534963378bdSLang Hames
535963378bdSLang Hames // Build initial worklist, record block dependencies/dependants and
536963378bdSLang Hames // non-local symbol dependencies.
537963378bdSLang Hames for (auto *B : G.blocks()) {
538963378bdSLang Hames auto &BI = BlockInfos[B];
539963378bdSLang Hames for (auto &E : B->edges()) {
540963378bdSLang Hames if (E.getTarget().getScope() == Scope::Local) {
541963378bdSLang Hames auto &TgtB = E.getTarget().getBlock();
542963378bdSLang Hames if (&TgtB != B) {
543963378bdSLang Hames BI.Dependencies.insert(&TgtB);
544963378bdSLang Hames BlockInfos[&TgtB].Dependants.insert(B);
545963378bdSLang Hames }
54611c8dfa5SLang Hames }
54711c8dfa5SLang Hames }
54811c8dfa5SLang Hames
549963378bdSLang Hames // If this node has both dependants and dependencies then add it to the
550963378bdSLang Hames // worklist to propagate the dependencies to the dependants.
551963378bdSLang Hames if (!BI.Dependants.empty() && !BI.Dependencies.empty())
552963378bdSLang Hames WorkList.push_back(B);
55311c8dfa5SLang Hames }
55411c8dfa5SLang Hames
555963378bdSLang Hames // Propagate block-level dependencies through the block-dependence graph.
556963378bdSLang Hames while (!WorkList.empty()) {
55784b07c9bSKazu Hirata auto *B = WorkList.pop_back_val();
55811c8dfa5SLang Hames
559963378bdSLang Hames auto &BI = BlockInfos[B];
560963378bdSLang Hames assert(BI.DependenciesChanged &&
561963378bdSLang Hames "Block in worklist has unchanged dependencies");
562963378bdSLang Hames BI.DependenciesChanged = false;
563963378bdSLang Hames for (auto *Dependant : BI.Dependants) {
564963378bdSLang Hames auto &DependantBI = BlockInfos[Dependant];
565963378bdSLang Hames for (auto *Dependency : BI.Dependencies) {
566963378bdSLang Hames if (Dependant != Dependency &&
567963378bdSLang Hames DependantBI.Dependencies.insert(Dependency).second)
568963378bdSLang Hames if (!DependantBI.DependenciesChanged) {
569963378bdSLang Hames DependantBI.DependenciesChanged = true;
570963378bdSLang Hames WorkList.push_back(Dependant);
57111c8dfa5SLang Hames }
57211c8dfa5SLang Hames }
57385fb9976SLang Hames }
57485fb9976SLang Hames }
57585fb9976SLang Hames
576963378bdSLang Hames DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
577963378bdSLang Hames for (auto &KV : BlockInfos)
578963378bdSLang Hames BlockDeps[KV.first] = std::move(KV.second.Dependencies);
579963378bdSLang Hames
580963378bdSLang Hames return BlockDependenciesMap(Layer.getExecutionSession(),
581963378bdSLang Hames std::move(BlockDeps));
58211c8dfa5SLang Hames }
58311c8dfa5SLang Hames
registerDependencies(const SymbolDependenceMap & QueryDeps)58411c8dfa5SLang Hames void registerDependencies(const SymbolDependenceMap &QueryDeps) {
585ca6f5848SLang Hames for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
58611c8dfa5SLang Hames auto &Name = NamedDepsEntry.first;
58711c8dfa5SLang Hames auto &NameDeps = NamedDepsEntry.second;
58811c8dfa5SLang Hames SymbolDependenceMap SymbolDeps;
58911c8dfa5SLang Hames
59011c8dfa5SLang Hames for (const auto &QueryDepsEntry : QueryDeps) {
59111c8dfa5SLang Hames JITDylib &SourceJD = *QueryDepsEntry.first;
59211c8dfa5SLang Hames const SymbolNameSet &Symbols = QueryDepsEntry.second;
59311c8dfa5SLang Hames auto &DepsForJD = SymbolDeps[&SourceJD];
59411c8dfa5SLang Hames
59511c8dfa5SLang Hames for (const auto &S : Symbols)
59611c8dfa5SLang Hames if (NameDeps.count(S))
59711c8dfa5SLang Hames DepsForJD.insert(S);
59811c8dfa5SLang Hames
59911c8dfa5SLang Hames if (DepsForJD.empty())
60011c8dfa5SLang Hames SymbolDeps.erase(&SourceJD);
60111c8dfa5SLang Hames }
60211c8dfa5SLang Hames
6037dcd0042SLang Hames MR->addDependencies(Name, SymbolDeps);
60411c8dfa5SLang Hames }
60511c8dfa5SLang Hames }
60611c8dfa5SLang Hames
60711c8dfa5SLang Hames ObjectLinkingLayer &Layer;
6087dcd0042SLang Hames std::unique_ptr<MaterializationResponsibility> MR;
60911c8dfa5SLang Hames std::unique_ptr<MemoryBuffer> ObjBuffer;
610ca6f5848SLang Hames DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
611ca6f5848SLang Hames DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
61211c8dfa5SLang Hames };
61311c8dfa5SLang Hames
6143a3cb929SKazu Hirata ObjectLinkingLayer::Plugin::~Plugin() = default;
615a9fdf375SLang Hames
616406ef36bSStefan Gränitz char ObjectLinkingLayer::ID;
617406ef36bSStefan Gränitz
618406ef36bSStefan Gränitz using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
619406ef36bSStefan Gränitz
ObjectLinkingLayer(ExecutionSession & ES)6202487db1fSLang Hames ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
6212487db1fSLang Hames : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
6222487db1fSLang Hames ES.registerResourceManager(*this);
6232487db1fSLang Hames }
6242487db1fSLang Hames
ObjectLinkingLayer(ExecutionSession & ES,JITLinkMemoryManager & MemMgr)62569091eb1SLang Hames ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
62669091eb1SLang Hames JITLinkMemoryManager &MemMgr)
627406ef36bSStefan Gränitz : BaseT(ES), MemMgr(MemMgr) {
6280aec49c8SLang Hames ES.registerResourceManager(*this);
6290aec49c8SLang Hames }
63069091eb1SLang Hames
ObjectLinkingLayer(ExecutionSession & ES,std::unique_ptr<JITLinkMemoryManager> MemMgr)631c0143f37SLang Hames ObjectLinkingLayer::ObjectLinkingLayer(
632c0143f37SLang Hames ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
633406ef36bSStefan Gränitz : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
6340aec49c8SLang Hames ES.registerResourceManager(*this);
6350aec49c8SLang Hames }
636a9fdf375SLang Hames
~ObjectLinkingLayer()637a9fdf375SLang Hames ObjectLinkingLayer::~ObjectLinkingLayer() {
6380aec49c8SLang Hames assert(Allocs.empty() && "Layer destroyed with resources still attached");
6390aec49c8SLang Hames getExecutionSession().deregisterResourceManager(*this);
640a9fdf375SLang Hames }
64111c8dfa5SLang Hames
add(ResourceTrackerSP RT,std::unique_ptr<LinkGraph> G)6420fda4c47SLang Hames Error ObjectLinkingLayer::add(ResourceTrackerSP RT,
6430fda4c47SLang Hames std::unique_ptr<LinkGraph> G) {
6440fda4c47SLang Hames auto &JD = RT->getJITDylib();
6450fda4c47SLang Hames return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
6460fda4c47SLang Hames std::move(RT));
6470fda4c47SLang Hames }
6480fda4c47SLang Hames
emit(std::unique_ptr<MaterializationResponsibility> R,std::unique_ptr<MemoryBuffer> O)6497dcd0042SLang Hames void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
65011c8dfa5SLang Hames std::unique_ptr<MemoryBuffer> O) {
65111c8dfa5SLang Hames assert(O && "Object must not be null");
652ef238923SStefan Gränitz MemoryBufferRef ObjBuffer = O->getMemBufferRef();
653ef238923SStefan Gränitz
654ec6b71dfSLang Hames auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
655ec6b71dfSLang Hames *this, std::move(R), std::move(O));
656ef238923SStefan Gränitz if (auto G = createLinkGraphFromObject(ObjBuffer)) {
657ef238923SStefan Gränitz Ctx->notifyMaterializing(**G);
658ec6b71dfSLang Hames link(std::move(*G), std::move(Ctx));
659ef238923SStefan Gränitz } else {
660ec6b71dfSLang Hames Ctx->notifyFailed(G.takeError());
661ec6b71dfSLang Hames }
662ef238923SStefan Gränitz }
663ec6b71dfSLang Hames
emit(std::unique_ptr<MaterializationResponsibility> R,std::unique_ptr<LinkGraph> G)664ec6b71dfSLang Hames void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
665ec6b71dfSLang Hames std::unique_ptr<LinkGraph> G) {
666ef238923SStefan Gränitz auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
667ef238923SStefan Gränitz *this, std::move(R), nullptr);
668ef238923SStefan Gränitz Ctx->notifyMaterializing(*G);
669ef238923SStefan Gränitz link(std::move(G), std::move(Ctx));
67011c8dfa5SLang Hames }
67111c8dfa5SLang Hames
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)672a9fdf375SLang Hames void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
6734e30b20bSLang Hames LinkGraph &G,
674a9fdf375SLang Hames PassConfiguration &PassConfig) {
675a9fdf375SLang Hames for (auto &P : Plugins)
6764e30b20bSLang Hames P->modifyPassConfig(MR, G, PassConfig);
67711c8dfa5SLang Hames }
67811c8dfa5SLang Hames
notifyLoaded(MaterializationResponsibility & MR)679a9fdf375SLang Hames void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
680a9fdf375SLang Hames for (auto &P : Plugins)
681a9fdf375SLang Hames P->notifyLoaded(MR);
68211c8dfa5SLang Hames }
68311c8dfa5SLang Hames
notifyEmitted(MaterializationResponsibility & MR,FinalizedAlloc FA)684a9fdf375SLang Hames Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
685962a2479SLang Hames FinalizedAlloc FA) {
686a9fdf375SLang Hames Error Err = Error::success();
687a9fdf375SLang Hames for (auto &P : Plugins)
688a9fdf375SLang Hames Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
68911c8dfa5SLang Hames
690a9fdf375SLang Hames if (Err)
691a9fdf375SLang Hames return Err;
69211c8dfa5SLang Hames
6930aec49c8SLang Hames return MR.withResourceKeyDo(
694962a2479SLang Hames [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
695a9fdf375SLang Hames }
69611c8dfa5SLang Hames
handleRemoveResources(ResourceKey K)6970aec49c8SLang Hames Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
698a9fdf375SLang Hames
699962a2479SLang Hames {
700a9fdf375SLang Hames Error Err = Error::success();
701a9fdf375SLang Hames for (auto &P : Plugins)
7020aec49c8SLang Hames Err = joinErrors(std::move(Err), P->notifyRemovingResources(K));
703962a2479SLang Hames if (Err)
704962a2479SLang Hames return Err;
705962a2479SLang Hames }
706a9fdf375SLang Hames
707962a2479SLang Hames std::vector<FinalizedAlloc> AllocsToRemove;
7080aec49c8SLang Hames getExecutionSession().runSessionLocked([&] {
7090aec49c8SLang Hames auto I = Allocs.find(K);
7100aec49c8SLang Hames if (I != Allocs.end()) {
7110aec49c8SLang Hames std::swap(AllocsToRemove, I->second);
7120aec49c8SLang Hames Allocs.erase(I);
713a9fdf375SLang Hames }
7140aec49c8SLang Hames });
715a9fdf375SLang Hames
716bfb40e83SLang Hames if (AllocsToRemove.empty())
717bfb40e83SLang Hames return Error::success();
718bfb40e83SLang Hames
719962a2479SLang Hames return MemMgr.deallocate(std::move(AllocsToRemove));
720a9fdf375SLang Hames }
721a9fdf375SLang Hames
handleTransferResources(ResourceKey DstKey,ResourceKey SrcKey)7220aec49c8SLang Hames void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
7230aec49c8SLang Hames ResourceKey SrcKey) {
7240aec49c8SLang Hames auto I = Allocs.find(SrcKey);
7250aec49c8SLang Hames if (I != Allocs.end()) {
7260aec49c8SLang Hames auto &SrcAllocs = I->second;
7270aec49c8SLang Hames auto &DstAllocs = Allocs[DstKey];
7280aec49c8SLang Hames DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
7290aec49c8SLang Hames for (auto &Alloc : SrcAllocs)
7300aec49c8SLang Hames DstAllocs.push_back(std::move(Alloc));
7310aec49c8SLang Hames
7320aec49c8SLang Hames // Erase SrcKey entry using value rather than iterator I: I may have been
7330aec49c8SLang Hames // invalidated when we looked up DstKey.
7340aec49c8SLang Hames Allocs.erase(SrcKey);
7350aec49c8SLang Hames }
7360aec49c8SLang Hames
7370aec49c8SLang Hames for (auto &P : Plugins)
7380aec49c8SLang Hames P->notifyTransferringResources(DstKey, SrcKey);
7390aec49c8SLang Hames }
7400aec49c8SLang Hames
EHFrameRegistrationPlugin(ExecutionSession & ES,std::unique_ptr<EHFrameRegistrar> Registrar)741f5a885fdSLang Hames EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
7420aec49c8SLang Hames ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
7430aec49c8SLang Hames : ES(ES), Registrar(std::move(Registrar)) {}
744f5a885fdSLang Hames
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)745f5a885fdSLang Hames void EHFrameRegistrationPlugin::modifyPassConfig(
7464e30b20bSLang Hames MaterializationResponsibility &MR, LinkGraph &G,
747a9fdf375SLang Hames PassConfiguration &PassConfig) {
748a9fdf375SLang Hames
749214a9f0dSLang Hames PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
750118e953bSLang Hames G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
751214a9f0dSLang Hames if (Addr) {
752214a9f0dSLang Hames std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
753214a9f0dSLang Hames assert(!InProcessLinks.count(&MR) &&
754214a9f0dSLang Hames "Link for MR already being tracked?");
755c48f1f6dSLang Hames InProcessLinks[&MR] = {Addr, Size};
756214a9f0dSLang Hames }
757a9fdf375SLang Hames }));
758a9fdf375SLang Hames }
759a9fdf375SLang Hames
notifyEmitted(MaterializationResponsibility & MR)760f5a885fdSLang Hames Error EHFrameRegistrationPlugin::notifyEmitted(
761a9fdf375SLang Hames MaterializationResponsibility &MR) {
7620aec49c8SLang Hames
763089acf25SLang Hames ExecutorAddrRange EmittedRange;
7640aec49c8SLang Hames {
765214a9f0dSLang Hames std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
766a9fdf375SLang Hames
767c48f1f6dSLang Hames auto EHFrameRangeItr = InProcessLinks.find(&MR);
768c48f1f6dSLang Hames if (EHFrameRangeItr == InProcessLinks.end())
769a9fdf375SLang Hames return Error::success();
770a9fdf375SLang Hames
7710aec49c8SLang Hames EmittedRange = EHFrameRangeItr->second;
772089acf25SLang Hames assert(EmittedRange.Start && "eh-frame addr to register can not be null");
773c48f1f6dSLang Hames InProcessLinks.erase(EHFrameRangeItr);
774a9fdf375SLang Hames }
775a9fdf375SLang Hames
7760aec49c8SLang Hames if (auto Err = MR.withResourceKeyDo(
7770aec49c8SLang Hames [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
7780aec49c8SLang Hames return Err;
779214a9f0dSLang Hames
780089acf25SLang Hames return Registrar->registerEHFrames(EmittedRange);
7810aec49c8SLang Hames }
7820aec49c8SLang Hames
notifyFailed(MaterializationResponsibility & MR)7830aec49c8SLang Hames Error EHFrameRegistrationPlugin::notifyFailed(
7840aec49c8SLang Hames MaterializationResponsibility &MR) {
7850aec49c8SLang Hames std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
7860aec49c8SLang Hames InProcessLinks.erase(&MR);
787a9fdf375SLang Hames return Error::success();
788a9fdf375SLang Hames }
789a9fdf375SLang Hames
notifyRemovingResources(ResourceKey K)7900aec49c8SLang Hames Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
791089acf25SLang Hames std::vector<ExecutorAddrRange> RangesToRemove;
792a9fdf375SLang Hames
7930aec49c8SLang Hames ES.runSessionLocked([&] {
7940aec49c8SLang Hames auto I = EHFrameRanges.find(K);
7950aec49c8SLang Hames if (I != EHFrameRanges.end()) {
7960aec49c8SLang Hames RangesToRemove = std::move(I->second);
7970aec49c8SLang Hames EHFrameRanges.erase(I);
7980aec49c8SLang Hames }
7990aec49c8SLang Hames });
800a9fdf375SLang Hames
801a9fdf375SLang Hames Error Err = Error::success();
8020aec49c8SLang Hames while (!RangesToRemove.empty()) {
8030aec49c8SLang Hames auto RangeToRemove = RangesToRemove.back();
8040aec49c8SLang Hames RangesToRemove.pop_back();
805089acf25SLang Hames assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
806089acf25SLang Hames Err = joinErrors(std::move(Err),
807089acf25SLang Hames Registrar->deregisterEHFrames(RangeToRemove));
808a9fdf375SLang Hames }
809a9fdf375SLang Hames
810a9fdf375SLang Hames return Err;
81111c8dfa5SLang Hames }
81211c8dfa5SLang Hames
notifyTransferringResources(ResourceKey DstKey,ResourceKey SrcKey)8130aec49c8SLang Hames void EHFrameRegistrationPlugin::notifyTransferringResources(
8140aec49c8SLang Hames ResourceKey DstKey, ResourceKey SrcKey) {
8150aec49c8SLang Hames auto SI = EHFrameRanges.find(SrcKey);
816c1baf946SLang Hames if (SI == EHFrameRanges.end())
817c1baf946SLang Hames return;
818c1baf946SLang Hames
819c1baf946SLang Hames auto DI = EHFrameRanges.find(DstKey);
820c1baf946SLang Hames if (DI != EHFrameRanges.end()) {
8210aec49c8SLang Hames auto &SrcRanges = SI->second;
822c1baf946SLang Hames auto &DstRanges = DI->second;
8230aec49c8SLang Hames DstRanges.reserve(DstRanges.size() + SrcRanges.size());
8240aec49c8SLang Hames for (auto &SrcRange : SrcRanges)
8250aec49c8SLang Hames DstRanges.push_back(std::move(SrcRange));
8260aec49c8SLang Hames EHFrameRanges.erase(SI);
827c1baf946SLang Hames } else {
828c1baf946SLang Hames // We need to move SrcKey's ranges over without invalidating the SI
829c1baf946SLang Hames // iterator.
830c1baf946SLang Hames auto Tmp = std::move(SI->second);
831c1baf946SLang Hames EHFrameRanges.erase(SI);
832c1baf946SLang Hames EHFrameRanges[DstKey] = std::move(Tmp);
8330aec49c8SLang Hames }
8340aec49c8SLang Hames }
8350aec49c8SLang Hames
83611c8dfa5SLang Hames } // End namespace orc.
83711c8dfa5SLang Hames } // End namespace llvm.
838