LLVM 22.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"
25
26namespace llvm {
27
28class Triple;
29
30namespace orc {
31
32/// Manages a set of 'lazy call-through' trampolines. These are compiler
33/// re-entry trampolines that are pre-bound to look up a given symbol in a given
34/// JITDylib, then jump to that address. Since compilation of symbols is
35/// triggered on first lookup, these call-through trampolines can be used to
36/// implement lazy compilation.
37///
38/// The easiest way to construct these call-throughs is using the lazyReexport
39/// function.
41public:
43 unique_function<Error(ExecutorAddr ResolvedAddr)>;
44
46 ExecutorAddr ErrorHandlerAddr,
47 TrampolinePool *TP);
48
49 // Return a free call-through trampoline and bind it to look up and call
50 // through to the given symbol.
53 NotifyResolvedFunction NotifyResolved);
54
56 ExecutorAddr TrampolineAddr,
58
59 virtual ~LazyCallThroughManager() = default;
60
61protected:
64
68 };
69
73 ExecutorAddr ResolvedAddr);
74 void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
75
76private:
77 using ReexportsMap = std::map<ExecutorAddr, ReexportsEntry>;
78
79 using NotifiersMap = std::map<ExecutorAddr, NotifyResolvedFunction>;
80
81 std::mutex LCTMMutex;
83 ExecutorAddr ErrorHandlerAddr;
84 TrampolinePool *TP = nullptr;
85 ReexportsMap Reexports;
86 NotifiersMap Notifiers;
87};
88
89/// A lazy call-through manager that builds trampolines in the current process.
91private:
93
95 ExecutorAddr ErrorHandlerAddr)
96 : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
97
98 template <typename ORCABI> Error init() {
100 [this](ExecutorAddr TrampolineAddr,
102 NotifyLandingResolved) {
103 resolveTrampolineLandingAddress(TrampolineAddr,
104 std::move(NotifyLandingResolved));
105 });
106
107 if (!TP)
108 return TP.takeError();
109
110 this->TP = std::move(*TP);
111 setTrampolinePool(*this->TP);
112 return Error::success();
113 }
114
115 std::unique_ptr<TrampolinePool> TP;
116
117public:
118 /// Create a LocalLazyCallThroughManager using the given ABI. See
119 /// createLocalLazyCallThroughManager.
120 template <typename ORCABI>
122 Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr) {
123 auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
124 new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
125
126 if (auto Err = LLCTM->init<ORCABI>())
127 return std::move(Err);
128
129 return std::move(LLCTM);
130 }
131};
132
133/// Create a LocalLazyCallThroughManager from the given triple and execution
134/// session.
136createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
137 ExecutorAddr ErrorHandlerAddr);
138
139/// A materialization unit that builds lazy re-exports. These are callable
140/// entry points that call through to the given symbols.
141/// Unlike a 'true' re-export, the address of the lazy re-export will not
142/// match the address of the re-exported symbol, but calling it will behave
143/// the same as calling the re-exported symbol.
145public:
147 RedirectableSymbolManager &RSManager,
148 JITDylib &SourceJD,
149 SymbolAliasMap CallableAliases,
150 ImplSymbolMap *SrcJDLoc);
151
152 StringRef getName() const override;
153
154private:
155 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
156 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
158 extractFlags(const SymbolAliasMap &Aliases);
159
160 LazyCallThroughManager &LCTManager;
161 RedirectableSymbolManager &RSManager;
162 JITDylib &SourceJD;
163 SymbolAliasMap CallableAliases;
164 ImplSymbolMap *AliaseeTable;
165};
166
167/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
168/// is a callable symbol that will look up and dispatch to the given aliasee on
169/// first call. All subsequent calls will go directly to the aliasee.
170inline std::unique_ptr<LazyReexportsMaterializationUnit>
172 RedirectableSymbolManager &RSManager, JITDylib &SourceJD,
173 SymbolAliasMap CallableAliases,
174 ImplSymbolMap *SrcJDLoc = nullptr) {
175 return std::make_unique<LazyReexportsMaterializationUnit>(
176 LCTManager, RSManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
177}
178
180
181 friend std::unique_ptr<MaterializationUnit>
183
184public:
189 };
190
192 public:
194
195 virtual ~Listener();
196
197 /// Called under the session lock when new lazy reexports are created.
199 const SymbolAliasMap &Reexports) = 0;
200
201 /// Called under the session lock when lazy reexports have their ownership
202 /// transferred to a new ResourceKey.
204 ResourceKey SrcK) = 0;
205
206 /// Called under the session lock when lazy reexports are removed.
208
209 /// Called outside the session lock when a lazy reexport is called.
210 /// NOTE: Since this is called outside the session lock there is a chance
211 /// that the reexport referred to has already been removed. Listeners
212 /// must be prepared to handle requests for stale reexports.
213 virtual void onLazyReexportCalled(const CallThroughInfo &CTI) = 0;
214 };
215
217 Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
219 unique_function<void(ResourceTrackerSP RT, size_t NumTrampolines,
220 OnTrampolinesReadyFn OnTrampolinesReady)>;
221
222 /// Create a LazyReexportsManager that uses the ORC runtime for reentry.
223 /// This will work both in-process and out-of-process.
225 Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr,
226 JITDylib &PlatformJD, Listener *L = nullptr);
227
230
231 Error handleRemoveResources(JITDylib &JD, ResourceKey K) override;
232 void handleTransferResources(JITDylib &JD, ResourceKey DstK,
233 ResourceKey SrcK) override;
234
235private:
236 class MU;
237 class Plugin;
238
239 using ResolveSendResultFn =
241
243 RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD,
244 Listener *L, Error &Err);
245
246 std::unique_ptr<MaterializationUnit>
247 createLazyReexports(SymbolAliasMap Reexports);
248
249 void emitReentryTrampolines(std::unique_ptr<MaterializationResponsibility> MR,
250 SymbolAliasMap Reexports);
251 void emitRedirectableSymbols(
252 std::unique_ptr<MaterializationResponsibility> MR,
253 SymbolAliasMap Reexports,
254 Expected<std::vector<ExecutorSymbolDef>> ReentryPoints);
255 void resolve(ResolveSendResultFn SendResult, ExecutorAddr ReentryStubAddr);
256
258 EmitTrampolinesFn EmitTrampolines;
260 Listener *L;
261
264};
265
266/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
267/// is a callable symbol that will look up and dispatch to the given aliasee on
268/// first call. All subsequent calls will go directly to the aliasee.
269inline std::unique_ptr<MaterializationUnit>
271 return LRM.createLazyReexports(std::move(Reexports));
272}
273
276public:
278 unique_function<void(const CallThroughInfo &CTI)>;
279
280 static std::shared_ptr<SimpleLazyReexportsSpeculator>
282 class make_shared_helper : public SimpleLazyReexportsSpeculator {
283 public:
284 make_shared_helper(ExecutionSession &ES,
285 RecordExecutionFunction RecordExec)
286 : SimpleLazyReexportsSpeculator(ES, std::move(RecordExec)) {}
287 };
288
289 auto Instance =
290 std::make_shared<make_shared_helper>(ES, std::move(RecordExec));
291 Instance->WeakThis = Instance;
292 return Instance;
293 }
294
299
300 void onLazyReexportsCreated(JITDylib &JD, ResourceKey K,
301 const SymbolAliasMap &Reexports) override;
302
303 void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK,
304 ResourceKey SrcK) override;
305
306 Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) override;
307
308 void onLazyReexportCalled(const CallThroughInfo &CTI) override;
309
310 void addSpeculationSuggestions(
311 std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions);
312
313private:
315 RecordExecutionFunction RecordExec)
316 : ES(ES), RecordExec(std::move(RecordExec)) {}
317
318 bool doNextSpeculativeLookup();
319
320 class SpeculateTask;
321
322 using KeyToFunctionBodiesMap =
324
326 RecordExecutionFunction RecordExec;
327 std::weak_ptr<SimpleLazyReexportsSpeculator> WeakThis;
329 std::deque<std::pair<std::string, SymbolStringPtr>> SpeculateSuggestions;
330 bool SpeculateTaskActive = false;
331};
332
333} // End namespace orc
334} // End namespace llvm
335
336#endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
#define LLVM_ABI
Definition: Compiler.h:213
std::string Name
static StringRef getName(Value *V)
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:159
static ErrorSuccess success()
Create a success value.
Definition: Error.h:336
Tagged union holding either a T or a Error.
Definition: Error.h:485
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:47
An ExecutionSession represents a running JIT program.
Definition: Core.h:1355
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Definition: Core.h:902
Manages a set of 'lazy call-through' trampolines.
Definition: LazyReexports.h:40
LLVM_ABI ExecutorAddr reportCallThroughError(Error Err)
LLVM_ABI Expected< ReexportsEntry > findReexport(ExecutorAddr TrampolineAddr)
LLVM_ABI Error notifyResolved(ExecutorAddr TrampolineAddr, ExecutorAddr ResolvedAddr)
void setTrampolinePool(TrampolinePool &TP)
Definition: LazyReexports.h:74
LLVM_ABI void resolveTrampolineLandingAddress(ExecutorAddr TrampolineAddr, TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved)
virtual ~LazyCallThroughManager()=default
LLVM_ABI 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...
LazyReexportsManager & operator=(LazyReexportsManager &&)=delete
LazyReexportsManager(LazyReexportsManager &&)=delete
A materialization unit that builds lazy re-exports.
A lazy call-through manager that builds trampolines in the current process.
Definition: LazyReexports.h:90
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:126
static std::shared_ptr< SimpleLazyReexportsSpeculator > Create(ExecutionSession &ES, RecordExecutionFunction RecordExec={})
SimpleLazyReexportsSpeculator(SimpleLazyReexportsSpeculator &&)=delete
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.
LLVM_ABI 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:75
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:1886
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:851