[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / ExecutionEngine / Orc / ObjectLinkingLayer.cpp
blob874decb2ade0bc9569b73b8af306def16794b92a
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 ~ObjectLinkingLayerJITLinkContext() {
33 // If there is an object buffer return function then use it to
34 // return ownership of the buffer.
35 if (Layer.ReturnObjectBuffer)
36 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
39 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
41 MemoryBufferRef getObjectBuffer() const override {
42 return ObjBuffer->getMemBufferRef();
45 void notifyFailed(Error Err) override {
46 Layer.getExecutionSession().reportError(std::move(Err));
47 MR.failMaterialization();
50 void lookup(const DenseSet<StringRef> &Symbols,
51 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
53 JITDylibSearchList SearchOrder;
54 MR.getTargetJITDylib().withSearchOrderDo(
55 [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
57 auto &ES = Layer.getExecutionSession();
59 SymbolNameSet InternedSymbols;
60 for (auto &S : Symbols)
61 InternedSymbols.insert(ES.intern(S));
63 // OnResolve -- De-intern the symbols and pass the result to the linker.
64 auto OnResolve = [this, LookupContinuation = std::move(LC)](
65 Expected<SymbolMap> Result) mutable {
66 auto Main = Layer.getExecutionSession().intern("_main");
67 if (!Result)
68 LookupContinuation->run(Result.takeError());
69 else {
70 AsyncLookupResult LR;
71 for (auto &KV : *Result)
72 LR[*KV.first] = KV.second;
73 LookupContinuation->run(std::move(LR));
77 ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
78 std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
79 registerDependencies(Deps);
80 });
83 void notifyResolved(LinkGraph &G) override {
84 auto &ES = Layer.getExecutionSession();
86 SymbolFlagsMap ExtraSymbolsToClaim;
87 bool AutoClaim = Layer.AutoClaimObjectSymbols;
89 SymbolMap InternedResult;
90 for (auto *Sym : G.defined_symbols())
91 if (Sym->hasName() && Sym->getScope() != Scope::Local) {
92 auto InternedName = ES.intern(Sym->getName());
93 JITSymbolFlags Flags;
95 if (Sym->isCallable())
96 Flags |= JITSymbolFlags::Callable;
97 if (Sym->getScope() == Scope::Default)
98 Flags |= JITSymbolFlags::Exported;
100 InternedResult[InternedName] =
101 JITEvaluatedSymbol(Sym->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 *Sym : G.absolute_symbols())
110 if (Sym->hasName()) {
111 auto InternedName = ES.intern(Sym->getName());
112 JITSymbolFlags Flags;
113 Flags |= JITSymbolFlags::Absolute;
114 if (Sym->isCallable())
115 Flags |= JITSymbolFlags::Callable;
116 if (Sym->getLinkage() == Linkage::Weak)
117 Flags |= JITSymbolFlags::Weak;
118 InternedResult[InternedName] =
119 JITEvaluatedSymbol(Sym->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 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
152 return [this](LinkGraph &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 // link graph to build the symbol dependence graph.
158 Config.PrePrunePasses.push_back(
159 [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
160 Config.PostPrunePasses.push_back(
161 [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
163 Layer.modifyPassConfig(MR, TT, Config);
165 return Error::success();
168 private:
169 using AnonToNamedDependenciesMap = DenseMap<const Symbol *, SymbolNameSet>;
171 Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
172 auto &ES = Layer.getExecutionSession();
173 for (auto *Sym : G.defined_symbols())
174 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
175 if (!MR.getSymbols().count(ES.intern(Sym->getName())))
176 G.makeExternal(*Sym);
179 for (auto *Sym : G.absolute_symbols())
180 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
181 if (!MR.getSymbols().count(ES.intern(Sym->getName())))
182 G.makeExternal(*Sym);
185 return Error::success();
188 Error markResponsibilitySymbolsLive(LinkGraph &G) const {
189 auto &ES = Layer.getExecutionSession();
190 for (auto *Sym : G.defined_symbols())
191 if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
192 Sym->setLive(true);
193 return Error::success();
196 Error computeNamedSymbolDependencies(LinkGraph &G) {
197 auto &ES = MR.getTargetJITDylib().getExecutionSession();
198 auto AnonDeps = computeAnonDeps(G);
200 for (auto *Sym : G.defined_symbols()) {
202 // Skip anonymous and non-global atoms: we do not need dependencies for
203 // these.
204 if (Sym->getScope() == Scope::Local)
205 continue;
207 auto SymName = ES.intern(Sym->getName());
208 SymbolNameSet &SymDeps = NamedSymbolDeps[SymName];
210 for (auto &E : Sym->getBlock().edges()) {
211 auto &TargetSym = E.getTarget();
213 if (TargetSym.getScope() != Scope::Local)
214 SymDeps.insert(ES.intern(TargetSym.getName()));
215 else {
216 assert(TargetSym.isDefined() &&
217 "Anonymous/local symbols must be defined");
218 auto I = AnonDeps.find(&TargetSym);
219 if (I != AnonDeps.end())
220 for (auto &S : I->second)
221 SymDeps.insert(S);
226 return Error::success();
229 AnonToNamedDependenciesMap computeAnonDeps(LinkGraph &G) {
231 auto &ES = MR.getTargetJITDylib().getExecutionSession();
232 AnonToNamedDependenciesMap DepMap;
234 // For all anonymous symbols:
235 // (1) Add their named dependencies.
236 // (2) Add them to the worklist for further iteration if they have any
237 // depend on any other anonymous symbols.
238 struct WorklistEntry {
239 WorklistEntry(Symbol *Sym, DenseSet<Symbol *> SymAnonDeps)
240 : Sym(Sym), SymAnonDeps(std::move(SymAnonDeps)) {}
242 Symbol *Sym = nullptr;
243 DenseSet<Symbol *> SymAnonDeps;
245 std::vector<WorklistEntry> Worklist;
246 for (auto *Sym : G.defined_symbols())
247 if (!Sym->hasName()) {
248 auto &SymNamedDeps = DepMap[Sym];
249 DenseSet<Symbol *> SymAnonDeps;
251 for (auto &E : Sym->getBlock().edges()) {
252 auto &TargetSym = E.getTarget();
253 if (TargetSym.hasName())
254 SymNamedDeps.insert(ES.intern(TargetSym.getName()));
255 else {
256 assert(TargetSym.isDefined() &&
257 "Anonymous symbols must be defined");
258 SymAnonDeps.insert(&TargetSym);
262 if (!SymAnonDeps.empty())
263 Worklist.push_back(WorklistEntry(Sym, std::move(SymAnonDeps)));
266 // Loop over all anonymous symbols with anonymous dependencies, propagating
267 // their respective *named* dependencies. Iterate until we hit a stable
268 // state.
269 bool Changed;
270 do {
271 Changed = false;
272 for (auto &WLEntry : Worklist) {
273 auto *Sym = WLEntry.Sym;
274 auto &SymNamedDeps = DepMap[Sym];
275 auto &SymAnonDeps = WLEntry.SymAnonDeps;
277 for (auto *TargetSym : SymAnonDeps) {
278 auto I = DepMap.find(TargetSym);
279 if (I != DepMap.end())
280 for (const auto &S : I->second)
281 Changed |= SymNamedDeps.insert(S).second;
284 } while (Changed);
286 return DepMap;
289 void registerDependencies(const SymbolDependenceMap &QueryDeps) {
290 for (auto &NamedDepsEntry : NamedSymbolDeps) {
291 auto &Name = NamedDepsEntry.first;
292 auto &NameDeps = NamedDepsEntry.second;
293 SymbolDependenceMap SymbolDeps;
295 for (const auto &QueryDepsEntry : QueryDeps) {
296 JITDylib &SourceJD = *QueryDepsEntry.first;
297 const SymbolNameSet &Symbols = QueryDepsEntry.second;
298 auto &DepsForJD = SymbolDeps[&SourceJD];
300 for (const auto &S : Symbols)
301 if (NameDeps.count(S))
302 DepsForJD.insert(S);
304 if (DepsForJD.empty())
305 SymbolDeps.erase(&SourceJD);
308 MR.addDependencies(Name, SymbolDeps);
312 ObjectLinkingLayer &Layer;
313 MaterializationResponsibility MR;
314 std::unique_ptr<MemoryBuffer> ObjBuffer;
315 DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
318 ObjectLinkingLayer::Plugin::~Plugin() {}
320 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
321 JITLinkMemoryManager &MemMgr)
322 : ObjectLayer(ES), MemMgr(MemMgr) {}
324 ObjectLinkingLayer::~ObjectLinkingLayer() {
325 if (auto Err = removeAllModules())
326 getExecutionSession().reportError(std::move(Err));
329 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
330 std::unique_ptr<MemoryBuffer> O) {
331 assert(O && "Object must not be null");
332 jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
333 *this, std::move(R), std::move(O)));
336 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
337 const Triple &TT,
338 PassConfiguration &PassConfig) {
339 for (auto &P : Plugins)
340 P->modifyPassConfig(MR, TT, PassConfig);
343 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
344 for (auto &P : Plugins)
345 P->notifyLoaded(MR);
348 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
349 AllocPtr Alloc) {
350 Error Err = Error::success();
351 for (auto &P : Plugins)
352 Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
354 if (Err)
355 return Err;
358 std::lock_guard<std::mutex> Lock(LayerMutex);
359 UntrackedAllocs.push_back(std::move(Alloc));
362 return Error::success();
365 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
366 Error Err = Error::success();
368 for (auto &P : Plugins)
369 Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
371 AllocPtr Alloc;
374 std::lock_guard<std::mutex> Lock(LayerMutex);
375 auto AllocItr = TrackedAllocs.find(K);
376 Alloc = std::move(AllocItr->second);
377 TrackedAllocs.erase(AllocItr);
380 assert(Alloc && "No allocation for key K");
382 return joinErrors(std::move(Err), Alloc->deallocate());
385 Error ObjectLinkingLayer::removeAllModules() {
387 Error Err = Error::success();
389 for (auto &P : Plugins)
390 Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
392 std::vector<AllocPtr> Allocs;
394 std::lock_guard<std::mutex> Lock(LayerMutex);
395 Allocs = std::move(UntrackedAllocs);
397 for (auto &KV : TrackedAllocs)
398 Allocs.push_back(std::move(KV.second));
400 TrackedAllocs.clear();
403 while (!Allocs.empty()) {
404 Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
405 Allocs.pop_back();
408 return Err;
411 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
412 EHFrameRegistrar &Registrar)
413 : Registrar(Registrar) {}
415 void EHFrameRegistrationPlugin::modifyPassConfig(
416 MaterializationResponsibility &MR, const Triple &TT,
417 PassConfiguration &PassConfig) {
418 assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
420 PassConfig.PostFixupPasses.push_back(
421 createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
422 size_t Size) {
423 if (Addr)
424 InProcessLinks[&MR] = { Addr, Size };
425 }));
428 Error EHFrameRegistrationPlugin::notifyEmitted(
429 MaterializationResponsibility &MR) {
431 auto EHFrameRangeItr = InProcessLinks.find(&MR);
432 if (EHFrameRangeItr == InProcessLinks.end())
433 return Error::success();
435 auto EHFrameRange = EHFrameRangeItr->second;
436 assert(EHFrameRange.Addr &&
437 "eh-frame addr to register can not be null");
439 InProcessLinks.erase(EHFrameRangeItr);
440 if (auto Key = MR.getVModuleKey())
441 TrackedEHFrameRanges[Key] = EHFrameRange;
442 else
443 UntrackedEHFrameRanges.push_back(EHFrameRange);
445 return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
448 Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
449 auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
450 if (EHFrameRangeItr == TrackedEHFrameRanges.end())
451 return Error::success();
453 auto EHFrameRange = EHFrameRangeItr->second;
454 assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
456 TrackedEHFrameRanges.erase(EHFrameRangeItr);
458 return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
461 Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
463 std::vector<EHFrameRange> EHFrameRanges =
464 std::move(UntrackedEHFrameRanges);
465 EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
467 for (auto &KV : TrackedEHFrameRanges)
468 EHFrameRanges.push_back(KV.second);
470 TrackedEHFrameRanges.clear();
472 Error Err = Error::success();
474 while (!EHFrameRanges.empty()) {
475 auto EHFrameRange = EHFrameRanges.back();
476 assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
477 EHFrameRanges.pop_back();
478 Err = joinErrors(std::move(Err),
479 Registrar.deregisterEHFrames(EHFrameRange.Addr,
480 EHFrameRange.Size));
483 return Err;
486 } // End namespace orc.
487 } // End namespace llvm.