- //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Contains core ORC APIs. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H 
- #define LLVM_EXECUTIONENGINE_ORC_CORE_H 
-   
- #include "llvm/ADT/BitmaskEnum.h" 
- #include "llvm/ADT/DenseSet.h" 
- #include "llvm/ADT/FunctionExtras.h" 
- #include "llvm/ADT/IntrusiveRefCntPtr.h" 
- #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h" 
- #include "llvm/ExecutionEngine/JITSymbol.h" 
- #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 
- #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" 
- #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" 
- #include "llvm/Support/Debug.h" 
- #include "llvm/Support/ExtensibleRTTI.h" 
-   
- #include <atomic> 
- #include <future> 
- #include <memory> 
- #include <vector> 
-   
- namespace llvm { 
- namespace orc { 
-   
- // Forward declare some classes. 
- class AsynchronousSymbolQuery; 
- class ExecutionSession; 
- class MaterializationUnit; 
- class MaterializationResponsibility; 
- class JITDylib; 
- class ResourceTracker; 
- class InProgressLookupState; 
-   
- enum class SymbolState : uint8_t; 
-   
- using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>; 
- using JITDylibSP = IntrusiveRefCntPtr<JITDylib>; 
-   
- using ResourceKey = uintptr_t; 
-   
- /// API to remove / transfer ownership of JIT resources. 
- class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> { 
- private: 
-   friend class ExecutionSession; 
-   friend class JITDylib; 
-   friend class MaterializationResponsibility; 
-   
- public: 
-   ResourceTracker(const ResourceTracker &) = delete; 
-   ResourceTracker &operator=(const ResourceTracker &) = delete; 
-   ResourceTracker(ResourceTracker &&) = delete; 
-   ResourceTracker &operator=(ResourceTracker &&) = delete; 
-   
-   ~ResourceTracker(); 
-   
-   /// Return the JITDylib targeted by this tracker. 
-   JITDylib &getJITDylib() const { 
-     return *reinterpret_cast<JITDylib *>(JDAndFlag.load() & 
-                                          ~static_cast<uintptr_t>(1)); 
-   } 
-   
-   /// Runs the given callback under the session lock, passing in the associated 
-   /// ResourceKey. This is the safe way to associate resources with trackers. 
-   template <typename Func> Error withResourceKeyDo(Func &&F); 
-   
-   /// Remove all resources associated with this key. 
-   Error remove(); 
-   
-   /// Transfer all resources associated with this key to the given 
-   /// tracker, which must target the same JITDylib as this one. 
-   void transferTo(ResourceTracker &DstRT); 
-   
-   /// Return true if this tracker has become defunct. 
-   bool isDefunct() const { return JDAndFlag.load() & 0x1; } 
-   
-   /// Returns the key associated with this tracker. 
-   /// This method should not be used except for debug logging: there is no 
-   /// guarantee that the returned value will remain valid. 
-   ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); } 
-   
- private: 
-   ResourceTracker(JITDylibSP JD); 
-   
-   void makeDefunct(); 
-   
-   std::atomic_uintptr_t JDAndFlag; 
- }; 
-   
- /// Listens for ResourceTracker operations. 
- class ResourceManager { 
- public: 
-   virtual ~ResourceManager(); 
-   virtual Error handleRemoveResources(JITDylib &JD, ResourceKey K) = 0; 
-   virtual void handleTransferResources(JITDylib &JD, ResourceKey DstK, 
-                                        ResourceKey SrcK) = 0; 
- }; 
-   
- /// A set of symbol names (represented by SymbolStringPtrs for 
- //         efficiency). 
- using SymbolNameSet = DenseSet<SymbolStringPtr>; 
-   
- /// A vector of symbol names. 
- using SymbolNameVector = std::vector<SymbolStringPtr>; 
-   
- /// A map from symbol names (as SymbolStringPtrs) to JITSymbols 
- /// (address/flags pairs). 
- using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>; 
-   
- /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags. 
- using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>; 
-   
- /// A map from JITDylibs to sets of symbols. 
- using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>; 
-   
- /// Lookup flags that apply to each dylib in the search order for a lookup. 
- /// 
- /// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then 
- /// only symbols in that Dylib's interface will be searched. If 
- /// MatchHiddenSymbols is used then symbols with hidden visibility will match 
- /// as well. 
- enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols }; 
-   
- /// Lookup flags that apply to each symbol in a lookup. 
- /// 
- /// If RequiredSymbol is used (the default) for a given symbol then that symbol 
- /// must be found during the lookup or the lookup will fail returning a 
- /// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given 
- /// symbol is not found then the query will continue, and no result for the 
- /// missing symbol will be present in the result (assuming the rest of the 
- /// lookup succeeds). 
- enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol }; 
-   
- /// Describes the kind of lookup being performed. The lookup kind is passed to 
- /// symbol generators (if they're invoked) to help them determine what 
- /// definitions to generate. 
- /// 
- /// Static -- Lookup is being performed as-if at static link time (e.g. 
- ///           generators representing static archives should pull in new 
- ///           definitions). 
- /// 
- /// DLSym -- Lookup is being performed as-if at runtime (e.g. generators 
- ///          representing static archives should not pull in new definitions). 
- enum class LookupKind { Static, DLSym }; 
-   
- /// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search 
- /// order during symbol lookup. 
- using JITDylibSearchOrder = 
-     std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>; 
-   
- /// Convenience function for creating a search order from an ArrayRef of 
- /// JITDylib*, all with the same flags. 
- inline JITDylibSearchOrder makeJITDylibSearchOrder( 
-     ArrayRef<JITDylib *> JDs, 
-     JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) { 
-   JITDylibSearchOrder O; 
-   O.reserve(JDs.size()); 
-   for (auto *JD : JDs) 
-     O.push_back(std::make_pair(JD, Flags)); 
-   return O; 
- } 
-   
- /// A set of symbols to look up, each associated with a SymbolLookupFlags 
- /// value. 
- /// 
- /// This class is backed by a vector and optimized for fast insertion, 
- /// deletion and iteration. It does not guarantee a stable order between 
- /// operations, and will not automatically detect duplicate elements (they 
- /// can be manually checked by calling the validate method). 
- class SymbolLookupSet { 
- public: 
-   using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>; 
-   using UnderlyingVector = std::vector<value_type>; 
-   using iterator = UnderlyingVector::iterator; 
-   using const_iterator = UnderlyingVector::const_iterator; 
-   
-   SymbolLookupSet() = default; 
-   
-   explicit SymbolLookupSet( 
-       SymbolStringPtr Name, 
-       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { 
-     add(std::move(Name), Flags); 
-   } 
-   
-   /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs. 
-   explicit SymbolLookupSet( 
-       std::initializer_list<SymbolStringPtr> Names, 
-       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { 
-     Symbols.reserve(Names.size()); 
-     for (const auto &Name : Names) 
-       add(std::move(Name), Flags); 
-   } 
-   
-   /// Construct a SymbolLookupSet from a SymbolNameSet with the given 
-   /// Flags used for each value. 
-   explicit SymbolLookupSet( 
-       const SymbolNameSet &Names, 
-       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { 
-     Symbols.reserve(Names.size()); 
-     for (const auto &Name : Names) 
-       add(Name, Flags); 
-   } 
-   
-   /// Construct a SymbolLookupSet from a vector of symbols with the given Flags 
-   /// used for each value. 
-   /// If the ArrayRef contains duplicates it is up to the client to remove these 
-   /// before using this instance for lookup. 
-   explicit SymbolLookupSet( 
-       ArrayRef<SymbolStringPtr> Names, 
-       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { 
-     Symbols.reserve(Names.size()); 
-     for (const auto &Name : Names) 
-       add(Name, Flags); 
-   } 
-   
-   /// Construct a SymbolLookupSet from DenseMap keys. 
-   template <typename KeyT> 
-   static SymbolLookupSet 
-   fromMapKeys(const DenseMap<SymbolStringPtr, KeyT> &M, 
-               SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { 
-     SymbolLookupSet Result; 
-     Result.Symbols.reserve(M.size()); 
-     for (const auto &KV : M) 
-       Result.add(KV.first, Flags); 
-     return Result; 
-   } 
-   
-   /// Add an element to the set. The client is responsible for checking that 
-   /// duplicates are not added. 
-   SymbolLookupSet & 
-   add(SymbolStringPtr Name, 
-       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { 
-     Symbols.push_back(std::make_pair(std::move(Name), Flags)); 
-     return *this; 
-   } 
-   
-   /// Quickly append one lookup set to another. 
-   SymbolLookupSet &append(SymbolLookupSet Other) { 
-     Symbols.reserve(Symbols.size() + Other.size()); 
-     for (auto &KV : Other) 
-       Symbols.push_back(std::move(KV)); 
-     return *this; 
-   } 
-   
-   bool empty() const { return Symbols.empty(); } 
-   UnderlyingVector::size_type size() const { return Symbols.size(); } 
-   iterator begin() { return Symbols.begin(); } 
-   iterator end() { return Symbols.end(); } 
-   const_iterator begin() const { return Symbols.begin(); } 
-   const_iterator end() const { return Symbols.end(); } 
-   
-   /// Removes the Ith element of the vector, replacing it with the last element. 
-   void remove(UnderlyingVector::size_type I) { 
-     std::swap(Symbols[I], Symbols.back()); 
-     Symbols.pop_back(); 
-   } 
-   
-   /// Removes the element pointed to by the given iterator. This iterator and 
-   /// all subsequent ones (including end()) are invalidated. 
-   void remove(iterator I) { remove(I - begin()); } 
-   
-   /// Removes all elements matching the given predicate, which must be callable 
-   /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags). 
-   template <typename PredFn> void remove_if(PredFn &&Pred) { 
-     UnderlyingVector::size_type I = 0; 
-     while (I != Symbols.size()) { 
-       const auto &Name = Symbols[I].first; 
-       auto Flags = Symbols[I].second; 
-       if (Pred(Name, Flags)) 
-         remove(I); 
-       else 
-         ++I; 
-     } 
-   } 
-   
-   /// Loop over the elements of this SymbolLookupSet, applying the Body function 
-   /// to each one. Body must be callable as 
-   /// bool(const SymbolStringPtr &, SymbolLookupFlags). 
-   /// If Body returns true then the element just passed in is removed from the 
-   /// set. If Body returns false then the element is retained. 
-   template <typename BodyFn> 
-   auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t< 
-       std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(), 
-                                  std::declval<SymbolLookupFlags>())), 
-                    bool>::value> { 
-     UnderlyingVector::size_type I = 0; 
-     while (I != Symbols.size()) { 
-       const auto &Name = Symbols[I].first; 
-       auto Flags = Symbols[I].second; 
-       if (Body(Name, Flags)) 
-         remove(I); 
-       else 
-         ++I; 
-     } 
-   } 
-   
-   /// Loop over the elements of this SymbolLookupSet, applying the Body function 
-   /// to each one. Body must be callable as 
-   /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags). 
-   /// If Body returns a failure value, the loop exits immediately. If Body 
-   /// returns true then the element just passed in is removed from the set. If 
-   /// Body returns false then the element is retained. 
-   template <typename BodyFn> 
-   auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t< 
-       std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(), 
-                                  std::declval<SymbolLookupFlags>())), 
-                    Expected<bool>>::value, 
-       Error> { 
-     UnderlyingVector::size_type I = 0; 
-     while (I != Symbols.size()) { 
-       const auto &Name = Symbols[I].first; 
-       auto Flags = Symbols[I].second; 
-       auto Remove = Body(Name, Flags); 
-       if (!Remove) 
-         return Remove.takeError(); 
-       if (*Remove) 
-         remove(I); 
-       else 
-         ++I; 
-     } 
-     return Error::success(); 
-   } 
-   
-   /// Construct a SymbolNameVector from this instance by dropping the Flags 
-   /// values. 
-   SymbolNameVector getSymbolNames() const { 
-     SymbolNameVector Names; 
-     Names.reserve(Symbols.size()); 
-     for (const auto &KV : Symbols) 
-       Names.push_back(KV.first); 
-     return Names; 
-   } 
-   
-   /// Sort the lookup set by pointer value. This sort is fast but sensitive to 
-   /// allocation order and so should not be used where a consistent order is 
-   /// required. 
-   void sortByAddress() { llvm::sort(Symbols, llvm::less_first()); } 
-   
-   /// Sort the lookup set lexicographically. This sort is slow but the order 
-   /// is unaffected by allocation order. 
-   void sortByName() { 
-     llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) { 
-       return *LHS.first < *RHS.first; 
-     }); 
-   } 
-   
-   /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free 
-   /// by construction, this method can be used to turn it into a proper set. 
-   void removeDuplicates() { 
-     sortByAddress(); 
-     auto LastI = std::unique(Symbols.begin(), Symbols.end()); 
-     Symbols.erase(LastI, Symbols.end()); 
-   } 
-   
- #ifndef NDEBUG 
-   /// Returns true if this set contains any duplicates. This should only be used 
-   /// in assertions. 
-   bool containsDuplicates() { 
-     if (Symbols.size() < 2) 
-       return false; 
-     sortByAddress(); 
-     for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I) 
-       if (Symbols[I].first == Symbols[I - 1].first) 
-         return true; 
-     return false; 
-   } 
- #endif 
-   
- private: 
-   UnderlyingVector Symbols; 
- }; 
-   
- struct SymbolAliasMapEntry { 
-   SymbolAliasMapEntry() = default; 
-   SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) 
-       : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} 
-   
-   SymbolStringPtr Aliasee; 
-   JITSymbolFlags AliasFlags; 
- }; 
-   
- /// A map of Symbols to (Symbol, Flags) pairs. 
- using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>; 
-   
- /// Callback to notify client that symbols have been resolved. 
- using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>; 
-   
- /// Callback to register the dependencies for a given query. 
- using RegisterDependenciesFunction = 
-     std::function<void(const SymbolDependenceMap &)>; 
-   
- /// This can be used as the value for a RegisterDependenciesFunction if there 
- /// are no dependants to register with. 
- extern RegisterDependenciesFunction NoDependenciesToRegister; 
-   
- class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> { 
- public: 
-   static char ID; 
-   
-   ResourceTrackerDefunct(ResourceTrackerSP RT); 
-   std::error_code convertToErrorCode() const override; 
-   void log(raw_ostream &OS) const override; 
-   
- private: 
-   ResourceTrackerSP RT; 
- }; 
-   
- /// Used to notify a JITDylib that the given set of symbols failed to 
- /// materialize. 
- class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> { 
- public: 
-   static char ID; 
-   
-   FailedToMaterialize(std::shared_ptr<SymbolStringPool> SSP, 
-                       std::shared_ptr<SymbolDependenceMap> Symbols); 
-   ~FailedToMaterialize(); 
-   std::error_code convertToErrorCode() const override; 
-   void log(raw_ostream &OS) const override; 
-   const SymbolDependenceMap &getSymbols() const { return *Symbols; } 
-   
- private: 
-   std::shared_ptr<SymbolStringPool> SSP; 
-   std::shared_ptr<SymbolDependenceMap> Symbols; 
- }; 
-   
- /// Used to notify clients when symbols can not be found during a lookup. 
- class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> { 
- public: 
-   static char ID; 
-   
-   SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols); 
-   SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, 
-                   SymbolNameVector Symbols); 
-   std::error_code convertToErrorCode() const override; 
-   void log(raw_ostream &OS) const override; 
-   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; } 
-   const SymbolNameVector &getSymbols() const { return Symbols; } 
-   
- private: 
-   std::shared_ptr<SymbolStringPool> SSP; 
-   SymbolNameVector Symbols; 
- }; 
-   
- /// Used to notify clients that a set of symbols could not be removed. 
- class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> { 
- public: 
-   static char ID; 
-   
-   SymbolsCouldNotBeRemoved(std::shared_ptr<SymbolStringPool> SSP, 
-                            SymbolNameSet Symbols); 
-   std::error_code convertToErrorCode() const override; 
-   void log(raw_ostream &OS) const override; 
-   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; } 
-   const SymbolNameSet &getSymbols() const { return Symbols; } 
-   
- private: 
-   std::shared_ptr<SymbolStringPool> SSP; 
-   SymbolNameSet Symbols; 
- }; 
-   
- /// Errors of this type should be returned if a module fails to include 
- /// definitions that are claimed by the module's associated 
- /// MaterializationResponsibility. If this error is returned it is indicative of 
- /// a broken transformation / compiler / object cache. 
- class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> { 
- public: 
-   static char ID; 
-   
-   MissingSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP, 
-                            std::string ModuleName, SymbolNameVector Symbols) 
-       : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)), 
-         Symbols(std::move(Symbols)) {} 
-   std::error_code convertToErrorCode() const override; 
-   void log(raw_ostream &OS) const override; 
-   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; } 
-   const std::string &getModuleName() const { return ModuleName; } 
-   const SymbolNameVector &getSymbols() const { return Symbols; } 
- private: 
-   std::shared_ptr<SymbolStringPool> SSP; 
-   std::string ModuleName; 
-   SymbolNameVector Symbols; 
- }; 
-   
- /// Errors of this type should be returned if a module contains definitions for 
- /// symbols that are not claimed by the module's associated 
- /// MaterializationResponsibility. If this error is returned it is indicative of 
- /// a broken transformation / compiler / object cache. 
- class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> { 
- public: 
-   static char ID; 
-   
-   UnexpectedSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP, 
-                               std::string ModuleName, SymbolNameVector Symbols) 
-       : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)), 
-         Symbols(std::move(Symbols)) {} 
-   std::error_code convertToErrorCode() const override; 
-   void log(raw_ostream &OS) const override; 
-   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; } 
-   const std::string &getModuleName() const { return ModuleName; } 
-   const SymbolNameVector &getSymbols() const { return Symbols; } 
- private: 
-   std::shared_ptr<SymbolStringPool> SSP; 
-   std::string ModuleName; 
-   SymbolNameVector Symbols; 
- }; 
-   
- /// Tracks responsibility for materialization, and mediates interactions between 
- /// MaterializationUnits and JDs. 
- /// 
- /// An instance of this class is passed to MaterializationUnits when their 
- /// materialize method is called. It allows MaterializationUnits to resolve and 
- /// emit symbols, or abandon materialization by notifying any unmaterialized 
- /// symbols of an error. 
- class MaterializationResponsibility { 
-   friend class ExecutionSession; 
-   friend class JITDylib; 
-   
- public: 
-   MaterializationResponsibility(MaterializationResponsibility &&) = delete; 
-   MaterializationResponsibility & 
-   operator=(MaterializationResponsibility &&) = delete; 
-   
-   /// Destruct a MaterializationResponsibility instance. In debug mode 
-   ///        this asserts that all symbols being tracked have been either 
-   ///        emitted or notified of an error. 
-   ~MaterializationResponsibility(); 
-   
-   /// Runs the given callback under the session lock, passing in the associated 
-   /// ResourceKey. This is the safe way to associate resources with trackers. 
-   template <typename Func> Error withResourceKeyDo(Func &&F) const { 
-     return RT->withResourceKeyDo(std::forward<Func>(F)); 
-   } 
-   
-   /// Returns the target JITDylib that these symbols are being materialized 
-   ///        into. 
-   JITDylib &getTargetJITDylib() const { return JD; } 
-   
-   /// Returns the ExecutionSession for this instance. 
-   ExecutionSession &getExecutionSession() const; 
-   
-   /// Returns the symbol flags map for this responsibility instance. 
-   /// Note: The returned flags may have transient flags (Lazy, Materializing) 
-   /// set. These should be stripped with JITSymbolFlags::stripTransientFlags 
-   /// before using. 
-   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } 
-   
-   /// Returns the initialization pseudo-symbol, if any. This symbol will also 
-   /// be present in the SymbolFlagsMap for this MaterializationResponsibility 
-   /// object. 
-   const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; } 
-   
-   /// Returns the names of any symbols covered by this 
-   /// MaterializationResponsibility object that have queries pending. This 
-   /// information can be used to return responsibility for unrequested symbols 
-   /// back to the JITDylib via the delegate method. 
-   SymbolNameSet getRequestedSymbols() const; 
-   
-   /// Notifies the target JITDylib that the given symbols have been resolved. 
-   /// This will update the given symbols' addresses in the JITDylib, and notify 
-   /// any pending queries on the given symbols of their resolution. The given 
-   /// symbols must be ones covered by this MaterializationResponsibility 
-   /// instance. Individual calls to this method may resolve a subset of the 
-   /// symbols, but all symbols must have been resolved prior to calling emit. 
-   /// 
-   /// This method will return an error if any symbols being resolved have been 
-   /// moved to the error state due to the failure of a dependency. If this 
-   /// method returns an error then clients should log it and call 
-   /// failMaterialize. If no dependencies have been registered for the 
-   /// symbols covered by this MaterializationResponsibiility then this method 
-   /// is guaranteed to return Error::success() and can be wrapped with cantFail. 
-   Error notifyResolved(const SymbolMap &Symbols); 
-   
-   /// Notifies the target JITDylib (and any pending queries on that JITDylib) 
-   /// that all symbols covered by this MaterializationResponsibility instance 
-   /// have been emitted. 
-   /// 
-   /// This method will return an error if any symbols being resolved have been 
-   /// moved to the error state due to the failure of a dependency. If this 
-   /// method returns an error then clients should log it and call 
-   /// failMaterialize. If no dependencies have been registered for the 
-   /// symbols covered by this MaterializationResponsibiility then this method 
-   /// is guaranteed to return Error::success() and can be wrapped with cantFail. 
-   Error notifyEmitted(); 
-   
-   /// Attempt to claim responsibility for new definitions. This method can be 
-   /// used to claim responsibility for symbols that are added to a 
-   /// materialization unit during the compilation process (e.g. literal pool 
-   /// symbols). Symbol linkage rules are the same as for symbols that are 
-   /// defined up front: duplicate strong definitions will result in errors. 
-   /// Duplicate weak definitions will be discarded (in which case they will 
-   /// not be added to this responsibility instance). 
-   /// 
-   ///   This method can be used by materialization units that want to add 
-   /// additional symbols at materialization time (e.g. stubs, compile 
-   /// callbacks, metadata). 
-   Error defineMaterializing(SymbolFlagsMap SymbolFlags); 
-   
-   /// Define the given symbols as non-existent, removing it from the symbol 
-   /// table and notifying any pending queries. Queries that lookup up the 
-   /// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will 
-   /// behave as if the symbol had not been matched in the first place. Queries 
-   /// that required this symbol will fail with a missing symbol definition 
-   /// error. 
-   /// 
-   /// This method is intended to support cleanup of special symbols like 
-   /// initializer symbols: Queries using 
-   /// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their 
-   /// emission, and this method can be used to remove them from the JITDylib 
-   /// once materialization is complete. 
-   void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols); 
-   
-   /// Notify all not-yet-emitted covered by this MaterializationResponsibility 
-   /// instance that an error has occurred. 
-   /// This will remove all symbols covered by this MaterializationResponsibilty 
-   /// from the target JITDylib, and send an error to any queries waiting on 
-   /// these symbols. 
-   void failMaterialization(); 
-   
-   /// Transfers responsibility to the given MaterializationUnit for all 
-   /// symbols defined by that MaterializationUnit. This allows 
-   /// materializers to break up work based on run-time information (e.g. 
-   /// by introspecting which symbols have actually been looked up and 
-   /// materializing only those). 
-   Error replace(std::unique_ptr<MaterializationUnit> MU); 
-   
-   /// Delegates responsibility for the given symbols to the returned 
-   /// materialization responsibility. Useful for breaking up work between 
-   /// threads, or different kinds of materialization processes. 
-   Expected<std::unique_ptr<MaterializationResponsibility>> 
-   delegate(const SymbolNameSet &Symbols); 
-   
-   void addDependencies(const SymbolStringPtr &Name, 
-                        const SymbolDependenceMap &Dependencies); 
-   
-   /// Add dependencies that apply to all symbols covered by this instance. 
-   void addDependenciesForAll(const SymbolDependenceMap &Dependencies); 
-   
- private: 
-   /// Create a MaterializationResponsibility for the given JITDylib and 
-   ///        initial symbols. 
-   MaterializationResponsibility(ResourceTrackerSP RT, 
-                                 SymbolFlagsMap SymbolFlags, 
-                                 SymbolStringPtr InitSymbol) 
-       : JD(RT->getJITDylib()), RT(std::move(RT)), 
-         SymbolFlags(std::move(SymbolFlags)), InitSymbol(std::move(InitSymbol)) { 
-     assert(!this->SymbolFlags.empty() && "Materializing nothing?"); 
-   } 
-   
-   JITDylib &JD; 
-   ResourceTrackerSP RT; 
-   SymbolFlagsMap SymbolFlags; 
-   SymbolStringPtr InitSymbol; 
- }; 
-   
- /// A MaterializationUnit represents a set of symbol definitions that can 
- ///        be materialized as a group, or individually discarded (when 
- ///        overriding definitions are encountered). 
- /// 
- /// MaterializationUnits are used when providing lazy definitions of symbols to 
- /// JITDylibs. The JITDylib will call materialize when the address of a symbol 
- /// is requested via the lookup method. The JITDylib will call discard if a 
- /// stronger definition is added or already present. 
- class MaterializationUnit { 
-   friend class ExecutionSession; 
-   friend class JITDylib; 
-   
- public: 
-   static char ID; 
-   
-   struct Interface { 
-     Interface() = default; 
-     Interface(SymbolFlagsMap InitalSymbolFlags, SymbolStringPtr InitSymbol) 
-         : SymbolFlags(std::move(InitalSymbolFlags)), 
-           InitSymbol(std::move(InitSymbol)) { 
-       assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) && 
-              "If set, InitSymbol should appear in InitialSymbolFlags map"); 
-     } 
-   
-     SymbolFlagsMap SymbolFlags; 
-     SymbolStringPtr InitSymbol; 
-   }; 
-   
-   MaterializationUnit(Interface I) 
-       : SymbolFlags(std::move(I.SymbolFlags)), 
-         InitSymbol(std::move(I.InitSymbol)) {} 
-   virtual ~MaterializationUnit() = default; 
-   
-   /// Return the name of this materialization unit. Useful for debugging 
-   /// output. 
-   virtual StringRef getName() const = 0; 
-   
-   /// Return the set of symbols that this source provides. 
-   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } 
-   
-   /// Returns the initialization symbol for this MaterializationUnit (if any). 
-   const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; } 
-   
-   /// Implementations of this method should materialize all symbols 
-   ///        in the materialzation unit, except for those that have been 
-   ///        previously discarded. 
-   virtual void 
-   materialize(std::unique_ptr<MaterializationResponsibility> R) = 0; 
-   
-   /// Called by JITDylibs to notify MaterializationUnits that the given symbol 
-   /// has been overridden. 
-   void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) { 
-     SymbolFlags.erase(Name); 
-     if (InitSymbol == Name) { 
-       DEBUG_WITH_TYPE("orc", { 
-         dbgs() << "In " << getName() << ": discarding init symbol \"" 
-                << *Name << "\"\n"; 
-       }); 
-       InitSymbol = nullptr; 
-     } 
-     discard(JD, std::move(Name)); 
-   } 
-   
- protected: 
-   SymbolFlagsMap SymbolFlags; 
-   SymbolStringPtr InitSymbol; 
-   
- private: 
-   virtual void anchor(); 
-   
-   /// Implementations of this method should discard the given symbol 
-   ///        from the source (e.g. if the source is an LLVM IR Module and the 
-   ///        symbol is a function, delete the function body or mark it available 
-   ///        externally). 
-   virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0; 
- }; 
-   
- /// A MaterializationUnit implementation for pre-existing absolute symbols. 
- /// 
- /// All symbols will be resolved and marked ready as soon as the unit is 
- /// materialized. 
- class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit { 
- public: 
-   AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols); 
-   
-   StringRef getName() const override; 
-   
- private: 
-   void materialize(std::unique_ptr<MaterializationResponsibility> R) override; 
-   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; 
-   static MaterializationUnit::Interface extractFlags(const SymbolMap &Symbols); 
-   
-   SymbolMap Symbols; 
- }; 
-   
- /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols. 
- /// Useful for inserting absolute symbols into a JITDylib. E.g.: 
- /// \code{.cpp} 
- ///   JITDylib &JD = ...; 
- ///   SymbolStringPtr Foo = ...; 
- ///   JITEvaluatedSymbol FooSym = ...; 
- ///   if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}}))) 
- ///     return Err; 
- /// \endcode 
- /// 
- inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit> 
- absoluteSymbols(SymbolMap Symbols) { 
-   return std::make_unique<AbsoluteSymbolsMaterializationUnit>( 
-       std::move(Symbols)); 
- } 
-   
- /// A materialization unit for symbol aliases. Allows existing symbols to be 
- /// aliased with alternate flags. 
- class ReExportsMaterializationUnit : public MaterializationUnit { 
- public: 
-   /// SourceJD is allowed to be nullptr, in which case the source JITDylib is 
-   /// taken to be whatever JITDylib these definitions are materialized in (and 
-   /// MatchNonExported has no effect). This is useful for defining aliases 
-   /// within a JITDylib. 
-   /// 
-   /// Note: Care must be taken that no sets of aliases form a cycle, as such 
-   ///       a cycle will result in a deadlock when any symbol in the cycle is 
-   ///       resolved. 
-   ReExportsMaterializationUnit(JITDylib *SourceJD, 
-                                JITDylibLookupFlags SourceJDLookupFlags, 
-                                SymbolAliasMap Aliases); 
-   
-   StringRef getName() const override; 
-   
- private: 
-   void materialize(std::unique_ptr<MaterializationResponsibility> R) override; 
-   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; 
-   static MaterializationUnit::Interface 
-   extractFlags(const SymbolAliasMap &Aliases); 
-   
-   JITDylib *SourceJD = nullptr; 
-   JITDylibLookupFlags SourceJDLookupFlags; 
-   SymbolAliasMap Aliases; 
- }; 
-   
- /// Create a ReExportsMaterializationUnit with the given aliases. 
- /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing 
- /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" 
- /// (for "bar") with: \code{.cpp} 
- ///   SymbolStringPtr Baz = ...; 
- ///   SymbolStringPtr Qux = ...; 
- ///   if (auto Err = JD.define(symbolAliases({ 
- ///       {Baz, { Foo, JITSymbolFlags::Exported }}, 
- ///       {Qux, { Bar, JITSymbolFlags::Weak }}})) 
- ///     return Err; 
- /// \endcode 
- inline std::unique_ptr<ReExportsMaterializationUnit> 
- symbolAliases(SymbolAliasMap Aliases) { 
-   return std::make_unique<ReExportsMaterializationUnit>( 
-       nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases)); 
- } 
-   
- /// Create a materialization unit for re-exporting symbols from another JITDylib 
- /// with alternative names/flags. 
- /// SourceJD will be searched using the given JITDylibLookupFlags. 
- inline std::unique_ptr<ReExportsMaterializationUnit> 
- reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, 
-           JITDylibLookupFlags SourceJDLookupFlags = 
-               JITDylibLookupFlags::MatchExportedSymbolsOnly) { 
-   return std::make_unique<ReExportsMaterializationUnit>( 
-       &SourceJD, SourceJDLookupFlags, std::move(Aliases)); 
- } 
-   
- /// Build a SymbolAliasMap for the common case where you want to re-export 
- /// symbols from another JITDylib with the same linkage/flags. 
- Expected<SymbolAliasMap> 
- buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); 
-   
- /// Represents the state that a symbol has reached during materialization. 
- enum class SymbolState : uint8_t { 
-   Invalid,       /// No symbol should be in this state. 
-   NeverSearched, /// Added to the symbol table, never queried. 
-   Materializing, /// Queried, materialization begun. 
-   Resolved,      /// Assigned address, still materializing. 
-   Emitted,       /// Emitted to memory, but waiting on transitive dependencies. 
-   Ready = 0x3f   /// Ready and safe for clients to access. 
- }; 
-   
- /// A symbol query that returns results via a callback when results are 
- ///        ready. 
- /// 
- /// makes a callback when all symbols are available. 
- class AsynchronousSymbolQuery { 
-   friend class ExecutionSession; 
-   friend class InProgressFullLookupState; 
-   friend class JITDylib; 
-   friend class JITSymbolResolverAdapter; 
-   friend class MaterializationResponsibility; 
-   
- public: 
-   /// Create a query for the given symbols. The NotifyComplete 
-   /// callback will be called once all queried symbols reach the given 
-   /// minimum state. 
-   AsynchronousSymbolQuery(const SymbolLookupSet &Symbols, 
-                           SymbolState RequiredState, 
-                           SymbolsResolvedCallback NotifyComplete); 
-   
-   /// Notify the query that a requested symbol has reached the required state. 
-   void notifySymbolMetRequiredState(const SymbolStringPtr &Name, 
-                                     JITEvaluatedSymbol Sym); 
-   
-   /// Returns true if all symbols covered by this query have been 
-   ///        resolved. 
-   bool isComplete() const { return OutstandingSymbolsCount == 0; } 
-   
-   
- private: 
-   void handleComplete(ExecutionSession &ES); 
-   
-   SymbolState getRequiredState() { return RequiredState; } 
-   
-   void addQueryDependence(JITDylib &JD, SymbolStringPtr Name); 
-   
-   void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name); 
-   
-   void dropSymbol(const SymbolStringPtr &Name); 
-   
-   void handleFailed(Error Err); 
-   
-   void detach(); 
-   
-   SymbolsResolvedCallback NotifyComplete; 
-   SymbolDependenceMap QueryRegistrations; 
-   SymbolMap ResolvedSymbols; 
-   size_t OutstandingSymbolsCount; 
-   SymbolState RequiredState; 
- }; 
-   
- /// Wraps state for a lookup-in-progress. 
- /// DefinitionGenerators can optionally take ownership of a LookupState object 
- /// to suspend a lookup-in-progress while they search for definitions. 
- class LookupState { 
-   friend class OrcV2CAPIHelper; 
-   friend class ExecutionSession; 
-   
- public: 
-   LookupState(); 
-   LookupState(LookupState &&); 
-   LookupState &operator=(LookupState &&); 
-   ~LookupState(); 
-   
-   /// Continue the lookup. This can be called by DefinitionGenerators 
-   /// to re-start a captured query-application operation. 
-   void continueLookup(Error Err); 
-   
- private: 
-   LookupState(std::unique_ptr<InProgressLookupState> IPLS); 
-   
-   // For C API. 
-   void reset(InProgressLookupState *IPLS); 
-   
-   std::unique_ptr<InProgressLookupState> IPLS; 
- }; 
-   
- /// Definition generators can be attached to JITDylibs to generate new 
- /// definitions for otherwise unresolved symbols during lookup. 
- class DefinitionGenerator { 
- public: 
-   virtual ~DefinitionGenerator(); 
-   
-   /// DefinitionGenerators should override this method to insert new 
-   /// definitions into the parent JITDylib. K specifies the kind of this 
-   /// lookup. JD specifies the target JITDylib being searched, and 
-   /// JDLookupFlags specifies whether the search should match against 
-   /// hidden symbols. Finally, Symbols describes the set of unresolved 
-   /// symbols and their associated lookup flags. 
-   virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 
-                               JITDylibLookupFlags JDLookupFlags, 
-                               const SymbolLookupSet &LookupSet) = 0; 
- }; 
-   
- /// Represents a JIT'd dynamic library. 
- /// 
- /// This class aims to mimic the behavior of a regular dylib or shared object, 
- /// but without requiring the contained program representations to be compiled 
- /// up-front. The JITDylib's content is defined by adding MaterializationUnits, 
- /// and contained MaterializationUnits will typically rely on the JITDylib's 
- /// links-against order to resolve external references (similar to a regular 
- /// dylib). 
- /// 
- /// The JITDylib object is a thin wrapper that references state held by the 
- /// ExecutionSession. JITDylibs can be removed, clearing this underlying state 
- /// and leaving the JITDylib object in a defunct state. In this state the 
- /// JITDylib's name is guaranteed to remain accessible. If the ExecutionSession 
- /// is still alive then other operations are callable but will return an Error 
- /// or null result (depending on the API). It is illegal to call any operation 
- /// other than getName on a JITDylib after the ExecutionSession has been torn 
- /// down. 
- /// 
- /// JITDylibs cannot be moved or copied. Their address is stable, and useful as 
- /// a key in some JIT data structures. 
- class JITDylib : public ThreadSafeRefCountedBase<JITDylib>, 
-                  public jitlink::JITLinkDylib { 
-   friend class AsynchronousSymbolQuery; 
-   friend class ExecutionSession; 
-   friend class Platform; 
-   friend class MaterializationResponsibility; 
- public: 
-   
-   JITDylib(const JITDylib &) = delete; 
-   JITDylib &operator=(const JITDylib &) = delete; 
-   JITDylib(JITDylib &&) = delete; 
-   JITDylib &operator=(JITDylib &&) = delete; 
-   ~JITDylib(); 
-   
-   /// Get a reference to the ExecutionSession for this JITDylib. 
-   /// 
-   /// It is legal to call this method on a defunct JITDylib, however the result 
-   /// will only usable if the ExecutionSession is still alive. If this JITDylib 
-   /// is held by an error that may have torn down the JIT then the result 
-   /// should not be used. 
-   ExecutionSession &getExecutionSession() const { return ES; } 
-   
-   /// Dump current JITDylib state to OS. 
-   /// 
-   /// It is legal to call this method on a defunct JITDylib. 
-   void dump(raw_ostream &OS); 
-   
-   /// Calls remove on all trackers currently associated with this JITDylib. 
-   /// Does not run static deinits. 
-   /// 
-   /// Note that removal happens outside the session lock, so new code may be 
-   /// added concurrently while the clear is underway, and the newly added 
-   /// code will *not* be cleared. Adding new code concurrently with a clear 
-   /// is usually a bug and should be avoided. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   Error clear(); 
-   
-   /// Get the default resource tracker for this JITDylib. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   ResourceTrackerSP getDefaultResourceTracker(); 
-   
-   /// Create a resource tracker for this JITDylib. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   ResourceTrackerSP createResourceTracker(); 
-   
-   /// Adds a definition generator to this JITDylib and returns a referenece to 
-   /// it. 
-   /// 
-   /// When JITDylibs are searched during lookup, if no existing definition of 
-   /// a symbol is found, then any generators that have been added are run (in 
-   /// the order that they were added) to potentially generate a definition. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   template <typename GeneratorT> 
-   GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator); 
-   
-   /// Remove a definition generator from this JITDylib. 
-   /// 
-   /// The given generator must exist in this JITDylib's generators list (i.e. 
-   /// have been added and not yet removed). 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   void removeGenerator(DefinitionGenerator &G); 
-   
-   /// Set the link order to be used when fixing up definitions in JITDylib. 
-   /// This will replace the previous link order, and apply to any symbol 
-   /// resolutions made for definitions in this JITDylib after the call to 
-   /// setLinkOrder (even if the definition itself was added before the 
-   /// call). 
-   /// 
-   /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib 
-   /// will add itself to the beginning of the LinkOrder (Clients should not 
-   /// put this JITDylib in the list in this case, to avoid redundant lookups). 
-   /// 
-   /// If LinkAgainstThisJITDylibFirst is false then the link order will be used 
-   /// as-is. The primary motivation for this feature is to support deliberate 
-   /// shadowing of symbols in this JITDylib by a facade JITDylib. For example, 
-   /// the facade may resolve function names to stubs, and the stubs may compile 
-   /// lazily by looking up symbols in this dylib. Adding the facade dylib 
-   /// as the first in the link order (instead of this dylib) ensures that 
-   /// definitions within this dylib resolve to the lazy-compiling stubs, 
-   /// rather than immediately materializing the definitions in this dylib. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   void setLinkOrder(JITDylibSearchOrder NewSearchOrder, 
-                     bool LinkAgainstThisJITDylibFirst = true); 
-   
-   /// Add the given JITDylib to the link order for definitions in this 
-   /// JITDylib. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   void addToLinkOrder(JITDylib &JD, 
-                       JITDylibLookupFlags JDLookupFlags = 
-                           JITDylibLookupFlags::MatchExportedSymbolsOnly); 
-   
-   /// Replace OldJD with NewJD in the link order if OldJD is present. 
-   /// Otherwise this operation is a no-op. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD, 
-                           JITDylibLookupFlags JDLookupFlags = 
-                               JITDylibLookupFlags::MatchExportedSymbolsOnly); 
-   
-   /// Remove the given JITDylib from the link order for this JITDylib if it is 
-   /// present. Otherwise this operation is a no-op. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   void removeFromLinkOrder(JITDylib &JD); 
-   
-   /// Do something with the link order (run under the session lock). 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   template <typename Func> 
-   auto withLinkOrderDo(Func &&F) 
-       -> decltype(F(std::declval<const JITDylibSearchOrder &>())); 
-   
-   /// Define all symbols provided by the materialization unit to be part of this 
-   /// JITDylib. 
-   /// 
-   /// If RT is not specified then the default resource tracker will be used. 
-   /// 
-   /// This overload always takes ownership of the MaterializationUnit. If any 
-   /// errors occur, the MaterializationUnit consumed. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   template <typename MaterializationUnitType> 
-   Error define(std::unique_ptr<MaterializationUnitType> &&MU, 
-                ResourceTrackerSP RT = nullptr); 
-   
-   /// Define all symbols provided by the materialization unit to be part of this 
-   /// JITDylib. 
-   /// 
-   /// This overload only takes ownership of the MaterializationUnit no error is 
-   /// generated. If an error occurs, ownership remains with the caller. This 
-   /// may allow the caller to modify the MaterializationUnit to correct the 
-   /// issue, then re-call define. 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   template <typename MaterializationUnitType> 
-   Error define(std::unique_ptr<MaterializationUnitType> &MU, 
-                ResourceTrackerSP RT = nullptr); 
-   
-   /// Tries to remove the given symbols. 
-   /// 
-   /// If any symbols are not defined in this JITDylib this method will return 
-   /// a SymbolsNotFound error covering the missing symbols. 
-   /// 
-   /// If all symbols are found but some symbols are in the process of being 
-   /// materialized this method will return a SymbolsCouldNotBeRemoved error. 
-   /// 
-   /// On success, all symbols are removed. On failure, the JITDylib state is 
-   /// left unmodified (no symbols are removed). 
-   /// 
-   /// It is illegal to call this method on a defunct JITDylib and the client 
-   /// is responsible for ensuring that they do not do so. 
-   Error remove(const SymbolNameSet &Names); 
-   
-   /// Returns the given JITDylibs and all of their transitive dependencies in 
-   /// DFS order (based on linkage relationships). Each JITDylib will appear 
-   /// only once. 
-   /// 
-   /// If any JITDylib in the order is defunct then this method will return an 
-   /// error, otherwise returns the order. 
-   static Expected<std::vector<JITDylibSP>> 
-   getDFSLinkOrder(ArrayRef<JITDylibSP> JDs); 
-   
-   /// Returns the given JITDylibs and all of their transitive dependencies in 
-   /// reverse DFS order (based on linkage relationships). Each JITDylib will 
-   /// appear only once. 
-   /// 
-   /// If any JITDylib in the order is defunct then this method will return an 
-   /// error, otherwise returns the order. 
-   static Expected<std::vector<JITDylibSP>> 
-   getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs); 
-   
-   /// Return this JITDylib and its transitive dependencies in DFS order 
-   /// based on linkage relationships. 
-   /// 
-   /// If any JITDylib in the order is defunct then this method will return an 
-   /// error, otherwise returns the order. 
-   Expected<std::vector<JITDylibSP>> getDFSLinkOrder(); 
-   
-   /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order 
-   /// based on linkage relationships. 
-   /// 
-   /// If any JITDylib in the order is defunct then this method will return an 
-   /// error, otherwise returns the order. 
-   Expected<std::vector<JITDylibSP>> getReverseDFSLinkOrder(); 
-   
- private: 
-   using AsynchronousSymbolQuerySet = 
-     std::set<std::shared_ptr<AsynchronousSymbolQuery>>; 
-   
-   using AsynchronousSymbolQueryList = 
-       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>; 
-   
-   struct UnmaterializedInfo { 
-     UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU, 
-                        ResourceTracker *RT) 
-         : MU(std::move(MU)), RT(RT) {} 
-   
-     std::unique_ptr<MaterializationUnit> MU; 
-     ResourceTracker *RT; 
-   }; 
-   
-   using UnmaterializedInfosMap = 
-       DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; 
-   
-   using UnmaterializedInfosList = 
-       std::vector<std::shared_ptr<UnmaterializedInfo>>; 
-   
-   struct MaterializingInfo { 
-     SymbolDependenceMap Dependants; 
-     SymbolDependenceMap UnemittedDependencies; 
-   
-     void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q); 
-     void removeQuery(const AsynchronousSymbolQuery &Q); 
-     AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState); 
-     AsynchronousSymbolQueryList takeAllPendingQueries() { 
-       return std::move(PendingQueries); 
-     } 
-     bool hasQueriesPending() const { return !PendingQueries.empty(); } 
-     const AsynchronousSymbolQueryList &pendingQueries() const { 
-       return PendingQueries; 
-     } 
-   private: 
-     AsynchronousSymbolQueryList PendingQueries; 
-   }; 
-   
-   using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>; 
-   
-   class SymbolTableEntry { 
-   public: 
-     SymbolTableEntry() = default; 
-     SymbolTableEntry(JITSymbolFlags Flags) 
-         : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)), 
-           MaterializerAttached(false), PendingRemoval(false) {} 
-   
-     JITTargetAddress getAddress() const { return Addr; } 
-     JITSymbolFlags getFlags() const { return Flags; } 
-     SymbolState getState() const { return static_cast<SymbolState>(State); } 
-   
-     bool hasMaterializerAttached() const { return MaterializerAttached; } 
-     bool isPendingRemoval() const { return PendingRemoval; } 
-   
-     void setAddress(JITTargetAddress Addr) { this->Addr = Addr; } 
-     void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; } 
-     void setState(SymbolState State) { 
-       assert(static_cast<uint8_t>(State) < (1 << 6) && 
-              "State does not fit in bitfield"); 
-       this->State = static_cast<uint8_t>(State); 
-     } 
-   
-     void setMaterializerAttached(bool MaterializerAttached) { 
-       this->MaterializerAttached = MaterializerAttached; 
-     } 
-   
-     void setPendingRemoval(bool PendingRemoval) { 
-       this->PendingRemoval = PendingRemoval; 
-     } 
-   
-     JITEvaluatedSymbol getSymbol() const { 
-       return JITEvaluatedSymbol(Addr, Flags); 
-     } 
-   
-   private: 
-     JITTargetAddress Addr = 0; 
-     JITSymbolFlags Flags; 
-     uint8_t State : 6; 
-     uint8_t MaterializerAttached : 1; 
-     uint8_t PendingRemoval : 1; 
-   }; 
-   
-   using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>; 
-   
-   JITDylib(ExecutionSession &ES, std::string Name); 
-   
-   std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>> 
-   removeTracker(ResourceTracker &RT); 
-   
-   void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); 
-   
-   Error defineImpl(MaterializationUnit &MU); 
-   
-   void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU, 
-                                   ResourceTracker &RT); 
-   
-   void detachQueryHelper(AsynchronousSymbolQuery &Q, 
-                          const SymbolNameSet &QuerySymbols); 
-   
-   void transferEmittedNodeDependencies(MaterializingInfo &DependantMI, 
-                                        const SymbolStringPtr &DependantName, 
-                                        MaterializingInfo &EmittedMI); 
-   
-   Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags); 
-   
-   Error replace(MaterializationResponsibility &FromMR, 
-                 std::unique_ptr<MaterializationUnit> MU); 
-   
-   Expected<std::unique_ptr<MaterializationResponsibility>> 
-   delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags, 
-            SymbolStringPtr InitSymbol); 
-   
-   SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const; 
-   
-   void addDependencies(const SymbolStringPtr &Name, 
-                        const SymbolDependenceMap &Dependants); 
-   
-   Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved); 
-   
-   Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted); 
-   
-   void unlinkMaterializationResponsibility(MaterializationResponsibility &MR); 
-   
-   using FailedSymbolsWorklist = 
-       std::vector<std::pair<JITDylib *, SymbolStringPtr>>; 
-   
-   static std::pair<AsynchronousSymbolQuerySet, 
-                    std::shared_ptr<SymbolDependenceMap>> 
-       failSymbols(FailedSymbolsWorklist); 
-   
-   ExecutionSession &ES; 
-   enum { Open, Closing, Closed } State = Open; 
-   std::mutex GeneratorsMutex; 
-   SymbolTable Symbols; 
-   UnmaterializedInfosMap UnmaterializedInfos; 
-   MaterializingInfosMap MaterializingInfos; 
-   std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators; 
-   JITDylibSearchOrder LinkOrder; 
-   ResourceTrackerSP DefaultTracker; 
-   
-   // Map trackers to sets of symbols tracked. 
-   DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols; 
-   DenseMap<ResourceTracker *, DenseSet<MaterializationResponsibility *>> 
-       TrackerMRs; 
- }; 
-   
- /// Platforms set up standard symbols and mediate interactions between dynamic 
- /// initializers (e.g. C++ static constructors) and ExecutionSession state. 
- /// Note that Platforms do not automatically run initializers: clients are still 
- /// responsible for doing this. 
- class Platform { 
- public: 
-   virtual ~Platform(); 
-   
-   /// This method will be called outside the session lock each time a JITDylib 
-   /// is created (unless it is created with EmptyJITDylib set) to allow the 
-   /// Platform to install any JITDylib specific standard symbols (e.g 
-   /// __dso_handle). 
-   virtual Error setupJITDylib(JITDylib &JD) = 0; 
-   
-   /// This method will be called outside the session lock each time a JITDylib 
-   /// is removed to allow the Platform to remove any JITDylib-specific data. 
-   virtual Error teardownJITDylib(JITDylib &JD) = 0; 
-   
-   /// This method will be called under the ExecutionSession lock each time a 
-   /// MaterializationUnit is added to a JITDylib. 
-   virtual Error notifyAdding(ResourceTracker &RT, 
-                              const MaterializationUnit &MU) = 0; 
-   
-   /// This method will be called under the ExecutionSession lock when a 
-   /// ResourceTracker is removed. 
-   virtual Error notifyRemoving(ResourceTracker &RT) = 0; 
-   
-   /// A utility function for looking up initializer symbols. Performs a blocking 
-   /// lookup for the given symbols in each of the given JITDylibs. 
-   /// 
-   /// Note: This function is deprecated and will be removed in the near future. 
-   static Expected<DenseMap<JITDylib *, SymbolMap>> 
-   lookupInitSymbols(ExecutionSession &ES, 
-                     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms); 
-   
-   /// Performs an async lookup for the given symbols in each of the given 
-   /// JITDylibs, calling the given handler once all lookups have completed. 
-   static void 
-   lookupInitSymbolsAsync(unique_function<void(Error)> OnComplete, 
-                          ExecutionSession &ES, 
-                          const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms); 
- }; 
-   
- /// A materialization task. 
- class MaterializationTask : public RTTIExtends<MaterializationTask, Task> { 
- public: 
-   static char ID; 
-   
-   MaterializationTask(std::unique_ptr<MaterializationUnit> MU, 
-                       std::unique_ptr<MaterializationResponsibility> MR) 
-       : MU(std::move(MU)), MR(std::move(MR)) {} 
-   void printDescription(raw_ostream &OS) override; 
-   void run() override; 
-   
- private: 
-   std::unique_ptr<MaterializationUnit> MU; 
-   std::unique_ptr<MaterializationResponsibility> MR; 
- }; 
-   
- /// An ExecutionSession represents a running JIT program. 
- class ExecutionSession { 
-   friend class InProgressLookupFlagsState; 
-   friend class InProgressFullLookupState; 
-   friend class JITDylib; 
-   friend class LookupState; 
-   friend class MaterializationResponsibility; 
-   friend class ResourceTracker; 
-   
- public: 
-   /// For reporting errors. 
-   using ErrorReporter = std::function<void(Error)>; 
-   
-   /// Send a result to the remote. 
-   using SendResultFunction = unique_function<void(shared::WrapperFunctionResult)>; 
-   
-   /// For dispatching ORC tasks (typically materialization tasks). 
-   using DispatchTaskFunction = unique_function<void(std::unique_ptr<Task> T)>; 
-   
-   /// An asynchronous wrapper-function callable from the executor via 
-   /// jit-dispatch. 
-   using JITDispatchHandlerFunction = unique_function<void( 
-       SendResultFunction SendResult, 
-       const char *ArgData, size_t ArgSize)>; 
-   
-   /// A map associating tag names with asynchronous wrapper function 
-   /// implementations in the JIT. 
-   using JITDispatchHandlerAssociationMap = 
-       DenseMap<SymbolStringPtr, JITDispatchHandlerFunction>; 
-   
-   /// Construct an ExecutionSession with the given ExecutorProcessControl 
-   /// object. 
-   ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC); 
-   
-   /// Destroy an ExecutionSession. Verifies that endSession was called prior to 
-   /// destruction. 
-   ~ExecutionSession(); 
-   
-   /// End the session. Closes all JITDylibs and disconnects from the 
-   /// executor. Clients must call this method before destroying the session. 
-   Error endSession(); 
-   
-   /// Get the ExecutorProcessControl object associated with this 
-   /// ExecutionSession. 
-   ExecutorProcessControl &getExecutorProcessControl() { return *EPC; } 
-   
-   /// Get the SymbolStringPool for this instance. 
-   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { 
-     return EPC->getSymbolStringPool(); 
-   } 
-   
-   /// Add a symbol name to the SymbolStringPool and return a pointer to it. 
-   SymbolStringPtr intern(StringRef SymName) { return EPC->intern(SymName); } 
-   
-   /// Set the Platform for this ExecutionSession. 
-   void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); } 
-   
-   /// Get the Platform for this session. 
-   /// Will return null if no Platform has been set for this ExecutionSession. 
-   Platform *getPlatform() { return P.get(); } 
-   
-   /// Run the given lambda with the session mutex locked. 
-   template <typename Func> decltype(auto) runSessionLocked(Func &&F) { 
-     std::lock_guard<std::recursive_mutex> Lock(SessionMutex); 
-     return F(); 
-   } 
-   
-   /// Register the given ResourceManager with this ExecutionSession. 
-   /// Managers will be notified of events in reverse order of registration. 
-   void registerResourceManager(ResourceManager &RM); 
-   
-   /// Deregister the given ResourceManager with this ExecutionSession. 
-   /// Manager must have been previously registered. 
-   void deregisterResourceManager(ResourceManager &RM); 
-   
-   /// Return a pointer to the "name" JITDylib. 
-   /// Ownership of JITDylib remains within Execution Session 
-   JITDylib *getJITDylibByName(StringRef Name); 
-   
-   /// Add a new bare JITDylib to this ExecutionSession. 
-   /// 
-   /// The JITDylib Name is required to be unique. Clients should verify that 
-   /// names are not being re-used (E.g. by calling getJITDylibByName) if names 
-   /// are based on user input. 
-   /// 
-   /// This call does not install any library code or symbols into the newly 
-   /// created JITDylib. The client is responsible for all configuration. 
-   JITDylib &createBareJITDylib(std::string Name); 
-   
-   /// Add a new JITDylib to this ExecutionSession. 
-   /// 
-   /// The JITDylib Name is required to be unique. Clients should verify that 
-   /// names are not being re-used (e.g. by calling getJITDylibByName) if names 
-   /// are based on user input. 
-   /// 
-   /// If a Platform is attached then Platform::setupJITDylib will be called to 
-   /// install standard platform symbols (e.g. standard library interposes). 
-   /// If no Platform is attached this call is equivalent to createBareJITDylib. 
-   Expected<JITDylib &> createJITDylib(std::string Name); 
-   
-   /// Closes the given JITDylib. 
-   /// 
-   /// This method clears all resources held for the JITDylib, puts it in the 
-   /// closed state, and clears all references held by the ExecutionSession and 
-   /// other JITDylibs. No further code can be added to the JITDylib, and the 
-   /// object will be freed once any remaining JITDylibSPs to it are destroyed. 
-   /// 
-   /// This method does *not* run static destructors. 
-   /// 
-   /// This method can only be called once for each JITDylib. 
-   Error removeJITDylib(JITDylib &JD); 
-   
-   /// Set the error reporter function. 
-   ExecutionSession &setErrorReporter(ErrorReporter ReportError) { 
-     this->ReportError = std::move(ReportError); 
-     return *this; 
-   } 
-   
-   /// Report a error for this execution session. 
-   /// 
-   /// Unhandled errors can be sent here to log them. 
-   void reportError(Error Err) { ReportError(std::move(Err)); } 
-   
-   /// Set the task dispatch function. 
-   ExecutionSession &setDispatchTask(DispatchTaskFunction DispatchTask) { 
-     this->DispatchTask = std::move(DispatchTask); 
-     return *this; 
-   } 
-   
-   /// Search the given JITDylibs to find the flags associated with each of the 
-   /// given symbols. 
-   void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder, 
-                    SymbolLookupSet Symbols, 
-                    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete); 
-   
-   /// Blocking version of lookupFlags. 
-   Expected<SymbolFlagsMap> lookupFlags(LookupKind K, 
-                                        JITDylibSearchOrder SearchOrder, 
-                                        SymbolLookupSet Symbols); 
-   
-   /// Search the given JITDylibs for the given symbols. 
-   /// 
-   /// SearchOrder lists the JITDylibs to search. For each dylib, the associated 
-   /// boolean indicates whether the search should match against non-exported 
-   /// (hidden visibility) symbols in that dylib (true means match against 
-   /// non-exported symbols, false means do not match). 
-   /// 
-   /// The NotifyComplete callback will be called once all requested symbols 
-   /// reach the required state. 
-   /// 
-   /// If all symbols are found, the RegisterDependencies function will be called 
-   /// while the session lock is held. This gives clients a chance to register 
-   /// dependencies for on the queried symbols for any symbols they are 
-   /// materializing (if a MaterializationResponsibility instance is present, 
-   /// this can be implemented by calling 
-   /// MaterializationResponsibility::addDependencies). If there are no 
-   /// dependenant symbols for this query (e.g. it is being made by a top level 
-   /// client to get an address to call) then the value NoDependenciesToRegister 
-   /// can be used. 
-   void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, 
-               SymbolLookupSet Symbols, SymbolState RequiredState, 
-               SymbolsResolvedCallback NotifyComplete, 
-               RegisterDependenciesFunction RegisterDependencies); 
-   
-   /// Blocking version of lookup above. Returns the resolved symbol map. 
-   /// If WaitUntilReady is true (the default), will not return until all 
-   /// requested symbols are ready (or an error occurs). If WaitUntilReady is 
-   /// false, will return as soon as all requested symbols are resolved, 
-   /// or an error occurs. If WaitUntilReady is false and an error occurs 
-   /// after resolution, the function will return a success value, but the 
-   /// error will be reported via reportErrors. 
-   Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder, 
-                              SymbolLookupSet Symbols, 
-                              LookupKind K = LookupKind::Static, 
-                              SymbolState RequiredState = SymbolState::Ready, 
-                              RegisterDependenciesFunction RegisterDependencies = 
-                                  NoDependenciesToRegister); 
-   
-   /// Convenience version of blocking lookup. 
-   /// Searches each of the JITDylibs in the search order in turn for the given 
-   /// symbol. 
-   Expected<JITEvaluatedSymbol> 
-   lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol, 
-          SymbolState RequiredState = SymbolState::Ready); 
-   
-   /// Convenience version of blocking lookup. 
-   /// Searches each of the JITDylibs in the search order in turn for the given 
-   /// symbol. The search will not find non-exported symbols. 
-   Expected<JITEvaluatedSymbol> 
-   lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol, 
-          SymbolState RequiredState = SymbolState::Ready); 
-   
-   /// Convenience version of blocking lookup. 
-   /// Searches each of the JITDylibs in the search order in turn for the given 
-   /// symbol. The search will not find non-exported symbols. 
-   Expected<JITEvaluatedSymbol> 
-   lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol, 
-          SymbolState RequiredState = SymbolState::Ready); 
-   
-   /// Materialize the given unit. 
-   void dispatchTask(std::unique_ptr<Task> T) { 
-     assert(T && "T must be non-null"); 
-     DEBUG_WITH_TYPE("orc", dumpDispatchInfo(*T)); 
-     DispatchTask(std::move(T)); 
-   } 
-   
-   /// Run a wrapper function in the executor. 
-   /// 
-   /// The wrapper function should be callable as: 
-   /// 
-   /// \code{.cpp} 
-   ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size); 
-   /// \endcode{.cpp} 
-   /// 
-   /// The given OnComplete function will be called to return the result. 
-   template <typename... ArgTs> 
-   void callWrapperAsync(ArgTs &&... Args) { 
-     EPC->callWrapperAsync(std::forward<ArgTs>(Args)...); 
-   } 
-   
-   /// Run a wrapper function in the executor. The wrapper function should be 
-   /// callable as: 
-   /// 
-   /// \code{.cpp} 
-   ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size); 
-   /// \endcode{.cpp} 
-   shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr, 
-                                             ArrayRef<char> ArgBuffer) { 
-     return EPC->callWrapper(WrapperFnAddr, ArgBuffer); 
-   } 
-   
-   /// Run a wrapper function using SPS to serialize the arguments and 
-   /// deserialize the results. 
-   template <typename SPSSignature, typename SendResultT, typename... ArgTs> 
-   void callSPSWrapperAsync(ExecutorAddr WrapperFnAddr, SendResultT &&SendResult, 
-                            const ArgTs &...Args) { 
-     EPC->callSPSWrapperAsync<SPSSignature, SendResultT, ArgTs...>( 
-         WrapperFnAddr, std::forward<SendResultT>(SendResult), Args...); 
-   } 
-   
-   /// Run a wrapper function using SPS to serialize the arguments and 
-   /// deserialize the results. 
-   /// 
-   /// If SPSSignature is a non-void function signature then the second argument 
-   /// (the first in the Args list) should be a reference to a return value. 
-   template <typename SPSSignature, typename... WrapperCallArgTs> 
-   Error callSPSWrapper(ExecutorAddr WrapperFnAddr, 
-                        WrapperCallArgTs &&...WrapperCallArgs) { 
-     return EPC->callSPSWrapper<SPSSignature, WrapperCallArgTs...>( 
-         WrapperFnAddr, std::forward<WrapperCallArgTs>(WrapperCallArgs)...); 
-   } 
-   
-   /// Wrap a handler that takes concrete argument types (and a sender for a 
-   /// concrete return type) to produce an AsyncHandlerWrapperFunction. Uses SPS 
-   /// to unpack the arguments and pack the result. 
-   /// 
-   /// This function is intended to support easy construction of 
-   /// AsyncHandlerWrapperFunctions that can be associated with a tag 
-   /// (using registerJITDispatchHandler) and called from the executor. 
-   template <typename SPSSignature, typename HandlerT> 
-   static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) { 
-     return [H = std::forward<HandlerT>(H)]( 
-                SendResultFunction SendResult, 
-                const char *ArgData, size_t ArgSize) mutable { 
-       shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H, 
-                                                          std::move(SendResult)); 
-     }; 
-   } 
-   
-   /// Wrap a class method that takes concrete argument types (and a sender for 
-   /// a concrete return type) to produce an AsyncHandlerWrapperFunction. Uses 
-   /// SPS to unpack teh arguments and pack the result. 
-   /// 
-   /// This function is intended to support easy construction of 
-   /// AsyncHandlerWrapperFunctions that can be associated with a tag 
-   /// (using registerJITDispatchHandler) and called from the executor. 
-   template <typename SPSSignature, typename ClassT, typename... MethodArgTs> 
-   static JITDispatchHandlerFunction 
-   wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) { 
-     return wrapAsyncWithSPS<SPSSignature>( 
-         [Instance, Method](MethodArgTs &&...MethodArgs) { 
-           (Instance->*Method)(std::forward<MethodArgTs>(MethodArgs)...); 
-         }); 
-   } 
-   
-   /// For each tag symbol name, associate the corresponding 
-   /// AsyncHandlerWrapperFunction with the address of that symbol. The 
-   /// handler becomes callable from the executor using the ORC runtime 
-   /// __orc_rt_jit_dispatch function and the given tag. 
-   /// 
-   /// Tag symbols will be looked up in JD using LookupKind::Static, 
-   /// JITDylibLookupFlags::MatchAllSymbols (hidden tags will be found), and 
-   /// LookupFlags::WeaklyReferencedSymbol. Missing tag definitions will not 
-   /// cause an error, the handler will simply be dropped. 
-   Error registerJITDispatchHandlers(JITDylib &JD, 
-                                     JITDispatchHandlerAssociationMap WFs); 
-   
-   /// Run a registered jit-side wrapper function. 
-   /// This should be called by the ExecutorProcessControl instance in response 
-   /// to incoming jit-dispatch requests from the executor. 
-   void 
-   runJITDispatchHandler(SendResultFunction SendResult, 
-                         JITTargetAddress HandlerFnTagAddr, 
-                         ArrayRef<char> ArgBuffer); 
-   
-   /// Dump the state of all the JITDylibs in this session. 
-   void dump(raw_ostream &OS); 
-   
- private: 
-   static void logErrorsToStdErr(Error Err) { 
-     logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: "); 
-   } 
-   
-   static void runOnCurrentThread(std::unique_ptr<Task> T) { T->run(); } 
-   
-   void dispatchOutstandingMUs(); 
-   
-   static std::unique_ptr<MaterializationResponsibility> 
-   createMaterializationResponsibility(ResourceTracker &RT, 
-                                       SymbolFlagsMap Symbols, 
-                                       SymbolStringPtr InitSymbol) { 
-     auto &JD = RT.getJITDylib(); 
-     std::unique_ptr<MaterializationResponsibility> MR( 
-         new MaterializationResponsibility(&RT, std::move(Symbols), 
-                                           std::move(InitSymbol))); 
-     JD.TrackerMRs[&RT].insert(MR.get()); 
-     return MR; 
-   } 
-   
-   Error removeResourceTracker(ResourceTracker &RT); 
-   void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); 
-   void destroyResourceTracker(ResourceTracker &RT); 
-   
-   // State machine functions for query application.. 
-   
-   /// IL_updateCandidatesFor is called to remove already-defined symbols that 
-   /// match a given query from the set of candidate symbols to generate 
-   /// definitions for (no need to generate a definition if one already exists). 
-   Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags, 
-                                SymbolLookupSet &Candidates, 
-                                SymbolLookupSet *NonCandidates); 
-   
-   /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering 
-   /// definition generation. It is called when a lookup is performed, and again 
-   /// each time that LookupState::continueLookup is called. 
-   void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS, 
-                            Error Err); 
-   
-   /// OL_completeLookup is run once phase 1 successfully completes for a lookup 
-   /// call. It attempts to attach the symbol to all symbol table entries and 
-   /// collect all MaterializationUnits to dispatch. If this method fails then 
-   /// all MaterializationUnits will be left un-materialized. 
-   void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS, 
-                          std::shared_ptr<AsynchronousSymbolQuery> Q, 
-                          RegisterDependenciesFunction RegisterDependencies); 
-   
-   /// OL_completeLookupFlags is run once phase 1 successfully completes for a 
-   /// lookupFlags call. 
-   void OL_completeLookupFlags( 
-       std::unique_ptr<InProgressLookupState> IPLS, 
-       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete); 
-   
-   // State machine functions for MaterializationResponsibility. 
-   void OL_destroyMaterializationResponsibility( 
-       MaterializationResponsibility &MR); 
-   SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR); 
-   Error OL_notifyResolved(MaterializationResponsibility &MR, 
-                           const SymbolMap &Symbols); 
-   Error OL_notifyEmitted(MaterializationResponsibility &MR); 
-   Error OL_defineMaterializing(MaterializationResponsibility &MR, 
-                                SymbolFlagsMap SymbolFlags); 
-   void OL_notifyFailed(MaterializationResponsibility &MR); 
-   Error OL_replace(MaterializationResponsibility &MR, 
-                    std::unique_ptr<MaterializationUnit> MU); 
-   Expected<std::unique_ptr<MaterializationResponsibility>> 
-   OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols); 
-   void OL_addDependencies(MaterializationResponsibility &MR, 
-                           const SymbolStringPtr &Name, 
-                           const SymbolDependenceMap &Dependencies); 
-   void OL_addDependenciesForAll(MaterializationResponsibility &MR, 
-                                 const SymbolDependenceMap &Dependencies); 
-   
- #ifndef NDEBUG 
-   void dumpDispatchInfo(Task &T); 
- #endif // NDEBUG 
-   
-   mutable std::recursive_mutex SessionMutex; 
-   bool SessionOpen = true; 
-   std::unique_ptr<ExecutorProcessControl> EPC; 
-   std::unique_ptr<Platform> P; 
-   ErrorReporter ReportError = logErrorsToStdErr; 
-   DispatchTaskFunction DispatchTask = runOnCurrentThread; 
-   
-   std::vector<ResourceManager *> ResourceManagers; 
-   
-   std::vector<JITDylibSP> JDs; 
-   
-   // FIXME: Remove this (and runOutstandingMUs) once the linking layer works 
-   //        with callbacks from asynchronous queries. 
-   mutable std::recursive_mutex OutstandingMUsMutex; 
-   std::vector<std::pair<std::unique_ptr<MaterializationUnit>, 
-                         std::unique_ptr<MaterializationResponsibility>>> 
-       OutstandingMUs; 
-   
-   mutable std::mutex JITDispatchHandlersMutex; 
-   DenseMap<JITTargetAddress, std::shared_ptr<JITDispatchHandlerFunction>> 
-       JITDispatchHandlers; 
- }; 
-   
- template <typename Func> Error ResourceTracker::withResourceKeyDo(Func &&F) { 
-   return getJITDylib().getExecutionSession().runSessionLocked([&]() -> Error { 
-     if (isDefunct()) 
-       return make_error<ResourceTrackerDefunct>(this); 
-     F(getKeyUnsafe()); 
-     return Error::success(); 
-   }); 
- } 
-   
- inline ExecutionSession & 
- MaterializationResponsibility::getExecutionSession() const { 
-   return JD.getExecutionSession(); 
- } 
-   
- template <typename GeneratorT> 
- GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) { 
-   auto &G = *DefGenerator; 
-   ES.runSessionLocked([&] { 
-     assert(State == Open && "Cannot add generator to closed JITDylib"); 
-     DefGenerators.push_back(std::move(DefGenerator)); 
-   }); 
-   return G; 
- } 
-   
- template <typename Func> 
- auto JITDylib::withLinkOrderDo(Func &&F) 
-     -> decltype(F(std::declval<const JITDylibSearchOrder &>())) { 
-   assert(State == Open && "Cannot use link order of closed JITDylib"); 
-   return ES.runSessionLocked([&]() { return F(LinkOrder); }); 
- } 
-   
- template <typename MaterializationUnitType> 
- Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU, 
-                        ResourceTrackerSP RT) { 
-   assert(MU && "Can not define with a null MU"); 
-   
-   if (MU->getSymbols().empty()) { 
-     // Empty MUs are allowable but pathological, so issue a warning. 
-     DEBUG_WITH_TYPE("orc", { 
-       dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for " 
-              << getName() << "\n"; 
-     }); 
-     return Error::success(); 
-   } else 
-     DEBUG_WITH_TYPE("orc", { 
-       dbgs() << "Defining MU " << MU->getName() << " for " << getName() 
-              << " (tracker: "; 
-       if (RT == getDefaultResourceTracker()) 
-         dbgs() << "default)"; 
-       else if (RT) 
-         dbgs() << RT.get() << ")\n"; 
-       else 
-         dbgs() << "0x0, default will be used)\n"; 
-     }); 
-   
-   return ES.runSessionLocked([&, this]() -> Error { 
-     assert(State == Open && "JD is defunct"); 
-   
-     if (auto Err = defineImpl(*MU)) 
-       return Err; 
-   
-     if (!RT) 
-       RT = getDefaultResourceTracker(); 
-   
-     if (auto *P = ES.getPlatform()) { 
-       if (auto Err = P->notifyAdding(*RT, *MU)) 
-         return Err; 
-     } 
-   
-     installMaterializationUnit(std::move(MU), *RT); 
-     return Error::success(); 
-   }); 
- } 
-   
- template <typename MaterializationUnitType> 
- Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU, 
-                        ResourceTrackerSP RT) { 
-   assert(MU && "Can not define with a null MU"); 
-   
-   if (MU->getSymbols().empty()) { 
-     // Empty MUs are allowable but pathological, so issue a warning. 
-     DEBUG_WITH_TYPE("orc", { 
-       dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName() 
-              << "\n"; 
-     }); 
-     return Error::success(); 
-   } else 
-     DEBUG_WITH_TYPE("orc", { 
-       dbgs() << "Defining MU " << MU->getName() << " for " << getName() 
-              << " (tracker: "; 
-       if (RT == getDefaultResourceTracker()) 
-         dbgs() << "default)"; 
-       else if (RT) 
-         dbgs() << RT.get() << ")\n"; 
-       else 
-         dbgs() << "0x0, default will be used)\n"; 
-     }); 
-   
-   return ES.runSessionLocked([&, this]() -> Error { 
-     assert(State == Open && "JD is defunct"); 
-   
-     if (auto Err = defineImpl(*MU)) 
-       return Err; 
-   
-     if (!RT) 
-       RT = getDefaultResourceTracker(); 
-   
-     if (auto *P = ES.getPlatform()) { 
-       if (auto Err = P->notifyAdding(*RT, *MU)) 
-         return Err; 
-     } 
-   
-     installMaterializationUnit(std::move(MU), *RT); 
-     return Error::success(); 
-   }); 
- } 
-   
- /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically 
- /// re-export a subset of the source JITDylib's symbols in the target. 
- class ReexportsGenerator : public DefinitionGenerator { 
- public: 
-   using SymbolPredicate = std::function<bool(SymbolStringPtr)>; 
-   
-   /// Create a reexports generator. If an Allow predicate is passed, only 
-   /// symbols for which the predicate returns true will be reexported. If no 
-   /// Allow predicate is passed, all symbols will be exported. 
-   ReexportsGenerator(JITDylib &SourceJD, 
-                      JITDylibLookupFlags SourceJDLookupFlags, 
-                      SymbolPredicate Allow = SymbolPredicate()); 
-   
-   Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, 
-                       JITDylibLookupFlags JDLookupFlags, 
-                       const SymbolLookupSet &LookupSet) override; 
-   
- private: 
-   JITDylib &SourceJD; 
-   JITDylibLookupFlags SourceJDLookupFlags; 
-   SymbolPredicate Allow; 
- }; 
-   
- // --------------- IMPLEMENTATION -------------- 
- // Implementations for inline functions/methods. 
- // --------------------------------------------- 
-   
- inline MaterializationResponsibility::~MaterializationResponsibility() { 
-   getExecutionSession().OL_destroyMaterializationResponsibility(*this); 
- } 
-   
- inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const { 
-   return getExecutionSession().OL_getRequestedSymbols(*this); 
- } 
-   
- inline Error MaterializationResponsibility::notifyResolved( 
-     const SymbolMap &Symbols) { 
-   return getExecutionSession().OL_notifyResolved(*this, Symbols); 
- } 
-   
- inline Error MaterializationResponsibility::notifyEmitted() { 
-   return getExecutionSession().OL_notifyEmitted(*this); 
- } 
-   
- inline Error MaterializationResponsibility::defineMaterializing( 
-     SymbolFlagsMap SymbolFlags) { 
-   return getExecutionSession().OL_defineMaterializing(*this, 
-                                                       std::move(SymbolFlags)); 
- } 
-   
- inline void MaterializationResponsibility::failMaterialization() { 
-   getExecutionSession().OL_notifyFailed(*this); 
- } 
-   
- inline Error MaterializationResponsibility::replace( 
-     std::unique_ptr<MaterializationUnit> MU) { 
-   return getExecutionSession().OL_replace(*this, std::move(MU)); 
- } 
-   
- inline Expected<std::unique_ptr<MaterializationResponsibility>> 
- MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) { 
-   return getExecutionSession().OL_delegate(*this, Symbols); 
- } 
-   
- inline void MaterializationResponsibility::addDependencies( 
-     const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) { 
-   getExecutionSession().OL_addDependencies(*this, Name, Dependencies); 
- } 
-   
- inline void MaterializationResponsibility::addDependenciesForAll( 
-     const SymbolDependenceMap &Dependencies) { 
-   getExecutionSession().OL_addDependenciesForAll(*this, Dependencies); 
- } 
-   
- } // End namespace orc 
- } // End namespace llvm 
-   
- #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H 
-