- //===--- EPCIndirectionUtils.h - EPC based indirection utils ----*- 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 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Indirection utilities (stubs, trampolines, lazy call-throughs) that use the 
- // ExecutorProcessControl API to interact with the executor process. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H 
- #define LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H 
-   
- #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" 
- #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" 
- #include "llvm/ExecutionEngine/Orc/LazyReexports.h" 
-   
- #include <mutex> 
-   
- namespace llvm { 
- namespace orc { 
-   
- class ExecutorProcessControl; 
-   
- /// Provides ExecutorProcessControl based indirect stubs, trampoline pool and 
- /// lazy call through manager. 
- class EPCIndirectionUtils { 
-   friend class EPCIndirectionUtilsAccess; 
-   
- public: 
-   /// ABI support base class. Used to write resolver, stub, and trampoline 
-   /// blocks. 
-   class ABISupport { 
-   protected: 
-     ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize, 
-                unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize) 
-         : PointerSize(PointerSize), TrampolineSize(TrampolineSize), 
-           StubSize(StubSize), 
-           StubToPointerMaxDisplacement(StubToPointerMaxDisplacement), 
-           ResolverCodeSize(ResolverCodeSize) {} 
-   
-   public: 
-     virtual ~ABISupport(); 
-   
-     unsigned getPointerSize() const { return PointerSize; } 
-     unsigned getTrampolineSize() const { return TrampolineSize; } 
-     unsigned getStubSize() const { return StubSize; } 
-     unsigned getStubToPointerMaxDisplacement() const { 
-       return StubToPointerMaxDisplacement; 
-     } 
-     unsigned getResolverCodeSize() const { return ResolverCodeSize; } 
-   
-     virtual void writeResolverCode(char *ResolverWorkingMem, 
-                                    JITTargetAddress ResolverTargetAddr, 
-                                    JITTargetAddress ReentryFnAddr, 
-                                    JITTargetAddress ReentryCtxAddr) const = 0; 
-   
-     virtual void writeTrampolines(char *TrampolineBlockWorkingMem, 
-                                   JITTargetAddress TrampolineBlockTragetAddr, 
-                                   JITTargetAddress ResolverAddr, 
-                                   unsigned NumTrampolines) const = 0; 
-   
-     virtual void 
-     writeIndirectStubsBlock(char *StubsBlockWorkingMem, 
-                             JITTargetAddress StubsBlockTargetAddress, 
-                             JITTargetAddress PointersBlockTargetAddress, 
-                             unsigned NumStubs) const = 0; 
-   
-   private: 
-     unsigned PointerSize = 0; 
-     unsigned TrampolineSize = 0; 
-     unsigned StubSize = 0; 
-     unsigned StubToPointerMaxDisplacement = 0; 
-     unsigned ResolverCodeSize = 0; 
-   }; 
-   
-   /// Create using the given ABI class. 
-   template <typename ORCABI> 
-   static std::unique_ptr<EPCIndirectionUtils> 
-   CreateWithABI(ExecutorProcessControl &EPC); 
-   
-   /// Create based on the ExecutorProcessControl triple. 
-   static Expected<std::unique_ptr<EPCIndirectionUtils>> 
-   Create(ExecutorProcessControl &EPC); 
-   
-   /// Return a reference to the ExecutorProcessControl object. 
-   ExecutorProcessControl &getExecutorProcessControl() const { return EPC; } 
-   
-   /// Return a reference to the ABISupport object for this instance. 
-   ABISupport &getABISupport() const { return *ABI; } 
-   
-   /// Release memory for resources held by this instance. This *must* be called 
-   /// prior to destruction of the class. 
-   Error cleanup(); 
-   
-   /// Write resolver code to the executor process and return its address. 
-   /// This must be called before any call to createTrampolinePool or 
-   /// createLazyCallThroughManager. 
-   Expected<JITTargetAddress> 
-   writeResolverBlock(JITTargetAddress ReentryFnAddr, 
-                      JITTargetAddress ReentryCtxAddr); 
-   
-   /// Returns the address of the Resolver block. Returns zero if the 
-   /// writeResolverBlock method has not previously been called. 
-   JITTargetAddress getResolverBlockAddress() const { return ResolverBlockAddr; } 
-   
-   /// Create an IndirectStubsManager for the executor process. 
-   std::unique_ptr<IndirectStubsManager> createIndirectStubsManager(); 
-   
-   /// Create a TrampolinePool for the executor process. 
-   TrampolinePool &getTrampolinePool(); 
-   
-   /// Create a LazyCallThroughManager. 
-   /// This function should only be called once. 
-   LazyCallThroughManager & 
-   createLazyCallThroughManager(ExecutionSession &ES, 
-                                JITTargetAddress ErrorHandlerAddr); 
-   
-   /// Create a LazyCallThroughManager for the executor process. 
-   LazyCallThroughManager &getLazyCallThroughManager() { 
-     assert(LCTM && "createLazyCallThroughManager must be called first"); 
-     return *LCTM; 
-   } 
-   
- private: 
-   using FinalizedAlloc = jitlink::JITLinkMemoryManager::FinalizedAlloc; 
-   
-   struct IndirectStubInfo { 
-     IndirectStubInfo() = default; 
-     IndirectStubInfo(JITTargetAddress StubAddress, 
-                      JITTargetAddress PointerAddress) 
-         : StubAddress(StubAddress), PointerAddress(PointerAddress) {} 
-     JITTargetAddress StubAddress = 0; 
-     JITTargetAddress PointerAddress = 0; 
-   }; 
-   
-   using IndirectStubInfoVector = std::vector<IndirectStubInfo>; 
-   
-   /// Create an EPCIndirectionUtils instance. 
-   EPCIndirectionUtils(ExecutorProcessControl &EPC, 
-                       std::unique_ptr<ABISupport> ABI); 
-   
-   Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs); 
-   
-   std::mutex EPCUIMutex; 
-   ExecutorProcessControl &EPC; 
-   std::unique_ptr<ABISupport> ABI; 
-   JITTargetAddress ResolverBlockAddr = 0; 
-   FinalizedAlloc ResolverBlock; 
-   std::unique_ptr<TrampolinePool> TP; 
-   std::unique_ptr<LazyCallThroughManager> LCTM; 
-   
-   std::vector<IndirectStubInfo> AvailableIndirectStubs; 
-   std::vector<FinalizedAlloc> IndirectStubAllocs; 
- }; 
-   
- /// This will call writeResolver on the given EPCIndirectionUtils instance 
- /// to set up re-entry via a function that will directly return the trampoline 
- /// landing address. 
- /// 
- /// The EPCIndirectionUtils' LazyCallThroughManager must have been previously 
- /// created via EPCIndirectionUtils::createLazyCallThroughManager. 
- /// 
- /// The EPCIndirectionUtils' writeResolver method must not have been previously 
- /// called. 
- /// 
- /// This function is experimental and likely subject to revision. 
- Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU); 
-   
- namespace detail { 
-   
- template <typename ORCABI> 
- class ABISupportImpl : public EPCIndirectionUtils::ABISupport { 
- public: 
-   ABISupportImpl() 
-       : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize, 
-                    ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement, 
-                    ORCABI::ResolverCodeSize) {} 
-   
-   void writeResolverCode(char *ResolverWorkingMem, 
-                          JITTargetAddress ResolverTargetAddr, 
-                          JITTargetAddress ReentryFnAddr, 
-                          JITTargetAddress ReentryCtxAddr) const override { 
-     ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr, 
-                               ReentryFnAddr, ReentryCtxAddr); 
-   } 
-   
-   void writeTrampolines(char *TrampolineBlockWorkingMem, 
-                         JITTargetAddress TrampolineBlockTargetAddr, 
-                         JITTargetAddress ResolverAddr, 
-                         unsigned NumTrampolines) const override { 
-     ORCABI::writeTrampolines(TrampolineBlockWorkingMem, 
-                              TrampolineBlockTargetAddr, ResolverAddr, 
-                              NumTrampolines); 
-   } 
-   
-   void writeIndirectStubsBlock(char *StubsBlockWorkingMem, 
-                                JITTargetAddress StubsBlockTargetAddress, 
-                                JITTargetAddress PointersBlockTargetAddress, 
-                                unsigned NumStubs) const override { 
-     ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem, 
-                                     StubsBlockTargetAddress, 
-                                     PointersBlockTargetAddress, NumStubs); 
-   } 
- }; 
-   
- } // end namespace detail 
-   
- template <typename ORCABI> 
- std::unique_ptr<EPCIndirectionUtils> 
- EPCIndirectionUtils::CreateWithABI(ExecutorProcessControl &EPC) { 
-   return std::unique_ptr<EPCIndirectionUtils>(new EPCIndirectionUtils( 
-       EPC, std::make_unique<detail::ABISupportImpl<ORCABI>>())); 
- } 
-   
- } // end namespace orc 
- } // end namespace llvm 
-   
- #endif // LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H 
-