LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - Core.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 83 97 85.6 %
Date: 2018-10-20 13:21:21 Functions: 24 35 68.6 %
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             : #include "llvm/Support/Debug.h"
      22             : 
      23             : #include <memory>
      24             : #include <vector>
      25             : 
      26             : #define DEBUG_TYPE "orc"
      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 JITDylib;
      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 = DenseSet<SymbolStringPtr>;
      45             : 
      46             : /// A map from symbol names (as SymbolStringPtrs) to JITSymbols
      47             : ///        (address/flags pairs).
      48             : using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
      49             : 
      50             : /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
      51             : using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
      52             : 
      53             : /// A base class for materialization failures that allows the failing
      54             : ///        symbols to be obtained for logging.
      55             : using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
      56             : 
      57             : /// A list of JITDylib pointers.
      58             : using JITDylibList = std::vector<JITDylib *>;
      59             : 
      60             : /// Render a SymbolStringPtr.
      61             : raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
      62             : 
      63             : /// Render a SymbolNameSet.
      64             : raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
      65             : 
      66             : /// Render a SymbolFlagsMap entry.
      67             : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV);
      68             : 
      69             : /// Render a SymbolMap entry.
      70             : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV);
      71             : 
      72             : /// Render a SymbolFlagsMap.
      73             : raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
      74             : 
      75             : /// Render a SymbolMap.
      76             : raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
      77             : 
      78             : /// Render a SymbolDependenceMap entry.
      79             : raw_ostream &operator<<(raw_ostream &OS,
      80             :                         const SymbolDependenceMap::value_type &KV);
      81             : 
      82             : /// Render a SymbolDependendeMap.
      83             : raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
      84             : 
      85             : /// Render a MaterializationUnit.
      86             : raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
      87             : 
      88             : /// Render a JITDylibList.
      89             : raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs);
      90             : 
      91             : /// Callback to notify client that symbols have been resolved.
      92             : using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
      93             : 
      94             : /// Callback to notify client that symbols are ready for execution.
      95             : using SymbolsReadyCallback = std::function<void(Error)>;
      96             : 
      97             : /// Callback to register the dependencies for a given query.
      98             : using RegisterDependenciesFunction =
      99             :     std::function<void(const SymbolDependenceMap &)>;
     100             : 
     101             : /// This can be used as the value for a RegisterDependenciesFunction if there
     102             : /// are no dependants to register with.
     103             : extern RegisterDependenciesFunction NoDependenciesToRegister;
     104             : 
     105             : /// Used to notify a JITDylib that the given set of symbols failed to
     106             : /// materialize.
     107             : class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
     108             : public:
     109             :   static char ID;
     110             : 
     111             :   FailedToMaterialize(SymbolNameSet Symbols);
     112             :   std::error_code convertToErrorCode() const override;
     113             :   void log(raw_ostream &OS) const override;
     114             :   const SymbolNameSet &getSymbols() const { return Symbols; }
     115             : 
     116             : private:
     117             :   SymbolNameSet Symbols;
     118             : };
     119             : 
     120             : /// Used to notify clients when symbols can not be found during a lookup.
     121             : class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
     122             : public:
     123             :   static char ID;
     124             : 
     125             :   SymbolsNotFound(SymbolNameSet Symbols);
     126             :   std::error_code convertToErrorCode() const override;
     127             :   void log(raw_ostream &OS) const override;
     128             :   const SymbolNameSet &getSymbols() const { return Symbols; }
     129             : 
     130             : private:
     131             :   SymbolNameSet Symbols;
     132             : };
     133             : 
     134             : /// Used to notify clients that a set of symbols could not be removed.
     135             : class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
     136             : public:
     137             :   static char ID;
     138             : 
     139             :   SymbolsCouldNotBeRemoved(SymbolNameSet Symbols);
     140             :   std::error_code convertToErrorCode() const override;
     141             :   void log(raw_ostream &OS) const override;
     142             :   const SymbolNameSet &getSymbols() const { return Symbols; }
     143             : 
     144             : private:
     145             :   SymbolNameSet Symbols;
     146             : };
     147             : 
     148             : /// Tracks responsibility for materialization, and mediates interactions between
     149             : /// MaterializationUnits and JDs.
     150             : ///
     151             : /// An instance of this class is passed to MaterializationUnits when their
     152             : /// materialize method is called. It allows MaterializationUnits to resolve and
     153             : /// emit symbols, or abandon materialization by notifying any unmaterialized
     154             : /// symbols of an error.
     155             : class MaterializationResponsibility {
     156             :   friend class MaterializationUnit;
     157             : public:
     158         362 :   MaterializationResponsibility(MaterializationResponsibility &&) = default;
     159             :   MaterializationResponsibility &
     160             :   operator=(MaterializationResponsibility &&) = delete;
     161             : 
     162             :   /// Destruct a MaterializationResponsibility instance. In debug mode
     163             :   ///        this asserts that all symbols being tracked have been either
     164             :   ///        emitted or notified of an error.
     165             :   ~MaterializationResponsibility();
     166             : 
     167             :   /// Returns the target JITDylib that these symbols are being materialized
     168             :   ///        into.
     169           0 :   JITDylib &getTargetJITDylib() const { return JD; }
     170             : 
     171             :   /// Returns the VModuleKey for this instance.
     172           0 :   VModuleKey getVModuleKey() const { return K; }
     173             : 
     174             :   /// Returns the symbol flags map for this responsibility instance.
     175             :   /// Note: The returned flags may have transient flags (Lazy, Materializing)
     176             :   /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
     177             :   /// before using.
     178          35 :   const SymbolFlagsMap &getSymbols() { return SymbolFlags; }
     179             : 
     180             :   /// Returns the names of any symbols covered by this
     181             :   /// MaterializationResponsibility object that have queries pending. This
     182             :   /// information can be used to return responsibility for unrequested symbols
     183             :   /// back to the JITDylib via the delegate method.
     184             :   SymbolNameSet getRequestedSymbols() const;
     185             : 
     186             :   /// Notifies the target JITDylib that the given symbols have been resolved.
     187             :   /// This will update the given symbols' addresses in the JITDylib, and notify
     188             :   /// any pending queries on the given symbols of their resolution. The given
     189             :   /// symbols must be ones covered by this MaterializationResponsibility
     190             :   /// instance. Individual calls to this method may resolve a subset of the
     191             :   /// symbols, but all symbols must have been resolved prior to calling emit.
     192             :   void resolve(const SymbolMap &Symbols);
     193             : 
     194             :   /// Notifies the target JITDylib (and any pending queries on that JITDylib)
     195             :   /// that all symbols covered by this MaterializationResponsibility instance
     196             :   /// have been emitted.
     197             :   void emit();
     198             : 
     199             :   /// Adds new symbols to the JITDylib and this responsibility instance.
     200             :   ///        JITDylib entries start out in the materializing state.
     201             :   ///
     202             :   ///   This method can be used by materialization units that want to add
     203             :   /// additional symbols at materialization time (e.g. stubs, compile
     204             :   /// callbacks, metadata).
     205             :   Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
     206             : 
     207             :   /// Notify all not-yet-emitted covered by this MaterializationResponsibility
     208             :   /// instance that an error has occurred.
     209             :   /// This will remove all symbols covered by this MaterializationResponsibilty
     210             :   /// from the target JITDylib, and send an error to any queries waiting on
     211             :   /// these symbols.
     212             :   void failMaterialization();
     213             : 
     214             :   /// Transfers responsibility to the given MaterializationUnit for all
     215             :   /// symbols defined by that MaterializationUnit. This allows
     216             :   /// materializers to break up work based on run-time information (e.g.
     217             :   /// by introspecting which symbols have actually been looked up and
     218             :   /// materializing only those).
     219             :   void replace(std::unique_ptr<MaterializationUnit> MU);
     220             : 
     221             :   /// Delegates responsibility for the given symbols to the returned
     222             :   /// materialization responsibility. Useful for breaking up work between
     223             :   /// threads, or different kinds of materialization processes.
     224             :   MaterializationResponsibility delegate(const SymbolNameSet &Symbols,
     225             :                                          VModuleKey NewKey = VModuleKey());
     226             : 
     227             :   void addDependencies(const SymbolStringPtr &Name,
     228             :                        const SymbolDependenceMap &Dependencies);
     229             : 
     230             :   /// Add dependencies that apply to all symbols covered by this instance.
     231             :   void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
     232             : 
     233             : private:
     234             :   /// Create a MaterializationResponsibility for the given JITDylib and
     235             :   ///        initial symbols.
     236             :   MaterializationResponsibility(JITDylib &JD, SymbolFlagsMap SymbolFlags,
     237             :                                 VModuleKey K);
     238             : 
     239             :   JITDylib &JD;
     240             :   SymbolFlagsMap SymbolFlags;
     241             :   VModuleKey K;
     242             : };
     243             : 
     244             : /// A MaterializationUnit represents a set of symbol definitions that can
     245             : ///        be materialized as a group, or individually discarded (when
     246             : ///        overriding definitions are encountered).
     247             : ///
     248             : /// MaterializationUnits are used when providing lazy definitions of symbols to
     249             : /// JITDylibs. The JITDylib will call materialize when the address of a symbol
     250             : /// is requested via the lookup method. The JITDylib will call discard if a
     251             : /// stronger definition is added or already present.
     252             : class MaterializationUnit {
     253             : public:
     254             :   MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, VModuleKey K)
     255         314 :       : SymbolFlags(std::move(InitalSymbolFlags)), K(std::move(K)) {}
     256             : 
     257          22 :   virtual ~MaterializationUnit() {}
     258             : 
     259             :   /// Return the name of this materialization unit. Useful for debugging
     260             :   /// output.
     261             :   virtual StringRef getName() const = 0;
     262             : 
     263             :   /// Return the set of symbols that this source provides.
     264         251 :   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
     265             : 
     266             :   /// Called by materialization dispatchers (see
     267             :   /// ExecutionSession::DispatchMaterializationFunction) to trigger
     268             :   /// materialization of this MaterializationUnit.
     269         107 :   void doMaterialize(JITDylib &JD) {
     270         107 :     materialize(MaterializationResponsibility(JD, std::move(SymbolFlags),
     271         107 :                                               std::move(K)));
     272         107 :   }
     273             : 
     274             :   /// Called by JITDylibs to notify MaterializationUnits that the given symbol
     275             :   /// has been overridden.
     276             :   void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
     277           7 :     SymbolFlags.erase(Name);
     278           7 :     discard(JD, std::move(Name));
     279             :   }
     280             : 
     281             : protected:
     282             :   SymbolFlagsMap SymbolFlags;
     283             :   VModuleKey K;
     284             : 
     285             : private:
     286             :   virtual void anchor();
     287             : 
     288             :   /// Implementations of this method should materialize all symbols
     289             :   ///        in the materialzation unit, except for those that have been
     290             :   ///        previously discarded.
     291             :   virtual void materialize(MaterializationResponsibility R) = 0;
     292             : 
     293             :   /// Implementations of this method should discard the given symbol
     294             :   ///        from the source (e.g. if the source is an LLVM IR Module and the
     295             :   ///        symbol is a function, delete the function body or mark it available
     296             :   ///        externally).
     297             :   virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
     298             : };
     299             : 
     300             : using MaterializationUnitList =
     301             :     std::vector<std::unique_ptr<MaterializationUnit>>;
     302             : 
     303             : /// A MaterializationUnit implementation for pre-existing absolute symbols.
     304             : ///
     305             : /// All symbols will be resolved and marked ready as soon as the unit is
     306             : /// materialized.
     307             : class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
     308             : public:
     309             :   AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K);
     310             : 
     311             :   StringRef getName() const override;
     312             : 
     313             : private:
     314             :   void materialize(MaterializationResponsibility R) override;
     315             :   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
     316             :   static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
     317             : 
     318             :   SymbolMap Symbols;
     319             : };
     320             : 
     321             : /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
     322             : /// Useful for inserting absolute symbols into a JITDylib. E.g.:
     323             : /// \code{.cpp}
     324             : ///   JITDylib &JD = ...;
     325             : ///   SymbolStringPtr Foo = ...;
     326             : ///   JITEvaluatedSymbol FooSym = ...;
     327             : ///   if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
     328             : ///     return Err;
     329             : /// \endcode
     330             : ///
     331             : inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
     332             : absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) {
     333             :   return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
     334          33 :       std::move(Symbols), std::move(K));
     335             : }
     336             : 
     337         117 : struct SymbolAliasMapEntry {
     338             :   SymbolAliasMapEntry() = default;
     339             :   SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
     340          14 :       : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
     341             : 
     342             :   SymbolStringPtr Aliasee;
     343             :   JITSymbolFlags AliasFlags;
     344             : };
     345             : 
     346             : /// A map of Symbols to (Symbol, Flags) pairs.
     347             : using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
     348             : 
     349             : /// A materialization unit for symbol aliases. Allows existing symbols to be
     350             : /// aliased with alternate flags.
     351             : class ReExportsMaterializationUnit : public MaterializationUnit {
     352             : public:
     353             :   /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
     354             :   /// taken to be whatever JITDylib these definitions are materialized in. This
     355             :   /// is useful for defining aliases within a JITDylib.
     356             :   ///
     357             :   /// Note: Care must be taken that no sets of aliases form a cycle, as such
     358             :   ///       a cycle will result in a deadlock when any symbol in the cycle is
     359             :   ///       resolved.
     360             :   ReExportsMaterializationUnit(JITDylib *SourceJD, SymbolAliasMap Aliases,
     361             :                                VModuleKey K);
     362             : 
     363             :   StringRef getName() const override;
     364             : 
     365             : private:
     366             :   void materialize(MaterializationResponsibility R) override;
     367             :   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
     368             :   static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
     369             : 
     370             :   JITDylib *SourceJD = nullptr;
     371             :   SymbolAliasMap Aliases;
     372             : };
     373             : 
     374             : /// Create a ReExportsMaterializationUnit with the given aliases.
     375             : /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
     376             : /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
     377             : /// (for "bar") with: \code{.cpp}
     378             : ///   SymbolStringPtr Baz = ...;
     379             : ///   SymbolStringPtr Qux = ...;
     380             : ///   if (auto Err = JD.define(symbolAliases({
     381             : ///       {Baz, { Foo, JITSymbolFlags::Exported }},
     382             : ///       {Qux, { Bar, JITSymbolFlags::Weak }}}))
     383             : ///     return Err;
     384             : /// \endcode
     385             : inline std::unique_ptr<ReExportsMaterializationUnit>
     386             : symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
     387             :   return llvm::make_unique<ReExportsMaterializationUnit>(
     388           2 :       nullptr, std::move(Aliases), std::move(K));
     389             : }
     390             : 
     391             : /// Create a materialization unit for re-exporting symbols from another JITDylib
     392             : /// with alternative names/flags.
     393             : inline std::unique_ptr<ReExportsMaterializationUnit>
     394             : reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
     395             :           VModuleKey K = VModuleKey()) {
     396             :   return llvm::make_unique<ReExportsMaterializationUnit>(
     397          18 :       &SourceJD, std::move(Aliases), std::move(K));
     398             : }
     399             : 
     400             : /// Build a SymbolAliasMap for the common case where you want to re-export
     401             : /// symbols from another JITDylib with the same linkage/flags.
     402             : Expected<SymbolAliasMap>
     403             : buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
     404             : 
     405             : /// ReexportsGenerator can be used with JITDylib::setGenerator to automatically
     406             : /// re-export a subset of the source JITDylib's symbols in the target.
     407           0 : class ReexportsGenerator {
     408             : public:
     409             :   using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
     410             : 
     411             :   /// Create a reexports generator. If an Allow predicate is passed, only
     412             :   /// symbols for which the predicate returns true will be reexported. If no
     413             :   /// Allow predicate is passed, all symbols will be exported.
     414             :   ReexportsGenerator(JITDylib &SourceJD,
     415             :                      SymbolPredicate Allow = SymbolPredicate());
     416             : 
     417             :   SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
     418             : 
     419             : private:
     420             :   JITDylib &SourceJD;
     421             :   SymbolPredicate Allow;
     422             : };
     423             : 
     424             : /// A symbol query that returns results via a callback when results are
     425             : ///        ready.
     426             : ///
     427             : /// makes a callback when all symbols are available.
     428             : class AsynchronousSymbolQuery {
     429             :   friend class ExecutionSession;
     430             :   friend class JITDylib;
     431             :   friend class JITSymbolResolverAdapter;
     432             : 
     433             : public:
     434             : 
     435             :   /// Create a query for the given symbols, notify-resolved and
     436             :   ///        notify-ready callbacks.
     437             :   AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
     438             :                           SymbolsResolvedCallback NotifySymbolsResolved,
     439             :                           SymbolsReadyCallback NotifySymbolsReady);
     440             : 
     441             :   /// Set the resolved symbol information for the given symbol name.
     442             :   void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
     443             : 
     444             :   /// Returns true if all symbols covered by this query have been
     445             :   ///        resolved.
     446           0 :   bool isFullyResolved() const { return NotYetResolvedCount == 0; }
     447             : 
     448             :   /// Call the NotifySymbolsResolved callback.
     449             :   ///
     450             :   /// This should only be called if all symbols covered by the query have been
     451             :   /// resolved.
     452             :   void handleFullyResolved();
     453             : 
     454             :   /// Notify the query that a requested symbol is ready for execution.
     455             :   void notifySymbolReady();
     456             : 
     457             :   /// Returns true if all symbols covered by this query are ready.
     458           0 :   bool isFullyReady() const { return NotYetReadyCount == 0; }
     459             : 
     460             :   /// Calls the NotifySymbolsReady callback.
     461             :   ///
     462             :   /// This should only be called if all symbols covered by this query are ready.
     463             :   void handleFullyReady();
     464             : 
     465             : private:
     466             :   void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
     467             : 
     468             :   void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
     469             : 
     470             :   bool canStillFail();
     471             : 
     472             :   void handleFailed(Error Err);
     473             : 
     474             :   void detach();
     475             : 
     476             :   SymbolsResolvedCallback NotifySymbolsResolved;
     477             :   SymbolsReadyCallback NotifySymbolsReady;
     478             :   SymbolDependenceMap QueryRegistrations;
     479             :   SymbolMap ResolvedSymbols;
     480             :   size_t NotYetResolvedCount;
     481             :   size_t NotYetReadyCount;
     482             : };
     483             : 
     484             : /// A symbol table that supports asynchoronous symbol queries.
     485             : ///
     486             : /// Represents a virtual shared object. Instances can not be copied or moved, so
     487             : /// their addresses may be used as keys for resource management.
     488             : /// JITDylib state changes must be made via an ExecutionSession to guarantee
     489             : /// that they are synchronized with respect to other JITDylib operations.
     490             : class JITDylib {
     491             :   friend class AsynchronousSymbolQuery;
     492             :   friend class ExecutionSession;
     493             :   friend class MaterializationResponsibility;
     494             : public:
     495             :   using GeneratorFunction = std::function<SymbolNameSet(
     496             :       JITDylib &Parent, const SymbolNameSet &Names)>;
     497             : 
     498             :   using AsynchronousSymbolQuerySet =
     499             :     std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
     500             : 
     501             :   JITDylib(const JITDylib &) = delete;
     502             :   JITDylib &operator=(const JITDylib &) = delete;
     503             :   JITDylib(JITDylib &&) = delete;
     504             :   JITDylib &operator=(JITDylib &&) = delete;
     505             : 
     506             :   /// Get the name for this JITDylib.
     507          12 :   const std::string &getName() const { return JITDylibName; }
     508             : 
     509             :   /// Get a reference to the ExecutionSession for this JITDylib.
     510           0 :   ExecutionSession &getExecutionSession() const { return ES; }
     511             : 
     512             :   /// Set a definition generator. If set, whenever a symbol fails to resolve
     513             :   /// within this JITDylib, lookup and lookupFlags will pass the unresolved
     514             :   /// symbols set to the definition generator. The generator can optionally
     515             :   /// add a definition for the unresolved symbols to the dylib.
     516             :   void setGenerator(GeneratorFunction DefGenerator) {
     517          15 :     this->DefGenerator = std::move(DefGenerator);
     518             :   }
     519             : 
     520             :   /// Set the search order to be used when fixing up definitions in JITDylib.
     521             :   /// This will replace the previous search order, and apply to any symbol
     522             :   /// resolutions made for definitions in this JITDylib after the call to
     523             :   /// setSearchOrder (even if the definition itself was added before the
     524             :   /// call).
     525             :   ///
     526             :   /// If SearchThisJITDylibFirst is set, which by default it is, then this
     527             :   /// JITDylib will add itself to the beginning of the SearchOrder (Clients
     528             :   /// should *not* put this JITDylib in the list in this case, to avoid
     529             :   /// redundant lookups).
     530             :   ///
     531             :   /// If SearchThisJITDylibFirst is false then the search order will be used as
     532             :   /// given. The main motivation for this feature is to support deliberate
     533             :   /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
     534             :   /// the facade may resolve function names to stubs, and the stubs may compile
     535             :   /// lazily by looking up symbols in this dylib. Adding the facade dylib
     536             :   /// as the first in the search order (instead of this dylib) ensures that
     537             :   /// definitions within this dylib resolve to the lazy-compiling stubs,
     538             :   /// rather than immediately materializing the definitions in this dylib.
     539             :   void setSearchOrder(JITDylibList NewSearchOrder,
     540             :                       bool SearchThisJITDylibFirst = true);
     541             : 
     542             :   /// Add the given JITDylib to the search order for definitions in this
     543             :   /// JITDylib.
     544             :   void addToSearchOrder(JITDylib &JD);
     545             : 
     546             :   /// Replace OldJD with NewJD in the search order if OldJD is present.
     547             :   /// Otherwise this operation is a no-op.
     548             :   void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD);
     549             : 
     550             :   /// Remove the given JITDylib from the search order for this JITDylib if it is
     551             :   /// present. Otherwise this operation is a no-op.
     552             :   void removeFromSearchOrder(JITDylib &JD);
     553             : 
     554             :   /// Do something with the search order (run under the session lock).
     555             :   template <typename Func>
     556             :   auto withSearchOrderDo(Func &&F)
     557             :       -> decltype(F(std::declval<const JITDylibList &>()));
     558             : 
     559             :   /// Define all symbols provided by the materialization unit to be part of this
     560             :   /// JITDylib.
     561             :   ///
     562             :   /// This overload always takes ownership of the MaterializationUnit. If any
     563             :   /// errors occur, the MaterializationUnit consumed.
     564             :   template <typename MaterializationUnitType>
     565             :   Error define(std::unique_ptr<MaterializationUnitType> &&MU);
     566             : 
     567             :   /// Define all symbols provided by the materialization unit to be part of this
     568             :   /// JITDylib.
     569             :   ///
     570             :   /// This overload only takes ownership of the MaterializationUnit no error is
     571             :   /// generated. If an error occurs, ownership remains with the caller. This
     572             :   /// may allow the caller to modify the MaterializationUnit to correct the
     573             :   /// issue, then re-call define.
     574             :   template <typename MaterializationUnitType>
     575             :   Error define(std::unique_ptr<MaterializationUnitType> &MU);
     576             : 
     577             :   /// Tries to remove the given symbols.
     578             :   ///
     579             :   /// If any symbols are not defined in this JITDylib this method will return
     580             :   /// a SymbolsNotFound error covering the missing symbols.
     581             :   ///
     582             :   /// If all symbols are found but some symbols are in the process of being
     583             :   /// materialized this method will return a SymbolsCouldNotBeRemoved error.
     584             :   ///
     585             :   /// On success, all symbols are removed. On failure, the JITDylib state is
     586             :   /// left unmodified (no symbols are removed).
     587             :   Error remove(const SymbolNameSet &Names);
     588             : 
     589             :   /// Search the given JITDylib for the symbols in Symbols. If found, store
     590             :   ///        the flags for each symbol in Flags. Returns any unresolved symbols.
     591             :   SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
     592             : 
     593             :   /// Dump current JITDylib state to OS.
     594             :   void dump(raw_ostream &OS);
     595             : 
     596             :   /// FIXME: Remove this when we remove the old ORC layers.
     597             :   /// Search the given JITDylibs in order for the symbols in Symbols. Results
     598             :   ///        (once they become available) will be returned via the given Query.
     599             :   ///
     600             :   /// If any symbol is not found then the unresolved symbols will be returned,
     601             :   /// and the query will not be applied. The Query is not failed and can be
     602             :   /// re-used in a subsequent lookup once the symbols have been added, or
     603             :   /// manually failed.
     604             :   SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
     605             :                              SymbolNameSet Names);
     606             : 
     607             : private:
     608             :   using AsynchronousSymbolQueryList =
     609             :       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
     610             : 
     611         141 :   struct UnmaterializedInfo {
     612             :     UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
     613             :         : MU(std::move(MU)) {}
     614             : 
     615             :     std::unique_ptr<MaterializationUnit> MU;
     616             :   };
     617             : 
     618             :   using UnmaterializedInfosMap =
     619             :       DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
     620             : 
     621             :   struct MaterializingInfo {
     622             :     AsynchronousSymbolQueryList PendingQueries;
     623             :     SymbolDependenceMap Dependants;
     624             :     SymbolDependenceMap UnemittedDependencies;
     625             :     bool IsEmitted = false;
     626             :   };
     627             : 
     628             :   using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
     629             : 
     630             :   using LookupImplActionFlags = enum {
     631             :     None = 0,
     632             :     NotifyFullyResolved = 1 << 0U,
     633             :     NotifyFullyReady = 1 << 1U,
     634             :     LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
     635             :   };
     636             : 
     637             :   JITDylib(ExecutionSession &ES, std::string Name);
     638             : 
     639             :   Error defineImpl(MaterializationUnit &MU);
     640             : 
     641             :   SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
     642             :                                 const SymbolNameSet &Names);
     643             : 
     644             :   void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     645             :                   SymbolNameSet &Unresolved, JITDylib *MatchNonExportedInJD,
     646             :                   bool MatchNonExported, MaterializationUnitList &MUs);
     647             : 
     648             :   void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     649             :                       SymbolNameSet &Unresolved, JITDylib *MatchNonExportedInJD,
     650             :                       bool MatchNonExported, MaterializationUnitList &MUs);
     651             : 
     652             :   LookupImplActionFlags
     653             :   lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     654             :              std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
     655             :              SymbolNameSet &Unresolved);
     656             : 
     657             :   void detachQueryHelper(AsynchronousSymbolQuery &Q,
     658             :                          const SymbolNameSet &QuerySymbols);
     659             : 
     660             :   void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
     661             :                                        const SymbolStringPtr &DependantName,
     662             :                                        MaterializingInfo &EmittedMI);
     663             : 
     664             :   Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
     665             : 
     666             :   void replace(std::unique_ptr<MaterializationUnit> MU);
     667             : 
     668             :   SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
     669             : 
     670             :   void addDependencies(const SymbolStringPtr &Name,
     671             :                        const SymbolDependenceMap &Dependants);
     672             : 
     673             :   void resolve(const SymbolMap &Resolved);
     674             : 
     675             :   void emit(const SymbolFlagsMap &Emitted);
     676             : 
     677             :   void notifyFailed(const SymbolNameSet &FailedSymbols);
     678             : 
     679             :   ExecutionSession &ES;
     680             :   std::string JITDylibName;
     681             :   SymbolMap Symbols;
     682             :   UnmaterializedInfosMap UnmaterializedInfos;
     683             :   MaterializingInfosMap MaterializingInfos;
     684             :   GeneratorFunction DefGenerator;
     685             :   JITDylibList SearchOrder;
     686             : };
     687             : 
     688             : /// An ExecutionSession represents a running JIT program.
     689             : class ExecutionSession {
     690             :   // FIXME: Remove this when we remove the old ORC layers.
     691             :   friend class JITDylib;
     692             : 
     693             : public:
     694             :   /// For reporting errors.
     695             :   using ErrorReporter = std::function<void(Error)>;
     696             : 
     697             :   /// For dispatching MaterializationUnit::materialize calls.
     698             :   using DispatchMaterializationFunction = std::function<void(
     699             :       JITDylib &JD, std::unique_ptr<MaterializationUnit> MU)>;
     700             : 
     701             :   /// Construct an ExecutionSession.
     702             :   ///
     703             :   /// SymbolStringPools may be shared between ExecutionSessions.
     704             :   ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
     705             : 
     706             :   /// Add a symbol name to the SymbolStringPool and return a pointer to it.
     707         319 :   SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
     708             : 
     709             :   /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
     710             :   std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
     711             : 
     712             :   /// Run the given lambda with the session mutex locked.
     713         420 :   template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
     714         807 :     std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
     715         691 :     return F();
     716             :   }
     717           0 : 
     718           0 :   /// Get the "main" JITDylib, which is created automatically on construction of
     719           0 :   /// the ExecutionSession.
     720             :   JITDylib &getMainJITDylib();
     721           1 : 
     722           1 :   /// Add a new JITDylib to this ExecutionSession.
     723           1 :   JITDylib &createJITDylib(std::string Name,
     724             :                            bool AddToMainDylibSearchOrder = true);
     725           0 : 
     726           0 :   /// Allocate a module key for a new module to add to the JIT.
     727           0 :   VModuleKey allocateVModule() {
     728         131 :     return runSessionLocked([this]() { return ++LastKey; });
     729           4 :   }
     730           4 : 
     731           4 :   /// Return a module key to the ExecutionSession so that it can be
     732             :   ///        re-used. This should only be done once all resources associated
     733           3 :   ///        with the original key have been released.
     734           3 :   void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
     735           3 :   }
     736             : 
     737           0 :   /// Set the error reporter function.
     738           0 :   ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
     739          24 :     this->ReportError = std::move(ReportError);
     740             :     return *this;
     741          61 :   }
     742          61 : 
     743          61 :   /// Report a error for this execution session.
     744             :   ///
     745          12 :   /// Unhandled errors can be sent here to log them.
     746          66 :   void reportError(Error Err) { ReportError(std::move(Err)); }
     747          12 : 
     748             :   /// Set the materialization dispatch function.
     749           1 :   ExecutionSession &setDispatchMaterialization(
     750           1 :       DispatchMaterializationFunction DispatchMaterialization) {
     751           4 :     this->DispatchMaterialization = std::move(DispatchMaterialization);
     752             :     return *this;
     753          95 :   }
     754          95 : 
     755          95 :   void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
     756             : 
     757          95 :   using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
     758          95 :       std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
     759          95 : 
     760             :   /// A legacy lookup function for JITSymbolResolverAdapter.
     761          52 :   /// Do not use -- this will be removed soon.
     762          52 :   Expected<SymbolMap>
     763          52 :   legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
     764             :                bool WaiUntilReady,
     765          61 :                RegisterDependenciesFunction RegisterDependencies);
     766          61 : 
     767          61 :   /// Search the given JITDylib list for the given symbols.
     768             :   ///
     769           7 :   ///
     770           7 :   /// The OnResolve callback will be called once all requested symbols are
     771           7 :   /// resolved, or if an error occurs prior to resolution.
     772             :   ///
     773             :   /// The OnReady callback will be called once all requested symbols are ready,
     774             :   /// or if an error occurs after resolution but before all symbols are ready.
     775             :   ///
     776             :   /// If all symbols are found, the RegisterDependencies function will be called
     777             :   /// while the session lock is held. This gives clients a chance to register
     778             :   /// dependencies for on the queried symbols for any symbols they are
     779             :   /// materializing (if a MaterializationResponsibility instance is present,
     780             :   /// this can be implemented by calling
     781             :   /// MaterializationResponsibility::addDependencies). If there are no
     782             :   /// dependenant symbols for this query (e.g. it is being made by a top level
     783             :   /// client to get an address to call) then the value NoDependenciesToRegister
     784             :   /// can be used.
     785             :   ///
     786             :   /// If the MatchNonExportedInJD pointer is non-null, then the lookup will find
     787             :   /// non-exported symbols defined in the JITDylib pointed to by
     788             :   /// MatchNonExportedInJD.
     789             :   /// If MatchNonExported is true the lookup will find non-exported symbols in
     790             :   /// any JITDylib (setting MatchNonExportedInJD is redundant in such cases).
     791             :   /// If MatchNonExported is false and MatchNonExportedInJD is null,
     792             :   /// non-exported symbols will never be found.
     793             :   void lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
     794             :               SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
     795             :               RegisterDependenciesFunction RegisterDependencies,
     796             :               JITDylib *MatchNonExportedInJD = nullptr,
     797             :               bool MatchNonExported = false);
     798             : 
     799             :   /// Blocking version of lookup above. Returns the resolved symbol map.
     800             :   /// If WaitUntilReady is true (the default), will not return until all
     801             :   /// requested symbols are ready (or an error occurs). If WaitUntilReady is
     802           9 :   /// false, will return as soon as all requested symbols are resolved,
     803             :   /// or an error occurs. If WaitUntilReady is false and an error occurs
     804             :   /// after resolution, the function will return a success value, but the
     805             :   /// error will be reported via reportErrors.
     806             :   Expected<SymbolMap> lookup(const JITDylibList &JDs,
     807             :                              const SymbolNameSet &Symbols,
     808             :                              RegisterDependenciesFunction RegisterDependencies =
     809             :                                  NoDependenciesToRegister,
     810             :                              bool WaitUntilReady = true,
     811             :                              JITDylib *MatchNonExportedInJD = nullptr,
     812             :                              bool MatchNonExported = false);
     813             : 
     814             :   /// Convenience version of blocking lookup.
     815             :   /// Performs a single-symbol lookup.
     816             :   Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs,
     817             :                                       SymbolStringPtr Symbol,
     818             :                                       bool MatchNonExported = false);
     819             : 
     820             :   /// Convenience version of blocking lookup.
     821             :   /// Performs a single-symbol lookup, auto-interning the given symbol name.
     822             :   Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs, StringRef Symbol,
     823             :                                       bool MatchNonExported = false);
     824             : 
     825             :   /// Materialize the given unit.
     826             :   void dispatchMaterialization(JITDylib &JD,
     827             :                                std::unique_ptr<MaterializationUnit> MU) {
     828             :     LLVM_DEBUG(runSessionLocked([&]() {
     829             :                  dbgs() << "Compiling, for " << JD.getName() << ", " << *MU
     830             :                         << "\n";
     831             :                }););
     832             :     DispatchMaterialization(JD, std::move(MU));
     833             :   }
     834             : 
     835             :   /// Dump the state of all the JITDylibs in this session.
     836             :   void dump(raw_ostream &OS);
     837             : 
     838             : private:
     839             :   static void logErrorsToStdErr(Error Err) {
     840             :     logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
     841             :   }
     842             : 
     843             :   static void
     844             :   materializeOnCurrentThread(JITDylib &JD,
     845             :                              std::unique_ptr<MaterializationUnit> MU) {
     846             :     MU->doMaterialize(JD);
     847             :   }
     848             : 
     849             :   void runOutstandingMUs();
     850             : 
     851             :   mutable std::recursive_mutex SessionMutex;
     852             :   std::shared_ptr<SymbolStringPool> SSP;
     853             :   VModuleKey LastKey = 0;
     854             :   ErrorReporter ReportError = logErrorsToStdErr;
     855             :   DispatchMaterializationFunction DispatchMaterialization =
     856             :       materializeOnCurrentThread;
     857             : 
     858             :   std::vector<std::unique_ptr<JITDylib>> JDs;
     859             : 
     860             :   // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
     861             :   //        with callbacks from asynchronous queries.
     862             :   mutable std::recursive_mutex OutstandingMUsMutex;
     863             :   std::vector<std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>>>
     864             :       OutstandingMUs;
     865             : };
     866             : 
     867             : template <typename Func>
     868             : auto JITDylib::withSearchOrderDo(Func &&F)
     869             :     -> decltype(F(std::declval<const JITDylibList &>())) {
     870          52 :   return ES.runSessionLocked([&]() { return F(SearchOrder); });
     871             : }
     872             : 
     873             : template <typename MaterializationUnitType>
     874          77 : Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
     875             :   assert(MU && "Can not define with a null MU");
     876          79 :   return ES.runSessionLocked([&, this]() -> Error {
     877             :     if (auto Err = defineImpl(*MU))
     878             :       return Err;
     879             : 
     880             :     /// defineImpl succeeded.
     881             :     auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
     882         107 :     for (auto &KV : UMI->MU->getSymbols())
     883             :       UnmaterializedInfos[KV.first] = UMI;
     884             : 
     885             :     return Error::success();
     886          79 :   });
     887             : }
     888         111 : 
     889         107 : template <typename MaterializationUnitType>
     890           4 : Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
     891             :   assert(MU && "Can not define with a null MU");
     892             : 
     893             :   return ES.runSessionLocked([&, this]() -> Error {
     894             :     if (auto Err = defineImpl(*MU))
     895          63 :       return Err;
     896          63 : 
     897          63 :     /// defineImpl succeeded.
     898             :     auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
     899             :     for (auto &KV : UMI->MU->getSymbols())
     900         102 :       UnmaterializedInfos[KV.first] = UMI;
     901             : 
     902         116 :     return Error::success();
     903          98 :   });
     904          18 : }
     905             : 
     906             : /// Mangles symbol names then uniques them in the context of an
     907             : /// ExecutionSession.
     908             : class MangleAndInterner {
     909             : public:
     910             :   MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
     911             :   SymbolStringPtr operator()(StringRef Name);
     912             : 
     913             : private:
     914          18 :   ExecutionSession &ES;
     915             :   const DataLayout &DL;
     916           5 : };
     917             : 
     918           5 : } // End namespace orc
     919             : } // End namespace llvm
     920             : 
     921             : #undef DEBUG_TYPE // "orc"
     922             : 
     923             : #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H

Generated by: LCOV version 1.13