LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - Core.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 12 12 100.0 %
Date: 2018-02-22 16:16:46 Functions: 15 35 42.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- 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             : // Contains core ORC APIs.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
      15             : #define LLVM_EXECUTIONENGINE_ORC_CORE_H
      16             : 
      17             : #include "llvm/ExecutionEngine/JITSymbol.h"
      18             : #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
      19             : 
      20             : #include <map>
      21             : #include <memory>
      22             : #include <set>
      23             : #include <vector>
      24             : 
      25             : namespace llvm {
      26             : namespace orc {
      27             : 
      28             : /// VModuleKey provides a unique identifier (allocated and managed by
      29             : /// ExecutionSessions) for a module added to the JIT.
      30             : using VModuleKey = uint64_t;
      31             : 
      32             : class VSO;
      33             : 
      34             : /// @brief A set of symbol names (represented by SymbolStringPtrs for
      35             : //         efficiency).
      36             : using SymbolNameSet = std::set<SymbolStringPtr>;
      37             : 
      38             : /// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbols
      39             : ///        (address/flags pairs).
      40             : using SymbolMap = std::map<SymbolStringPtr, JITEvaluatedSymbol>;
      41             : 
      42             : /// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
      43             : using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>;
      44             : 
      45             : /// @brief A symbol query that returns results via a callback when results are
      46             : ///        ready.
      47             : ///
      48             : /// makes a callback when all symbols are available.
      49         114 : class AsynchronousSymbolQuery {
      50             : public:
      51             :   /// @brief Callback to notify client that symbols have been resolved.
      52             :   using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
      53             : 
      54             :   /// @brief Callback to notify client that symbols are ready for execution.
      55             :   using SymbolsReadyCallback = std::function<void(Error)>;
      56             : 
      57             :   /// @brief Create a query for the given symbols, notify-resolved and
      58             :   ///        notify-ready callbacks.
      59             :   AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
      60             :                           SymbolsResolvedCallback NotifySymbolsResolved,
      61             :                           SymbolsReadyCallback NotifySymbolsReady);
      62             : 
      63             :   /// @brief Notify client that the query failed.
      64             :   ///
      65             :   /// If the notify-resolved callback has not been made yet, then it is called
      66             :   /// with the given error, and the notify-finalized callback is never made.
      67             :   ///
      68             :   /// If the notify-resolved callback has already been made then then the
      69             :   /// notify-finalized callback is called with the given error.
      70             :   ///
      71             :   /// It is illegal to call setFailed after both callbacks have been made.
      72             :   void setFailed(Error Err);
      73             : 
      74             :   /// @brief Set the resolved symbol information for the given symbol name.
      75             :   ///
      76             :   /// If this symbol was the last one not resolved, this will trigger a call to
      77             :   /// the notify-finalized callback passing the completed sybol map.
      78             :   void setDefinition(SymbolStringPtr Name, JITEvaluatedSymbol Sym);
      79             : 
      80             :   /// @brief Notify the query that a requested symbol is ready for execution.
      81             :   ///
      82             :   /// This decrements the query's internal count of not-yet-ready symbols. If
      83             :   /// this call to notifySymbolFinalized sets the counter to zero, it will call
      84             :   /// the notify-finalized callback with Error::success as the value.
      85             :   void notifySymbolFinalized();
      86             : 
      87             : private:
      88             :   SymbolMap Symbols;
      89             :   size_t OutstandingResolutions = 0;
      90             :   size_t OutstandingFinalizations = 0;
      91             :   SymbolsResolvedCallback NotifySymbolsResolved;
      92             :   SymbolsReadyCallback NotifySymbolsReady;
      93             : };
      94             : 
      95             : /// @brief SymbolResolver is a composable interface for looking up symbol flags
      96             : ///        and addresses using the AsynchronousSymbolQuery type. It will
      97             : ///        eventually replace the LegacyJITSymbolResolver interface as the
      98             : ///        stardard ORC symbol resolver type.
      99             : class SymbolResolver {
     100             : public:
     101             :   virtual ~SymbolResolver() = default;
     102             : 
     103             :   /// @brief Returns the flags for each symbol in Symbols that can be found,
     104             :   ///        along with the set of symbol that could not be found.
     105             :   virtual SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
     106             :                                     const SymbolNameSet &Symbols) = 0;
     107             : 
     108             :   /// @brief For each symbol in Symbols that can be found, assigns that symbols
     109             :   ///        value in Query. Returns the set of symbols that could not be found.
     110             :   virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     111             :                                SymbolNameSet Symbols) = 0;
     112             : 
     113             : private:
     114             :   virtual void anchor();
     115             : };
     116             : 
     117             : /// @brief Implements SymbolResolver with a pair of supplied function objects
     118             : ///        for convenience. See createSymbolResolver.
     119             : template <typename LookupFlagsFn, typename LookupFn>
     120          30 : class LambdaSymbolResolver final : public SymbolResolver {
     121             : public:
     122             :   template <typename LookupFlagsFnRef, typename LookupFnRef>
     123          30 :   LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
     124             :       : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
     125          30 :         Lookup(std::forward<LookupFnRef>(Lookup)) {}
     126             : 
     127          39 :   SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
     128             :                             const SymbolNameSet &Symbols) final {
     129          40 :     return LookupFlags(Flags, Symbols);
     130             :   }
     131             : 
     132          24 :   SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     133             :                        SymbolNameSet Symbols) final {
     134          73 :     return Lookup(std::move(Query), std::move(Symbols));
     135             :   }
     136             : 
     137             : private:
     138             :   LookupFlagsFn LookupFlags;
     139             :   LookupFn Lookup;
     140             : };
     141             : 
     142             : /// @brief Creates a SymbolResolver implementation from the pair of supplied
     143             : ///        function objects.
     144             : template <typename LookupFlagsFn, typename LookupFn>
     145             : std::unique_ptr<LambdaSymbolResolver<
     146             :     typename std::remove_cv<
     147             :         typename std::remove_reference<LookupFlagsFn>::type>::type,
     148             :     typename std::remove_cv<
     149             :         typename std::remove_reference<LookupFn>::type>::type>>
     150             : createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
     151             :   using LambdaSymbolResolverImpl = LambdaSymbolResolver<
     152             :       typename std::remove_cv<
     153             :           typename std::remove_reference<LookupFlagsFn>::type>::type,
     154             :       typename std::remove_cv<
     155             :           typename std::remove_reference<LookupFn>::type>::type>;
     156             :   return llvm::make_unique<LambdaSymbolResolverImpl>(
     157          20 :       std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
     158             : }
     159             : 
     160             : /// @brief Represents a source of symbol definitions which may be materialized
     161             : ///        (turned into data / code through some materialization process) or
     162             : ///        discarded (if the definition is overridden by a stronger one).
     163             : ///
     164             : /// SymbolSources are used when providing lazy definitions of symbols to VSOs.
     165             : /// The VSO will call materialize when the address of a symbol is requested via
     166             : /// the lookup method. The VSO will call discard if a stronger definition is
     167             : /// added or already present.
     168             : class SymbolSource {
     169             : public:
     170             :   virtual ~SymbolSource() {}
     171             : 
     172             :   /// @brief Implementations of this method should materialize the given
     173             :   ///        symbols (plus any additional symbols required) by adding a
     174             :   ///        Materializer to the ExecutionSession's MaterializationQueue.
     175             :   virtual Error materialize(VSO &V, SymbolNameSet Symbols) = 0;
     176             : 
     177             :   /// @brief Implementations of this method should discard the given symbol
     178             :   ///        from the source (e.g. if the source is an LLVM IR Module and the
     179             :   ///        symbol is a function, delete the function body or mark it available
     180             :   ///        externally).
     181             :   virtual void discard(VSO &V, SymbolStringPtr Name) = 0;
     182             : 
     183             : private:
     184             :   virtual void anchor();
     185             : };
     186             : 
     187             : /// @brief Represents a dynamic linkage unit in a JIT process.
     188             : ///
     189             : /// VSO acts as a symbol table (symbol definitions can be set and the dylib
     190             : /// queried to find symbol addresses) and as a key for tracking resources
     191             : /// (since a VSO's address is fixed).
     192           5 : class VSO {
     193             :   friend class ExecutionSession;
     194             : 
     195             : public:
     196             :   enum RelativeLinkageStrength {
     197             :     NewDefinitionIsStronger,
     198             :     DuplicateDefinition,
     199             :     ExistingDefinitionIsStronger
     200             :   };
     201             : 
     202             :   using SetDefinitionsResult =
     203             :       std::map<SymbolStringPtr, RelativeLinkageStrength>;
     204             :   using SourceWorkMap = std::map<std::shared_ptr<SymbolSource>, SymbolNameSet>;
     205             : 
     206           8 :   struct LookupResult {
     207             :     SourceWorkMap MaterializationWork;
     208             :     SymbolNameSet UnresolvedSymbols;
     209             :   };
     210             : 
     211             :   VSO() = default;
     212             : 
     213             :   VSO(const VSO &) = delete;
     214             :   VSO &operator=(const VSO &) = delete;
     215             :   VSO(VSO &&) = delete;
     216             :   VSO &operator=(VSO &&) = delete;
     217             : 
     218             :   /// @brief Compare new linkage with existing linkage.
     219             :   static RelativeLinkageStrength
     220             :   compareLinkage(Optional<JITSymbolFlags> OldFlags, JITSymbolFlags NewFlags);
     221             : 
     222             :   /// @brief Compare new linkage with an existing symbol's linkage.
     223             :   RelativeLinkageStrength compareLinkage(SymbolStringPtr Name,
     224             :                                          JITSymbolFlags NewFlags) const;
     225             : 
     226             :   /// @brief Adds the given symbols to the mapping as resolved, finalized
     227             :   ///        symbols.
     228             :   ///
     229             :   /// FIXME: We can take this by const-ref once symbol-based laziness is
     230             :   ///        removed.
     231             :   Error define(SymbolMap NewSymbols);
     232             : 
     233             :   /// @brief Adds the given symbols to the mapping as lazy symbols.
     234             :   Error defineLazy(const SymbolFlagsMap &NewSymbols,
     235             :                    std::shared_ptr<SymbolSource> Source);
     236             : 
     237             :   /// @brief Add the given symbol/address mappings to the dylib, but do not
     238             :   ///        mark the symbols as finalized yet.
     239             :   void resolve(SymbolMap SymbolValues);
     240             : 
     241             :   /// @brief Finalize the given symbols.
     242             :   void finalize(SymbolNameSet SymbolsToFinalize);
     243             : 
     244             :   /// @brief Look up the flags for the given symbols.
     245             :   ///
     246             :   /// Returns the flags for the give symbols, together with the set of symbols
     247             :   /// not found.
     248             :   SymbolNameSet lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Symbols);
     249             : 
     250             :   /// @brief Apply the given query to the given symbols in this VSO.
     251             :   ///
     252             :   /// For symbols in this VSO that have already been materialized, their address
     253             :   /// will be set in the query immediately.
     254             :   ///
     255             :   /// For symbols in this VSO that have not been materialized, the query will be
     256             :   /// recorded and the source for those symbols (plus the set of symbols to be
     257             :   /// materialized by that source) will be returned as the MaterializationWork
     258             :   /// field of the LookupResult.
     259             :   ///
     260             :   /// Any symbols not found in this VSO will be returned in the
     261             :   /// UnresolvedSymbols field of the LookupResult.
     262             :   LookupResult lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     263             :                       SymbolNameSet Symbols);
     264             : 
     265             : private:
     266           6 :   class MaterializationInfo {
     267             :   public:
     268             :     MaterializationInfo(JITSymbolFlags Flags,
     269             :                         std::shared_ptr<SymbolSource> Query);
     270             :     JITSymbolFlags getFlags() const;
     271             :     JITTargetAddress getAddress() const;
     272             :     void replaceWithSource(VSO &V, SymbolStringPtr Name,
     273             :                            JITSymbolFlags NewFlags,
     274             :                            std::shared_ptr<SymbolSource> NewSource);
     275             :     std::shared_ptr<SymbolSource>
     276             :     query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
     277             :     void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
     278             :     void finalize();
     279             : 
     280             :   private:
     281             :     JITSymbolFlags Flags;
     282             :     JITTargetAddress Address = 0;
     283             :     std::shared_ptr<SymbolSource> Source;
     284             :     std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingResolution;
     285             :     std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingFinalization;
     286             :   };
     287             : 
     288             :   class SymbolTableEntry {
     289             :   public:
     290             :     SymbolTableEntry(JITSymbolFlags Flags,
     291             :                      std::shared_ptr<SymbolSource> Source);
     292             :     SymbolTableEntry(JITEvaluatedSymbol Sym);
     293             :     SymbolTableEntry(SymbolTableEntry &&Other);
     294             :     ~SymbolTableEntry();
     295             :     JITSymbolFlags getFlags() const;
     296             :     void replaceWithSource(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
     297             :                            std::shared_ptr<SymbolSource> NewSource);
     298             :     std::shared_ptr<SymbolSource>
     299             :     query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
     300             :     void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
     301             :     void finalize();
     302             : 
     303             :   private:
     304             :     JITSymbolFlags Flags;
     305             :     union {
     306             :       JITTargetAddress Address;
     307             :       std::unique_ptr<MaterializationInfo> MatInfo;
     308             :     };
     309             :   };
     310             : 
     311             :   std::map<SymbolStringPtr, SymbolTableEntry> Symbols;
     312             : };
     313             : 
     314             : /// @brief An ExecutionSession represents a running JIT program.
     315             : class ExecutionSession {
     316             : public:
     317             :   /// @brief Construct an ExecutionEngine.
     318             :   ///
     319             :   /// SymbolStringPools may be shared between ExecutionSessions.
     320             :   ExecutionSession(SymbolStringPool &SSP);
     321             : 
     322             :   /// @brief Returns the SymbolStringPool for this ExecutionSession.
     323             :   SymbolStringPool &getSymbolStringPool() const { return SSP; }
     324             : 
     325             :   /// @brief Allocate a module key for a new module to add to the JIT.
     326             :   VModuleKey allocateVModule();
     327             : 
     328             :   /// @brief Return a module key to the ExecutionSession so that it can be
     329             :   ///        re-used. This should only be done once all resources associated
     330             :   ////       with the original key have been released.
     331             :   void releaseVModule(VModuleKey Key);
     332             : 
     333             : public:
     334             :   SymbolStringPool &SSP;
     335             :   VModuleKey LastKey = 0;
     336             : };
     337             : 
     338             : } // End namespace orc
     339             : } // End namespace llvm
     340             : 
     341             : #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H

Generated by: LCOV version 1.13