![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /usr/include/llvm-10/llvm/ExecutionEngine/Orc/ |
Upload File : |
//===------ LazyReexports.h -- Utilities for lazy reexports -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Lazy re-exports are similar to normal re-exports, except that for callable // symbols the definitions are replaced with trampolines that will look up and // call through to the re-exported symbol at runtime. This can be used to // enable lazy compilation. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H #define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/Speculation.h" namespace llvm { class Triple; namespace orc { /// Manages a set of 'lazy call-through' trampolines. These are compiler /// re-entry trampolines that are pre-bound to look up a given symbol in a given /// JITDylib, then jump to that address. Since compilation of symbols is /// triggered on first lookup, these call-through trampolines can be used to /// implement lazy compilation. /// /// The easiest way to construct these call-throughs is using the lazyReexport /// function. class LazyCallThroughManager { public: /// Clients will want to take some action on first resolution, e.g. updating /// a stub pointer. Instances of this class can be used to implement this. class NotifyResolvedFunction { public: virtual ~NotifyResolvedFunction() {} /// Called the first time a lazy call through is executed and the target /// symbol resolved. virtual Error operator()(JITDylib &SourceJD, const SymbolStringPtr &SymbolName, JITTargetAddress ResolvedAddr) = 0; private: virtual void anchor(); }; template <typename NotifyResolvedImpl> class NotifyResolvedFunctionImpl : public NotifyResolvedFunction { public: NotifyResolvedFunctionImpl(NotifyResolvedImpl NotifyResolved) : NotifyResolved(std::move(NotifyResolved)) {} Error operator()(JITDylib &SourceJD, const SymbolStringPtr &SymbolName, JITTargetAddress ResolvedAddr) { return NotifyResolved(SourceJD, SymbolName, ResolvedAddr); } private: NotifyResolvedImpl NotifyResolved; }; /// Create a shared NotifyResolvedFunction from a given type that is /// callable with the correct signature. template <typename NotifyResolvedImpl> static std::unique_ptr<NotifyResolvedFunction> createNotifyResolvedFunction(NotifyResolvedImpl NotifyResolved) { return std::make_unique<NotifyResolvedFunctionImpl<NotifyResolvedImpl>>( std::move(NotifyResolved)); } // Return a free call-through trampoline and bind it to look up and call // through to the given symbol. Expected<JITTargetAddress> getCallThroughTrampoline( JITDylib &SourceJD, SymbolStringPtr SymbolName, std::shared_ptr<NotifyResolvedFunction> NotifyResolved); protected: LazyCallThroughManager(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, std::unique_ptr<TrampolinePool> TP); JITTargetAddress callThroughToSymbol(JITTargetAddress TrampolineAddr); void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) { this->TP = std::move(TP); } private: using ReexportsMap = std::map<JITTargetAddress, std::pair<JITDylib *, SymbolStringPtr>>; using NotifiersMap = std::map<JITTargetAddress, std::shared_ptr<NotifyResolvedFunction>>; std::mutex LCTMMutex; ExecutionSession &ES; JITTargetAddress ErrorHandlerAddr; std::unique_ptr<TrampolinePool> TP; ReexportsMap Reexports; NotifiersMap Notifiers; }; /// A lazy call-through manager that builds trampolines in the current process. class LocalLazyCallThroughManager : public LazyCallThroughManager { private: LocalLazyCallThroughManager(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {} template <typename ORCABI> Error init() { auto TP = LocalTrampolinePool<ORCABI>::Create( [this](JITTargetAddress TrampolineAddr) { return callThroughToSymbol(TrampolineAddr); }); if (!TP) return TP.takeError(); setTrampolinePool(std::move(*TP)); return Error::success(); } public: /// Create a LocalLazyCallThroughManager using the given ABI. See /// createLocalLazyCallThroughManager. template <typename ORCABI> static Expected<std::unique_ptr<LocalLazyCallThroughManager>> Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) { auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>( new LocalLazyCallThroughManager(ES, ErrorHandlerAddr)); if (auto Err = LLCTM->init<ORCABI>()) return std::move(Err); return std::move(LLCTM); } }; /// Create a LocalLazyCallThroughManager from the given triple and execution /// session. Expected<std::unique_ptr<LazyCallThroughManager>> createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr); /// A materialization unit that builds lazy re-exports. These are callable /// entry points that call through to the given symbols. /// Unlike a 'true' re-export, the address of the lazy re-export will not /// match the address of the re-exported symbol, but calling it will behave /// the same as calling the re-exported symbol. class LazyReexportsMaterializationUnit : public MaterializationUnit { public: LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc, VModuleKey K); StringRef getName() const override; private: void materialize(MaterializationResponsibility R) override; void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); LazyCallThroughManager &LCTManager; IndirectStubsManager &ISManager; JITDylib &SourceJD; SymbolAliasMap CallableAliases; std::shared_ptr<LazyCallThroughManager::NotifyResolvedFunction> NotifyResolved; ImplSymbolMap *AliaseeTable; }; /// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export /// is a callable symbol that will look up and dispatch to the given aliasee on /// first call. All subsequent calls will go directly to the aliasee. inline std::unique_ptr<LazyReexportsMaterializationUnit> lazyReexports(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc = nullptr, VModuleKey K = VModuleKey()) { return std::make_unique<LazyReexportsMaterializationUnit>( LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc, std::move(K)); } } // End namespace orc } // End namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H