Home | History | Annotate | Line # | Download | only in Orc
      1 //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // Contains core ORC APIs.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
     14 #define LLVM_EXECUTIONENGINE_ORC_CORE_H
     15 
     16 #include "llvm/ADT/BitmaskEnum.h"
     17 #include "llvm/ADT/DenseSet.h"
     18 #include "llvm/ADT/FunctionExtras.h"
     19 #include "llvm/ADT/IntrusiveRefCntPtr.h"
     20 #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
     21 #include "llvm/ExecutionEngine/JITSymbol.h"
     22 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
     23 #include "llvm/ExecutionEngine/OrcV1Deprecation.h"
     24 #include "llvm/Support/Debug.h"
     25 #include "llvm/Support/ExtensibleRTTI.h"
     26 
     27 #include <atomic>
     28 #include <memory>
     29 #include <vector>
     30 
     31 namespace llvm {
     32 namespace orc {
     33 
     34 // Forward declare some classes.
     35 class AsynchronousSymbolQuery;
     36 class ExecutionSession;
     37 class MaterializationUnit;
     38 class MaterializationResponsibility;
     39 class JITDylib;
     40 class ResourceTracker;
     41 class InProgressLookupState;
     42 
     43 enum class SymbolState : uint8_t;
     44 
     45 using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
     46 using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
     47 
     48 using ResourceKey = uintptr_t;
     49 
     50 /// API to remove / transfer ownership of JIT resources.
     51 class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
     52 private:
     53   friend class ExecutionSession;
     54   friend class JITDylib;
     55   friend class MaterializationResponsibility;
     56 
     57 public:
     58   ResourceTracker(const ResourceTracker &) = delete;
     59   ResourceTracker &operator=(const ResourceTracker &) = delete;
     60   ResourceTracker(ResourceTracker &&) = delete;
     61   ResourceTracker &operator=(ResourceTracker &&) = delete;
     62 
     63   ~ResourceTracker();
     64 
     65   /// Return the JITDylib targeted by this tracker.
     66   JITDylib &getJITDylib() const {
     67     return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
     68                                          ~static_cast<uintptr_t>(1));
     69   }
     70 
     71   /// Remove all resources associated with this key.
     72   Error remove();
     73 
     74   /// Transfer all resources associated with this key to the given
     75   /// tracker, which must target the same JITDylib as this one.
     76   void transferTo(ResourceTracker &DstRT);
     77 
     78   /// Return true if this tracker has become defunct.
     79   bool isDefunct() const { return JDAndFlag.load() & 0x1; }
     80 
     81   /// Returns the key associated with this tracker.
     82   /// This method should not be used except for debug logging: there is no
     83   /// guarantee that the returned value will remain valid.
     84   ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
     85 
     86 private:
     87   ResourceTracker(JITDylibSP JD);
     88 
     89   void makeDefunct();
     90 
     91   std::atomic_uintptr_t JDAndFlag;
     92 };
     93 
     94 /// Listens for ResourceTracker operations.
     95 class ResourceManager {
     96 public:
     97   virtual ~ResourceManager();
     98   virtual Error handleRemoveResources(ResourceKey K) = 0;
     99   virtual void handleTransferResources(ResourceKey DstK, ResourceKey SrcK) = 0;
    100 };
    101 
    102 /// A set of symbol names (represented by SymbolStringPtrs for
    103 //         efficiency).
    104 using SymbolNameSet = DenseSet<SymbolStringPtr>;
    105 
    106 /// A vector of symbol names.
    107 using SymbolNameVector = std::vector<SymbolStringPtr>;
    108 
    109 /// A map from symbol names (as SymbolStringPtrs) to JITSymbols
    110 /// (address/flags pairs).
    111 using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
    112 
    113 /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
    114 using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
    115 
    116 /// A map from JITDylibs to sets of symbols.
    117 using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
    118 
    119 /// Lookup flags that apply to each dylib in the search order for a lookup.
    120 ///
    121 /// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
    122 /// only symbols in that Dylib's interface will be searched. If
    123 /// MatchHiddenSymbols is used then symbols with hidden visibility will match
    124 /// as well.
    125 enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
    126 
    127 /// Lookup flags that apply to each symbol in a lookup.
    128 ///
    129 /// If RequiredSymbol is used (the default) for a given symbol then that symbol
    130 /// must be found during the lookup or the lookup will fail returning a
    131 /// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
    132 /// symbol is not found then the query will continue, and no result for the
    133 /// missing symbol will be present in the result (assuming the rest of the
    134 /// lookup succeeds).
    135 enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
    136 
    137 /// Describes the kind of lookup being performed. The lookup kind is passed to
    138 /// symbol generators (if they're invoked) to help them determine what
    139 /// definitions to generate.
    140 ///
    141 /// Static -- Lookup is being performed as-if at static link time (e.g.
    142 ///           generators representing static archives should pull in new
    143 ///           definitions).
    144 ///
    145 /// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
    146 ///          representing static archives should not pull in new definitions).
    147 enum class LookupKind { Static, DLSym };
    148 
    149 /// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
    150 /// order during symbol lookup.
    151 using JITDylibSearchOrder =
    152     std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
    153 
    154 /// Convenience function for creating a search order from an ArrayRef of
    155 /// JITDylib*, all with the same flags.
    156 inline JITDylibSearchOrder makeJITDylibSearchOrder(
    157     ArrayRef<JITDylib *> JDs,
    158     JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
    159   JITDylibSearchOrder O;
    160   O.reserve(JDs.size());
    161   for (auto *JD : JDs)
    162     O.push_back(std::make_pair(JD, Flags));
    163   return O;
    164 }
    165 
    166 /// A set of symbols to look up, each associated with a SymbolLookupFlags
    167 /// value.
    168 ///
    169 /// This class is backed by a vector and optimized for fast insertion,
    170 /// deletion and iteration. It does not guarantee a stable order between
    171 /// operations, and will not automatically detect duplicate elements (they
    172 /// can be manually checked by calling the validate method).
    173 class SymbolLookupSet {
    174 public:
    175   using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
    176   using UnderlyingVector = std::vector<value_type>;
    177   using iterator = UnderlyingVector::iterator;
    178   using const_iterator = UnderlyingVector::const_iterator;
    179 
    180   SymbolLookupSet() = default;
    181 
    182   explicit SymbolLookupSet(
    183       SymbolStringPtr Name,
    184       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
    185     add(std::move(Name), Flags);
    186   }
    187 
    188   /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
    189   explicit SymbolLookupSet(
    190       std::initializer_list<SymbolStringPtr> Names,
    191       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
    192     Symbols.reserve(Names.size());
    193     for (auto &Name : Names)
    194       add(std::move(Name), Flags);
    195   }
    196 
    197   /// Construct a SymbolLookupSet from a SymbolNameSet with the given
    198   /// Flags used for each value.
    199   explicit SymbolLookupSet(
    200       const SymbolNameSet &Names,
    201       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
    202     Symbols.reserve(Names.size());
    203     for (const auto &Name : Names)
    204       add(Name, Flags);
    205   }
    206 
    207   /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
    208   /// used for each value.
    209   /// If the ArrayRef contains duplicates it is up to the client to remove these
    210   /// before using this instance for lookup.
    211   explicit SymbolLookupSet(
    212       ArrayRef<SymbolStringPtr> Names,
    213       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
    214     Symbols.reserve(Names.size());
    215     for (const auto &Name : Names)
    216       add(Name, Flags);
    217   }
    218 
    219   /// Add an element to the set. The client is responsible for checking that
    220   /// duplicates are not added.
    221   SymbolLookupSet &
    222   add(SymbolStringPtr Name,
    223       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
    224     Symbols.push_back(std::make_pair(std::move(Name), Flags));
    225     return *this;
    226   }
    227 
    228   /// Quickly append one lookup set to another.
    229   SymbolLookupSet &append(SymbolLookupSet Other) {
    230     Symbols.reserve(Symbols.size() + Other.size());
    231     for (auto &KV : Other)
    232       Symbols.push_back(std::move(KV));
    233     return *this;
    234   }
    235 
    236   bool empty() const { return Symbols.empty(); }
    237   UnderlyingVector::size_type size() const { return Symbols.size(); }
    238   iterator begin() { return Symbols.begin(); }
    239   iterator end() { return Symbols.end(); }
    240   const_iterator begin() const { return Symbols.begin(); }
    241   const_iterator end() const { return Symbols.end(); }
    242 
    243   /// Removes the Ith element of the vector, replacing it with the last element.
    244   void remove(UnderlyingVector::size_type I) {
    245     std::swap(Symbols[I], Symbols.back());
    246     Symbols.pop_back();
    247   }
    248 
    249   /// Removes the element pointed to by the given iterator. This iterator and
    250   /// all subsequent ones (including end()) are invalidated.
    251   void remove(iterator I) { remove(I - begin()); }
    252 
    253   /// Removes all elements matching the given predicate, which must be callable
    254   /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
    255   template <typename PredFn> void remove_if(PredFn &&Pred) {
    256     UnderlyingVector::size_type I = 0;
    257     while (I != Symbols.size()) {
    258       const auto &Name = Symbols[I].first;
    259       auto Flags = Symbols[I].second;
    260       if (Pred(Name, Flags))
    261         remove(I);
    262       else
    263         ++I;
    264     }
    265   }
    266 
    267   /// Loop over the elements of this SymbolLookupSet, applying the Body function
    268   /// to each one. Body must be callable as
    269   /// bool(const SymbolStringPtr &, SymbolLookupFlags).
    270   /// If Body returns true then the element just passed in is removed from the
    271   /// set. If Body returns false then the element is retained.
    272   template <typename BodyFn>
    273   auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
    274       std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
    275                                  std::declval<SymbolLookupFlags>())),
    276                    bool>::value> {
    277     UnderlyingVector::size_type I = 0;
    278     while (I != Symbols.size()) {
    279       const auto &Name = Symbols[I].first;
    280       auto Flags = Symbols[I].second;
    281       if (Body(Name, Flags))
    282         remove(I);
    283       else
    284         ++I;
    285     }
    286   }
    287 
    288   /// Loop over the elements of this SymbolLookupSet, applying the Body function
    289   /// to each one. Body must be callable as
    290   /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
    291   /// If Body returns a failure value, the loop exits immediately. If Body
    292   /// returns true then the element just passed in is removed from the set. If
    293   /// Body returns false then the element is retained.
    294   template <typename BodyFn>
    295   auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
    296       std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
    297                                  std::declval<SymbolLookupFlags>())),
    298                    Expected<bool>>::value,
    299       Error> {
    300     UnderlyingVector::size_type I = 0;
    301     while (I != Symbols.size()) {
    302       const auto &Name = Symbols[I].first;
    303       auto Flags = Symbols[I].second;
    304       auto Remove = Body(Name, Flags);
    305       if (!Remove)
    306         return Remove.takeError();
    307       if (*Remove)
    308         remove(I);
    309       else
    310         ++I;
    311     }
    312     return Error::success();
    313   }
    314 
    315   /// Construct a SymbolNameVector from this instance by dropping the Flags
    316   /// values.
    317   SymbolNameVector getSymbolNames() const {
    318     SymbolNameVector Names;
    319     Names.reserve(Symbols.size());
    320     for (auto &KV : Symbols)
    321       Names.push_back(KV.first);
    322     return Names;
    323   }
    324 
    325   /// Sort the lookup set by pointer value. This sort is fast but sensitive to
    326   /// allocation order and so should not be used where a consistent order is
    327   /// required.
    328   void sortByAddress() {
    329     llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
    330       return LHS.first < RHS.first;
    331     });
    332   }
    333 
    334   /// Sort the lookup set lexicographically. This sort is slow but the order
    335   /// is unaffected by allocation order.
    336   void sortByName() {
    337     llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
    338       return *LHS.first < *RHS.first;
    339     });
    340   }
    341 
    342   /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
    343   /// by construction, this method can be used to turn it into a proper set.
    344   void removeDuplicates() {
    345     sortByAddress();
    346     auto LastI = std::unique(Symbols.begin(), Symbols.end());
    347     Symbols.erase(LastI, Symbols.end());
    348   }
    349 
    350 #ifndef NDEBUG
    351   /// Returns true if this set contains any duplicates. This should only be used
    352   /// in assertions.
    353   bool containsDuplicates() {
    354     if (Symbols.size() < 2)
    355       return false;
    356     sortByAddress();
    357     for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
    358       if (Symbols[I].first == Symbols[I - 1].first)
    359         return true;
    360     return false;
    361   }
    362 #endif
    363 
    364 private:
    365   UnderlyingVector Symbols;
    366 };
    367 
    368 struct SymbolAliasMapEntry {
    369   SymbolAliasMapEntry() = default;
    370   SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
    371       : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
    372 
    373   SymbolStringPtr Aliasee;
    374   JITSymbolFlags AliasFlags;
    375 };
    376 
    377 /// A map of Symbols to (Symbol, Flags) pairs.
    378 using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
    379 
    380 /// Callback to notify client that symbols have been resolved.
    381 using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
    382 
    383 /// Callback to register the dependencies for a given query.
    384 using RegisterDependenciesFunction =
    385     std::function<void(const SymbolDependenceMap &)>;
    386 
    387 /// This can be used as the value for a RegisterDependenciesFunction if there
    388 /// are no dependants to register with.
    389 extern RegisterDependenciesFunction NoDependenciesToRegister;
    390 
    391 class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
    392 public:
    393   static char ID;
    394 
    395   ResourceTrackerDefunct(ResourceTrackerSP RT);
    396   std::error_code convertToErrorCode() const override;
    397   void log(raw_ostream &OS) const override;
    398 
    399 private:
    400   ResourceTrackerSP RT;
    401 };
    402 
    403 /// Used to notify a JITDylib that the given set of symbols failed to
    404 /// materialize.
    405 class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
    406 public:
    407   static char ID;
    408 
    409   FailedToMaterialize(std::shared_ptr<SymbolDependenceMap> Symbols);
    410   std::error_code convertToErrorCode() const override;
    411   void log(raw_ostream &OS) const override;
    412   const SymbolDependenceMap &getSymbols() const { return *Symbols; }
    413 
    414 private:
    415   std::shared_ptr<SymbolDependenceMap> Symbols;
    416 };
    417 
    418 /// Used to notify clients when symbols can not be found during a lookup.
    419 class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
    420 public:
    421   static char ID;
    422 
    423   SymbolsNotFound(SymbolNameSet Symbols);
    424   SymbolsNotFound(SymbolNameVector Symbols);
    425   std::error_code convertToErrorCode() const override;
    426   void log(raw_ostream &OS) const override;
    427   const SymbolNameVector &getSymbols() const { return Symbols; }
    428 
    429 private:
    430   SymbolNameVector Symbols;
    431 };
    432 
    433 /// Used to notify clients that a set of symbols could not be removed.
    434 class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
    435 public:
    436   static char ID;
    437 
    438   SymbolsCouldNotBeRemoved(SymbolNameSet Symbols);
    439   std::error_code convertToErrorCode() const override;
    440   void log(raw_ostream &OS) const override;
    441   const SymbolNameSet &getSymbols() const { return Symbols; }
    442 
    443 private:
    444   SymbolNameSet Symbols;
    445 };
    446 
    447 /// Errors of this type should be returned if a module fails to include
    448 /// definitions that are claimed by the module's associated
    449 /// MaterializationResponsibility. If this error is returned it is indicative of
    450 /// a broken transformation / compiler / object cache.
    451 class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
    452 public:
    453   static char ID;
    454 
    455   MissingSymbolDefinitions(std::string ModuleName, SymbolNameVector Symbols)
    456     : ModuleName(std::move(ModuleName)), Symbols(std::move(Symbols)) {}
    457   std::error_code convertToErrorCode() const override;
    458   void log(raw_ostream &OS) const override;
    459   const std::string &getModuleName() const { return ModuleName; }
    460   const SymbolNameVector &getSymbols() const { return Symbols; }
    461 private:
    462   std::string ModuleName;
    463   SymbolNameVector Symbols;
    464 };
    465 
    466 /// Errors of this type should be returned if a module contains definitions for
    467 /// symbols that are not claimed by the module's associated
    468 /// MaterializationResponsibility. If this error is returned it is indicative of
    469 /// a broken transformation / compiler / object cache.
    470 class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
    471 public:
    472   static char ID;
    473 
    474   UnexpectedSymbolDefinitions(std::string ModuleName, SymbolNameVector Symbols)
    475     : ModuleName(std::move(ModuleName)), Symbols(std::move(Symbols)) {}
    476   std::error_code convertToErrorCode() const override;
    477   void log(raw_ostream &OS) const override;
    478   const std::string &getModuleName() const { return ModuleName; }
    479   const SymbolNameVector &getSymbols() const { return Symbols; }
    480 private:
    481   std::string ModuleName;
    482   SymbolNameVector Symbols;
    483 };
    484 
    485 /// Tracks responsibility for materialization, and mediates interactions between
    486 /// MaterializationUnits and JDs.
    487 ///
    488 /// An instance of this class is passed to MaterializationUnits when their
    489 /// materialize method is called. It allows MaterializationUnits to resolve and
    490 /// emit symbols, or abandon materialization by notifying any unmaterialized
    491 /// symbols of an error.
    492 class MaterializationResponsibility {
    493   friend class ExecutionSession;
    494 
    495 public:
    496   MaterializationResponsibility(MaterializationResponsibility &&) = delete;
    497   MaterializationResponsibility &
    498   operator=(MaterializationResponsibility &&) = delete;
    499 
    500   /// Destruct a MaterializationResponsibility instance. In debug mode
    501   ///        this asserts that all symbols being tracked have been either
    502   ///        emitted or notified of an error.
    503   ~MaterializationResponsibility();
    504 
    505   /// Returns the ResourceTracker for this instance.
    506   template <typename Func> Error withResourceKeyDo(Func &&F) const;
    507 
    508   /// Returns the target JITDylib that these symbols are being materialized
    509   ///        into.
    510   JITDylib &getTargetJITDylib() const { return *JD; }
    511 
    512   /// Returns the ExecutionSession for this instance.
    513   ExecutionSession &getExecutionSession();
    514 
    515   /// Returns the symbol flags map for this responsibility instance.
    516   /// Note: The returned flags may have transient flags (Lazy, Materializing)
    517   /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
    518   /// before using.
    519   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
    520 
    521   /// Returns the initialization pseudo-symbol, if any. This symbol will also
    522   /// be present in the SymbolFlagsMap for this MaterializationResponsibility
    523   /// object.
    524   const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
    525 
    526   /// Returns the names of any symbols covered by this
    527   /// MaterializationResponsibility object that have queries pending. This
    528   /// information can be used to return responsibility for unrequested symbols
    529   /// back to the JITDylib via the delegate method.
    530   SymbolNameSet getRequestedSymbols() const;
    531 
    532   /// Notifies the target JITDylib that the given symbols have been resolved.
    533   /// This will update the given symbols' addresses in the JITDylib, and notify
    534   /// any pending queries on the given symbols of their resolution. The given
    535   /// symbols must be ones covered by this MaterializationResponsibility
    536   /// instance. Individual calls to this method may resolve a subset of the
    537   /// symbols, but all symbols must have been resolved prior to calling emit.
    538   ///
    539   /// This method will return an error if any symbols being resolved have been
    540   /// moved to the error state due to the failure of a dependency. If this
    541   /// method returns an error then clients should log it and call
    542   /// failMaterialize. If no dependencies have been registered for the
    543   /// symbols covered by this MaterializationResponsibiility then this method
    544   /// is guaranteed to return Error::success() and can be wrapped with cantFail.
    545   Error notifyResolved(const SymbolMap &Symbols);
    546 
    547   /// Notifies the target JITDylib (and any pending queries on that JITDylib)
    548   /// that all symbols covered by this MaterializationResponsibility instance
    549   /// have been emitted.
    550   ///
    551   /// This method will return an error if any symbols being resolved have been
    552   /// moved to the error state due to the failure of a dependency. If this
    553   /// method returns an error then clients should log it and call
    554   /// failMaterialize. If no dependencies have been registered for the
    555   /// symbols covered by this MaterializationResponsibiility then this method
    556   /// is guaranteed to return Error::success() and can be wrapped with cantFail.
    557   Error notifyEmitted();
    558 
    559   /// Attempt to claim responsibility for new definitions. This method can be
    560   /// used to claim responsibility for symbols that are added to a
    561   /// materialization unit during the compilation process (e.g. literal pool
    562   /// symbols). Symbol linkage rules are the same as for symbols that are
    563   /// defined up front: duplicate strong definitions will result in errors.
    564   /// Duplicate weak definitions will be discarded (in which case they will
    565   /// not be added to this responsibility instance).
    566   ///
    567   ///   This method can be used by materialization units that want to add
    568   /// additional symbols at materialization time (e.g. stubs, compile
    569   /// callbacks, metadata).
    570   Error defineMaterializing(SymbolFlagsMap SymbolFlags);
    571 
    572   /// Define the given symbols as non-existent, removing it from the symbol
    573   /// table and notifying any pending queries. Queries that lookup up the
    574   /// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will
    575   /// behave as if the symbol had not been matched in the first place. Queries
    576   /// that required this symbol will fail with a missing symbol definition
    577   /// error.
    578   ///
    579   /// This method is intended to support cleanup of special symbols like
    580   /// initializer symbols: Queries using
    581   /// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their
    582   /// emission, and this method can be used to remove them from the JITDylib
    583   /// once materialization is complete.
    584   void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols);
    585 
    586   /// Notify all not-yet-emitted covered by this MaterializationResponsibility
    587   /// instance that an error has occurred.
    588   /// This will remove all symbols covered by this MaterializationResponsibilty
    589   /// from the target JITDylib, and send an error to any queries waiting on
    590   /// these symbols.
    591   void failMaterialization();
    592 
    593   /// Transfers responsibility to the given MaterializationUnit for all
    594   /// symbols defined by that MaterializationUnit. This allows
    595   /// materializers to break up work based on run-time information (e.g.
    596   /// by introspecting which symbols have actually been looked up and
    597   /// materializing only those).
    598   Error replace(std::unique_ptr<MaterializationUnit> MU);
    599 
    600   /// Delegates responsibility for the given symbols to the returned
    601   /// materialization responsibility. Useful for breaking up work between
    602   /// threads, or different kinds of materialization processes.
    603   Expected<std::unique_ptr<MaterializationResponsibility>>
    604   delegate(const SymbolNameSet &Symbols);
    605 
    606   void addDependencies(const SymbolStringPtr &Name,
    607                        const SymbolDependenceMap &Dependencies);
    608 
    609   /// Add dependencies that apply to all symbols covered by this instance.
    610   void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
    611 
    612 private:
    613   /// Create a MaterializationResponsibility for the given JITDylib and
    614   ///        initial symbols.
    615   MaterializationResponsibility(JITDylibSP JD, SymbolFlagsMap SymbolFlags,
    616                                 SymbolStringPtr InitSymbol)
    617       : JD(std::move(JD)), SymbolFlags(std::move(SymbolFlags)),
    618         InitSymbol(std::move(InitSymbol)) {
    619     assert(this->JD && "Cannot initialize with null JITDylib");
    620     assert(!this->SymbolFlags.empty() && "Materializing nothing?");
    621   }
    622 
    623   JITDylibSP JD;
    624   SymbolFlagsMap SymbolFlags;
    625   SymbolStringPtr InitSymbol;
    626 };
    627 
    628 /// A MaterializationUnit represents a set of symbol definitions that can
    629 ///        be materialized as a group, or individually discarded (when
    630 ///        overriding definitions are encountered).
    631 ///
    632 /// MaterializationUnits are used when providing lazy definitions of symbols to
    633 /// JITDylibs. The JITDylib will call materialize when the address of a symbol
    634 /// is requested via the lookup method. The JITDylib will call discard if a
    635 /// stronger definition is added or already present.
    636 class MaterializationUnit {
    637   friend class ExecutionSession;
    638   friend class JITDylib;
    639 
    640 public:
    641   static char ID;
    642 
    643   MaterializationUnit(SymbolFlagsMap InitalSymbolFlags,
    644                       SymbolStringPtr InitSymbol)
    645       : SymbolFlags(std::move(InitalSymbolFlags)),
    646         InitSymbol(std::move(InitSymbol)) {
    647     assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&
    648            "If set, InitSymbol should appear in InitialSymbolFlags map");
    649   }
    650 
    651   virtual ~MaterializationUnit() {}
    652 
    653   /// Return the name of this materialization unit. Useful for debugging
    654   /// output.
    655   virtual StringRef getName() const = 0;
    656 
    657   /// Return the set of symbols that this source provides.
    658   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
    659 
    660   /// Returns the initialization symbol for this MaterializationUnit (if any).
    661   const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
    662 
    663   /// Implementations of this method should materialize all symbols
    664   ///        in the materialzation unit, except for those that have been
    665   ///        previously discarded.
    666   virtual void
    667   materialize(std::unique_ptr<MaterializationResponsibility> R) = 0;
    668 
    669   /// Called by JITDylibs to notify MaterializationUnits that the given symbol
    670   /// has been overridden.
    671   void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
    672     SymbolFlags.erase(Name);
    673     discard(JD, std::move(Name));
    674   }
    675 
    676 protected:
    677   SymbolFlagsMap SymbolFlags;
    678   SymbolStringPtr InitSymbol;
    679 
    680 private:
    681   virtual void anchor();
    682 
    683   /// Implementations of this method should discard the given symbol
    684   ///        from the source (e.g. if the source is an LLVM IR Module and the
    685   ///        symbol is a function, delete the function body or mark it available
    686   ///        externally).
    687   virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
    688 };
    689 
    690 /// A MaterializationUnit implementation for pre-existing absolute symbols.
    691 ///
    692 /// All symbols will be resolved and marked ready as soon as the unit is
    693 /// materialized.
    694 class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
    695 public:
    696   AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
    697 
    698   StringRef getName() const override;
    699 
    700 private:
    701   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
    702   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
    703   static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
    704 
    705   SymbolMap Symbols;
    706 };
    707 
    708 /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
    709 /// Useful for inserting absolute symbols into a JITDylib. E.g.:
    710 /// \code{.cpp}
    711 ///   JITDylib &JD = ...;
    712 ///   SymbolStringPtr Foo = ...;
    713 ///   JITEvaluatedSymbol FooSym = ...;
    714 ///   if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
    715 ///     return Err;
    716 /// \endcode
    717 ///
    718 inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
    719 absoluteSymbols(SymbolMap Symbols) {
    720   return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
    721       std::move(Symbols));
    722 }
    723 
    724 /// A materialization unit for symbol aliases. Allows existing symbols to be
    725 /// aliased with alternate flags.
    726 class ReExportsMaterializationUnit : public MaterializationUnit {
    727 public:
    728   /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
    729   /// taken to be whatever JITDylib these definitions are materialized in (and
    730   /// MatchNonExported has no effect). This is useful for defining aliases
    731   /// within a JITDylib.
    732   ///
    733   /// Note: Care must be taken that no sets of aliases form a cycle, as such
    734   ///       a cycle will result in a deadlock when any symbol in the cycle is
    735   ///       resolved.
    736   ReExportsMaterializationUnit(JITDylib *SourceJD,
    737                                JITDylibLookupFlags SourceJDLookupFlags,
    738                                SymbolAliasMap Aliases);
    739 
    740   StringRef getName() const override;
    741 
    742 private:
    743   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
    744   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
    745   static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
    746 
    747   JITDylib *SourceJD = nullptr;
    748   JITDylibLookupFlags SourceJDLookupFlags;
    749   SymbolAliasMap Aliases;
    750 };
    751 
    752 /// Create a ReExportsMaterializationUnit with the given aliases.
    753 /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
    754 /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
    755 /// (for "bar") with: \code{.cpp}
    756 ///   SymbolStringPtr Baz = ...;
    757 ///   SymbolStringPtr Qux = ...;
    758 ///   if (auto Err = JD.define(symbolAliases({
    759 ///       {Baz, { Foo, JITSymbolFlags::Exported }},
    760 ///       {Qux, { Bar, JITSymbolFlags::Weak }}}))
    761 ///     return Err;
    762 /// \endcode
    763 inline std::unique_ptr<ReExportsMaterializationUnit>
    764 symbolAliases(SymbolAliasMap Aliases) {
    765   return std::make_unique<ReExportsMaterializationUnit>(
    766       nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
    767 }
    768 
    769 /// Create a materialization unit for re-exporting symbols from another JITDylib
    770 /// with alternative names/flags.
    771 /// SourceJD will be searched using the given JITDylibLookupFlags.
    772 inline std::unique_ptr<ReExportsMaterializationUnit>
    773 reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
    774           JITDylibLookupFlags SourceJDLookupFlags =
    775               JITDylibLookupFlags::MatchExportedSymbolsOnly) {
    776   return std::make_unique<ReExportsMaterializationUnit>(
    777       &SourceJD, SourceJDLookupFlags, std::move(Aliases));
    778 }
    779 
    780 /// Build a SymbolAliasMap for the common case where you want to re-export
    781 /// symbols from another JITDylib with the same linkage/flags.
    782 Expected<SymbolAliasMap>
    783 buildSimpleReexportsAAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
    784 
    785 /// Represents the state that a symbol has reached during materialization.
    786 enum class SymbolState : uint8_t {
    787   Invalid,       /// No symbol should be in this state.
    788   NeverSearched, /// Added to the symbol table, never queried.
    789   Materializing, /// Queried, materialization begun.
    790   Resolved,      /// Assigned address, still materializing.
    791   Emitted,       /// Emitted to memory, but waiting on transitive dependencies.
    792   Ready = 0x3f   /// Ready and safe for clients to access.
    793 };
    794 
    795 /// A symbol query that returns results via a callback when results are
    796 ///        ready.
    797 ///
    798 /// makes a callback when all symbols are available.
    799 class AsynchronousSymbolQuery {
    800   friend class ExecutionSession;
    801   friend class InProgressFullLookupState;
    802   friend class JITDylib;
    803   friend class JITSymbolResolverAdapter;
    804   friend class MaterializationResponsibility;
    805 
    806 public:
    807   /// Create a query for the given symbols. The NotifyComplete
    808   /// callback will be called once all queried symbols reach the given
    809   /// minimum state.
    810   AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
    811                           SymbolState RequiredState,
    812                           SymbolsResolvedCallback NotifyComplete);
    813 
    814   /// Notify the query that a requested symbol has reached the required state.
    815   void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
    816                                     JITEvaluatedSymbol Sym);
    817 
    818   /// Returns true if all symbols covered by this query have been
    819   ///        resolved.
    820   bool isComplete() const { return OutstandingSymbolsCount == 0; }
    821 
    822 
    823 private:
    824   void handleComplete(ExecutionSession &ES);
    825 
    826   SymbolState getRequiredState() { return RequiredState; }
    827 
    828   void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
    829 
    830   void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
    831 
    832   void dropSymbol(const SymbolStringPtr &Name);
    833 
    834   void handleFailed(Error Err);
    835 
    836   void detach();
    837 
    838   SymbolsResolvedCallback NotifyComplete;
    839   SymbolDependenceMap QueryRegistrations;
    840   SymbolMap ResolvedSymbols;
    841   size_t OutstandingSymbolsCount;
    842   SymbolState RequiredState;
    843 };
    844 
    845 /// Wraps state for a lookup-in-progress.
    846 /// DefinitionGenerators can optionally take ownership of a LookupState object
    847 /// to suspend a lookup-in-progress while they search for definitions.
    848 class LookupState {
    849   friend class OrcV2CAPIHelper;
    850   friend class ExecutionSession;
    851 
    852 public:
    853   LookupState();
    854   LookupState(LookupState &&);
    855   LookupState &operator=(LookupState &&);
    856   ~LookupState();
    857 
    858   /// Continue the lookup. This can be called by DefinitionGenerators
    859   /// to re-start a captured query-application operation.
    860   void continueLookup(Error Err);
    861 
    862 private:
    863   LookupState(std::unique_ptr<InProgressLookupState> IPLS);
    864 
    865   // For C API.
    866   void reset(InProgressLookupState *IPLS);
    867 
    868   std::unique_ptr<InProgressLookupState> IPLS;
    869 };
    870 
    871 /// Definition generators can be attached to JITDylibs to generate new
    872 /// definitions for otherwise unresolved symbols during lookup.
    873 class DefinitionGenerator {
    874 public:
    875   virtual ~DefinitionGenerator();
    876 
    877   /// DefinitionGenerators should override this method to insert new
    878   /// definitions into the parent JITDylib. K specifies the kind of this
    879   /// lookup. JD specifies the target JITDylib being searched, and
    880   /// JDLookupFlags specifies whether the search should match against
    881   /// hidden symbols. Finally, Symbols describes the set of unresolved
    882   /// symbols and their associated lookup flags.
    883   virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
    884                               JITDylibLookupFlags JDLookupFlags,
    885                               const SymbolLookupSet &LookupSet) = 0;
    886 };
    887 
    888 /// A symbol table that supports asynchoronous symbol queries.
    889 ///
    890 /// Represents a virtual shared object. Instances can not be copied or moved, so
    891 /// their addresses may be used as keys for resource management.
    892 /// JITDylib state changes must be made via an ExecutionSession to guarantee
    893 /// that they are synchronized with respect to other JITDylib operations.
    894 class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
    895                  public jitlink::JITLinkDylib {
    896   friend class AsynchronousSymbolQuery;
    897   friend class ExecutionSession;
    898   friend class Platform;
    899   friend class MaterializationResponsibility;
    900 public:
    901 
    902   using AsynchronousSymbolQuerySet =
    903     std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
    904 
    905   JITDylib(const JITDylib &) = delete;
    906   JITDylib &operator=(const JITDylib &) = delete;
    907   JITDylib(JITDylib &&) = delete;
    908   JITDylib &operator=(JITDylib &&) = delete;
    909 
    910   /// Get the name for this JITDylib.
    911   const std::string &getName() const { return JITDylibName; }
    912 
    913   /// Get a reference to the ExecutionSession for this JITDylib.
    914   ExecutionSession &getExecutionSession() const { return ES; }
    915 
    916   /// Calls remove on all trackers currently associated with this JITDylib.
    917   /// Does not run static deinits.
    918   ///
    919   /// Note that removal happens outside the session lock, so new code may be
    920   /// added concurrently while the clear is underway, and the newly added
    921   /// code will *not* be cleared. Adding new code concurrently with a clear
    922   /// is usually a bug and should be avoided.
    923   Error clear();
    924 
    925   /// Get the default resource tracker for this JITDylib.
    926   ResourceTrackerSP getDefaultResourceTracker();
    927 
    928   /// Create a resource tracker for this JITDylib.
    929   ResourceTrackerSP createResourceTracker();
    930 
    931   /// Adds a definition generator to this JITDylib and returns a referenece to
    932   /// it.
    933   ///
    934   /// When JITDylibs are searched during lookup, if no existing definition of
    935   /// a symbol is found, then any generators that have been added are run (in
    936   /// the order that they were added) to potentially generate a definition.
    937   template <typename GeneratorT>
    938   GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
    939 
    940   /// Remove a definition generator from this JITDylib.
    941   ///
    942   /// The given generator must exist in this JITDylib's generators list (i.e.
    943   /// have been added and not yet removed).
    944   void removeGenerator(DefinitionGenerator &G);
    945 
    946   /// Set the link order to be used when fixing up definitions in JITDylib.
    947   /// This will replace the previous link order, and apply to any symbol
    948   /// resolutions made for definitions in this JITDylib after the call to
    949   /// setLinkOrder (even if the definition itself was added before the
    950   /// call).
    951   ///
    952   /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib
    953   /// will add itself to the beginning of the LinkOrder (Clients should not
    954   /// put this JITDylib in the list in this case, to avoid redundant lookups).
    955   ///
    956   /// If LinkAgainstThisJITDylibFirst is false then the link order will be used
    957   /// as-is. The primary motivation for this feature is to support deliberate
    958   /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
    959   /// the facade may resolve function names to stubs, and the stubs may compile
    960   /// lazily by looking up symbols in this dylib. Adding the facade dylib
    961   /// as the first in the link order (instead of this dylib) ensures that
    962   /// definitions within this dylib resolve to the lazy-compiling stubs,
    963   /// rather than immediately materializing the definitions in this dylib.
    964   void setLinkOrder(JITDylibSearchOrder NewSearchOrder,
    965                     bool LinkAgainstThisJITDylibFirst = true);
    966 
    967   /// Add the given JITDylib to the link order for definitions in this
    968   /// JITDylib.
    969   void addToLinkOrder(JITDylib &JD,
    970                       JITDylibLookupFlags JDLookupFlags =
    971                           JITDylibLookupFlags::MatchExportedSymbolsOnly);
    972 
    973   /// Replace OldJD with NewJD in the link order if OldJD is present.
    974   /// Otherwise this operation is a no-op.
    975   void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
    976                           JITDylibLookupFlags JDLookupFlags =
    977                               JITDylibLookupFlags::MatchExportedSymbolsOnly);
    978 
    979   /// Remove the given JITDylib from the link order for this JITDylib if it is
    980   /// present. Otherwise this operation is a no-op.
    981   void removeFromLinkOrder(JITDylib &JD);
    982 
    983   /// Do something with the link order (run under the session lock).
    984   template <typename Func>
    985   auto withLinkOrderDo(Func &&F)
    986       -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
    987 
    988   /// Define all symbols provided by the materialization unit to be part of this
    989   /// JITDylib.
    990   ///
    991   /// If RT is not specified then the default resource tracker will be used.
    992   ///
    993   /// This overload always takes ownership of the MaterializationUnit. If any
    994   /// errors occur, the MaterializationUnit consumed.
    995   template <typename MaterializationUnitType>
    996   Error define(std::unique_ptr<MaterializationUnitType> &&MU,
    997                ResourceTrackerSP RT = nullptr);
    998 
    999   /// Define all symbols provided by the materialization unit to be part of this
   1000   /// JITDylib.
   1001   ///
   1002   /// This overload only takes ownership of the MaterializationUnit no error is
   1003   /// generated. If an error occurs, ownership remains with the caller. This
   1004   /// may allow the caller to modify the MaterializationUnit to correct the
   1005   /// issue, then re-call define.
   1006   template <typename MaterializationUnitType>
   1007   Error define(std::unique_ptr<MaterializationUnitType> &MU,
   1008                ResourceTrackerSP RT = nullptr);
   1009 
   1010   /// Tries to remove the given symbols.
   1011   ///
   1012   /// If any symbols are not defined in this JITDylib this method will return
   1013   /// a SymbolsNotFound error covering the missing symbols.
   1014   ///
   1015   /// If all symbols are found but some symbols are in the process of being
   1016   /// materialized this method will return a SymbolsCouldNotBeRemoved error.
   1017   ///
   1018   /// On success, all symbols are removed. On failure, the JITDylib state is
   1019   /// left unmodified (no symbols are removed).
   1020   Error remove(const SymbolNameSet &Names);
   1021 
   1022   /// Dump current JITDylib state to OS.
   1023   void dump(raw_ostream &OS);
   1024 
   1025   /// Returns the given JITDylibs and all of their transitive dependencies in
   1026   /// DFS order (based on linkage relationships). Each JITDylib will appear
   1027   /// only once.
   1028   static std::vector<JITDylibSP> getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
   1029 
   1030   /// Returns the given JITDylibs and all of their transitive dependensies in
   1031   /// reverse DFS order (based on linkage relationships). Each JITDylib will
   1032   /// appear only once.
   1033   static std::vector<JITDylibSP>
   1034   getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
   1035 
   1036   /// Return this JITDylib and its transitive dependencies in DFS order
   1037   /// based on linkage relationships.
   1038   std::vector<JITDylibSP> getDFSLinkOrder();
   1039 
   1040   /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
   1041   /// based on linkage relationships.
   1042   std::vector<JITDylibSP> getReverseDFSLinkOrder();
   1043 
   1044 private:
   1045   using AsynchronousSymbolQueryList =
   1046       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
   1047 
   1048   struct UnmaterializedInfo {
   1049     UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
   1050                        ResourceTracker *RT)
   1051         : MU(std::move(MU)), RT(RT) {}
   1052 
   1053     std::unique_ptr<MaterializationUnit> MU;
   1054     ResourceTracker *RT;
   1055   };
   1056 
   1057   using UnmaterializedInfosMap =
   1058       DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
   1059 
   1060   using UnmaterializedInfosList =
   1061       std::vector<std::shared_ptr<UnmaterializedInfo>>;
   1062 
   1063   struct MaterializingInfo {
   1064     SymbolDependenceMap Dependants;
   1065     SymbolDependenceMap UnemittedDependencies;
   1066 
   1067     void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
   1068     void removeQuery(const AsynchronousSymbolQuery &Q);
   1069     AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
   1070     AsynchronousSymbolQueryList takeAllPendingQueries() {
   1071       return std::move(PendingQueries);
   1072     }
   1073     bool hasQueriesPending() const { return !PendingQueries.empty(); }
   1074     const AsynchronousSymbolQueryList &pendingQueries() const {
   1075       return PendingQueries;
   1076     }
   1077   private:
   1078     AsynchronousSymbolQueryList PendingQueries;
   1079   };
   1080 
   1081   using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
   1082 
   1083   class SymbolTableEntry {
   1084   public:
   1085     SymbolTableEntry() = default;
   1086     SymbolTableEntry(JITSymbolFlags Flags)
   1087         : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
   1088           MaterializerAttached(false), PendingRemoval(false) {}
   1089 
   1090     JITTargetAddress getAddress() const { return Addr; }
   1091     JITSymbolFlags getFlags() const { return Flags; }
   1092     SymbolState getState() const { return static_cast<SymbolState>(State); }
   1093 
   1094     bool hasMaterializerAttached() const { return MaterializerAttached; }
   1095     bool isPendingRemoval() const { return PendingRemoval; }
   1096 
   1097     void setAddress(JITTargetAddress Addr) { this->Addr = Addr; }
   1098     void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; }
   1099     void setState(SymbolState State) {
   1100       assert(static_cast<uint8_t>(State) < (1 << 6) &&
   1101              "State does not fit in bitfield");
   1102       this->State = static_cast<uint8_t>(State);
   1103     }
   1104 
   1105     void setMaterializerAttached(bool MaterializerAttached) {
   1106       this->MaterializerAttached = MaterializerAttached;
   1107     }
   1108 
   1109     void setPendingRemoval(bool PendingRemoval) {
   1110       this->PendingRemoval = PendingRemoval;
   1111     }
   1112 
   1113     JITEvaluatedSymbol getSymbol() const {
   1114       return JITEvaluatedSymbol(Addr, Flags);
   1115     }
   1116 
   1117   private:
   1118     JITTargetAddress Addr = 0;
   1119     JITSymbolFlags Flags;
   1120     uint8_t State : 6;
   1121     uint8_t MaterializerAttached : 1;
   1122     uint8_t PendingRemoval : 1;
   1123   };
   1124 
   1125   using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
   1126 
   1127   JITDylib(ExecutionSession &ES, std::string Name);
   1128 
   1129   ResourceTrackerSP getTracker(MaterializationResponsibility &MR);
   1130   std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
   1131   removeTracker(ResourceTracker &RT);
   1132 
   1133   void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
   1134 
   1135   Error defineImpl(MaterializationUnit &MU);
   1136 
   1137   void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
   1138                                   ResourceTracker &RT);
   1139 
   1140   void detachQueryHelper(AsynchronousSymbolQuery &Q,
   1141                          const SymbolNameSet &QuerySymbols);
   1142 
   1143   void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
   1144                                        const SymbolStringPtr &DependantName,
   1145                                        MaterializingInfo &EmittedMI);
   1146 
   1147   Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
   1148 
   1149   Error replace(MaterializationResponsibility &FromMR,
   1150                 std::unique_ptr<MaterializationUnit> MU);
   1151 
   1152   Expected<std::unique_ptr<MaterializationResponsibility>>
   1153   delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
   1154            SymbolStringPtr InitSymbol);
   1155 
   1156   SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
   1157 
   1158   void addDependencies(const SymbolStringPtr &Name,
   1159                        const SymbolDependenceMap &Dependants);
   1160 
   1161   Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
   1162 
   1163   Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted);
   1164 
   1165   void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
   1166 
   1167   using FailedSymbolsWorklist =
   1168       std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
   1169 
   1170   static std::pair<AsynchronousSymbolQuerySet,
   1171                    std::shared_ptr<SymbolDependenceMap>>
   1172       failSymbols(FailedSymbolsWorklist);
   1173 
   1174   ExecutionSession &ES;
   1175   std::string JITDylibName;
   1176   std::mutex GeneratorsMutex;
   1177   bool Open = true;
   1178   SymbolTable Symbols;
   1179   UnmaterializedInfosMap UnmaterializedInfos;
   1180   MaterializingInfosMap MaterializingInfos;
   1181   std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
   1182   JITDylibSearchOrder LinkOrder;
   1183   ResourceTrackerSP DefaultTracker;
   1184 
   1185   // Map trackers to sets of symbols tracked.
   1186   DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
   1187   DenseMap<MaterializationResponsibility *, ResourceTracker *> MRTrackers;
   1188 };
   1189 
   1190 /// Platforms set up standard symbols and mediate interactions between dynamic
   1191 /// initializers (e.g. C++ static constructors) and ExecutionSession state.
   1192 /// Note that Platforms do not automatically run initializers: clients are still
   1193 /// responsible for doing this.
   1194 class Platform {
   1195 public:
   1196   virtual ~Platform();
   1197 
   1198   /// This method will be called outside the session lock each time a JITDylib
   1199   /// is created (unless it is created with EmptyJITDylib set) to allow the
   1200   /// Platform to install any JITDylib specific standard symbols (e.g
   1201   /// __dso_handle).
   1202   virtual Error setupJITDylib(JITDylib &JD) = 0;
   1203 
   1204   /// This method will be called under the ExecutionSession lock each time a
   1205   /// MaterializationUnit is added to a JITDylib.
   1206   virtual Error notifyAdding(ResourceTracker &RT,
   1207                              const MaterializationUnit &MU) = 0;
   1208 
   1209   /// This method will be called under the ExecutionSession lock when a
   1210   /// ResourceTracker is removed.
   1211   virtual Error notifyRemoving(ResourceTracker &RT) = 0;
   1212 
   1213   /// A utility function for looking up initializer symbols. Performs a blocking
   1214   /// lookup for the given symbols in each of the given JITDylibs.
   1215   static Expected<DenseMap<JITDylib *, SymbolMap>>
   1216   lookupInitSymbols(ExecutionSession &ES,
   1217                     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
   1218 };
   1219 
   1220 /// Represents an abstract task for ORC to run.
   1221 class Task : public RTTIExtends<Task, RTTIRoot> {
   1222 public:
   1223   static char ID;
   1224 
   1225   /// Description of the task to be performed. Used for logging.
   1226   virtual void printDescription(raw_ostream &OS) = 0;
   1227 
   1228   /// Run the task.
   1229   virtual void run() = 0;
   1230 
   1231 private:
   1232   void anchor() override;
   1233 };
   1234 
   1235 /// A materialization task.
   1236 class MaterializationTask : public RTTIExtends<MaterializationTask, Task> {
   1237 public:
   1238   static char ID;
   1239 
   1240   MaterializationTask(std::unique_ptr<MaterializationUnit> MU,
   1241                       std::unique_ptr<MaterializationResponsibility> MR)
   1242       : MU(std::move(MU)), MR(std::move(MR)) {}
   1243   void printDescription(raw_ostream &OS) override;
   1244   void run() override;
   1245 
   1246 private:
   1247   std::unique_ptr<MaterializationUnit> MU;
   1248   std::unique_ptr<MaterializationResponsibility> MR;
   1249 };
   1250 
   1251 /// An ExecutionSession represents a running JIT program.
   1252 class ExecutionSession {
   1253   friend class InProgressLookupFlagsState;
   1254   friend class InProgressFullLookupState;
   1255   friend class JITDylib;
   1256   friend class LookupState;
   1257   friend class MaterializationResponsibility;
   1258   friend class ResourceTracker;
   1259 
   1260 public:
   1261   /// For reporting errors.
   1262   using ErrorReporter = std::function<void(Error)>;
   1263 
   1264   /// For dispatching ORC tasks (typically materialization tasks).
   1265   using DispatchTaskFunction = unique_function<void(std::unique_ptr<Task> T)>;
   1266 
   1267   /// Construct an ExecutionSession.
   1268   ///
   1269   /// SymbolStringPools may be shared between ExecutionSessions.
   1270   ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
   1271 
   1272   /// End the session. Closes all JITDylibs.
   1273   Error endSession();
   1274 
   1275   /// Add a symbol name to the SymbolStringPool and return a pointer to it.
   1276   SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
   1277 
   1278   /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
   1279   std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
   1280 
   1281   /// Set the Platform for this ExecutionSession.
   1282   void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
   1283 
   1284   /// Get the Platform for this session.
   1285   /// Will return null if no Platform has been set for this ExecutionSession.
   1286   Platform *getPlatform() { return P.get(); }
   1287 
   1288   /// Run the given lambda with the session mutex locked.
   1289   template <typename Func> decltype(auto) runSessionLocked(Func &&F) {
   1290     std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
   1291     return F();
   1292   }
   1293 
   1294   /// Register the given ResourceManager with this ExecutionSession.
   1295   /// Managers will be notified of events in reverse order of registration.
   1296   void registerResourceManager(ResourceManager &RM);
   1297 
   1298   /// Deregister the given ResourceManager with this ExecutionSession.
   1299   /// Manager must have been previously registered.
   1300   void deregisterResourceManager(ResourceManager &RM);
   1301 
   1302   /// Return a pointer to the "name" JITDylib.
   1303   /// Ownership of JITDylib remains within Execution Session
   1304   JITDylib *getJITDylibByName(StringRef Name);
   1305 
   1306   /// Add a new bare JITDylib to this ExecutionSession.
   1307   ///
   1308   /// The JITDylib Name is required to be unique. Clients should verify that
   1309   /// names are not being re-used (E.g. by calling getJITDylibByName) if names
   1310   /// are based on user input.
   1311   ///
   1312   /// This call does not install any library code or symbols into the newly
   1313   /// created JITDylib. The client is responsible for all configuration.
   1314   JITDylib &createBareJITDylib(std::string Name);
   1315 
   1316   /// Add a new JITDylib to this ExecutionSession.
   1317   ///
   1318   /// The JITDylib Name is required to be unique. Clients should verify that
   1319   /// names are not being re-used (e.g. by calling getJITDylibByName) if names
   1320   /// are based on user input.
   1321   ///
   1322   /// If a Platform is attached then Platform::setupJITDylib will be called to
   1323   /// install standard platform symbols (e.g. standard library interposes).
   1324   /// If no Platform is attached this call is equivalent to createBareJITDylib.
   1325   Expected<JITDylib &> createJITDylib(std::string Name);
   1326 
   1327   /// Set the error reporter function.
   1328   ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
   1329     this->ReportError = std::move(ReportError);
   1330     return *this;
   1331   }
   1332 
   1333   /// Report a error for this execution session.
   1334   ///
   1335   /// Unhandled errors can be sent here to log them.
   1336   void reportError(Error Err) { ReportError(std::move(Err)); }
   1337 
   1338   /// Set the task dispatch function.
   1339   ExecutionSession &setDispatchTask(DispatchTaskFunction DispatchTask) {
   1340     this->DispatchTask = std::move(DispatchTask);
   1341     return *this;
   1342   }
   1343 
   1344   /// Search the given JITDylibs to find the flags associated with each of the
   1345   /// given symbols.
   1346   void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
   1347                    SymbolLookupSet Symbols,
   1348                    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
   1349 
   1350   /// Blocking version of lookupFlags.
   1351   Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
   1352                                        JITDylibSearchOrder SearchOrder,
   1353                                        SymbolLookupSet Symbols);
   1354 
   1355   /// Search the given JITDylibs for the given symbols.
   1356   ///
   1357   /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
   1358   /// boolean indicates whether the search should match against non-exported
   1359   /// (hidden visibility) symbols in that dylib (true means match against
   1360   /// non-exported symbols, false means do not match).
   1361   ///
   1362   /// The NotifyComplete callback will be called once all requested symbols
   1363   /// reach the required state.
   1364   ///
   1365   /// If all symbols are found, the RegisterDependencies function will be called
   1366   /// while the session lock is held. This gives clients a chance to register
   1367   /// dependencies for on the queried symbols for any symbols they are
   1368   /// materializing (if a MaterializationResponsibility instance is present,
   1369   /// this can be implemented by calling
   1370   /// MaterializationResponsibility::addDependencies). If there are no
   1371   /// dependenant symbols for this query (e.g. it is being made by a top level
   1372   /// client to get an address to call) then the value NoDependenciesToRegister
   1373   /// can be used.
   1374   void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
   1375               SymbolLookupSet Symbols, SymbolState RequiredState,
   1376               SymbolsResolvedCallback NotifyComplete,
   1377               RegisterDependenciesFunction RegisterDependencies);
   1378 
   1379   /// Blocking version of lookup above. Returns the resolved symbol map.
   1380   /// If WaitUntilReady is true (the default), will not return until all
   1381   /// requested symbols are ready (or an error occurs). If WaitUntilReady is
   1382   /// false, will return as soon as all requested symbols are resolved,
   1383   /// or an error occurs. If WaitUntilReady is false and an error occurs
   1384   /// after resolution, the function will return a success value, but the
   1385   /// error will be reported via reportErrors.
   1386   Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
   1387                              const SymbolLookupSet &Symbols,
   1388                              LookupKind K = LookupKind::Static,
   1389                              SymbolState RequiredState = SymbolState::Ready,
   1390                              RegisterDependenciesFunction RegisterDependencies =
   1391                                  NoDependenciesToRegister);
   1392 
   1393   /// Convenience version of blocking lookup.
   1394   /// Searches each of the JITDylibs in the search order in turn for the given
   1395   /// symbol.
   1396   Expected<JITEvaluatedSymbol>
   1397   lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,
   1398          SymbolState RequiredState = SymbolState::Ready);
   1399 
   1400   /// Convenience version of blocking lookup.
   1401   /// Searches each of the JITDylibs in the search order in turn for the given
   1402   /// symbol. The search will not find non-exported symbols.
   1403   Expected<JITEvaluatedSymbol>
   1404   lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,
   1405          SymbolState RequiredState = SymbolState::Ready);
   1406 
   1407   /// Convenience version of blocking lookup.
   1408   /// Searches each of the JITDylibs in the search order in turn for the given
   1409   /// symbol. The search will not find non-exported symbols.
   1410   Expected<JITEvaluatedSymbol>
   1411   lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,
   1412          SymbolState RequiredState = SymbolState::Ready);
   1413 
   1414   /// Materialize the given unit.
   1415   void dispatchTask(std::unique_ptr<Task> T) {
   1416     assert(T && "T must be non-null");
   1417     DEBUG_WITH_TYPE("orc", dumpDispatchInfo(*T));
   1418     DispatchTask(std::move(T));
   1419   }
   1420 
   1421   /// Dump the state of all the JITDylibs in this session.
   1422   void dump(raw_ostream &OS);
   1423 
   1424 private:
   1425   static void logErrorsToStdErr(Error Err) {
   1426     logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
   1427   }
   1428 
   1429   static void runOnCurrentThread(std::unique_ptr<Task> T) { T->run(); }
   1430 
   1431   void dispatchOutstandingMUs();
   1432 
   1433   static std::unique_ptr<MaterializationResponsibility>
   1434   createMaterializationResponsibility(ResourceTracker &RT,
   1435                                       SymbolFlagsMap Symbols,
   1436                                       SymbolStringPtr InitSymbol) {
   1437     auto &JD = RT.getJITDylib();
   1438     std::unique_ptr<MaterializationResponsibility> MR(
   1439         new MaterializationResponsibility(&JD, std::move(Symbols),
   1440                                           std::move(InitSymbol)));
   1441     JD.MRTrackers[MR.get()] = &RT;
   1442     return MR;
   1443   }
   1444 
   1445   Error removeResourceTracker(ResourceTracker &RT);
   1446   void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
   1447   void destroyResourceTracker(ResourceTracker &RT);
   1448 
   1449   // State machine functions for query application..
   1450 
   1451   /// IL_updateCandidatesFor is called to remove already-defined symbols that
   1452   /// match a given query from the set of candidate symbols to generate
   1453   /// definitions for (no need to generate a definition if one already exists).
   1454   Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
   1455                                SymbolLookupSet &Candidates,
   1456                                SymbolLookupSet *NonCandidates);
   1457 
   1458   /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
   1459   /// definition generation. It is called when a lookup is performed, and again
   1460   /// each time that LookupState::continueLookup is called.
   1461   void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
   1462                            Error Err);
   1463 
   1464   /// OL_completeLookup is run once phase 1 successfully completes for a lookup
   1465   /// call. It attempts to attach the symbol to all symbol table entries and
   1466   /// collect all MaterializationUnits to dispatch. If this method fails then
   1467   /// all MaterializationUnits will be left un-materialized.
   1468   void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
   1469                          std::shared_ptr<AsynchronousSymbolQuery> Q,
   1470                          RegisterDependenciesFunction RegisterDependencies);
   1471 
   1472   /// OL_completeLookupFlags is run once phase 1 successfully completes for a
   1473   /// lookupFlags call.
   1474   void OL_completeLookupFlags(
   1475       std::unique_ptr<InProgressLookupState> IPLS,
   1476       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
   1477 
   1478   // State machine functions for MaterializationResponsibility.
   1479   void OL_destroyMaterializationResponsibility(
   1480       MaterializationResponsibility &MR);
   1481   SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
   1482   Error OL_notifyResolved(MaterializationResponsibility &MR,
   1483                           const SymbolMap &Symbols);
   1484   Error OL_notifyEmitted(MaterializationResponsibility &MR);
   1485   Error OL_defineMaterializing(MaterializationResponsibility &MR,
   1486                                SymbolFlagsMap SymbolFlags);
   1487   void OL_notifyFailed(MaterializationResponsibility &MR);
   1488   Error OL_replace(MaterializationResponsibility &MR,
   1489                    std::unique_ptr<MaterializationUnit> MU);
   1490   Expected<std::unique_ptr<MaterializationResponsibility>>
   1491   OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols);
   1492   void OL_addDependencies(MaterializationResponsibility &MR,
   1493                           const SymbolStringPtr &Name,
   1494                           const SymbolDependenceMap &Dependencies);
   1495   void OL_addDependenciesForAll(MaterializationResponsibility &MR,
   1496                                 const SymbolDependenceMap &Dependencies);
   1497 
   1498 #ifndef NDEBUG
   1499   void dumpDispatchInfo(Task &T);
   1500 #endif // NDEBUG
   1501 
   1502   mutable std::recursive_mutex SessionMutex;
   1503   bool SessionOpen = true;
   1504   std::shared_ptr<SymbolStringPool> SSP;
   1505   std::unique_ptr<Platform> P;
   1506   ErrorReporter ReportError = logErrorsToStdErr;
   1507   DispatchTaskFunction DispatchTask = runOnCurrentThread;
   1508 
   1509   std::vector<ResourceManager *> ResourceManagers;
   1510 
   1511   std::vector<JITDylibSP> JDs;
   1512 
   1513   // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
   1514   //        with callbacks from asynchronous queries.
   1515   mutable std::recursive_mutex OutstandingMUsMutex;
   1516   std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
   1517                         std::unique_ptr<MaterializationResponsibility>>>
   1518       OutstandingMUs;
   1519 };
   1520 
   1521 inline ExecutionSession &MaterializationResponsibility::getExecutionSession() {
   1522   return JD->getExecutionSession();
   1523 }
   1524 
   1525 template <typename Func>
   1526 Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const {
   1527   return JD->getExecutionSession().runSessionLocked([&]() -> Error {
   1528     auto I = JD->MRTrackers.find(this);
   1529     assert(I != JD->MRTrackers.end() && "No tracker for this MR");
   1530     if (I->second->isDefunct())
   1531       return make_error<ResourceTrackerDefunct>(I->second);
   1532     F(I->second->getKeyUnsafe());
   1533     return Error::success();
   1534   });
   1535 }
   1536 
   1537 template <typename GeneratorT>
   1538 GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
   1539   auto &G = *DefGenerator;
   1540   std::lock_guard<std::mutex> Lock(GeneratorsMutex);
   1541   DefGenerators.push_back(std::move(DefGenerator));
   1542   return G;
   1543 }
   1544 
   1545 template <typename Func>
   1546 auto JITDylib::withLinkOrderDo(Func &&F)
   1547     -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
   1548   return ES.runSessionLocked([&]() { return F(LinkOrder); });
   1549 }
   1550 
   1551 template <typename MaterializationUnitType>
   1552 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
   1553                        ResourceTrackerSP RT) {
   1554   assert(MU && "Can not define with a null MU");
   1555 
   1556   if (MU->getSymbols().empty()) {
   1557     // Empty MUs are allowable but pathological, so issue a warning.
   1558     DEBUG_WITH_TYPE("orc", {
   1559       dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for "
   1560              << getName() << "\n";
   1561     });
   1562     return Error::success();
   1563   } else
   1564     DEBUG_WITH_TYPE("orc", {
   1565       dbgs() << "Defining MU " << MU->getName() << " for " << getName()
   1566              << " (tracker: ";
   1567       if (RT == getDefaultResourceTracker())
   1568         dbgs() << "default)";
   1569       else if (RT)
   1570         dbgs() << RT.get() << ")\n";
   1571       else
   1572         dbgs() << "0x0, default will be used)\n";
   1573     });
   1574 
   1575   return ES.runSessionLocked([&, this]() -> Error {
   1576     if (auto Err = defineImpl(*MU))
   1577       return Err;
   1578 
   1579     if (!RT)
   1580       RT = getDefaultResourceTracker();
   1581 
   1582     if (auto *P = ES.getPlatform()) {
   1583       if (auto Err = P->notifyAdding(*RT, *MU))
   1584         return Err;
   1585     }
   1586 
   1587     installMaterializationUnit(std::move(MU), *RT);
   1588     return Error::success();
   1589   });
   1590 }
   1591 
   1592 template <typename MaterializationUnitType>
   1593 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
   1594                        ResourceTrackerSP RT) {
   1595   assert(MU && "Can not define with a null MU");
   1596 
   1597   if (MU->getSymbols().empty()) {
   1598     // Empty MUs are allowable but pathological, so issue a warning.
   1599     DEBUG_WITH_TYPE("orc", {
   1600       dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName()
   1601              << "\n";
   1602     });
   1603     return Error::success();
   1604   } else
   1605     DEBUG_WITH_TYPE("orc", {
   1606       dbgs() << "Defining MU " << MU->getName() << " for " << getName()
   1607              << " (tracker: ";
   1608       if (RT == getDefaultResourceTracker())
   1609         dbgs() << "default)";
   1610       else if (RT)
   1611         dbgs() << RT.get() << ")\n";
   1612       else
   1613         dbgs() << "0x0, default will be used)\n";
   1614     });
   1615 
   1616   return ES.runSessionLocked([&, this]() -> Error {
   1617     if (auto Err = defineImpl(*MU))
   1618       return Err;
   1619 
   1620     if (!RT)
   1621       RT = getDefaultResourceTracker();
   1622 
   1623     if (auto *P = ES.getPlatform()) {
   1624       if (auto Err = P->notifyAdding(*RT, *MU))
   1625         return Err;
   1626     }
   1627 
   1628     installMaterializationUnit(std::move(MU), *RT);
   1629     return Error::success();
   1630   });
   1631 }
   1632 
   1633 /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
   1634 /// re-export a subset of the source JITDylib's symbols in the target.
   1635 class ReexportsGenerator : public DefinitionGenerator {
   1636 public:
   1637   using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
   1638 
   1639   /// Create a reexports generator. If an Allow predicate is passed, only
   1640   /// symbols for which the predicate returns true will be reexported. If no
   1641   /// Allow predicate is passed, all symbols will be exported.
   1642   ReexportsGenerator(JITDylib &SourceJD,
   1643                      JITDylibLookupFlags SourceJDLookupFlags,
   1644                      SymbolPredicate Allow = SymbolPredicate());
   1645 
   1646   Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
   1647                       JITDylibLookupFlags JDLookupFlags,
   1648                       const SymbolLookupSet &LookupSet) override;
   1649 
   1650 private:
   1651   JITDylib &SourceJD;
   1652   JITDylibLookupFlags SourceJDLookupFlags;
   1653   SymbolPredicate Allow;
   1654 };
   1655 
   1656 // --------------- IMPLEMENTATION --------------
   1657 // Implementations for inline functions/methods.
   1658 // ---------------------------------------------
   1659 
   1660 inline MaterializationResponsibility::~MaterializationResponsibility() {
   1661   JD->getExecutionSession().OL_destroyMaterializationResponsibility(*this);
   1662 }
   1663 
   1664 inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
   1665   return JD->getExecutionSession().OL_getRequestedSymbols(*this);
   1666 }
   1667 
   1668 inline Error MaterializationResponsibility::notifyResolved(
   1669     const SymbolMap &Symbols) {
   1670   return JD->getExecutionSession().OL_notifyResolved(*this, Symbols);
   1671 }
   1672 
   1673 inline Error MaterializationResponsibility::notifyEmitted() {
   1674   return JD->getExecutionSession().OL_notifyEmitted(*this);
   1675 }
   1676 
   1677 inline Error MaterializationResponsibility::defineMaterializing(
   1678     SymbolFlagsMap SymbolFlags) {
   1679   return JD->getExecutionSession().OL_defineMaterializing(
   1680       *this, std::move(SymbolFlags));
   1681 }
   1682 
   1683 inline void MaterializationResponsibility::failMaterialization() {
   1684   JD->getExecutionSession().OL_notifyFailed(*this);
   1685 }
   1686 
   1687 inline Error MaterializationResponsibility::replace(
   1688     std::unique_ptr<MaterializationUnit> MU) {
   1689   return JD->getExecutionSession().OL_replace(*this, std::move(MU));
   1690 }
   1691 
   1692 inline Expected<std::unique_ptr<MaterializationResponsibility>>
   1693 MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
   1694   return JD->getExecutionSession().OL_delegate(*this, Symbols);
   1695 }
   1696 
   1697 inline void MaterializationResponsibility::addDependencies(
   1698     const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
   1699   JD->getExecutionSession().OL_addDependencies(*this, Name, Dependencies);
   1700 }
   1701 
   1702 inline void MaterializationResponsibility::addDependenciesForAll(
   1703     const SymbolDependenceMap &Dependencies) {
   1704   JD->getExecutionSession().OL_addDependenciesForAll(*this, Dependencies);
   1705 }
   1706 
   1707 } // End namespace orc
   1708 } // End namespace llvm
   1709 
   1710 #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H
   1711