[InstCombine] Signed saturation patterns
[llvm-complete.git] / lib / ExecutionEngine / Orc / LazyReexports.cpp
blob93aabd817d60114a73a3cac44f2ece5ab686b9f8
1 //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
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/LazyReexports.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
14 #define DEBUG_TYPE "orc"
16 namespace llvm {
17 namespace orc {
19 void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
21 LazyCallThroughManager::LazyCallThroughManager(
22 ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
23 std::unique_ptr<TrampolinePool> TP)
24 : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
26 Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
27 JITDylib &SourceJD, SymbolStringPtr SymbolName,
28 std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
29 std::lock_guard<std::mutex> Lock(LCTMMutex);
30 auto Trampoline = TP->getTrampoline();
32 if (!Trampoline)
33 return Trampoline.takeError();
35 Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
36 Notifiers[*Trampoline] = std::move(NotifyResolved);
37 return *Trampoline;
40 JITTargetAddress
41 LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
42 JITDylib *SourceJD = nullptr;
43 SymbolStringPtr SymbolName;
46 std::lock_guard<std::mutex> Lock(LCTMMutex);
47 auto I = Reexports.find(TrampolineAddr);
48 if (I == Reexports.end())
49 return ErrorHandlerAddr;
50 SourceJD = I->second.first;
51 SymbolName = I->second.second;
53 auto LookupResult =
54 ES.lookup(JITDylibSearchList({{SourceJD, true}}), SymbolName);
56 if (!LookupResult) {
57 ES.reportError(LookupResult.takeError());
58 return ErrorHandlerAddr;
61 auto ResolvedAddr = LookupResult->getAddress();
63 std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
65 std::lock_guard<std::mutex> Lock(LCTMMutex);
66 auto I = Notifiers.find(TrampolineAddr);
67 if (I != Notifiers.end()) {
68 NotifyResolved = I->second;
69 Notifiers.erase(I);
73 if (NotifyResolved) {
74 if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
75 ES.reportError(std::move(Err));
76 return ErrorHandlerAddr;
80 return ResolvedAddr;
83 Expected<std::unique_ptr<LazyCallThroughManager>>
84 createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
85 JITTargetAddress ErrorHandlerAddr) {
86 switch (T.getArch()) {
87 default:
88 return make_error<StringError>(
89 std::string("No callback manager available for ") + T.str(),
90 inconvertibleErrorCode());
92 case Triple::aarch64:
93 case Triple::aarch64_32:
94 return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
95 ErrorHandlerAddr);
97 case Triple::x86:
98 return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
100 case Triple::mips:
101 return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
102 ErrorHandlerAddr);
104 case Triple::mipsel:
105 return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
106 ErrorHandlerAddr);
108 case Triple::mips64:
109 case Triple::mips64el:
110 return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
112 case Triple::x86_64:
113 if (T.getOS() == Triple::OSType::Win32)
114 return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
115 ES, ErrorHandlerAddr);
116 else
117 return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
118 ES, ErrorHandlerAddr);
122 LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
123 LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
124 JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc,
125 VModuleKey K)
126 : MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
127 LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
128 CallableAliases(std::move(CallableAliases)),
129 NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
130 [&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
131 JITTargetAddress ResolvedAddr) {
132 return ISManager.updatePointer(*SymbolName, ResolvedAddr);
133 })),
134 AliaseeTable(SrcJDLoc) {}
136 StringRef LazyReexportsMaterializationUnit::getName() const {
137 return "<Lazy Reexports>";
140 void LazyReexportsMaterializationUnit::materialize(
141 MaterializationResponsibility R) {
142 auto RequestedSymbols = R.getRequestedSymbols();
144 SymbolAliasMap RequestedAliases;
145 for (auto &RequestedSymbol : RequestedSymbols) {
146 auto I = CallableAliases.find(RequestedSymbol);
147 assert(I != CallableAliases.end() && "Symbol not found in alias map?");
148 RequestedAliases[I->first] = std::move(I->second);
149 CallableAliases.erase(I);
152 if (!CallableAliases.empty())
153 R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
154 std::move(CallableAliases), AliaseeTable));
156 IndirectStubsManager::StubInitsMap StubInits;
157 for (auto &Alias : RequestedAliases) {
159 auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
160 SourceJD, Alias.second.Aliasee, NotifyResolved);
162 if (!CallThroughTrampoline) {
163 SourceJD.getExecutionSession().reportError(
164 CallThroughTrampoline.takeError());
165 R.failMaterialization();
166 return;
169 StubInits[*Alias.first] =
170 std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
173 if (AliaseeTable != nullptr && !RequestedAliases.empty())
174 AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
176 if (auto Err = ISManager.createStubs(StubInits)) {
177 SourceJD.getExecutionSession().reportError(std::move(Err));
178 R.failMaterialization();
179 return;
182 SymbolMap Stubs;
183 for (auto &Alias : RequestedAliases)
184 Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
186 // No registered dependencies, so these calls cannot fail.
187 cantFail(R.notifyResolved(Stubs));
188 cantFail(R.notifyEmitted());
191 void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
192 const SymbolStringPtr &Name) {
193 assert(CallableAliases.count(Name) &&
194 "Symbol not covered by this MaterializationUnit");
195 CallableAliases.erase(Name);
198 SymbolFlagsMap
199 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
200 SymbolFlagsMap SymbolFlags;
201 for (auto &KV : Aliases) {
202 assert(KV.second.AliasFlags.isCallable() &&
203 "Lazy re-exports must be callable symbols");
204 SymbolFlags[KV.first] = KV.second.AliasFlags;
206 return SymbolFlags;
209 } // End namespace orc.
210 } // End namespace llvm.