File indexing completed on 2026-05-10 08:43:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
0017 #define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
0018
0019 #include "llvm/ADT/STLExtras.h"
0020 #include "llvm/ExecutionEngine/Orc/Core.h"
0021 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
0022 #include "llvm/ExecutionEngine/Orc/RedirectionManager.h"
0023 #include "llvm/ExecutionEngine/Orc/Speculation.h"
0024
0025 namespace llvm {
0026
0027 class Triple;
0028
0029 namespace orc {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 class LazyCallThroughManager {
0040 public:
0041 using NotifyResolvedFunction =
0042 unique_function<Error(ExecutorAddr ResolvedAddr)>;
0043
0044 LazyCallThroughManager(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr,
0045 TrampolinePool *TP);
0046
0047
0048
0049 Expected<ExecutorAddr>
0050 getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName,
0051 NotifyResolvedFunction NotifyResolved);
0052
0053 void resolveTrampolineLandingAddress(
0054 ExecutorAddr TrampolineAddr,
0055 TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved);
0056
0057 virtual ~LazyCallThroughManager() = default;
0058
0059 protected:
0060 using NotifyLandingResolvedFunction =
0061 TrampolinePool::NotifyLandingResolvedFunction;
0062
0063 struct ReexportsEntry {
0064 JITDylib *SourceJD;
0065 SymbolStringPtr SymbolName;
0066 };
0067
0068 ExecutorAddr reportCallThroughError(Error Err);
0069 Expected<ReexportsEntry> findReexport(ExecutorAddr TrampolineAddr);
0070 Error notifyResolved(ExecutorAddr TrampolineAddr, ExecutorAddr ResolvedAddr);
0071 void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
0072
0073 private:
0074 using ReexportsMap = std::map<ExecutorAddr, ReexportsEntry>;
0075
0076 using NotifiersMap = std::map<ExecutorAddr, NotifyResolvedFunction>;
0077
0078 std::mutex LCTMMutex;
0079 ExecutionSession &ES;
0080 ExecutorAddr ErrorHandlerAddr;
0081 TrampolinePool *TP = nullptr;
0082 ReexportsMap Reexports;
0083 NotifiersMap Notifiers;
0084 };
0085
0086
0087 class LocalLazyCallThroughManager : public LazyCallThroughManager {
0088 private:
0089 using NotifyTargetResolved = unique_function<void(ExecutorAddr)>;
0090
0091 LocalLazyCallThroughManager(ExecutionSession &ES,
0092 ExecutorAddr ErrorHandlerAddr)
0093 : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
0094
0095 template <typename ORCABI> Error init() {
0096 auto TP = LocalTrampolinePool<ORCABI>::Create(
0097 [this](ExecutorAddr TrampolineAddr,
0098 TrampolinePool::NotifyLandingResolvedFunction
0099 NotifyLandingResolved) {
0100 resolveTrampolineLandingAddress(TrampolineAddr,
0101 std::move(NotifyLandingResolved));
0102 });
0103
0104 if (!TP)
0105 return TP.takeError();
0106
0107 this->TP = std::move(*TP);
0108 setTrampolinePool(*this->TP);
0109 return Error::success();
0110 }
0111
0112 std::unique_ptr<TrampolinePool> TP;
0113
0114 public:
0115
0116
0117 template <typename ORCABI>
0118 static Expected<std::unique_ptr<LocalLazyCallThroughManager>>
0119 Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr) {
0120 auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
0121 new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
0122
0123 if (auto Err = LLCTM->init<ORCABI>())
0124 return std::move(Err);
0125
0126 return std::move(LLCTM);
0127 }
0128 };
0129
0130
0131
0132 Expected<std::unique_ptr<LazyCallThroughManager>>
0133 createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
0134 ExecutorAddr ErrorHandlerAddr);
0135
0136
0137
0138
0139
0140
0141 class LazyReexportsMaterializationUnit : public MaterializationUnit {
0142 public:
0143 LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager,
0144 RedirectableSymbolManager &RSManager,
0145 JITDylib &SourceJD,
0146 SymbolAliasMap CallableAliases,
0147 ImplSymbolMap *SrcJDLoc);
0148
0149 StringRef getName() const override;
0150
0151 private:
0152 void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
0153 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
0154 static MaterializationUnit::Interface
0155 extractFlags(const SymbolAliasMap &Aliases);
0156
0157 LazyCallThroughManager &LCTManager;
0158 RedirectableSymbolManager &RSManager;
0159 JITDylib &SourceJD;
0160 SymbolAliasMap CallableAliases;
0161 ImplSymbolMap *AliaseeTable;
0162 };
0163
0164
0165
0166
0167 inline std::unique_ptr<LazyReexportsMaterializationUnit>
0168 lazyReexports(LazyCallThroughManager &LCTManager,
0169 RedirectableSymbolManager &RSManager, JITDylib &SourceJD,
0170 SymbolAliasMap CallableAliases,
0171 ImplSymbolMap *SrcJDLoc = nullptr) {
0172 return std::make_unique<LazyReexportsMaterializationUnit>(
0173 LCTManager, RSManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
0174 }
0175
0176 class LazyReexportsManager : public ResourceManager {
0177
0178 friend std::unique_ptr<MaterializationUnit>
0179 lazyReexports(LazyReexportsManager &, SymbolAliasMap);
0180
0181 public:
0182 struct CallThroughInfo {
0183 JITDylibSP JD;
0184 SymbolStringPtr Name;
0185 SymbolStringPtr BodyName;
0186 };
0187
0188 class Listener {
0189 public:
0190 using CallThroughInfo = LazyReexportsManager::CallThroughInfo;
0191
0192 virtual ~Listener();
0193
0194
0195 virtual void onLazyReexportsCreated(JITDylib &JD, ResourceKey K,
0196 const SymbolAliasMap &Reexports) = 0;
0197
0198
0199
0200 virtual void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK,
0201 ResourceKey SrcK) = 0;
0202
0203
0204 virtual Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) = 0;
0205
0206
0207
0208
0209
0210 virtual void onLazyReexportCalled(const CallThroughInfo &CTI) = 0;
0211 };
0212
0213 using OnTrampolinesReadyFn = unique_function<void(
0214 Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
0215 using EmitTrampolinesFn =
0216 unique_function<void(ResourceTrackerSP RT, size_t NumTrampolines,
0217 OnTrampolinesReadyFn OnTrampolinesReady)>;
0218
0219
0220
0221 static Expected<std::unique_ptr<LazyReexportsManager>>
0222 Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr,
0223 JITDylib &PlatformJD, Listener *L = nullptr);
0224
0225 LazyReexportsManager(LazyReexportsManager &&) = delete;
0226 LazyReexportsManager &operator=(LazyReexportsManager &&) = delete;
0227
0228 Error handleRemoveResources(JITDylib &JD, ResourceKey K) override;
0229 void handleTransferResources(JITDylib &JD, ResourceKey DstK,
0230 ResourceKey SrcK) override;
0231
0232 private:
0233 class MU;
0234 class Plugin;
0235
0236 using ResolveSendResultFn =
0237 unique_function<void(Expected<ExecutorSymbolDef>)>;
0238
0239 LazyReexportsManager(EmitTrampolinesFn EmitTrampolines,
0240 RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD,
0241 Listener *L, Error &Err);
0242
0243 std::unique_ptr<MaterializationUnit>
0244 createLazyReexports(SymbolAliasMap Reexports);
0245
0246 void emitReentryTrampolines(std::unique_ptr<MaterializationResponsibility> MR,
0247 SymbolAliasMap Reexports);
0248 void emitRedirectableSymbols(
0249 std::unique_ptr<MaterializationResponsibility> MR,
0250 SymbolAliasMap Reexports,
0251 Expected<std::vector<ExecutorSymbolDef>> ReentryPoints);
0252 void resolve(ResolveSendResultFn SendResult, ExecutorAddr ReentryStubAddr);
0253
0254 ExecutionSession &ES;
0255 EmitTrampolinesFn EmitTrampolines;
0256 RedirectableSymbolManager &RSMgr;
0257 Listener *L;
0258
0259 DenseMap<ResourceKey, std::vector<ExecutorAddr>> KeyToReentryAddrs;
0260 DenseMap<ExecutorAddr, CallThroughInfo> CallThroughs;
0261 };
0262
0263
0264
0265
0266 inline std::unique_ptr<MaterializationUnit>
0267 lazyReexports(LazyReexportsManager &LRM, SymbolAliasMap Reexports) {
0268 return LRM.createLazyReexports(std::move(Reexports));
0269 }
0270
0271 class SimpleLazyReexportsSpeculator : public LazyReexportsManager::Listener {
0272 public:
0273 using RecordExecutionFunction =
0274 unique_function<void(const CallThroughInfo &CTI)>;
0275
0276 static std::shared_ptr<SimpleLazyReexportsSpeculator>
0277 Create(ExecutionSession &ES, RecordExecutionFunction RecordExec = {}) {
0278 class make_shared_helper : public SimpleLazyReexportsSpeculator {
0279 public:
0280 make_shared_helper(ExecutionSession &ES,
0281 RecordExecutionFunction RecordExec)
0282 : SimpleLazyReexportsSpeculator(ES, std::move(RecordExec)) {}
0283 };
0284
0285 auto Instance =
0286 std::make_shared<make_shared_helper>(ES, std::move(RecordExec));
0287 Instance->WeakThis = Instance;
0288 return Instance;
0289 }
0290
0291 SimpleLazyReexportsSpeculator(SimpleLazyReexportsSpeculator &&) = delete;
0292 SimpleLazyReexportsSpeculator &
0293 operator=(SimpleLazyReexportsSpeculator &&) = delete;
0294 ~SimpleLazyReexportsSpeculator() override;
0295
0296 void onLazyReexportsCreated(JITDylib &JD, ResourceKey K,
0297 const SymbolAliasMap &Reexports) override;
0298
0299 void onLazyReexportsTransfered(JITDylib &JD, ResourceKey DstK,
0300 ResourceKey SrcK) override;
0301
0302 Error onLazyReexportsRemoved(JITDylib &JD, ResourceKey K) override;
0303
0304 void onLazyReexportCalled(const CallThroughInfo &CTI) override;
0305
0306 void addSpeculationSuggestions(
0307 std::vector<std::pair<std::string, SymbolStringPtr>> NewSuggestions);
0308
0309 private:
0310 SimpleLazyReexportsSpeculator(ExecutionSession &ES,
0311 RecordExecutionFunction RecordExec)
0312 : ES(ES), RecordExec(std::move(RecordExec)) {}
0313
0314 bool doNextSpeculativeLookup();
0315
0316 class SpeculateTask;
0317
0318 using KeyToFunctionBodiesMap =
0319 DenseMap<ResourceKey, std::vector<SymbolStringPtr>>;
0320
0321 ExecutionSession &ES;
0322 RecordExecutionFunction RecordExec;
0323 std::weak_ptr<SimpleLazyReexportsSpeculator> WeakThis;
0324 DenseMap<JITDylib *, KeyToFunctionBodiesMap> LazyReexports;
0325 std::deque<std::pair<std::string, SymbolStringPtr>> SpeculateSuggestions;
0326 bool SpeculateTaskActive = false;
0327 };
0328
0329 }
0330 }
0331
0332 #endif