LLVM 17.0.0git
LazyReexports.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
10
13
14#define DEBUG_TYPE "orc"
15
16namespace llvm {
17namespace orc {
18
20 ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
21 : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
22
24 JITDylib &SourceJD, SymbolStringPtr SymbolName,
25 NotifyResolvedFunction NotifyResolved) {
26 assert(TP && "TrampolinePool not set");
27
28 std::lock_guard<std::mutex> Lock(LCTMMutex);
29 auto Trampoline = TP->getTrampoline();
30
31 if (!Trampoline)
32 return Trampoline.takeError();
33
34 Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};
35 Notifiers[*Trampoline] = std::move(NotifyResolved);
36 return *Trampoline;
37}
38
40 ES.reportError(std::move(Err));
41 return ErrorHandlerAddr;
42}
43
46 std::lock_guard<std::mutex> Lock(LCTMMutex);
47 auto I = Reexports.find(TrampolineAddr);
48 if (I == Reexports.end())
50 "Missing reexport for trampoline address %p",
51 TrampolineAddr);
52 return I->second;
53}
54
56 JITTargetAddress ResolvedAddr) {
57 NotifyResolvedFunction NotifyResolved;
58 {
59 std::lock_guard<std::mutex> Lock(LCTMMutex);
60 auto I = Notifiers.find(TrampolineAddr);
61 if (I != Notifiers.end()) {
62 NotifyResolved = std::move(I->second);
63 Notifiers.erase(I);
64 }
65 }
66
67 return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();
68}
69
71 JITTargetAddress TrampolineAddr,
72 NotifyLandingResolvedFunction NotifyLandingResolved) {
73
74 auto Entry = findReexport(TrampolineAddr);
75 if (!Entry)
76 return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
77
78 // Declaring SLS and the callback outside of the call to ES.lookup is a
79 // workaround to fix build failures on AIX and on z/OS platforms.
80 SymbolLookupSet SLS({Entry->SymbolName});
81 auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,
82 NotifyLandingResolved = std::move(NotifyLandingResolved)](
84 if (Result) {
85 assert(Result->size() == 1 && "Unexpected result size");
86 assert(Result->count(SymbolName) && "Unexpected result value");
87 JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
88
89 if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
90 NotifyLandingResolved(reportCallThroughError(std::move(Err)));
91 else
92 NotifyLandingResolved(LandingAddr);
93 } else {
94 NotifyLandingResolved(reportCallThroughError(Result.takeError()));
95 }
96 };
97
99 makeJITDylibSearchOrder(Entry->SourceJD,
101 std::move(SLS), SymbolState::Ready, std::move(Callback),
103}
104
107 JITTargetAddress ErrorHandlerAddr) {
108 switch (T.getArch()) {
109 default:
110 return make_error<StringError>(
111 std::string("No callback manager available for ") + T.str(),
113
114 case Triple::aarch64:
116 return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
117 ErrorHandlerAddr);
118
119 case Triple::x86:
120 return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
121
123 return LocalLazyCallThroughManager::Create<OrcLoongArch64>(
124 ES, ErrorHandlerAddr);
125
126 case Triple::mips:
127 return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
128 ErrorHandlerAddr);
129
130 case Triple::mipsel:
131 return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
132 ErrorHandlerAddr);
133
134 case Triple::mips64:
135 case Triple::mips64el:
136 return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
137
138 case Triple::riscv64:
139 return LocalLazyCallThroughManager::Create<OrcRiscv64>(ES,
140 ErrorHandlerAddr);
141
142 case Triple::x86_64:
143 if (T.getOS() == Triple::OSType::Win32)
144 return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
145 ES, ErrorHandlerAddr);
146 else
147 return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
148 ES, ErrorHandlerAddr);
149 }
150}
151
153 LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
154 JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
155 : MaterializationUnit(extractFlags(CallableAliases)),
156 LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
157 CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
158
160 return "<Lazy Reexports>";
161}
162
163void LazyReexportsMaterializationUnit::materialize(
164 std::unique_ptr<MaterializationResponsibility> R) {
165 auto RequestedSymbols = R->getRequestedSymbols();
166
167 SymbolAliasMap RequestedAliases;
168 for (auto &RequestedSymbol : RequestedSymbols) {
169 auto I = CallableAliases.find(RequestedSymbol);
170 assert(I != CallableAliases.end() && "Symbol not found in alias map?");
171 RequestedAliases[I->first] = std::move(I->second);
172 CallableAliases.erase(I);
173 }
174
175 if (!CallableAliases.empty())
176 if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
177 std::move(CallableAliases),
178 AliaseeTable))) {
179 R->getExecutionSession().reportError(std::move(Err));
180 R->failMaterialization();
181 return;
182 }
183
185 for (auto &Alias : RequestedAliases) {
186
187 auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
188 SourceJD, Alias.second.Aliasee,
189 [&ISManager = this->ISManager,
190 StubSym = Alias.first](JITTargetAddress ResolvedAddr) -> Error {
191 return ISManager.updatePointer(*StubSym, ResolvedAddr);
192 });
193
194 if (!CallThroughTrampoline) {
196 CallThroughTrampoline.takeError());
197 R->failMaterialization();
198 return;
199 }
200
201 StubInits[*Alias.first] =
202 std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
203 }
204
205 if (AliaseeTable != nullptr && !RequestedAliases.empty())
206 AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
207
208 if (auto Err = ISManager.createStubs(StubInits)) {
209 SourceJD.getExecutionSession().reportError(std::move(Err));
210 R->failMaterialization();
211 return;
212 }
213
214 SymbolMap Stubs;
215 for (auto &Alias : RequestedAliases)
216 Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
217
218 // No registered dependencies, so these calls cannot fail.
219 cantFail(R->notifyResolved(Stubs));
220 cantFail(R->notifyEmitted());
221}
222
223void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
224 const SymbolStringPtr &Name) {
225 assert(CallableAliases.count(Name) &&
226 "Symbol not covered by this MaterializationUnit");
227 CallableAliases.erase(Name);
228}
229
230MaterializationUnit::Interface
231LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
233 for (auto &KV : Aliases) {
234 assert(KV.second.AliasFlags.isCallable() &&
235 "Lazy re-exports must be callable symbols");
236 SymbolFlags[KV.first] = KV.second.AliasFlags;
237 }
238 return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
239}
240
241} // End namespace orc.
242} // End namespace llvm.
std::string Name
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
bool erase(const KeyT &Val)
Definition: DenseMap.h:315
bool empty() const
Definition: DenseMap.h:98
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:151
iterator end()
Definition: DenseMap.h:84
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
@ loongarch64
Definition: Triple.h:62
@ mips64el
Definition: Triple.h:67
@ aarch64_32
Definition: Triple.h:53
An ExecutionSession represents a running JIT program.
Definition: Core.h:1373
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:1496
void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
Definition: Core.cpp:2077
void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD)
Definition: Speculation.cpp:25
Base class for managing collections of named indirect stubs.
virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly)=0
Find the stub with the given name.
virtual Error createStubs(const StubInitsMap &StubInits)=0
Create StubInits.size() stubs with the given names, target addresses, and flags.
StringMap< std::pair< JITTargetAddress, JITSymbolFlags > > StubInitsMap
Map type for initializing the manager. See init.
Represents a JIT'd dynamic library.
Definition: Core.h:962
ExecutionSession & getExecutionSession() const
Get a reference to the ExecutionSession for this JITDylib.
Definition: Core.h:981
Manages a set of 'lazy call-through' trampolines.
Definition: LazyReexports.h:38
void resolveTrampolineLandingAddress(JITTargetAddress TrampolineAddr, TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved)
JITTargetAddress reportCallThroughError(Error Err)
Expected< JITTargetAddress > getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName, NotifyResolvedFunction NotifyResolved)
Error notifyResolved(JITTargetAddress TrampolineAddr, JITTargetAddress ResolvedAddr)
LazyCallThroughManager(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
Expected< ReexportsEntry > findReexport(JITTargetAddress TrampolineAddr)
StringRef getName() const override
Return the name of this materialization unit.
LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:673
SymbolFlagsMap SymbolFlags
Definition: Core.h:729
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:180
Pointer to a pooled string representing a symbol name.
Base class for pools of compiler re-entry trampolines.
Expected< JITTargetAddress > getTrampoline()
Get an available trampoline address.
unique_function is a type-erasing functor similar to std::function.
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
Definition: Core.h:163
DenseMap< SymbolStringPtr, JITEvaluatedSymbol > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
Definition: Core.h:118
DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap
A map of Symbols to (Symbol, Flags) pairs.
Definition: Core.h:393
DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
Definition: Core.h:121
std::unique_ptr< LazyReexportsMaterializationUnit > lazyReexports(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc=nullptr)
Define lazy-reexports based on the given SymbolAliasMap.
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition: Core.cpp:35
Expected< std::unique_ptr< LazyCallThroughManager > > createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr)
Create a LocalLazyCallThroughManager from the given triple and execution session.
@ Ready
Emitted to memory, but waiting on transitive dependencies.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:42
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:745
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1909
Definition: BitVector.h:851