[ARM] Generate 8.1-m CSINC, CSNEG and CSINV instructions.
[llvm-core.git] / lib / ExecutionEngine / Orc / ObjectLinkingLayer.cpp
blobe1b8d52acb4296cbc24c391e983cd8446681003f
1 //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
14 #include <vector>
16 #define DEBUG_TYPE "orc"
18 using namespace llvm;
19 using namespace llvm::jitlink;
20 using namespace llvm::orc;
22 namespace llvm {
23 namespace orc {
25 class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
26 public:
27 ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer,
28 MaterializationResponsibility MR,
29 std::unique_ptr<MemoryBuffer> ObjBuffer)
30 : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
32 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
34 MemoryBufferRef getObjectBuffer() const override {
35 return ObjBuffer->getMemBufferRef();
38 void notifyFailed(Error Err) override {
39 Layer.getExecutionSession().reportError(std::move(Err));
40 MR.failMaterialization();
43 void lookup(const DenseSet<StringRef> &Symbols,
44 JITLinkAsyncLookupContinuation LookupContinuation) override {
46 JITDylibSearchList SearchOrder;
47 MR.getTargetJITDylib().withSearchOrderDo(
48 [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
50 auto &ES = Layer.getExecutionSession();
52 SymbolNameSet InternedSymbols;
53 for (auto &S : Symbols)
54 InternedSymbols.insert(ES.intern(S));
56 // OnResolve -- De-intern the symbols and pass the result to the linker.
57 // FIXME: Capture LookupContinuation by move once we have c++14.
58 auto SharedLookupContinuation =
59 std::make_shared<JITLinkAsyncLookupContinuation>(
60 std::move(LookupContinuation));
61 auto OnResolve = [this, SharedLookupContinuation](Expected<SymbolMap> Result) {
62 auto Main = Layer.getExecutionSession().intern("_main");
63 if (!Result)
64 (*SharedLookupContinuation)(Result.takeError());
65 else {
66 AsyncLookupResult LR;
67 for (auto &KV : *Result)
68 LR[*KV.first] = KV.second;
69 (*SharedLookupContinuation)(std::move(LR));
73 ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
74 std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
75 registerDependencies(Deps);
76 });
79 void notifyResolved(AtomGraph &G) override {
80 auto &ES = Layer.getExecutionSession();
82 SymbolFlagsMap ExtraSymbolsToClaim;
83 bool AutoClaim = Layer.AutoClaimObjectSymbols;
85 SymbolMap InternedResult;
86 for (auto *DA : G.defined_atoms())
87 if (DA->hasName() && DA->isGlobal()) {
88 auto InternedName = ES.intern(DA->getName());
89 JITSymbolFlags Flags;
91 if (DA->isExported())
92 Flags |= JITSymbolFlags::Exported;
93 if (DA->isWeak())
94 Flags |= JITSymbolFlags::Weak;
95 if (DA->isCallable())
96 Flags |= JITSymbolFlags::Callable;
97 if (DA->isCommon())
98 Flags |= JITSymbolFlags::Common;
100 InternedResult[InternedName] =
101 JITEvaluatedSymbol(DA->getAddress(), Flags);
102 if (AutoClaim && !MR.getSymbols().count(InternedName)) {
103 assert(!ExtraSymbolsToClaim.count(InternedName) &&
104 "Duplicate symbol to claim?");
105 ExtraSymbolsToClaim[InternedName] = Flags;
109 for (auto *A : G.absolute_atoms())
110 if (A->hasName()) {
111 auto InternedName = ES.intern(A->getName());
112 JITSymbolFlags Flags;
113 Flags |= JITSymbolFlags::Absolute;
114 if (A->isWeak())
115 Flags |= JITSymbolFlags::Weak;
116 if (A->isCallable())
117 Flags |= JITSymbolFlags::Callable;
118 InternedResult[InternedName] =
119 JITEvaluatedSymbol(A->getAddress(), Flags);
120 if (AutoClaim && !MR.getSymbols().count(InternedName)) {
121 assert(!ExtraSymbolsToClaim.count(InternedName) &&
122 "Duplicate symbol to claim?");
123 ExtraSymbolsToClaim[InternedName] = Flags;
127 if (!ExtraSymbolsToClaim.empty())
128 if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
129 return notifyFailed(std::move(Err));
130 if (auto Err = MR.notifyResolved(InternedResult)) {
131 Layer.getExecutionSession().reportError(std::move(Err));
132 MR.failMaterialization();
133 return;
135 Layer.notifyLoaded(MR);
138 void notifyFinalized(
139 std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
140 if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
141 Layer.getExecutionSession().reportError(std::move(Err));
142 MR.failMaterialization();
143 return;
145 if (auto Err = MR.notifyEmitted()) {
146 Layer.getExecutionSession().reportError(std::move(Err));
147 MR.failMaterialization();
151 AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
152 return [this](AtomGraph &G) { return markResponsibilitySymbolsLive(G); };
155 Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
156 // Add passes to mark duplicate defs as should-discard, and to walk the
157 // atom graph to build the symbol dependence graph.
158 Config.PrePrunePasses.push_back(
159 [this](AtomGraph &G) { return markSymbolsToDiscard(G); });
160 Config.PostPrunePasses.push_back(
161 [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
163 Layer.modifyPassConfig(MR, TT, Config);
165 return Error::success();
168 private:
169 using AnonAtomNamedDependenciesMap =
170 DenseMap<const DefinedAtom *, SymbolNameSet>;
172 Error markSymbolsToDiscard(AtomGraph &G) {
173 auto &ES = Layer.getExecutionSession();
174 for (auto *DA : G.defined_atoms())
175 if (DA->isWeak() && DA->hasName()) {
176 auto S = ES.intern(DA->getName());
177 auto I = MR.getSymbols().find(S);
178 if (I == MR.getSymbols().end())
179 DA->setShouldDiscard(true);
182 for (auto *A : G.absolute_atoms())
183 if (A->isWeak() && A->hasName()) {
184 auto S = ES.intern(A->getName());
185 auto I = MR.getSymbols().find(S);
186 if (I == MR.getSymbols().end())
187 A->setShouldDiscard(true);
190 return Error::success();
193 Error markResponsibilitySymbolsLive(AtomGraph &G) const {
194 auto &ES = Layer.getExecutionSession();
195 for (auto *DA : G.defined_atoms())
196 if (DA->hasName() &&
197 MR.getSymbols().count(ES.intern(DA->getName())))
198 DA->setLive(true);
199 return Error::success();
202 Error computeNamedSymbolDependencies(AtomGraph &G) {
203 auto &ES = MR.getTargetJITDylib().getExecutionSession();
204 auto AnonDeps = computeAnonDeps(G);
206 for (auto *DA : G.defined_atoms()) {
208 // Skip anonymous and non-global atoms: we do not need dependencies for
209 // these.
210 if (!DA->hasName() || !DA->isGlobal())
211 continue;
213 auto DAName = ES.intern(DA->getName());
214 SymbolNameSet &DADeps = NamedSymbolDeps[DAName];
216 for (auto &E : DA->edges()) {
217 auto &TA = E.getTarget();
219 if (TA.hasName())
220 DADeps.insert(ES.intern(TA.getName()));
221 else {
222 assert(TA.isDefined() && "Anonymous atoms must be defined");
223 auto &DTA = static_cast<DefinedAtom &>(TA);
224 auto I = AnonDeps.find(&DTA);
225 if (I != AnonDeps.end())
226 for (auto &S : I->second)
227 DADeps.insert(S);
232 return Error::success();
235 AnonAtomNamedDependenciesMap computeAnonDeps(AtomGraph &G) {
237 auto &ES = MR.getTargetJITDylib().getExecutionSession();
238 AnonAtomNamedDependenciesMap DepMap;
240 // For all anonymous atoms:
241 // (1) Add their named dependencies.
242 // (2) Add them to the worklist for further iteration if they have any
243 // depend on any other anonymous atoms.
244 struct WorklistEntry {
245 WorklistEntry(DefinedAtom *DA, DenseSet<DefinedAtom *> DAAnonDeps)
246 : DA(DA), DAAnonDeps(std::move(DAAnonDeps)) {}
248 DefinedAtom *DA = nullptr;
249 DenseSet<DefinedAtom *> DAAnonDeps;
251 std::vector<WorklistEntry> Worklist;
252 for (auto *DA : G.defined_atoms())
253 if (!DA->hasName()) {
254 auto &DANamedDeps = DepMap[DA];
255 DenseSet<DefinedAtom *> DAAnonDeps;
257 for (auto &E : DA->edges()) {
258 auto &TA = E.getTarget();
259 if (TA.hasName())
260 DANamedDeps.insert(ES.intern(TA.getName()));
261 else {
262 assert(TA.isDefined() && "Anonymous atoms must be defined");
263 DAAnonDeps.insert(static_cast<DefinedAtom *>(&TA));
267 if (!DAAnonDeps.empty())
268 Worklist.push_back(WorklistEntry(DA, std::move(DAAnonDeps)));
271 // Loop over all anonymous atoms with anonymous dependencies, propagating
272 // their respective *named* dependencies. Iterate until we hit a stable
273 // state.
274 bool Changed;
275 do {
276 Changed = false;
277 for (auto &WLEntry : Worklist) {
278 auto *DA = WLEntry.DA;
279 auto &DANamedDeps = DepMap[DA];
280 auto &DAAnonDeps = WLEntry.DAAnonDeps;
282 for (auto *TA : DAAnonDeps) {
283 auto I = DepMap.find(TA);
284 if (I != DepMap.end())
285 for (const auto &S : I->second)
286 Changed |= DANamedDeps.insert(S).second;
289 } while (Changed);
291 return DepMap;
294 void registerDependencies(const SymbolDependenceMap &QueryDeps) {
295 for (auto &NamedDepsEntry : NamedSymbolDeps) {
296 auto &Name = NamedDepsEntry.first;
297 auto &NameDeps = NamedDepsEntry.second;
298 SymbolDependenceMap SymbolDeps;
300 for (const auto &QueryDepsEntry : QueryDeps) {
301 JITDylib &SourceJD = *QueryDepsEntry.first;
302 const SymbolNameSet &Symbols = QueryDepsEntry.second;
303 auto &DepsForJD = SymbolDeps[&SourceJD];
305 for (const auto &S : Symbols)
306 if (NameDeps.count(S))
307 DepsForJD.insert(S);
309 if (DepsForJD.empty())
310 SymbolDeps.erase(&SourceJD);
313 MR.addDependencies(Name, SymbolDeps);
317 ObjectLinkingLayer &Layer;
318 MaterializationResponsibility MR;
319 std::unique_ptr<MemoryBuffer> ObjBuffer;
320 DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
323 ObjectLinkingLayer::Plugin::~Plugin() {}
325 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
326 JITLinkMemoryManager &MemMgr)
327 : ObjectLayer(ES), MemMgr(MemMgr) {}
329 ObjectLinkingLayer::~ObjectLinkingLayer() {
330 if (auto Err = removeAllModules())
331 getExecutionSession().reportError(std::move(Err));
334 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
335 std::unique_ptr<MemoryBuffer> O) {
336 assert(O && "Object must not be null");
337 jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
338 *this, std::move(R), std::move(O)));
341 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
342 const Triple &TT,
343 PassConfiguration &PassConfig) {
344 for (auto &P : Plugins)
345 P->modifyPassConfig(MR, TT, PassConfig);
348 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
349 for (auto &P : Plugins)
350 P->notifyLoaded(MR);
353 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
354 AllocPtr Alloc) {
355 Error Err = Error::success();
356 for (auto &P : Plugins)
357 Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
359 if (Err)
360 return Err;
363 std::lock_guard<std::mutex> Lock(LayerMutex);
364 UntrackedAllocs.push_back(std::move(Alloc));
367 return Error::success();
370 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
371 Error Err = Error::success();
373 for (auto &P : Plugins)
374 Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
376 AllocPtr Alloc;
379 std::lock_guard<std::mutex> Lock(LayerMutex);
380 auto AllocItr = TrackedAllocs.find(K);
381 Alloc = std::move(AllocItr->second);
382 TrackedAllocs.erase(AllocItr);
385 assert(Alloc && "No allocation for key K");
387 return joinErrors(std::move(Err), Alloc->deallocate());
390 Error ObjectLinkingLayer::removeAllModules() {
392 Error Err = Error::success();
394 for (auto &P : Plugins)
395 Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
397 std::vector<AllocPtr> Allocs;
399 std::lock_guard<std::mutex> Lock(LayerMutex);
400 Allocs = std::move(UntrackedAllocs);
402 for (auto &KV : TrackedAllocs)
403 Allocs.push_back(std::move(KV.second));
405 TrackedAllocs.clear();
408 while (!Allocs.empty()) {
409 Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
410 Allocs.pop_back();
413 return Err;
416 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
417 jitlink::EHFrameRegistrar &Registrar)
418 : Registrar(Registrar) {}
420 void EHFrameRegistrationPlugin::modifyPassConfig(
421 MaterializationResponsibility &MR, const Triple &TT,
422 PassConfiguration &PassConfig) {
423 assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
425 PassConfig.PostFixupPasses.push_back(
426 createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
427 size_t Size) {
428 if (Addr)
429 InProcessLinks[&MR] = { Addr, Size };
430 }));
433 Error EHFrameRegistrationPlugin::notifyEmitted(
434 MaterializationResponsibility &MR) {
436 auto EHFrameRangeItr = InProcessLinks.find(&MR);
437 if (EHFrameRangeItr == InProcessLinks.end())
438 return Error::success();
440 auto EHFrameRange = EHFrameRangeItr->second;
441 assert(EHFrameRange.Addr &&
442 "eh-frame addr to register can not be null");
444 InProcessLinks.erase(EHFrameRangeItr);
445 if (auto Key = MR.getVModuleKey())
446 TrackedEHFrameRanges[Key] = EHFrameRange;
447 else
448 UntrackedEHFrameRanges.push_back(EHFrameRange);
450 return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
453 Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
454 auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
455 if (EHFrameRangeItr == TrackedEHFrameRanges.end())
456 return Error::success();
458 auto EHFrameRange = EHFrameRangeItr->second;
459 assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
461 TrackedEHFrameRanges.erase(EHFrameRangeItr);
463 return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
466 Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
468 std::vector<EHFrameRange> EHFrameRanges =
469 std::move(UntrackedEHFrameRanges);
470 EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
472 for (auto &KV : TrackedEHFrameRanges)
473 EHFrameRanges.push_back(KV.second);
475 TrackedEHFrameRanges.clear();
477 Error Err = Error::success();
479 while (!EHFrameRanges.empty()) {
480 auto EHFrameRange = EHFrameRanges.back();
481 assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
482 EHFrameRanges.pop_back();
483 Err = joinErrors(std::move(Err),
484 Registrar.deregisterEHFrames(EHFrameRange.Addr,
485 EHFrameRange.Size));
488 return Err;
491 } // End namespace orc.
492 } // End namespace llvm.