Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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"
  20. #include "llvm/ExecutionEngine/Orc/Core.h"
  21. #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
  22. #include "llvm/ExecutionEngine/Orc/Speculation.h"
  23.  
  24. namespace llvm {
  25.  
  26. class Triple;
  27.  
  28. namespace orc {
  29.  
  30. /// Manages a set of 'lazy call-through' trampolines. These are compiler
  31. /// re-entry trampolines that are pre-bound to look up a given symbol in a given
  32. /// JITDylib, then jump to that address. Since compilation of symbols is
  33. /// triggered on first lookup, these call-through trampolines can be used to
  34. /// implement lazy compilation.
  35. ///
  36. /// The easiest way to construct these call-throughs is using the lazyReexport
  37. /// function.
  38. class LazyCallThroughManager {
  39. public:
  40.   using NotifyResolvedFunction =
  41.       unique_function<Error(JITTargetAddress ResolvedAddr)>;
  42.  
  43.   LazyCallThroughManager(ExecutionSession &ES,
  44.                          JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP);
  45.  
  46.   // Return a free call-through trampoline and bind it to look up and call
  47.   // through to the given symbol.
  48.   Expected<JITTargetAddress>
  49.   getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName,
  50.                            NotifyResolvedFunction NotifyResolved);
  51.  
  52.   void resolveTrampolineLandingAddress(
  53.       JITTargetAddress TrampolineAddr,
  54.       TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved);
  55.  
  56.   virtual ~LazyCallThroughManager() = default;
  57.  
  58. protected:
  59.   using NotifyLandingResolvedFunction =
  60.       TrampolinePool::NotifyLandingResolvedFunction;
  61.  
  62.   struct ReexportsEntry {
  63.     JITDylib *SourceJD;
  64.     SymbolStringPtr SymbolName;
  65.   };
  66.  
  67.   JITTargetAddress reportCallThroughError(Error Err);
  68.   Expected<ReexportsEntry> findReexport(JITTargetAddress TrampolineAddr);
  69.   Error notifyResolved(JITTargetAddress TrampolineAddr,
  70.                        JITTargetAddress ResolvedAddr);
  71.   void setTrampolinePool(TrampolinePool &TP) { this->TP = &TP; }
  72.  
  73. private:
  74.   using ReexportsMap = std::map<JITTargetAddress, ReexportsEntry>;
  75.  
  76.   using NotifiersMap = std::map<JITTargetAddress, NotifyResolvedFunction>;
  77.  
  78.   std::mutex LCTMMutex;
  79.   ExecutionSession &ES;
  80.   JITTargetAddress 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.
  87. class LocalLazyCallThroughManager : public LazyCallThroughManager {
  88. private:
  89.   using NotifyTargetResolved = unique_function<void(JITTargetAddress)>;
  90.  
  91.   LocalLazyCallThroughManager(ExecutionSession &ES,
  92.                               JITTargetAddress ErrorHandlerAddr)
  93.       : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
  94.  
  95.   template <typename ORCABI> Error init() {
  96.     auto TP = LocalTrampolinePool<ORCABI>::Create(
  97.         [this](JITTargetAddress TrampolineAddr,
  98.                TrampolinePool::NotifyLandingResolvedFunction
  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.  
  114. public:
  115.   /// Create a LocalLazyCallThroughManager using the given ABI. See
  116.   /// createLocalLazyCallThroughManager.
  117.   template <typename ORCABI>
  118.   static Expected<std::unique_ptr<LocalLazyCallThroughManager>>
  119.   Create(ExecutionSession &ES, JITTargetAddress 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.
  132. Expected<std::unique_ptr<LazyCallThroughManager>>
  133. createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
  134.                                   JITTargetAddress 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.
  141. class LazyReexportsMaterializationUnit : public MaterializationUnit {
  142. public:
  143.   LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager,
  144.                                    IndirectStubsManager &ISManager,
  145.                                    JITDylib &SourceJD,
  146.                                    SymbolAliasMap CallableAliases,
  147.                                    ImplSymbolMap *SrcJDLoc);
  148.  
  149.   StringRef getName() const override;
  150.  
  151. private:
  152.   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
  153.   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
  154.   static MaterializationUnit::Interface
  155.   extractFlags(const SymbolAliasMap &Aliases);
  156.  
  157.   LazyCallThroughManager &LCTManager;
  158.   IndirectStubsManager &ISManager;
  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.
  167. inline std::unique_ptr<LazyReexportsMaterializationUnit>
  168. lazyReexports(LazyCallThroughManager &LCTManager,
  169.               IndirectStubsManager &ISManager, JITDylib &SourceJD,
  170.               SymbolAliasMap CallableAliases,
  171.               ImplSymbolMap *SrcJDLoc = nullptr) {
  172.   return std::make_unique<LazyReexportsMaterializationUnit>(
  173.       LCTManager, ISManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
  174. }
  175.  
  176. } // End namespace orc
  177. } // End namespace llvm
  178.  
  179. #endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
  180.