xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
10*0b57cec5SDimitry Andric 
11*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
12*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include <vector>
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #define DEBUG_TYPE "orc"
17*0b57cec5SDimitry Andric 
18*0b57cec5SDimitry Andric using namespace llvm;
19*0b57cec5SDimitry Andric using namespace llvm::jitlink;
20*0b57cec5SDimitry Andric using namespace llvm::orc;
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric namespace llvm {
23*0b57cec5SDimitry Andric namespace orc {
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
26*0b57cec5SDimitry Andric public:
27*0b57cec5SDimitry Andric   ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer,
28*0b57cec5SDimitry Andric                                    MaterializationResponsibility MR,
29*0b57cec5SDimitry Andric                                    std::unique_ptr<MemoryBuffer> ObjBuffer)
30*0b57cec5SDimitry Andric       : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric   JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric   MemoryBufferRef getObjectBuffer() const override {
35*0b57cec5SDimitry Andric     return ObjBuffer->getMemBufferRef();
36*0b57cec5SDimitry Andric   }
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric   void notifyFailed(Error Err) override {
39*0b57cec5SDimitry Andric     Layer.getExecutionSession().reportError(std::move(Err));
40*0b57cec5SDimitry Andric     MR.failMaterialization();
41*0b57cec5SDimitry Andric   }
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric   void lookup(const DenseSet<StringRef> &Symbols,
44*0b57cec5SDimitry Andric               JITLinkAsyncLookupContinuation LookupContinuation) override {
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric     JITDylibSearchList SearchOrder;
47*0b57cec5SDimitry Andric     MR.getTargetJITDylib().withSearchOrderDo(
48*0b57cec5SDimitry Andric         [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric     auto &ES = Layer.getExecutionSession();
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric     SymbolNameSet InternedSymbols;
53*0b57cec5SDimitry Andric     for (auto &S : Symbols)
54*0b57cec5SDimitry Andric       InternedSymbols.insert(ES.intern(S));
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric     // OnResolve -- De-intern the symbols and pass the result to the linker.
57*0b57cec5SDimitry Andric     // FIXME: Capture LookupContinuation by move once we have c++14.
58*0b57cec5SDimitry Andric     auto SharedLookupContinuation =
59*0b57cec5SDimitry Andric         std::make_shared<JITLinkAsyncLookupContinuation>(
60*0b57cec5SDimitry Andric             std::move(LookupContinuation));
61*0b57cec5SDimitry Andric     auto OnResolve = [SharedLookupContinuation](Expected<SymbolMap> Result) {
62*0b57cec5SDimitry Andric       if (!Result)
63*0b57cec5SDimitry Andric         (*SharedLookupContinuation)(Result.takeError());
64*0b57cec5SDimitry Andric       else {
65*0b57cec5SDimitry Andric         AsyncLookupResult LR;
66*0b57cec5SDimitry Andric         for (auto &KV : *Result)
67*0b57cec5SDimitry Andric           LR[*KV.first] = KV.second;
68*0b57cec5SDimitry Andric         (*SharedLookupContinuation)(std::move(LR));
69*0b57cec5SDimitry Andric       }
70*0b57cec5SDimitry Andric     };
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric     ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
73*0b57cec5SDimitry Andric               std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
74*0b57cec5SDimitry Andric                 registerDependencies(Deps);
75*0b57cec5SDimitry Andric               });
76*0b57cec5SDimitry Andric   }
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric   void notifyResolved(AtomGraph &G) override {
79*0b57cec5SDimitry Andric     auto &ES = Layer.getExecutionSession();
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric     SymbolFlagsMap ExtraSymbolsToClaim;
82*0b57cec5SDimitry Andric     bool AutoClaim = Layer.AutoClaimObjectSymbols;
83*0b57cec5SDimitry Andric 
84*0b57cec5SDimitry Andric     SymbolMap InternedResult;
85*0b57cec5SDimitry Andric     for (auto *DA : G.defined_atoms())
86*0b57cec5SDimitry Andric       if (DA->hasName() && DA->isGlobal()) {
87*0b57cec5SDimitry Andric         auto InternedName = ES.intern(DA->getName());
88*0b57cec5SDimitry Andric         JITSymbolFlags Flags;
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric         if (DA->isExported())
91*0b57cec5SDimitry Andric           Flags |= JITSymbolFlags::Exported;
92*0b57cec5SDimitry Andric         if (DA->isWeak())
93*0b57cec5SDimitry Andric           Flags |= JITSymbolFlags::Weak;
94*0b57cec5SDimitry Andric         if (DA->isCallable())
95*0b57cec5SDimitry Andric           Flags |= JITSymbolFlags::Callable;
96*0b57cec5SDimitry Andric         if (DA->isCommon())
97*0b57cec5SDimitry Andric           Flags |= JITSymbolFlags::Common;
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric         InternedResult[InternedName] =
100*0b57cec5SDimitry Andric             JITEvaluatedSymbol(DA->getAddress(), Flags);
101*0b57cec5SDimitry Andric         if (AutoClaim && !MR.getSymbols().count(InternedName)) {
102*0b57cec5SDimitry Andric           assert(!ExtraSymbolsToClaim.count(InternedName) &&
103*0b57cec5SDimitry Andric                  "Duplicate symbol to claim?");
104*0b57cec5SDimitry Andric           ExtraSymbolsToClaim[InternedName] = Flags;
105*0b57cec5SDimitry Andric         }
106*0b57cec5SDimitry Andric       }
107*0b57cec5SDimitry Andric 
108*0b57cec5SDimitry Andric     for (auto *A : G.absolute_atoms())
109*0b57cec5SDimitry Andric       if (A->hasName()) {
110*0b57cec5SDimitry Andric         auto InternedName = ES.intern(A->getName());
111*0b57cec5SDimitry Andric         JITSymbolFlags Flags;
112*0b57cec5SDimitry Andric         Flags |= JITSymbolFlags::Absolute;
113*0b57cec5SDimitry Andric         if (A->isWeak())
114*0b57cec5SDimitry Andric           Flags |= JITSymbolFlags::Weak;
115*0b57cec5SDimitry Andric         if (A->isCallable())
116*0b57cec5SDimitry Andric           Flags |= JITSymbolFlags::Callable;
117*0b57cec5SDimitry Andric         InternedResult[InternedName] =
118*0b57cec5SDimitry Andric             JITEvaluatedSymbol(A->getAddress(), Flags);
119*0b57cec5SDimitry Andric         if (AutoClaim && !MR.getSymbols().count(InternedName)) {
120*0b57cec5SDimitry Andric           assert(!ExtraSymbolsToClaim.count(InternedName) &&
121*0b57cec5SDimitry Andric                  "Duplicate symbol to claim?");
122*0b57cec5SDimitry Andric           ExtraSymbolsToClaim[InternedName] = Flags;
123*0b57cec5SDimitry Andric         }
124*0b57cec5SDimitry Andric       }
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric     if (!ExtraSymbolsToClaim.empty())
127*0b57cec5SDimitry Andric       if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
128*0b57cec5SDimitry Andric         return notifyFailed(std::move(Err));
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric     MR.notifyResolved(InternedResult);
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric     Layer.notifyLoaded(MR);
133*0b57cec5SDimitry Andric   }
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric   void notifyFinalized(
136*0b57cec5SDimitry Andric       std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric     if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
139*0b57cec5SDimitry Andric       Layer.getExecutionSession().reportError(std::move(Err));
140*0b57cec5SDimitry Andric       MR.failMaterialization();
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric       return;
143*0b57cec5SDimitry Andric     }
144*0b57cec5SDimitry Andric     MR.notifyEmitted();
145*0b57cec5SDimitry Andric   }
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric   AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
148*0b57cec5SDimitry Andric     return [this](AtomGraph &G) { return markResponsibilitySymbolsLive(G); };
149*0b57cec5SDimitry Andric   }
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric   Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
152*0b57cec5SDimitry Andric     // Add passes to mark duplicate defs as should-discard, and to walk the
153*0b57cec5SDimitry Andric     // atom graph to build the symbol dependence graph.
154*0b57cec5SDimitry Andric     Config.PrePrunePasses.push_back(
155*0b57cec5SDimitry Andric         [this](AtomGraph &G) { return markSymbolsToDiscard(G); });
156*0b57cec5SDimitry Andric     Config.PostPrunePasses.push_back(
157*0b57cec5SDimitry Andric         [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
158*0b57cec5SDimitry Andric 
159*0b57cec5SDimitry Andric     Layer.modifyPassConfig(MR, TT, Config);
160*0b57cec5SDimitry Andric 
161*0b57cec5SDimitry Andric     return Error::success();
162*0b57cec5SDimitry Andric   }
163*0b57cec5SDimitry Andric 
164*0b57cec5SDimitry Andric private:
165*0b57cec5SDimitry Andric   using AnonAtomNamedDependenciesMap =
166*0b57cec5SDimitry Andric       DenseMap<const DefinedAtom *, SymbolNameSet>;
167*0b57cec5SDimitry Andric 
168*0b57cec5SDimitry Andric   Error markSymbolsToDiscard(AtomGraph &G) {
169*0b57cec5SDimitry Andric     auto &ES = Layer.getExecutionSession();
170*0b57cec5SDimitry Andric     for (auto *DA : G.defined_atoms())
171*0b57cec5SDimitry Andric       if (DA->isWeak() && DA->hasName()) {
172*0b57cec5SDimitry Andric         auto S = ES.intern(DA->getName());
173*0b57cec5SDimitry Andric         auto I = MR.getSymbols().find(S);
174*0b57cec5SDimitry Andric         if (I == MR.getSymbols().end())
175*0b57cec5SDimitry Andric           DA->setShouldDiscard(true);
176*0b57cec5SDimitry Andric       }
177*0b57cec5SDimitry Andric 
178*0b57cec5SDimitry Andric     for (auto *A : G.absolute_atoms())
179*0b57cec5SDimitry Andric       if (A->isWeak() && A->hasName()) {
180*0b57cec5SDimitry Andric         auto S = ES.intern(A->getName());
181*0b57cec5SDimitry Andric         auto I = MR.getSymbols().find(S);
182*0b57cec5SDimitry Andric         if (I == MR.getSymbols().end())
183*0b57cec5SDimitry Andric           A->setShouldDiscard(true);
184*0b57cec5SDimitry Andric       }
185*0b57cec5SDimitry Andric 
186*0b57cec5SDimitry Andric     return Error::success();
187*0b57cec5SDimitry Andric   }
188*0b57cec5SDimitry Andric 
189*0b57cec5SDimitry Andric   Error markResponsibilitySymbolsLive(AtomGraph &G) const {
190*0b57cec5SDimitry Andric     auto &ES = Layer.getExecutionSession();
191*0b57cec5SDimitry Andric     for (auto *DA : G.defined_atoms())
192*0b57cec5SDimitry Andric       if (DA->hasName() &&
193*0b57cec5SDimitry Andric           MR.getSymbols().count(ES.intern(DA->getName())))
194*0b57cec5SDimitry Andric         DA->setLive(true);
195*0b57cec5SDimitry Andric     return Error::success();
196*0b57cec5SDimitry Andric   }
197*0b57cec5SDimitry Andric 
198*0b57cec5SDimitry Andric   Error computeNamedSymbolDependencies(AtomGraph &G) {
199*0b57cec5SDimitry Andric     auto &ES = MR.getTargetJITDylib().getExecutionSession();
200*0b57cec5SDimitry Andric     auto AnonDeps = computeAnonDeps(G);
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric     for (auto *DA : G.defined_atoms()) {
203*0b57cec5SDimitry Andric 
204*0b57cec5SDimitry Andric       // Skip anonymous and non-global atoms: we do not need dependencies for
205*0b57cec5SDimitry Andric       // these.
206*0b57cec5SDimitry Andric       if (!DA->hasName() || !DA->isGlobal())
207*0b57cec5SDimitry Andric         continue;
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric       auto DAName = ES.intern(DA->getName());
210*0b57cec5SDimitry Andric       SymbolNameSet &DADeps = NamedSymbolDeps[DAName];
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric       for (auto &E : DA->edges()) {
213*0b57cec5SDimitry Andric         auto &TA = E.getTarget();
214*0b57cec5SDimitry Andric 
215*0b57cec5SDimitry Andric         if (TA.hasName())
216*0b57cec5SDimitry Andric           DADeps.insert(ES.intern(TA.getName()));
217*0b57cec5SDimitry Andric         else {
218*0b57cec5SDimitry Andric           assert(TA.isDefined() && "Anonymous atoms must be defined");
219*0b57cec5SDimitry Andric           auto &DTA = static_cast<DefinedAtom &>(TA);
220*0b57cec5SDimitry Andric           auto I = AnonDeps.find(&DTA);
221*0b57cec5SDimitry Andric           if (I != AnonDeps.end())
222*0b57cec5SDimitry Andric             for (auto &S : I->second)
223*0b57cec5SDimitry Andric               DADeps.insert(S);
224*0b57cec5SDimitry Andric         }
225*0b57cec5SDimitry Andric       }
226*0b57cec5SDimitry Andric     }
227*0b57cec5SDimitry Andric 
228*0b57cec5SDimitry Andric     return Error::success();
229*0b57cec5SDimitry Andric   }
230*0b57cec5SDimitry Andric 
231*0b57cec5SDimitry Andric   AnonAtomNamedDependenciesMap computeAnonDeps(AtomGraph &G) {
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric     auto &ES = MR.getTargetJITDylib().getExecutionSession();
234*0b57cec5SDimitry Andric     AnonAtomNamedDependenciesMap DepMap;
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric     // For all anonymous atoms:
237*0b57cec5SDimitry Andric     // (1) Add their named dependencies.
238*0b57cec5SDimitry Andric     // (2) Add them to the worklist for further iteration if they have any
239*0b57cec5SDimitry Andric     //     depend on any other anonymous atoms.
240*0b57cec5SDimitry Andric     struct WorklistEntry {
241*0b57cec5SDimitry Andric       WorklistEntry(DefinedAtom *DA, DenseSet<DefinedAtom *> DAAnonDeps)
242*0b57cec5SDimitry Andric           : DA(DA), DAAnonDeps(std::move(DAAnonDeps)) {}
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric       DefinedAtom *DA = nullptr;
245*0b57cec5SDimitry Andric       DenseSet<DefinedAtom *> DAAnonDeps;
246*0b57cec5SDimitry Andric     };
247*0b57cec5SDimitry Andric     std::vector<WorklistEntry> Worklist;
248*0b57cec5SDimitry Andric     for (auto *DA : G.defined_atoms())
249*0b57cec5SDimitry Andric       if (!DA->hasName()) {
250*0b57cec5SDimitry Andric         auto &DANamedDeps = DepMap[DA];
251*0b57cec5SDimitry Andric         DenseSet<DefinedAtom *> DAAnonDeps;
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric         for (auto &E : DA->edges()) {
254*0b57cec5SDimitry Andric           auto &TA = E.getTarget();
255*0b57cec5SDimitry Andric           if (TA.hasName())
256*0b57cec5SDimitry Andric             DANamedDeps.insert(ES.intern(TA.getName()));
257*0b57cec5SDimitry Andric           else {
258*0b57cec5SDimitry Andric             assert(TA.isDefined() && "Anonymous atoms must be defined");
259*0b57cec5SDimitry Andric             DAAnonDeps.insert(static_cast<DefinedAtom *>(&TA));
260*0b57cec5SDimitry Andric           }
261*0b57cec5SDimitry Andric         }
262*0b57cec5SDimitry Andric 
263*0b57cec5SDimitry Andric         if (!DAAnonDeps.empty())
264*0b57cec5SDimitry Andric           Worklist.push_back(WorklistEntry(DA, std::move(DAAnonDeps)));
265*0b57cec5SDimitry Andric       }
266*0b57cec5SDimitry Andric 
267*0b57cec5SDimitry Andric     // Loop over all anonymous atoms with anonymous dependencies, propagating
268*0b57cec5SDimitry Andric     // their respective *named* dependencies. Iterate until we hit a stable
269*0b57cec5SDimitry Andric     // state.
270*0b57cec5SDimitry Andric     bool Changed;
271*0b57cec5SDimitry Andric     do {
272*0b57cec5SDimitry Andric       Changed = false;
273*0b57cec5SDimitry Andric       for (auto &WLEntry : Worklist) {
274*0b57cec5SDimitry Andric         auto *DA = WLEntry.DA;
275*0b57cec5SDimitry Andric         auto &DANamedDeps = DepMap[DA];
276*0b57cec5SDimitry Andric         auto &DAAnonDeps = WLEntry.DAAnonDeps;
277*0b57cec5SDimitry Andric 
278*0b57cec5SDimitry Andric         for (auto *TA : DAAnonDeps) {
279*0b57cec5SDimitry Andric           auto I = DepMap.find(TA);
280*0b57cec5SDimitry Andric           if (I != DepMap.end())
281*0b57cec5SDimitry Andric             for (const auto &S : I->second)
282*0b57cec5SDimitry Andric               Changed |= DANamedDeps.insert(S).second;
283*0b57cec5SDimitry Andric         }
284*0b57cec5SDimitry Andric       }
285*0b57cec5SDimitry Andric     } while (Changed);
286*0b57cec5SDimitry Andric 
287*0b57cec5SDimitry Andric     return DepMap;
288*0b57cec5SDimitry Andric   }
289*0b57cec5SDimitry Andric 
290*0b57cec5SDimitry Andric   void registerDependencies(const SymbolDependenceMap &QueryDeps) {
291*0b57cec5SDimitry Andric     for (auto &NamedDepsEntry : NamedSymbolDeps) {
292*0b57cec5SDimitry Andric       auto &Name = NamedDepsEntry.first;
293*0b57cec5SDimitry Andric       auto &NameDeps = NamedDepsEntry.second;
294*0b57cec5SDimitry Andric       SymbolDependenceMap SymbolDeps;
295*0b57cec5SDimitry Andric 
296*0b57cec5SDimitry Andric       for (const auto &QueryDepsEntry : QueryDeps) {
297*0b57cec5SDimitry Andric         JITDylib &SourceJD = *QueryDepsEntry.first;
298*0b57cec5SDimitry Andric         const SymbolNameSet &Symbols = QueryDepsEntry.second;
299*0b57cec5SDimitry Andric         auto &DepsForJD = SymbolDeps[&SourceJD];
300*0b57cec5SDimitry Andric 
301*0b57cec5SDimitry Andric         for (const auto &S : Symbols)
302*0b57cec5SDimitry Andric           if (NameDeps.count(S))
303*0b57cec5SDimitry Andric             DepsForJD.insert(S);
304*0b57cec5SDimitry Andric 
305*0b57cec5SDimitry Andric         if (DepsForJD.empty())
306*0b57cec5SDimitry Andric           SymbolDeps.erase(&SourceJD);
307*0b57cec5SDimitry Andric       }
308*0b57cec5SDimitry Andric 
309*0b57cec5SDimitry Andric       MR.addDependencies(Name, SymbolDeps);
310*0b57cec5SDimitry Andric     }
311*0b57cec5SDimitry Andric   }
312*0b57cec5SDimitry Andric 
313*0b57cec5SDimitry Andric   ObjectLinkingLayer &Layer;
314*0b57cec5SDimitry Andric   MaterializationResponsibility MR;
315*0b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> ObjBuffer;
316*0b57cec5SDimitry Andric   DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
317*0b57cec5SDimitry Andric };
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() {}
320*0b57cec5SDimitry Andric 
321*0b57cec5SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
322*0b57cec5SDimitry Andric                                        JITLinkMemoryManager &MemMgr)
323*0b57cec5SDimitry Andric     : ObjectLayer(ES), MemMgr(MemMgr) {}
324*0b57cec5SDimitry Andric 
325*0b57cec5SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() {
326*0b57cec5SDimitry Andric   if (auto Err = removeAllModules())
327*0b57cec5SDimitry Andric     getExecutionSession().reportError(std::move(Err));
328*0b57cec5SDimitry Andric }
329*0b57cec5SDimitry Andric 
330*0b57cec5SDimitry Andric void ObjectLinkingLayer::emit(MaterializationResponsibility R,
331*0b57cec5SDimitry Andric                               std::unique_ptr<MemoryBuffer> O) {
332*0b57cec5SDimitry Andric   assert(O && "Object must not be null");
333*0b57cec5SDimitry Andric   jitLink(llvm::make_unique<ObjectLinkingLayerJITLinkContext>(
334*0b57cec5SDimitry Andric       *this, std::move(R), std::move(O)));
335*0b57cec5SDimitry Andric }
336*0b57cec5SDimitry Andric 
337*0b57cec5SDimitry Andric void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
338*0b57cec5SDimitry Andric                                           const Triple &TT,
339*0b57cec5SDimitry Andric                                           PassConfiguration &PassConfig) {
340*0b57cec5SDimitry Andric   for (auto &P : Plugins)
341*0b57cec5SDimitry Andric     P->modifyPassConfig(MR, TT, PassConfig);
342*0b57cec5SDimitry Andric }
343*0b57cec5SDimitry Andric 
344*0b57cec5SDimitry Andric void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
345*0b57cec5SDimitry Andric   for (auto &P : Plugins)
346*0b57cec5SDimitry Andric     P->notifyLoaded(MR);
347*0b57cec5SDimitry Andric }
348*0b57cec5SDimitry Andric 
349*0b57cec5SDimitry Andric Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
350*0b57cec5SDimitry Andric                                         AllocPtr Alloc) {
351*0b57cec5SDimitry Andric   Error Err = Error::success();
352*0b57cec5SDimitry Andric   for (auto &P : Plugins)
353*0b57cec5SDimitry Andric     Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
354*0b57cec5SDimitry Andric 
355*0b57cec5SDimitry Andric   if (Err)
356*0b57cec5SDimitry Andric     return Err;
357*0b57cec5SDimitry Andric 
358*0b57cec5SDimitry Andric   {
359*0b57cec5SDimitry Andric     std::lock_guard<std::mutex> Lock(LayerMutex);
360*0b57cec5SDimitry Andric     UntrackedAllocs.push_back(std::move(Alloc));
361*0b57cec5SDimitry Andric   }
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric   return Error::success();
364*0b57cec5SDimitry Andric }
365*0b57cec5SDimitry Andric 
366*0b57cec5SDimitry Andric Error ObjectLinkingLayer::removeModule(VModuleKey K) {
367*0b57cec5SDimitry Andric   Error Err = Error::success();
368*0b57cec5SDimitry Andric 
369*0b57cec5SDimitry Andric   for (auto &P : Plugins)
370*0b57cec5SDimitry Andric     Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
371*0b57cec5SDimitry Andric 
372*0b57cec5SDimitry Andric   AllocPtr Alloc;
373*0b57cec5SDimitry Andric 
374*0b57cec5SDimitry Andric   {
375*0b57cec5SDimitry Andric     std::lock_guard<std::mutex> Lock(LayerMutex);
376*0b57cec5SDimitry Andric     auto AllocItr = TrackedAllocs.find(K);
377*0b57cec5SDimitry Andric     Alloc = std::move(AllocItr->second);
378*0b57cec5SDimitry Andric     TrackedAllocs.erase(AllocItr);
379*0b57cec5SDimitry Andric   }
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric   assert(Alloc && "No allocation for key K");
382*0b57cec5SDimitry Andric 
383*0b57cec5SDimitry Andric   return joinErrors(std::move(Err), Alloc->deallocate());
384*0b57cec5SDimitry Andric }
385*0b57cec5SDimitry Andric 
386*0b57cec5SDimitry Andric Error ObjectLinkingLayer::removeAllModules() {
387*0b57cec5SDimitry Andric 
388*0b57cec5SDimitry Andric   Error Err = Error::success();
389*0b57cec5SDimitry Andric 
390*0b57cec5SDimitry Andric   for (auto &P : Plugins)
391*0b57cec5SDimitry Andric     Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
392*0b57cec5SDimitry Andric 
393*0b57cec5SDimitry Andric   std::vector<AllocPtr> Allocs;
394*0b57cec5SDimitry Andric   {
395*0b57cec5SDimitry Andric     std::lock_guard<std::mutex> Lock(LayerMutex);
396*0b57cec5SDimitry Andric     Allocs = std::move(UntrackedAllocs);
397*0b57cec5SDimitry Andric 
398*0b57cec5SDimitry Andric     for (auto &KV : TrackedAllocs)
399*0b57cec5SDimitry Andric       Allocs.push_back(std::move(KV.second));
400*0b57cec5SDimitry Andric 
401*0b57cec5SDimitry Andric     TrackedAllocs.clear();
402*0b57cec5SDimitry Andric   }
403*0b57cec5SDimitry Andric 
404*0b57cec5SDimitry Andric   while (!Allocs.empty()) {
405*0b57cec5SDimitry Andric     Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
406*0b57cec5SDimitry Andric     Allocs.pop_back();
407*0b57cec5SDimitry Andric   }
408*0b57cec5SDimitry Andric 
409*0b57cec5SDimitry Andric   return Err;
410*0b57cec5SDimitry Andric }
411*0b57cec5SDimitry Andric 
412*0b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
413*0b57cec5SDimitry Andric     jitlink::EHFrameRegistrar &Registrar)
414*0b57cec5SDimitry Andric     : Registrar(Registrar) {}
415*0b57cec5SDimitry Andric 
416*0b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig(
417*0b57cec5SDimitry Andric     MaterializationResponsibility &MR, const Triple &TT,
418*0b57cec5SDimitry Andric     PassConfiguration &PassConfig) {
419*0b57cec5SDimitry Andric   assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
420*0b57cec5SDimitry Andric 
421*0b57cec5SDimitry Andric   PassConfig.PostFixupPasses.push_back(
422*0b57cec5SDimitry Andric       createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
423*0b57cec5SDimitry Andric         if (Addr)
424*0b57cec5SDimitry Andric           InProcessLinks[&MR] = Addr;
425*0b57cec5SDimitry Andric       }));
426*0b57cec5SDimitry Andric }
427*0b57cec5SDimitry Andric 
428*0b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted(
429*0b57cec5SDimitry Andric     MaterializationResponsibility &MR) {
430*0b57cec5SDimitry Andric 
431*0b57cec5SDimitry Andric   auto EHFrameAddrItr = InProcessLinks.find(&MR);
432*0b57cec5SDimitry Andric   if (EHFrameAddrItr == InProcessLinks.end())
433*0b57cec5SDimitry Andric     return Error::success();
434*0b57cec5SDimitry Andric 
435*0b57cec5SDimitry Andric   auto EHFrameAddr = EHFrameAddrItr->second;
436*0b57cec5SDimitry Andric   assert(EHFrameAddr && "eh-frame addr to register can not be null");
437*0b57cec5SDimitry Andric 
438*0b57cec5SDimitry Andric   InProcessLinks.erase(EHFrameAddrItr);
439*0b57cec5SDimitry Andric   if (auto Key = MR.getVModuleKey())
440*0b57cec5SDimitry Andric     TrackedEHFrameAddrs[Key] = EHFrameAddr;
441*0b57cec5SDimitry Andric   else
442*0b57cec5SDimitry Andric     UntrackedEHFrameAddrs.push_back(EHFrameAddr);
443*0b57cec5SDimitry Andric 
444*0b57cec5SDimitry Andric   return Registrar.registerEHFrames(EHFrameAddr);
445*0b57cec5SDimitry Andric }
446*0b57cec5SDimitry Andric 
447*0b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
448*0b57cec5SDimitry Andric   auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
449*0b57cec5SDimitry Andric   if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
450*0b57cec5SDimitry Andric     return Error::success();
451*0b57cec5SDimitry Andric 
452*0b57cec5SDimitry Andric   auto EHFrameAddr = EHFrameAddrItr->second;
453*0b57cec5SDimitry Andric   assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
454*0b57cec5SDimitry Andric 
455*0b57cec5SDimitry Andric   TrackedEHFrameAddrs.erase(EHFrameAddrItr);
456*0b57cec5SDimitry Andric 
457*0b57cec5SDimitry Andric   return Registrar.deregisterEHFrames(EHFrameAddr);
458*0b57cec5SDimitry Andric }
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
461*0b57cec5SDimitry Andric 
462*0b57cec5SDimitry Andric   std::vector<JITTargetAddress> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
463*0b57cec5SDimitry Andric   EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
464*0b57cec5SDimitry Andric 
465*0b57cec5SDimitry Andric   for (auto &KV : TrackedEHFrameAddrs)
466*0b57cec5SDimitry Andric     EHFrameAddrs.push_back(KV.second);
467*0b57cec5SDimitry Andric 
468*0b57cec5SDimitry Andric   TrackedEHFrameAddrs.clear();
469*0b57cec5SDimitry Andric 
470*0b57cec5SDimitry Andric   Error Err = Error::success();
471*0b57cec5SDimitry Andric 
472*0b57cec5SDimitry Andric   while (!EHFrameAddrs.empty()) {
473*0b57cec5SDimitry Andric     auto EHFrameAddr = EHFrameAddrs.back();
474*0b57cec5SDimitry Andric     assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
475*0b57cec5SDimitry Andric     EHFrameAddrs.pop_back();
476*0b57cec5SDimitry Andric     Err = joinErrors(std::move(Err), Registrar.deregisterEHFrames(EHFrameAddr));
477*0b57cec5SDimitry Andric   }
478*0b57cec5SDimitry Andric 
479*0b57cec5SDimitry Andric   return Err;
480*0b57cec5SDimitry Andric }
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric } // End namespace orc.
483*0b57cec5SDimitry Andric } // End namespace llvm.
484