LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - LazyReexports.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 23 67 34.3 %
Date: 2018-10-20 13:21:21 Functions: 5 19 26.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===------ LazyReexports.h -- Utilities for lazy reexports -----*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // Lazy re-exports are similar to normal re-exports, except that for callable
      11             : // symbols the definitions are replaced with trampolines that will look up and
      12             : // call through to the re-exported symbol at runtime. This can be used to
      13             : // enable lazy compilation.
      14             : //
      15             : //===----------------------------------------------------------------------===//
      16             : 
      17             : #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
      18             : #define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
      19             : 
      20             : #include "llvm/ExecutionEngine/Orc/Core.h"
      21             : #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
      22             : 
      23             : namespace llvm {
      24             : 
      25             : class Triple;
      26             : 
      27             : namespace orc {
      28             : 
      29             : /// Manages a set of 'lazy call-through' trampolines. These are compiler
      30             : /// re-entry trampolines that are pre-bound to look up a given symbol in a given
      31             : /// JITDylib, then jump to that address. Since compilation of symbols is
      32             : /// triggered on first lookup, these call-through trampolines can be used to
      33             : /// implement lazy compilation.
      34             : ///
      35             : /// The easiest way to construct these call-throughs is using the lazyReexport
      36             : /// function.
      37             : class LazyCallThroughManager {
      38             : public:
      39             :   /// Clients will want to take some action on first resolution, e.g. updating
      40             :   /// a stub pointer. Instances of this class can be used to implement this.
      41             :   class NotifyResolvedFunction {
      42             :   public:
      43           0 :     virtual ~NotifyResolvedFunction() {}
      44             : 
      45             :     /// Called the first time a lazy call through is executed and the target
      46             :     /// symbol resolved.
      47             :     virtual Error operator()(JITDylib &SourceJD,
      48             :                              const SymbolStringPtr &SymbolName,
      49             :                              JITTargetAddress ResolvedAddr) = 0;
      50             : 
      51             :   private:
      52             :     virtual void anchor();
      53             :   };
      54             : 
      55             :   template <typename NotifyResolvedImpl>
      56           0 :   class NotifyResolvedFunctionImpl : public NotifyResolvedFunction {
      57             :   public:
      58          23 :     NotifyResolvedFunctionImpl(NotifyResolvedImpl NotifyResolved)
      59          23 :         : NotifyResolved(std::move(NotifyResolved)) {}
      60          19 :     Error operator()(JITDylib &SourceJD, const SymbolStringPtr &SymbolName,
      61             :                      JITTargetAddress ResolvedAddr) {
      62          20 :       return NotifyResolved(SourceJD, SymbolName, ResolvedAddr);
      63             :     }
      64             : 
      65             :   private:
      66             :     NotifyResolvedImpl NotifyResolved;
      67             :   };
      68             : 
      69             :   /// Create a shared NotifyResolvedFunction from a given type that is
      70             :   /// callable with the correct signature.
      71             :   template <typename NotifyResolvedImpl>
      72             :   static std::unique_ptr<NotifyResolvedFunction>
      73             :   createNotifyResolvedFunction(NotifyResolvedImpl NotifyResolved) {
      74             :     return llvm::make_unique<NotifyResolvedFunctionImpl<NotifyResolvedImpl>>(
      75             :         std::move(NotifyResolved));
      76             :   }
      77             : 
      78             :   // Return a free call-through trampoline and bind it to look up and call
      79             :   // through to the given symbol.
      80             :   Expected<JITTargetAddress> getCallThroughTrampoline(
      81             :       JITDylib &SourceJD, SymbolStringPtr SymbolName,
      82             :       std::shared_ptr<NotifyResolvedFunction> NotifyResolved);
      83             : 
      84             : protected:
      85             :   LazyCallThroughManager(ExecutionSession &ES,
      86             :                          JITTargetAddress ErrorHandlerAddr,
      87             :                          std::unique_ptr<TrampolinePool> TP);
      88             : 
      89             :   JITTargetAddress callThroughToSymbol(JITTargetAddress TrampolineAddr);
      90             : 
      91             :   void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
      92             :     this->TP = std::move(TP);
      93             :   }
      94             : 
      95             : private:
      96             :   using ReexportsMap =
      97             :       std::map<JITTargetAddress, std::pair<JITDylib *, SymbolStringPtr>>;
      98             : 
      99             :   using NotifiersMap =
     100             :       std::map<JITTargetAddress, std::shared_ptr<NotifyResolvedFunction>>;
     101             : 
     102             :   std::mutex LCTMMutex;
     103             :   ExecutionSession &ES;
     104             :   JITTargetAddress ErrorHandlerAddr;
     105             :   std::unique_ptr<TrampolinePool> TP;
     106             :   ReexportsMap Reexports;
     107             :   NotifiersMap Notifiers;
     108             : };
     109             : 
     110             : /// A lazy call-through manager that builds trampolines in the current process.
     111           0 : class LocalLazyCallThroughManager : public LazyCallThroughManager {
     112             : private:
     113          14 :   LocalLazyCallThroughManager(ExecutionSession &ES,
     114             :                               JITTargetAddress ErrorHandlerAddr)
     115          28 :       : LazyCallThroughManager(ES, ErrorHandlerAddr, nullptr) {}
     116             : 
     117          14 :   template <typename ORCABI> Error init() {
     118          42 :     auto TP = LocalTrampolinePool<ORCABI>::Create(
     119             :         [this](JITTargetAddress TrampolineAddr) {
     120          20 :           return callThroughToSymbol(TrampolineAddr);
     121             :         });
     122             : 
     123          14 :     if (!TP)
     124             :       return TP.takeError();
     125             : 
     126             :     setTrampolinePool(std::move(*TP));
     127             :     return Error::success();
     128             :   }
     129          14 : 
     130          42 : public:
     131             :   /// Create a LocalLazyCallThroughManager using the given ABI. See
     132             :   /// createLocalLazyCallThroughManager.
     133             :   template <typename ORCABI>
     134             :   static Expected<std::unique_ptr<LocalLazyCallThroughManager>>
     135          14 :   Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
     136             :     auto LLCTM = std::unique_ptr<LocalLazyCallThroughManager>(
     137             :         new LocalLazyCallThroughManager(ES, ErrorHandlerAddr));
     138             : 
     139             :     if (auto Err = LLCTM->init<ORCABI>())
     140             :       return std::move(Err);
     141           0 : 
     142           0 :     return std::move(LLCTM);
     143             :   }
     144             : };
     145             : 
     146             : /// Create a LocalLazyCallThroughManager from the given triple and execution
     147           0 : /// session.
     148             : Expected<std::unique_ptr<LazyCallThroughManager>>
     149             : createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
     150             :                                   JITTargetAddress ErrorHandlerAddr);
     151             : 
     152             : /// A materialization unit that builds lazy re-exports. These are callable
     153           0 : /// entry points that call through to the given symbols.
     154           0 : /// Unlike a 'true' re-export, the address of the lazy re-export will not
     155             : /// match the address of the re-exported symbol, but calling it will behave
     156             : /// the same as calling the re-exported symbol.
     157             : class LazyReexportsMaterializationUnit : public MaterializationUnit {
     158             : public:
     159           0 :   LazyReexportsMaterializationUnit(LazyCallThroughManager &LCTManager,
     160             :                                    IndirectStubsManager &ISManager,
     161             :                                    JITDylib &SourceJD,
     162             :                                    SymbolAliasMap CallableAliases,
     163             :                                    VModuleKey K);
     164             : 
     165           0 :   StringRef getName() const override;
     166           0 : 
     167             : private:
     168             :   void materialize(MaterializationResponsibility R) override;
     169             :   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
     170             :   static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
     171           0 : 
     172             :   LazyCallThroughManager &LCTManager;
     173             :   IndirectStubsManager &ISManager;
     174             :   JITDylib &SourceJD;
     175             :   SymbolAliasMap CallableAliases;
     176             :   std::shared_ptr<LazyCallThroughManager::NotifyResolvedFunction>
     177           0 :       NotifyResolved;
     178           0 : };
     179             : 
     180             : /// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
     181             : /// is a callable symbol that will look up and dispatch to the given aliasee on
     182             : /// first call. All subsequent calls will go directly to the aliasee.
     183           0 : inline std::unique_ptr<LazyReexportsMaterializationUnit>
     184             : lazyReexports(LazyCallThroughManager &LCTManager,
     185             :               IndirectStubsManager &ISManager, JITDylib &SourceJD,
     186             :               SymbolAliasMap CallableAliases, VModuleKey K = VModuleKey()) {
     187             :   return llvm::make_unique<LazyReexportsMaterializationUnit>(
     188             :       LCTManager, ISManager, SourceJD, std::move(CallableAliases),
     189          13 :       std::move(K));
     190           0 : }
     191             : 
     192             : } // End namespace orc
     193             : } // End namespace llvm
     194             : 
     195           0 : #endif // LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H

Generated by: LCOV version 1.13