LLVM 20.0.0git
LazyReexports.h
Go to the documentation of this file.
1//===------ LazyReexports.h -- Utilities for lazy reexports -----*- C++ -*-===//
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//
9// Lazy re-exports are similar to normal re-exports, except that for callable
10// symbols the definitions are replaced with trampolines that will look up and
11// call through to the re-exported symbol at runtime. This can be used to
12// enable lazy compilation.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
17#define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
18
19#include "llvm/ADT/STLExtras.h"
24
25namespace llvm {
26
27class Triple;
28
29namespace orc {
30
31/// Manages a set of 'lazy call-through' trampolines. These are compiler
32/// re-entry trampolines that are pre-bound to look up a given symbol in a given
33/// JITDylib, then jump to that address. Since compilation of symbols is
34/// triggered on first lookup, these call-through trampolines can be used to
35/// implement lazy compilation.
36///
37/// The easiest way to construct these call-throughs is using the lazyReexport
38/// function.
40public:
42 unique_function<Error(ExecutorAddr ResolvedAddr)>;
43
45 TrampolinePool *TP);
46
47 // Return a free call-through trampoline and bind it to look up and call
48 // through to the given symbol.
51 NotifyResolvedFunction NotifyResolved);
52
54 ExecutorAddr TrampolineAddr,
56
57 virtual ~LazyCallThroughManager() = default;
58
59protected:
62
66 };
67
70 Error notifyResolved(ExecutorAddr TrampolineAddr, ExecutorAddr ResolvedAddr);
71 void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
72
73private:
74 using ReexportsMap = std::map<ExecutorAddr, ReexportsEntry>;
75
76 using NotifiersMap = std::map<ExecutorAddr, NotifyResolvedFunction>;
77
78 std::mutex LCTMMutex;
80 ExecutorAddr ErrorHandlerAddr;
81 TrampolinePool *TP = nullptr;
82 ReexportsMap Reexports;
83 NotifiersMap Notifiers;
84};
85
86/// A lazy call-through manager that builds trampolines in the current process.
88private:
90
92 ExecutorAddr ErrorHandlerAddr)
93 : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
94
95 template <typename ORCABI> Error init() {
97 [this](ExecutorAddr TrampolineAddr,
99 NotifyLandingResolved) {
100 resolveTrampolineLandingAddress(TrampolineAddr,
101 std::move(NotifyLandingResolved));
102 });
103
104 if (!TP)
105 return TP.takeError();
106
107 this->TP = std::move(*TP);
108 setTrampolinePool(*this->TP);
109 return Error::success();
110 }
111
112 std::unique_ptr<TrampolinePool> TP;
113
114public:
115 /// Create a LocalLazyCallThroughManager using the given ABI. See
116 /// createLocalLazyCallThroughManager.
117 template <typename ORCABI>
119 Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr) {
120 auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
121 new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
122
123 if (auto Err = LLCTM->init<ORCABI>())
124 return std::move(Err);
125
126 return std::move(LLCTM);
127 }
128};
129
130/// Create a LocalLazyCallThroughManager from the given triple and execution
131/// session.
133createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
134 ExecutorAddr ErrorHandlerAddr);
135
136/// A materialization unit that builds lazy re-exports. These are callable
137/// entry points that call through to the given symbols.
138/// Unlike a 'true' re-export, the address of the lazy re-export will not
139/// match the address of the re-exported symbol, but calling it will behave
140/// the same as calling the re-exported symbol.
142public:
144 RedirectableSymbolManager &RSManager,
145 JITDylib &SourceJD,
146 SymbolAliasMap CallableAliases,
147 ImplSymbolMap *SrcJDLoc);
148
149 StringRef getName() const override;
150
151private:
152 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
153 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
155 extractFlags(const SymbolAliasMap &Aliases);
156
157 LazyCallThroughManager &LCTManager;
158 RedirectableSymbolManager &RSManager;
159 JITDylib &SourceJD;
160 SymbolAliasMap CallableAliases;
161 ImplSymbolMap *AliaseeTable;
162};
163
164/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
165/// is a callable symbol that will look up and dispatch to the given aliasee on
166/// first call. All subsequent calls will go directly to the aliasee.
167inline std::unique_ptr<LazyReexportsMaterializationUnit>
169 RedirectableSymbolManager &RSManager, JITDylib &SourceJD,
170 SymbolAliasMap CallableAliases,
171 ImplSymbolMap *SrcJDLoc = nullptr) {
172 return std::make_unique<LazyReexportsMaterializationUnit>(
173 LCTManager, RSManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
174}
175
177
178 friend std::unique_ptr<MaterializationUnit>
180
181public:
186 };
187
188 class Listener {
189 public:
191
192 virtual ~Listener();
193
194 /// Called under the session lock when new lazy reexports are created.
196 const SymbolAliasMap &Reexports) = 0;
197
198 /// Called under the session lock when lazy reexports have their ownership
199 /// transferred to a new ResourceKey.
201 ResourceKey SrcK) = 0;
202
203 /// Called under the session lock when lazy reexports are removed.
205
206 /// Called outside the session lock when a lazy reexport is called.
207 /// NOTE: Since this is called outside the session lock there is a chance
208 /// that the reexport referred to has already been removed. Listeners
209 /// must be prepared to handle requests for stale reexports.
210 virtual void onLazyReexportCalled(const CallThroughInfo &CTI) = 0;
211 };
212
214 Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
216 unique_function<void(ResourceTrackerSP RT, size_t NumTrampolines,
217 OnTrampolinesReadyFn OnTrampolinesReady)>;
218
219 /// Create a LazyReexportsManager that uses the ORC runtime for reentry.
220 /// This will work both in-process and out-of-process.
222 Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr,
223 JITDylib &PlatformJD, Listener *L = nullptr);
224
227
230 ResourceKey SrcK) override;
231
232private:
233 class MU;
234 class Plugin;
235
236 using ResolveSendResultFn =
238
240 RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD,
241 Listener *L, Error &Err);
242
243 std::unique_ptr<MaterializationUnit>
244 createLazyReexports(SymbolAliasMap Reexports);
245
246 void emitReentryTrampolines(std::unique_ptr<MaterializationResponsibility> MR,
247 SymbolAliasMap Reexports);
248 void emitRedirectableSymbols(
249 std::unique_ptr<MaterializationResponsibility> MR,
250 SymbolAliasMap Reexports,
251 Expected<std::vector<ExecutorSymbolDef>> ReentryPoints);
252 void resolve(ResolveSendResultFn SendResult, ExecutorAddr ReentryStubAddr);
253
255 EmitTrampolinesFn EmitTrampolines;
257 Listener *L;
258
261};
262
263/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
264/// is a callable symbol that will look up and dispatch to the given aliasee on
265/// first call. All subsequent calls will go directly to the aliasee.
266inline std::unique_ptr<MaterializationUnit>
268 return LRM.createLazyReexports(std::move(Reexports));
269}
270
272public:
274 unique_function<void(const CallThroughInfo &CTI)>;
275
276 static std::shared_ptr<SimpleLazyReexportsSpeculator>
278 class make_shared_helper : public SimpleLazyReexportsSpeculator {
279 public:
280 make_shared_helper(ExecutionSession &ES,
281 RecordExecutionFunction RecordExec)
282 : SimpleLazyReexportsSpeculator(ES, std::move(RecordExec)) {}
283 };
284
285 auto Instance =
286 std::make_shared<make_shared_helper>(ES, std::move(RecordExec));
287 Instance->WeakThis = Instance;
288 return Instance;
289 }
290
295
297 const SymbolAliasMap &Reexports) override;
298
300 ResourceKey SrcK) override;
301
303
304 void onLazyReexportCalled(const CallThroughInfo &CTI) override;
305
307 std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions);
308
309private:
311 RecordExecutionFunction RecordExec)
312 : ES(ES), RecordExec(std::move(RecordExec)) {}
313
314 bool doNextSpeculativeLookup();
315
316 class SpeculateTask;
317
318 using KeyToFunctionBodiesMap =
320
322 RecordExecutionFunction RecordExec;
323 std::weak_ptr<SimpleLazyReexportsSpeculator> WeakThis;
325 std::deque<std::pair<std::string, SymbolStringPtr>> SpeculateSuggestions;
326 bool SpeculateTaskActive = false;
327};
328
329} // End namespace orc
330} // End namespace llvm
331
332#endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
std::string Name
This file contains some templates that are useful if you are working with the STL at all.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
An ExecutionSession represents a running JIT program.
Definition: Core.h:1340
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Definition: Core.h:897
Manages a set of 'lazy call-through' trampolines.
Definition: LazyReexports.h:39
ExecutorAddr reportCallThroughError(Error Err)
Expected< ReexportsEntry > findReexport(ExecutorAddr TrampolineAddr)
Error notifyResolved(ExecutorAddr TrampolineAddr, ExecutorAddr ResolvedAddr)
void setTrampolinePool(TrampolinePool &TP)
Definition: LazyReexports.h:71
void resolveTrampolineLandingAddress(ExecutorAddr TrampolineAddr, TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved)
virtual ~LazyCallThroughManager()=default
Expected< ExecutorAddr > getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName, NotifyResolvedFunction NotifyResolved)
virtual void onLazyReexportCalled(const CallThroughInfo &CTI)=0
Called outside the session lock when a lazy reexport is called.
virtual void onLazyReexportsCreated(JITDylib &JD, ResourceKey K, const SymbolAliasMap &Reexports)=0
Called under the session lock when new lazy reexports are created.
virtual Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K)=0
Called under the session lock when lazy reexports are removed.
virtual void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK, ResourceKey SrcK)=0
Called under the session lock when lazy reexports have their ownership transferred to a new ResourceK...
void handleTransferResources(JITDylib &JD, ResourceKey DstK, ResourceKey SrcK) override
This function will be called inside the session lock.
friend std::unique_ptr< MaterializationUnit > lazyReexports(LazyReexportsManager &, SymbolAliasMap)
Define lazy-reexports based on the given SymbolAliasMap.
Error handleRemoveResources(JITDylib &JD, ResourceKey K) override
This function will be called outside the session lock.
LazyReexportsManager & operator=(LazyReexportsManager &&)=delete
LazyReexportsManager(LazyReexportsManager &&)=delete
static Expected< std::unique_ptr< LazyReexportsManager > > Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD, Listener *L=nullptr)
Create a LazyReexportsManager that uses the ORC runtime for reentry.
A materialization unit that builds lazy re-exports.
StringRef getName() const override
Return the name of this materialization unit.
A lazy call-through manager that builds trampolines in the current process.
Definition: LazyReexports.h:87
static Expected< std::unique_ptr< LocalLazyCallThroughManager > > Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr)
Create a LocalLazyCallThroughManager using the given ABI.
static Expected< std::unique_ptr< LocalTrampolinePool > > Create(ResolveLandingFunction ResolveLanding)
Creates a LocalTrampolinePool with the given RunCallback function.
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Base class for managing redirectable symbols in which a call gets redirected to another symbol in run...
Listens for ResourceTracker operations.
Definition: Core.h:125
Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) override
Called under the session lock when lazy reexports are removed.
void onLazyReexportsCreated(JITDylib &JD, ResourceKey K, const SymbolAliasMap &Reexports) override
Called under the session lock when new lazy reexports are created.
void onLazyReexportCalled(const CallThroughInfo &CTI) override
Called outside the session lock when a lazy reexport is called.
void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK, ResourceKey SrcK) override
Called under the session lock when lazy reexports have their ownership transferred to a new ResourceK...
static std::shared_ptr< SimpleLazyReexportsSpeculator > Create(ExecutionSession &ES, RecordExecutionFunction RecordExec={})
SimpleLazyReexportsSpeculator(SimpleLazyReexportsSpeculator &&)=delete
unique_function< void(const CallThroughInfo &CTI)> RecordExecutionFunction
void addSpeculationSuggestions(std::vector< std::pair< std::string, SymbolStringPtr > > NewSuggestions)
SimpleLazyReexportsSpeculator & operator=(SimpleLazyReexportsSpeculator &&)=delete
Pointer to a pooled string representing a symbol name.
Base class for pools of compiler re-entry trampolines.
unique_function< void(ExecutorAddr) const > NotifyLandingResolvedFunction
unique_function is a type-erasing functor similar to std::function.
Expected< std::unique_ptr< LazyCallThroughManager > > createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr)
Create a LocalLazyCallThroughManager from the given triple and execution session.
std::unique_ptr< LazyReexportsMaterializationUnit > lazyReexports(LazyCallThroughManager &LCTManager, RedirectableSymbolManager &RSManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc=nullptr)
Define lazy-reexports based on the given SymbolAliasMap.
uintptr_t ResourceKey
Definition: Core.h:74
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1873
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858