LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - Core.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 61 62 98.4 %
Date: 2018-07-13 00:08:38 Functions: 47 67 70.1 %
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/ADT/BitmaskEnum.h"
      18             : #include "llvm/ExecutionEngine/JITSymbol.h"
      19             : #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
      20             : #include "llvm/IR/Module.h"
      21             : 
      22             : #include <list>
      23             : #include <map>
      24             : #include <memory>
      25             : #include <set>
      26             : #include <vector>
      27             : 
      28             : namespace llvm {
      29             : namespace orc {
      30             : 
      31             : // Forward declare some classes.
      32             : class AsynchronousSymbolQuery;
      33             : class ExecutionSession;
      34             : class MaterializationUnit;
      35             : class MaterializationResponsibility;
      36             : class VSO;
      37             : 
      38             : /// VModuleKey provides a unique identifier (allocated and managed by
      39             : /// ExecutionSessions) for a module added to the JIT.
      40             : using VModuleKey = uint64_t;
      41             : 
      42             : /// A set of symbol names (represented by SymbolStringPtrs for
      43             : //         efficiency).
      44             : using SymbolNameSet = std::set<SymbolStringPtr>;
      45             : 
      46             : /// Render a SymbolNameSet to an ostream.
      47             : raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
      48             : 
      49             : /// A map from symbol names (as SymbolStringPtrs) to JITSymbols
      50             : ///        (address/flags pairs).
      51             : using SymbolMap = std::map<SymbolStringPtr, JITEvaluatedSymbol>;
      52             : 
      53             : /// Render a SymbolMap to an ostream.
      54             : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
      55             : 
      56             : /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
      57             : using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>;
      58             : 
      59             : /// Render a SymbolMap to an ostream.
      60             : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &Symbols);
      61             : 
      62             : /// A base class for materialization failures that allows the failing
      63             : ///        symbols to be obtained for logging.
      64             : using SymbolDependenceMap = std::map<VSO *, SymbolNameSet>;
      65             : 
      66             : /// Render a SymbolDependendeMap.
      67             : raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
      68             : 
      69             : /// Used to notify a VSO that the given set of symbols failed to materialize.
      70           2 : class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
      71             : public:
      72             :   static char ID;
      73             : 
      74             :   FailedToMaterialize(SymbolNameSet Symbols);
      75             :   std::error_code convertToErrorCode() const override;
      76             :   void log(raw_ostream &OS) const override;
      77           1 :   const SymbolNameSet &getSymbols() const { return Symbols; }
      78             : 
      79             : private:
      80             :   SymbolNameSet Symbols;
      81             : };
      82             : 
      83             : /// Used to notify clients when symbols can not be found during a lookup.
      84           0 : class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
      85             : public:
      86             :   static char ID;
      87             : 
      88             :   SymbolsNotFound(SymbolNameSet Symbols);
      89             :   std::error_code convertToErrorCode() const override;
      90             :   void log(raw_ostream &OS) const override;
      91             :   const SymbolNameSet &getSymbols() const { return Symbols; }
      92             : 
      93             : private:
      94             :   SymbolNameSet Symbols;
      95             : };
      96             : 
      97             : /// Tracks responsibility for materialization, and mediates interactions between
      98             : /// MaterializationUnits and VSOs.
      99             : ///
     100             : /// An instance of this class is passed to MaterializationUnits when their
     101             : /// materialize method is called. It allows MaterializationUnits to resolve and
     102             : /// finalize symbols, or abandon materialization by notifying any unmaterialized
     103             : /// symbols of an error.
     104             : class MaterializationResponsibility {
     105             :   friend class MaterializationUnit;
     106             : public:
     107         120 :   MaterializationResponsibility(MaterializationResponsibility &&) = default;
     108             :   MaterializationResponsibility &
     109             :   operator=(MaterializationResponsibility &&) = default;
     110             : 
     111             :   /// Destruct a MaterializationResponsibility instance. In debug mode
     112             :   ///        this asserts that all symbols being tracked have been either
     113             :   ///        finalized or notified of an error.
     114             :   ~MaterializationResponsibility();
     115             : 
     116             :   /// Returns the target VSO that these symbols are being materialized
     117             :   ///        into.
     118             :   VSO &getTargetVSO() const { return V; }
     119             : 
     120             :   /// Returns the names of any symbols covered by this
     121             :   /// MaterializationResponsibility object that have queries pending. This
     122             :   /// information can be used to return responsibility for unrequested symbols
     123             :   /// back to the VSO via the delegate method.
     124             :   SymbolNameSet getRequestedSymbols();
     125             : 
     126             :   /// Resolves the given symbols. Individual calls to this method may
     127             :   ///        resolve a subset of the symbols, but all symbols must have been
     128             :   ///        resolved prior to calling finalize.
     129             :   void resolve(const SymbolMap &Symbols);
     130             : 
     131             :   /// Finalizes all symbols tracked by this instance.
     132             :   void finalize();
     133             : 
     134             :   /// Adds new symbols to the VSO and this responsibility instance.
     135             :   ///        VSO entries start out in the materializing state.
     136             :   ///
     137             :   ///   This method can be used by materialization units that want to add
     138             :   /// additional symbols at materialization time (e.g. stubs, compile
     139             :   /// callbacks, metadata).
     140             :   Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
     141             : 
     142             :   /// Notify all unfinalized symbols that an error has occurred.
     143             :   /// This will remove all symbols covered by this MaterializationResponsibilty
     144             :   /// from V, and send an error to any queries waiting on these symbols.
     145             :   void failMaterialization();
     146             : 
     147             :   /// Transfers responsibility to the given MaterializationUnit for all
     148             :   /// symbols defined by that MaterializationUnit. This allows
     149             :   /// materializers to break up work based on run-time information (e.g.
     150             :   /// by introspecting which symbols have actually been looked up and
     151             :   /// materializing only those).
     152             :   void replace(std::unique_ptr<MaterializationUnit> MU);
     153             : 
     154             :   /// Delegates responsibility for the given symbols to the returned
     155             :   /// materialization responsibility. Useful for breaking up work between
     156             :   /// threads, or different kinds of materialization processes.
     157             :   MaterializationResponsibility delegate(const SymbolNameSet &Symbols);
     158             : 
     159             :   /// Add dependencies for the symbols in this dylib.
     160             :   void addDependencies(const SymbolDependenceMap &Dependencies);
     161             : 
     162             : private:
     163             :   /// Create a MaterializationResponsibility for the given VSO and
     164             :   ///        initial symbols.
     165             :   MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
     166             : 
     167             :   VSO &V;
     168             :   SymbolFlagsMap SymbolFlags;
     169             : };
     170             : 
     171             : /// A MaterializationUnit represents a set of symbol definitions that can
     172             : ///        be materialized as a group, or individually discarded (when
     173             : ///        overriding definitions are encountered).
     174             : ///
     175             : /// MaterializationUnits are used when providing lazy definitions of symbols to
     176             : /// VSOs. The VSO will call materialize when the address of a symbol is
     177             : /// requested via the lookup method. The VSO will call discard if a stronger
     178             : /// definition is added or already present.
     179             : class MaterializationUnit {
     180             : public:
     181             :   MaterializationUnit(SymbolFlagsMap InitalSymbolFlags)
     182          88 :       : SymbolFlags(std::move(InitalSymbolFlags)) {}
     183             : 
     184          88 :   virtual ~MaterializationUnit() {}
     185             : 
     186             :   /// Return the set of symbols that this source provides.
     187             :   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
     188             : 
     189             :   /// Called by materialization dispatchers (see
     190             :   /// ExecutionSession::DispatchMaterializationFunction) to trigger
     191             :   /// materialization of this MaterializationUnit.
     192          66 :   void doMaterialize(VSO &V) {
     193         198 :     materialize(MaterializationResponsibility(V, std::move(SymbolFlags)));
     194          66 :   }
     195             : 
     196             :   /// Called by VSOs to notify MaterializationUnits that the given symbol has
     197             :   /// been overridden.
     198           5 :   void doDiscard(const VSO &V, SymbolStringPtr Name) {
     199             :     SymbolFlags.erase(Name);
     200          10 :     discard(V, std::move(Name));
     201           5 :   }
     202             : 
     203             : protected:
     204             :   SymbolFlagsMap SymbolFlags;
     205             : 
     206             : private:
     207             :   virtual void anchor();
     208             : 
     209             :   /// Implementations of this method should materialize all symbols
     210             :   ///        in the materialzation unit, except for those that have been
     211             :   ///        previously discarded.
     212             :   virtual void materialize(MaterializationResponsibility R) = 0;
     213             : 
     214             :   /// Implementations of this method should discard the given symbol
     215             :   ///        from the source (e.g. if the source is an LLVM IR Module and the
     216             :   ///        symbol is a function, delete the function body or mark it available
     217             :   ///        externally).
     218             :   virtual void discard(const VSO &V, SymbolStringPtr Name) = 0;
     219             : };
     220             : 
     221             : /// A MaterializationUnit implementation for pre-existing absolute symbols.
     222             : ///
     223             : /// All symbols will be resolved and marked ready as soon as the unit is
     224             : /// materialized.
     225          66 : class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
     226             : public:
     227             :   AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
     228             : 
     229             : private:
     230             :   void materialize(MaterializationResponsibility R) override;
     231             :   void discard(const VSO &V, SymbolStringPtr Name) override;
     232             :   static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
     233             : 
     234             :   SymbolMap Symbols;
     235             : };
     236             : 
     237             : /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
     238             : /// Useful for inserting absolute symbols into a VSO. E.g.:
     239             : /// \code{.cpp}
     240             : ///   VSO &V = ...;
     241             : ///   SymbolStringPtr Foo = ...;
     242             : ///   JITEvaluatedSymbol FooSym = ...;
     243             : ///   if (auto Err = V.define(absoluteSymbols({{Foo, FooSym}})))
     244             : ///     return Err;
     245             : /// \endcode
     246             : ///
     247             : inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
     248             : absoluteSymbols(SymbolMap Symbols) {
     249             :   return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
     250          22 :       std::move(Symbols));
     251             : }
     252             : 
     253          16 : struct SymbolAliasMapEntry {
     254             :   SymbolStringPtr Aliasee;
     255             :   JITSymbolFlags AliasFlags;
     256             : };
     257             : 
     258             : /// A map of Symbols to (Symbol, Flags) pairs.
     259             : using SymbolAliasMap = std::map<SymbolStringPtr, SymbolAliasMapEntry>;
     260             : 
     261             : /// A materialization unit for symbol aliases. Allows existing symbols to be
     262             : /// aliased with alternate flags.
     263          27 : class SymbolAliasesMaterializationUnit : public MaterializationUnit {
     264             : public:
     265             :   SymbolAliasesMaterializationUnit(SymbolAliasMap Aliases);
     266             : 
     267             : private:
     268             :   void materialize(MaterializationResponsibility R) override;
     269             :   void discard(const VSO &V, SymbolStringPtr Name) override;
     270             :   static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
     271             : 
     272             :   SymbolAliasMap Aliases;
     273             : };
     274             : 
     275             : /// Create a SymbolAliasesMaterializationUnit with the given aliases.
     276             : /// Useful for defining symbol aliases.: E.g., given a VSO V containing symbols
     277             : /// "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" (for
     278             : /// "bar") with:
     279             : /// \code{.cpp}
     280             : ///   SymbolStringPtr Baz = ...;
     281             : ///   SymbolStringPtr Qux = ...;
     282             : ///   if (auto Err = V.define(symbolAliases({
     283             : ///       {Baz, { Foo, JITSymbolFlags::Exported }},
     284             : ///       {Qux, { Bar, JITSymbolFlags::Weak }}}))
     285             : ///     return Err;
     286             : /// \endcode
     287             : inline std::unique_ptr<SymbolAliasesMaterializationUnit>
     288             : symbolAliases(SymbolAliasMap Aliases) {
     289             :   return llvm::make_unique<SymbolAliasesMaterializationUnit>(
     290           9 :       std::move(Aliases));
     291             : }
     292             : 
     293             : /// Base utilities for ExecutionSession.
     294         160 : class ExecutionSessionBase {
     295             : public:
     296             :   /// For reporting errors.
     297             :   using ErrorReporter = std::function<void(Error)>;
     298             : 
     299             :   /// For dispatching MaterializationUnit::materialize calls.
     300             :   using DispatchMaterializationFunction =
     301             :       std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
     302             : 
     303             :   /// Construct an ExecutionSessionBase.
     304             :   ///
     305             :   /// SymbolStringPools may be shared between ExecutionSessions.
     306         146 :   ExecutionSessionBase(std::shared_ptr<SymbolStringPool> SSP = nullptr)
     307         584 :       : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
     308             : 
     309             :   /// Returns the SymbolStringPool for this ExecutionSession.
     310             :   SymbolStringPool &getSymbolStringPool() const { return *SSP; }
     311             : 
     312             :   /// Run the given lambda with the session mutex locked.
     313             :   template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
     314         422 :     std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
     315         422 :     return F();
     316             :   }
     317             : 
     318             :   /// Set the error reporter function.
     319             :   ExecutionSessionBase &setErrorReporter(ErrorReporter ReportError) {
     320          24 :     this->ReportError = std::move(ReportError);
     321             :     return *this;
     322             :   }
     323             : 
     324             :   /// Set the materialization dispatch function.
     325             :   ExecutionSessionBase &setDispatchMaterialization(
     326             :       DispatchMaterializationFunction DispatchMaterialization) {
     327           2 :     this->DispatchMaterialization = std::move(DispatchMaterialization);
     328             :     return *this;
     329             :   }
     330             : 
     331             :   /// Report a error for this execution session.
     332             :   ///
     333             :   /// Unhandled errors can be sent here to log them.
     334           4 :   void reportError(Error Err) { ReportError(std::move(Err)); }
     335             : 
     336             :   /// Allocate a module key for a new module to add to the JIT.
     337         130 :   VModuleKey allocateVModule() { return ++LastKey; }
     338             : 
     339             :   /// Return a module key to the ExecutionSession so that it can be
     340             :   ///        re-used. This should only be done once all resources associated
     341             :   ///        with the original key have been released.
     342             :   void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
     343             :   }
     344             : 
     345             :   /// Cause the given query to fail with the given Error.
     346             :   ///
     347             :   /// This should only be used by legacy APIs and will be deprecated in the
     348             :   /// future.
     349             :   void failQuery(AsynchronousSymbolQuery &Q, Error Err);
     350             : 
     351             :   /// Materialize the given unit.
     352          66 :   void dispatchMaterialization(VSO &V,
     353             :                                std::unique_ptr<MaterializationUnit> MU) {
     354          66 :     DispatchMaterialization(V, std::move(MU));
     355          66 :   }
     356             : 
     357             : private:
     358           2 :   static void logErrorsToStdErr(Error Err) {
     359           6 :     logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
     360           2 :   }
     361             : 
     362             :   static void
     363          64 :   materializeOnCurrentThread(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
     364          64 :     MU->doMaterialize(V);
     365          64 :   }
     366             : 
     367             :   mutable std::recursive_mutex SessionMutex;
     368             :   std::shared_ptr<SymbolStringPool> SSP;
     369             :   VModuleKey LastKey = 0;
     370             :   ErrorReporter ReportError = logErrorsToStdErr;
     371             :   DispatchMaterializationFunction DispatchMaterialization =
     372             :       materializeOnCurrentThread;
     373             : };
     374             : 
     375             : /// A symbol query that returns results via a callback when results are
     376             : ///        ready.
     377             : ///
     378             : /// makes a callback when all symbols are available.
     379         260 : class AsynchronousSymbolQuery {
     380             :   friend class ExecutionSessionBase;
     381             :   friend class VSO;
     382             : 
     383             : public:
     384         539 :   class ResolutionResult {
     385             :   public:
     386             :     ResolutionResult(SymbolMap Symbols, const SymbolDependenceMap &Dependencies)
     387         256 :         : Symbols(std::move(Symbols)), Dependencies(Dependencies) {}
     388             : 
     389             :     SymbolMap Symbols;
     390             :     const SymbolDependenceMap &Dependencies;
     391             :   };
     392             : 
     393             :   /// Callback to notify client that symbols have been resolved.
     394             :   using SymbolsResolvedCallback =
     395             :       std::function<void(Expected<ResolutionResult>)>;
     396             : 
     397             :   /// Callback to notify client that symbols are ready for execution.
     398             :   using SymbolsReadyCallback = std::function<void(Error)>;
     399             : 
     400             :   /// Create a query for the given symbols, notify-resolved and
     401             :   ///        notify-ready callbacks.
     402             :   AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
     403             :                           SymbolsResolvedCallback NotifySymbolsResolved,
     404             :                           SymbolsReadyCallback NotifySymbolsReady);
     405             : 
     406             :   /// Set the resolved symbol information for the given symbol name.
     407             :   void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
     408             : 
     409             :   /// Returns true if all symbols covered by this query have been
     410             :   ///        resolved.
     411           1 :   bool isFullyResolved() const { return NotYetResolvedCount == 0; }
     412             : 
     413             :   /// Call the NotifySymbolsResolved callback.
     414             :   ///
     415             :   /// This should only be called if all symbols covered by the query have been
     416             :   /// resolved.
     417             :   void handleFullyResolved();
     418             : 
     419             :   /// Notify the query that a requested symbol is ready for execution.
     420             :   void notifySymbolReady();
     421             : 
     422             :   /// Returns true if all symbols covered by this query are ready.
     423             :   bool isFullyReady() const { return NotYetReadyCount == 0; }
     424             : 
     425             :   /// Calls the NotifySymbolsReady callback.
     426             :   ///
     427             :   /// This should only be called if all symbols covered by this query are ready.
     428             :   void handleFullyReady();
     429             : 
     430             : private:
     431             :   void addQueryDependence(VSO &V, SymbolStringPtr Name);
     432             : 
     433             :   void removeQueryDependence(VSO &V, const SymbolStringPtr &Name);
     434             : 
     435             :   bool canStillFail();
     436             : 
     437             :   void handleFailed(Error Err);
     438             : 
     439             :   void detach();
     440             : 
     441             :   SymbolsResolvedCallback NotifySymbolsResolved;
     442             :   SymbolsReadyCallback NotifySymbolsReady;
     443             :   SymbolDependenceMap QueryRegistrations;
     444             :   SymbolMap ResolvedSymbols;
     445             :   size_t NotYetResolvedCount;
     446             :   size_t NotYetReadyCount;
     447             : };
     448             : 
     449             : /// SymbolResolver is a composable interface for looking up symbol flags
     450             : ///        and addresses using the AsynchronousSymbolQuery type. It will
     451             : ///        eventually replace the LegacyJITSymbolResolver interface as the
     452             : ///        stardard ORC symbol resolver type.
     453             : ///
     454             : /// FIXME: SymbolResolvers should go away and be replaced with VSOs with
     455             : ///        defenition generators.
     456             : class SymbolResolver {
     457             : public:
     458             :   virtual ~SymbolResolver() = default;
     459             : 
     460             :   /// Returns the flags for each symbol in Symbols that can be found,
     461             :   ///        along with the set of symbol that could not be found.
     462             :   virtual SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
     463             :                                     const SymbolNameSet &Symbols) = 0;
     464             : 
     465             :   /// For each symbol in Symbols that can be found, assigns that symbols
     466             :   ///        value in Query. Returns the set of symbols that could not be found.
     467             :   virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     468             :                                SymbolNameSet Symbols) = 0;
     469             : 
     470             : private:
     471             :   virtual void anchor();
     472             : };
     473             : 
     474             : /// Implements SymbolResolver with a pair of supplied function objects
     475             : ///        for convenience. See createSymbolResolver.
     476             : template <typename LookupFlagsFn, typename LookupFn>
     477          57 : class LambdaSymbolResolver final : public SymbolResolver {
     478             : public:
     479             :   template <typename LookupFlagsFnRef, typename LookupFnRef>
     480          27 :   LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
     481             :       : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
     482          27 :         Lookup(std::forward<LookupFnRef>(Lookup)) {}
     483             : 
     484          41 :   SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
     485             :                             const SymbolNameSet &Symbols) final {
     486          41 :     return LookupFlags(Flags, Symbols);
     487             :   }
     488             : 
     489          25 :   SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     490             :                        SymbolNameSet Symbols) final {
     491          97 :     return Lookup(std::move(Query), std::move(Symbols));
     492             :   }
     493             : 
     494             : private:
     495             :   LookupFlagsFn LookupFlags;
     496             :   LookupFn Lookup;
     497             : };
     498             : 
     499             : /// Creates a SymbolResolver implementation from the pair of supplied
     500             : ///        function objects.
     501             : template <typename LookupFlagsFn, typename LookupFn>
     502             : std::unique_ptr<LambdaSymbolResolver<
     503             :     typename std::remove_cv<
     504             :         typename std::remove_reference<LookupFlagsFn>::type>::type,
     505             :     typename std::remove_cv<
     506             :         typename std::remove_reference<LookupFn>::type>::type>>
     507             : createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
     508             :   using LambdaSymbolResolverImpl = LambdaSymbolResolver<
     509             :       typename std::remove_cv<
     510             :           typename std::remove_reference<LookupFlagsFn>::type>::type,
     511             :       typename std::remove_cv<
     512             :           typename std::remove_reference<LookupFn>::type>::type>;
     513             :   return llvm::make_unique<LambdaSymbolResolverImpl>(
     514          16 :       std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
     515             : }
     516             : 
     517             : /// A symbol table that supports asynchoronous symbol queries.
     518             : ///
     519             : /// Represents a virtual shared object. Instances can not be copied or moved, so
     520             : /// their addresses may be used as keys for resource management.
     521             : /// VSO state changes must be made via an ExecutionSession to guarantee that
     522             : /// they are synchronized with respect to other VSO operations.
     523          92 : class VSO {
     524             :   friend class AsynchronousSymbolQuery;
     525             :   friend class ExecutionSession;
     526             :   friend class MaterializationResponsibility;
     527             : public:
     528             :   using FallbackDefinitionGeneratorFunction =
     529             :       std::function<SymbolNameSet(VSO &Parent, const SymbolNameSet &Names)>;
     530             : 
     531             :   using AsynchronousSymbolQuerySet =
     532             :       std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
     533             : 
     534             :   using MaterializationUnitList =
     535             :       std::vector<std::unique_ptr<MaterializationUnit>>;
     536             : 
     537             :   VSO(const VSO &) = delete;
     538             :   VSO &operator=(const VSO &) = delete;
     539             :   VSO(VSO &&) = delete;
     540             :   VSO &operator=(VSO &&) = delete;
     541             : 
     542             :   /// Get the name for this VSO.
     543             :   const std::string &getName() const { return VSOName; }
     544             : 
     545             :   /// Get a reference to the ExecutionSession for this VSO.
     546             :   ExecutionSessionBase &getExecutionSession() const { return ES; }
     547             : 
     548             :   /// Set a fallback defenition generator. If set, lookup and lookupFlags will
     549             :   /// pass the unresolved symbols set to the fallback definition generator,
     550             :   /// allowing it to add a new definition to the VSO.
     551             :   void setFallbackDefinitionGenerator(
     552             :       FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) {
     553           8 :     this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator);
     554             :   }
     555             : 
     556             :   /// Define all symbols provided by the materialization unit to be part
     557             :   ///        of the given VSO.
     558             :   template <typename UniquePtrToMaterializationUnit>
     559             :   typename std::enable_if<
     560             :       std::is_convertible<
     561             :           typename std::decay<UniquePtrToMaterializationUnit>::type,
     562             :           std::unique_ptr<MaterializationUnit>>::value,
     563             :       Error>::type
     564          71 :   define(UniquePtrToMaterializationUnit &&MU) {
     565         251 :     return ES.runSessionLocked([&, this]() -> Error {
     566             :       assert(MU && "Can't define with a null MU");
     567             : 
     568         283 :       if (auto Err = defineImpl(*MU))
     569             :         return Err;
     570             : 
     571             :       /// defineImpl succeeded.
     572             :       auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
     573         179 :       for (auto &KV : UMI->MU->getSymbols())
     574         218 :         UnmaterializedInfos[KV.first] = UMI;
     575             : 
     576             :       return Error::success();
     577         142 :     });
     578             :   }
     579             : 
     580             :   /// Search the given VSO for the symbols in Symbols. If found, store
     581             :   ///        the flags for each symbol in Flags. Returns any unresolved symbols.
     582             :   SymbolNameSet lookupFlags(SymbolFlagsMap &Flags, const SymbolNameSet &Names);
     583             : 
     584             :   /// Search the given VSOs in order for the symbols in Symbols. Results
     585             :   ///        (once they become available) will be returned via the given Query.
     586             :   ///
     587             :   /// If any symbol is not found then the unresolved symbols will be returned,
     588             :   /// and the query will not be applied. The Query is not failed and can be
     589             :   /// re-used in a subsequent lookup once the symbols have been added, or
     590             :   /// manually failed.
     591             :   SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
     592             :                        SymbolNameSet Names);
     593             : 
     594             :   /// Dump current VSO state to OS.
     595             :   void dump(raw_ostream &OS);
     596             : 
     597             : private:
     598             :   using AsynchronousSymbolQueryList =
     599             :       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
     600             : 
     601          87 :   struct UnmaterializedInfo {
     602             :     UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
     603             :         : MU(std::move(MU)) {}
     604             : 
     605             :     std::unique_ptr<MaterializationUnit> MU;
     606             :   };
     607             : 
     608             :   using UnmaterializedInfosMap =
     609             :       std::map<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
     610             : 
     611         261 :   struct MaterializingInfo {
     612             :     AsynchronousSymbolQueryList PendingQueries;
     613             :     SymbolDependenceMap Dependants;
     614             :     SymbolDependenceMap UnfinalizedDependencies;
     615             :     bool IsFinalized = false;
     616             :   };
     617             : 
     618             :   using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
     619             : 
     620             :   using LookupImplActionFlags = enum {
     621             :     None = 0,
     622             :     NotifyFullyResolved = 1 << 0U,
     623             :     NotifyFullyReady = 1 << 1U,
     624             :     LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
     625             :   };
     626             : 
     627          46 :   VSO(ExecutionSessionBase &ES, std::string Name)
     628          92 :       : ES(ES), VSOName(std::move(Name)) {}
     629             : 
     630             :   Error defineImpl(MaterializationUnit &MU);
     631             : 
     632             :   SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
     633             :                                 const SymbolNameSet &Names);
     634             : 
     635             :   LookupImplActionFlags
     636             :   lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     637             :              std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
     638             :              SymbolNameSet &Unresolved);
     639             : 
     640             :   void detachQueryHelper(AsynchronousSymbolQuery &Q,
     641             :                          const SymbolNameSet &QuerySymbols);
     642             : 
     643             :   void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
     644             :                                          const SymbolStringPtr &DependantName,
     645             :                                          MaterializingInfo &FinalizedMI);
     646             : 
     647             :   Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
     648             : 
     649             :   void replace(std::unique_ptr<MaterializationUnit> MU);
     650             : 
     651             :   SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
     652             : 
     653             :   void addDependencies(const SymbolFlagsMap &Dependents,
     654             :                        const SymbolDependenceMap &Dependencies);
     655             : 
     656             :   void resolve(const SymbolMap &Resolved);
     657             : 
     658             :   void finalize(const SymbolFlagsMap &Finalized);
     659             : 
     660             :   void notifyFailed(const SymbolNameSet &FailedSymbols);
     661             : 
     662             :   void runOutstandingMUs();
     663             : 
     664             :   ExecutionSessionBase &ES;
     665             :   std::string VSOName;
     666             :   SymbolMap Symbols;
     667             :   UnmaterializedInfosMap UnmaterializedInfos;
     668             :   MaterializingInfosMap MaterializingInfos;
     669             :   FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
     670             : 
     671             :   // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
     672             :   //        with callbacks from asynchronous queries.
     673             :   mutable std::recursive_mutex OutstandingMUsMutex;
     674             :   std::vector<std::unique_ptr<MaterializationUnit>> OutstandingMUs;
     675             : };
     676             : 
     677             : /// An ExecutionSession represents a running JIT program.
     678          80 : class ExecutionSession : public ExecutionSessionBase {
     679             : public:
     680             :   using ErrorReporter = std::function<void(Error)>;
     681             : 
     682             :   using DispatchMaterializationFunction =
     683             :       std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
     684             : 
     685             :   /// Construct an ExecutionEngine.
     686             :   ///
     687             :   /// SymbolStringPools may be shared between ExecutionSessions.
     688         146 :   ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr)
     689         584 :       : ExecutionSessionBase(std::move(SSP)) {}
     690             : 
     691             :   /// Add a new VSO to this ExecutionSession.
     692             :   VSO &createVSO(std::string Name);
     693             : 
     694             : private:
     695             :   std::vector<std::unique_ptr<VSO>> VSOs;
     696             : };
     697             : 
     698             : using AsynchronousLookupFunction = std::function<SymbolNameSet(
     699             :     std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
     700             : 
     701             : /// Perform a blocking lookup on the given symbols.
     702             : Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES,
     703             :                                    AsynchronousLookupFunction AsyncLookup,
     704             :                                    SymbolNameSet Names, bool WaiUntilReady,
     705             :                                    MaterializationResponsibility *MR = nullptr);
     706             : 
     707             : using VSOList = std::vector<VSO *>;
     708             : 
     709             : /// Look up the given names in the given VSOs.
     710             : /// VSOs will be searched in order and no VSO pointer may be null.
     711             : /// All symbols must be found within the given VSOs or an error
     712             : /// will be returned.
     713             : Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names);
     714             : 
     715             : /// Look up a symbol by searching a list of VSOs.
     716             : Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name);
     717             : 
     718             : /// Mangles symbol names then uniques them in the context of an
     719             : /// ExecutionSession.
     720             : class MangleAndInterner {
     721             : public:
     722             :   MangleAndInterner(ExecutionSessionBase &ES, const DataLayout &DL);
     723             :   SymbolStringPtr operator()(StringRef Name);
     724             : 
     725             : private:
     726             :   ExecutionSessionBase &ES;
     727             :   const DataLayout &DL;
     728             : };
     729             : 
     730             : } // End namespace orc
     731             : } // End namespace llvm
     732             : 
     733             : #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H

Generated by: LCOV version 1.13