Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:52

0001 //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Contains core ORC APIs.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
0014 #define LLVM_EXECUTIONENGINE_ORC_CORE_H
0015 
0016 #include "llvm/ADT/BitmaskEnum.h"
0017 #include "llvm/ADT/DenseSet.h"
0018 #include "llvm/ADT/FunctionExtras.h"
0019 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0020 #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
0021 #include "llvm/ExecutionEngine/JITSymbol.h"
0022 #include "llvm/ExecutionEngine/Orc/CoreContainers.h"
0023 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
0024 #include "llvm/ExecutionEngine/Orc/MaterializationUnit.h"
0025 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
0026 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
0027 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
0028 #include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
0029 #include "llvm/Support/Debug.h"
0030 #include "llvm/Support/ExtensibleRTTI.h"
0031 
0032 #include <atomic>
0033 #include <deque>
0034 #include <future>
0035 #include <memory>
0036 #include <vector>
0037 
0038 namespace llvm {
0039 namespace orc {
0040 
0041 // Forward declare some classes.
0042 class AsynchronousSymbolQuery;
0043 class ExecutionSession;
0044 class MaterializationResponsibility;
0045 class JITDylib;
0046 class ResourceTracker;
0047 class InProgressLookupState;
0048 
0049 enum class SymbolState : uint8_t;
0050 
0051 using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
0052 using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
0053 
0054 /// A definition of a Symbol within a JITDylib.
0055 class SymbolInstance {
0056 public:
0057   using LookupAsyncOnCompleteFn =
0058       unique_function<void(Expected<ExecutorSymbolDef>)>;
0059 
0060   SymbolInstance(JITDylibSP JD, SymbolStringPtr Name)
0061       : JD(std::move(JD)), Name(std::move(Name)) {}
0062 
0063   const JITDylib &getJITDylib() const { return *JD; }
0064   const SymbolStringPtr &getName() const { return Name; }
0065 
0066   Expected<ExecutorSymbolDef> lookup() const;
0067   void lookupAsync(LookupAsyncOnCompleteFn OnComplete) const;
0068 
0069 private:
0070   JITDylibSP JD;
0071   SymbolStringPtr Name;
0072 };
0073 
0074 using ResourceKey = uintptr_t;
0075 
0076 /// API to remove / transfer ownership of JIT resources.
0077 class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
0078 private:
0079   friend class ExecutionSession;
0080   friend class JITDylib;
0081   friend class MaterializationResponsibility;
0082 
0083 public:
0084   ResourceTracker(const ResourceTracker &) = delete;
0085   ResourceTracker &operator=(const ResourceTracker &) = delete;
0086   ResourceTracker(ResourceTracker &&) = delete;
0087   ResourceTracker &operator=(ResourceTracker &&) = delete;
0088 
0089   ~ResourceTracker();
0090 
0091   /// Return the JITDylib targeted by this tracker.
0092   JITDylib &getJITDylib() const {
0093     return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
0094                                          ~static_cast<uintptr_t>(1));
0095   }
0096 
0097   /// Runs the given callback under the session lock, passing in the associated
0098   /// ResourceKey. This is the safe way to associate resources with trackers.
0099   template <typename Func> Error withResourceKeyDo(Func &&F);
0100 
0101   /// Remove all resources associated with this key.
0102   Error remove();
0103 
0104   /// Transfer all resources associated with this key to the given
0105   /// tracker, which must target the same JITDylib as this one.
0106   void transferTo(ResourceTracker &DstRT);
0107 
0108   /// Return true if this tracker has become defunct.
0109   bool isDefunct() const { return JDAndFlag.load() & 0x1; }
0110 
0111   /// Returns the key associated with this tracker.
0112   /// This method should not be used except for debug logging: there is no
0113   /// guarantee that the returned value will remain valid.
0114   ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
0115 
0116 private:
0117   ResourceTracker(JITDylibSP JD);
0118 
0119   void makeDefunct();
0120 
0121   std::atomic_uintptr_t JDAndFlag;
0122 };
0123 
0124 /// Listens for ResourceTracker operations.
0125 class ResourceManager {
0126 public:
0127   virtual ~ResourceManager();
0128 
0129   /// This function will be called *outside* the session lock. ResourceManagers
0130   /// should perform book-keeping under the session lock, and any expensive
0131   /// cleanup outside the session lock.
0132   virtual Error handleRemoveResources(JITDylib &JD, ResourceKey K) = 0;
0133 
0134   /// This function will be called *inside* the session lock. ResourceManagers
0135   /// DO NOT need to re-lock the session.
0136   virtual void handleTransferResources(JITDylib &JD, ResourceKey DstK,
0137                                        ResourceKey SrcK) = 0;
0138 };
0139 
0140 /// Lookup flags that apply to each dylib in the search order for a lookup.
0141 ///
0142 /// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
0143 /// only symbols in that Dylib's interface will be searched. If
0144 /// MatchHiddenSymbols is used then symbols with hidden visibility will match
0145 /// as well.
0146 enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
0147 
0148 /// Lookup flags that apply to each symbol in a lookup.
0149 ///
0150 /// If RequiredSymbol is used (the default) for a given symbol then that symbol
0151 /// must be found during the lookup or the lookup will fail returning a
0152 /// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
0153 /// symbol is not found then the query will continue, and no result for the
0154 /// missing symbol will be present in the result (assuming the rest of the
0155 /// lookup succeeds).
0156 enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
0157 
0158 /// Describes the kind of lookup being performed. The lookup kind is passed to
0159 /// symbol generators (if they're invoked) to help them determine what
0160 /// definitions to generate.
0161 ///
0162 /// Static -- Lookup is being performed as-if at static link time (e.g.
0163 ///           generators representing static archives should pull in new
0164 ///           definitions).
0165 ///
0166 /// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
0167 ///          representing static archives should not pull in new definitions).
0168 enum class LookupKind { Static, DLSym };
0169 
0170 /// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
0171 /// order during symbol lookup.
0172 using JITDylibSearchOrder =
0173     std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
0174 
0175 /// Convenience function for creating a search order from an ArrayRef of
0176 /// JITDylib*, all with the same flags.
0177 inline JITDylibSearchOrder makeJITDylibSearchOrder(
0178     ArrayRef<JITDylib *> JDs,
0179     JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
0180   JITDylibSearchOrder O;
0181   O.reserve(JDs.size());
0182   for (auto *JD : JDs)
0183     O.push_back(std::make_pair(JD, Flags));
0184   return O;
0185 }
0186 
0187 /// A set of symbols to look up, each associated with a SymbolLookupFlags
0188 /// value.
0189 ///
0190 /// This class is backed by a vector and optimized for fast insertion,
0191 /// deletion and iteration. It does not guarantee a stable order between
0192 /// operations, and will not automatically detect duplicate elements (they
0193 /// can be manually checked by calling the validate method).
0194 class SymbolLookupSet {
0195 public:
0196   using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
0197   using UnderlyingVector = std::vector<value_type>;
0198   using iterator = UnderlyingVector::iterator;
0199   using const_iterator = UnderlyingVector::const_iterator;
0200 
0201   SymbolLookupSet() = default;
0202 
0203   SymbolLookupSet(std::initializer_list<value_type> Elems) {
0204     for (auto &E : Elems)
0205       Symbols.push_back(std::move(E));
0206   }
0207 
0208   explicit SymbolLookupSet(
0209       SymbolStringPtr Name,
0210       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
0211     add(std::move(Name), Flags);
0212   }
0213 
0214   /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
0215   explicit SymbolLookupSet(
0216       std::initializer_list<SymbolStringPtr> Names,
0217       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
0218     Symbols.reserve(Names.size());
0219     for (const auto &Name : Names)
0220       add(std::move(Name), Flags);
0221   }
0222 
0223   /// Construct a SymbolLookupSet from a SymbolNameSet with the given
0224   /// Flags used for each value.
0225   explicit SymbolLookupSet(
0226       const SymbolNameSet &Names,
0227       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
0228     Symbols.reserve(Names.size());
0229     for (const auto &Name : Names)
0230       add(Name, Flags);
0231   }
0232 
0233   /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
0234   /// used for each value.
0235   /// If the ArrayRef contains duplicates it is up to the client to remove these
0236   /// before using this instance for lookup.
0237   explicit SymbolLookupSet(
0238       ArrayRef<SymbolStringPtr> Names,
0239       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
0240     Symbols.reserve(Names.size());
0241     for (const auto &Name : Names)
0242       add(Name, Flags);
0243   }
0244 
0245   /// Construct a SymbolLookupSet from DenseMap keys.
0246   template <typename ValT>
0247   static SymbolLookupSet
0248   fromMapKeys(const DenseMap<SymbolStringPtr, ValT> &M,
0249               SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
0250     SymbolLookupSet Result;
0251     Result.Symbols.reserve(M.size());
0252     for (const auto &[Name, Val] : M)
0253       Result.add(Name, Flags);
0254     return Result;
0255   }
0256 
0257   /// Add an element to the set. The client is responsible for checking that
0258   /// duplicates are not added.
0259   SymbolLookupSet &
0260   add(SymbolStringPtr Name,
0261       SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
0262     Symbols.push_back(std::make_pair(std::move(Name), Flags));
0263     return *this;
0264   }
0265 
0266   /// Quickly append one lookup set to another.
0267   SymbolLookupSet &append(SymbolLookupSet Other) {
0268     Symbols.reserve(Symbols.size() + Other.size());
0269     for (auto &KV : Other)
0270       Symbols.push_back(std::move(KV));
0271     return *this;
0272   }
0273 
0274   bool empty() const { return Symbols.empty(); }
0275   UnderlyingVector::size_type size() const { return Symbols.size(); }
0276   iterator begin() { return Symbols.begin(); }
0277   iterator end() { return Symbols.end(); }
0278   const_iterator begin() const { return Symbols.begin(); }
0279   const_iterator end() const { return Symbols.end(); }
0280 
0281   /// Removes the Ith element of the vector, replacing it with the last element.
0282   void remove(UnderlyingVector::size_type I) {
0283     std::swap(Symbols[I], Symbols.back());
0284     Symbols.pop_back();
0285   }
0286 
0287   /// Removes the element pointed to by the given iterator. This iterator and
0288   /// all subsequent ones (including end()) are invalidated.
0289   void remove(iterator I) { remove(I - begin()); }
0290 
0291   /// Removes all elements matching the given predicate, which must be callable
0292   /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
0293   template <typename PredFn> void remove_if(PredFn &&Pred) {
0294     UnderlyingVector::size_type I = 0;
0295     while (I != Symbols.size()) {
0296       const auto &Name = Symbols[I].first;
0297       auto Flags = Symbols[I].second;
0298       if (Pred(Name, Flags))
0299         remove(I);
0300       else
0301         ++I;
0302     }
0303   }
0304 
0305   /// Loop over the elements of this SymbolLookupSet, applying the Body function
0306   /// to each one. Body must be callable as
0307   /// bool(const SymbolStringPtr &, SymbolLookupFlags).
0308   /// If Body returns true then the element just passed in is removed from the
0309   /// set. If Body returns false then the element is retained.
0310   template <typename BodyFn>
0311   auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
0312       std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
0313                                  std::declval<SymbolLookupFlags>())),
0314                    bool>::value> {
0315     UnderlyingVector::size_type I = 0;
0316     while (I != Symbols.size()) {
0317       const auto &Name = Symbols[I].first;
0318       auto Flags = Symbols[I].second;
0319       if (Body(Name, Flags))
0320         remove(I);
0321       else
0322         ++I;
0323     }
0324   }
0325 
0326   /// Loop over the elements of this SymbolLookupSet, applying the Body function
0327   /// to each one. Body must be callable as
0328   /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
0329   /// If Body returns a failure value, the loop exits immediately. If Body
0330   /// returns true then the element just passed in is removed from the set. If
0331   /// Body returns false then the element is retained.
0332   template <typename BodyFn>
0333   auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
0334       std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
0335                                  std::declval<SymbolLookupFlags>())),
0336                    Expected<bool>>::value,
0337       Error> {
0338     UnderlyingVector::size_type I = 0;
0339     while (I != Symbols.size()) {
0340       const auto &Name = Symbols[I].first;
0341       auto Flags = Symbols[I].second;
0342       auto Remove = Body(Name, Flags);
0343       if (!Remove)
0344         return Remove.takeError();
0345       if (*Remove)
0346         remove(I);
0347       else
0348         ++I;
0349     }
0350     return Error::success();
0351   }
0352 
0353   /// Construct a SymbolNameVector from this instance by dropping the Flags
0354   /// values.
0355   SymbolNameVector getSymbolNames() const {
0356     SymbolNameVector Names;
0357     Names.reserve(Symbols.size());
0358     for (const auto &KV : Symbols)
0359       Names.push_back(KV.first);
0360     return Names;
0361   }
0362 
0363   /// Sort the lookup set by pointer value. This sort is fast but sensitive to
0364   /// allocation order and so should not be used where a consistent order is
0365   /// required.
0366   void sortByAddress() { llvm::sort(Symbols, llvm::less_first()); }
0367 
0368   /// Sort the lookup set lexicographically. This sort is slow but the order
0369   /// is unaffected by allocation order.
0370   void sortByName() {
0371     llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
0372       return *LHS.first < *RHS.first;
0373     });
0374   }
0375 
0376   /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
0377   /// by construction, this method can be used to turn it into a proper set.
0378   void removeDuplicates() {
0379     sortByAddress();
0380     auto LastI = llvm::unique(Symbols);
0381     Symbols.erase(LastI, Symbols.end());
0382   }
0383 
0384 #ifndef NDEBUG
0385   /// Returns true if this set contains any duplicates. This should only be used
0386   /// in assertions.
0387   bool containsDuplicates() {
0388     if (Symbols.size() < 2)
0389       return false;
0390     sortByAddress();
0391     for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
0392       if (Symbols[I].first == Symbols[I - 1].first)
0393         return true;
0394     return false;
0395   }
0396 #endif
0397 
0398 private:
0399   UnderlyingVector Symbols;
0400 };
0401 
0402 struct SymbolAliasMapEntry {
0403   SymbolAliasMapEntry() = default;
0404   SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
0405       : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
0406 
0407   SymbolStringPtr Aliasee;
0408   JITSymbolFlags AliasFlags;
0409 };
0410 
0411 /// A map of Symbols to (Symbol, Flags) pairs.
0412 using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
0413 
0414 /// Callback to notify client that symbols have been resolved.
0415 using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
0416 
0417 /// Callback to register the dependencies for a given query.
0418 using RegisterDependenciesFunction =
0419     std::function<void(const SymbolDependenceMap &)>;
0420 
0421 /// This can be used as the value for a RegisterDependenciesFunction if there
0422 /// are no dependants to register with.
0423 extern RegisterDependenciesFunction NoDependenciesToRegister;
0424 
0425 class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
0426 public:
0427   static char ID;
0428 
0429   ResourceTrackerDefunct(ResourceTrackerSP RT);
0430   std::error_code convertToErrorCode() const override;
0431   void log(raw_ostream &OS) const override;
0432 
0433 private:
0434   ResourceTrackerSP RT;
0435 };
0436 
0437 /// Used to notify a JITDylib that the given set of symbols failed to
0438 /// materialize.
0439 class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
0440 public:
0441   static char ID;
0442 
0443   FailedToMaterialize(std::shared_ptr<SymbolStringPool> SSP,
0444                       std::shared_ptr<SymbolDependenceMap> Symbols);
0445   ~FailedToMaterialize();
0446   std::error_code convertToErrorCode() const override;
0447   void log(raw_ostream &OS) const override;
0448   const SymbolDependenceMap &getSymbols() const { return *Symbols; }
0449 
0450 private:
0451   std::shared_ptr<SymbolStringPool> SSP;
0452   std::shared_ptr<SymbolDependenceMap> Symbols;
0453 };
0454 
0455 /// Used to report failure due to unsatisfiable symbol dependencies.
0456 class UnsatisfiedSymbolDependencies
0457     : public ErrorInfo<UnsatisfiedSymbolDependencies> {
0458 public:
0459   static char ID;
0460 
0461   UnsatisfiedSymbolDependencies(std::shared_ptr<SymbolStringPool> SSP,
0462                                 JITDylibSP JD, SymbolNameSet FailedSymbols,
0463                                 SymbolDependenceMap BadDeps,
0464                                 std::string Explanation);
0465   std::error_code convertToErrorCode() const override;
0466   void log(raw_ostream &OS) const override;
0467 
0468 private:
0469   std::shared_ptr<SymbolStringPool> SSP;
0470   JITDylibSP JD;
0471   SymbolNameSet FailedSymbols;
0472   SymbolDependenceMap BadDeps;
0473   std::string Explanation;
0474 };
0475 
0476 /// Used to notify clients when symbols can not be found during a lookup.
0477 class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
0478 public:
0479   static char ID;
0480 
0481   SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols);
0482   SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
0483                   SymbolNameVector Symbols);
0484   std::error_code convertToErrorCode() const override;
0485   void log(raw_ostream &OS) const override;
0486   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
0487   const SymbolNameVector &getSymbols() const { return Symbols; }
0488 
0489 private:
0490   std::shared_ptr<SymbolStringPool> SSP;
0491   SymbolNameVector Symbols;
0492 };
0493 
0494 /// Used to notify clients that a set of symbols could not be removed.
0495 class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
0496 public:
0497   static char ID;
0498 
0499   SymbolsCouldNotBeRemoved(std::shared_ptr<SymbolStringPool> SSP,
0500                            SymbolNameSet Symbols);
0501   std::error_code convertToErrorCode() const override;
0502   void log(raw_ostream &OS) const override;
0503   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
0504   const SymbolNameSet &getSymbols() const { return Symbols; }
0505 
0506 private:
0507   std::shared_ptr<SymbolStringPool> SSP;
0508   SymbolNameSet Symbols;
0509 };
0510 
0511 /// Errors of this type should be returned if a module fails to include
0512 /// definitions that are claimed by the module's associated
0513 /// MaterializationResponsibility. If this error is returned it is indicative of
0514 /// a broken transformation / compiler / object cache.
0515 class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
0516 public:
0517   static char ID;
0518 
0519   MissingSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP,
0520                            std::string ModuleName, SymbolNameVector Symbols)
0521       : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)),
0522         Symbols(std::move(Symbols)) {}
0523   std::error_code convertToErrorCode() const override;
0524   void log(raw_ostream &OS) const override;
0525   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
0526   const std::string &getModuleName() const { return ModuleName; }
0527   const SymbolNameVector &getSymbols() const { return Symbols; }
0528 private:
0529   std::shared_ptr<SymbolStringPool> SSP;
0530   std::string ModuleName;
0531   SymbolNameVector Symbols;
0532 };
0533 
0534 /// Errors of this type should be returned if a module contains definitions for
0535 /// symbols that are not claimed by the module's associated
0536 /// MaterializationResponsibility. If this error is returned it is indicative of
0537 /// a broken transformation / compiler / object cache.
0538 class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
0539 public:
0540   static char ID;
0541 
0542   UnexpectedSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP,
0543                               std::string ModuleName, SymbolNameVector Symbols)
0544       : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)),
0545         Symbols(std::move(Symbols)) {}
0546   std::error_code convertToErrorCode() const override;
0547   void log(raw_ostream &OS) const override;
0548   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
0549   const std::string &getModuleName() const { return ModuleName; }
0550   const SymbolNameVector &getSymbols() const { return Symbols; }
0551 private:
0552   std::shared_ptr<SymbolStringPool> SSP;
0553   std::string ModuleName;
0554   SymbolNameVector Symbols;
0555 };
0556 
0557 /// A set of symbols and the their dependencies. Used to describe dependencies
0558 /// for the MaterializationResponsibility::notifyEmitted operation.
0559 struct SymbolDependenceGroup {
0560   SymbolNameSet Symbols;
0561   SymbolDependenceMap Dependencies;
0562 };
0563 
0564 /// Tracks responsibility for materialization, and mediates interactions between
0565 /// MaterializationUnits and JDs.
0566 ///
0567 /// An instance of this class is passed to MaterializationUnits when their
0568 /// materialize method is called. It allows MaterializationUnits to resolve and
0569 /// emit symbols, or abandon materialization by notifying any unmaterialized
0570 /// symbols of an error.
0571 class MaterializationResponsibility {
0572   friend class ExecutionSession;
0573   friend class JITDylib;
0574 
0575 public:
0576   MaterializationResponsibility(MaterializationResponsibility &&) = delete;
0577   MaterializationResponsibility &
0578   operator=(MaterializationResponsibility &&) = delete;
0579 
0580   /// Destruct a MaterializationResponsibility instance. In debug mode
0581   ///        this asserts that all symbols being tracked have been either
0582   ///        emitted or notified of an error.
0583   ~MaterializationResponsibility();
0584 
0585   /// Return the ResourceTracker associated with this instance.
0586   const ResourceTrackerSP &getResourceTracker() const { return RT; }
0587 
0588   /// Runs the given callback under the session lock, passing in the associated
0589   /// ResourceKey. This is the safe way to associate resources with trackers.
0590   template <typename Func> Error withResourceKeyDo(Func &&F) const {
0591     return RT->withResourceKeyDo(std::forward<Func>(F));
0592   }
0593 
0594   /// Returns the target JITDylib that these symbols are being materialized
0595   ///        into.
0596   JITDylib &getTargetJITDylib() const { return JD; }
0597 
0598   /// Returns the ExecutionSession for this instance.
0599   ExecutionSession &getExecutionSession() const;
0600 
0601   /// Returns the symbol flags map for this responsibility instance.
0602   /// Note: The returned flags may have transient flags (Lazy, Materializing)
0603   /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
0604   /// before using.
0605   const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
0606 
0607   /// Returns the initialization pseudo-symbol, if any. This symbol will also
0608   /// be present in the SymbolFlagsMap for this MaterializationResponsibility
0609   /// object.
0610   const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
0611 
0612   /// Returns the names of any symbols covered by this
0613   /// MaterializationResponsibility object that have queries pending. This
0614   /// information can be used to return responsibility for unrequested symbols
0615   /// back to the JITDylib via the delegate method.
0616   SymbolNameSet getRequestedSymbols() const;
0617 
0618   /// Notifies the target JITDylib that the given symbols have been resolved.
0619   /// This will update the given symbols' addresses in the JITDylib, and notify
0620   /// any pending queries on the given symbols of their resolution. The given
0621   /// symbols must be ones covered by this MaterializationResponsibility
0622   /// instance. Individual calls to this method may resolve a subset of the
0623   /// symbols, but all symbols must have been resolved prior to calling emit.
0624   ///
0625   /// This method will return an error if any symbols being resolved have been
0626   /// moved to the error state due to the failure of a dependency. If this
0627   /// method returns an error then clients should log it and call
0628   /// failMaterialize. If no dependencies have been registered for the
0629   /// symbols covered by this MaterializationResponsibility then this method
0630   /// is guaranteed to return Error::success() and can be wrapped with cantFail.
0631   Error notifyResolved(const SymbolMap &Symbols);
0632 
0633   /// Notifies the target JITDylib (and any pending queries on that JITDylib)
0634   /// that all symbols covered by this MaterializationResponsibility instance
0635   /// have been emitted.
0636   ///
0637   /// The DepGroups array describes the dependencies of symbols being emitted on
0638   /// symbols that are outside this MaterializationResponsibility object. Each
0639   /// group consists of a pair of a set of symbols and a SymbolDependenceMap
0640   /// that describes the dependencies for the symbols in the first set. The
0641   /// elements of DepGroups must be non-overlapping (no symbol should appear in
0642   /// more than one of hte symbol sets), but do not have to be exhaustive. Any
0643   /// symbol in this MaterializationResponsibility object that is not covered
0644   /// by an entry will be treated as having no dependencies.
0645   ///
0646   /// This method will return an error if any symbols being resolved have been
0647   /// moved to the error state due to the failure of a dependency. If this
0648   /// method returns an error then clients should log it and call
0649   /// failMaterialize. If no dependencies have been registered for the
0650   /// symbols covered by this MaterializationResponsibility then this method
0651   /// is guaranteed to return Error::success() and can be wrapped with cantFail.
0652   Error notifyEmitted(ArrayRef<SymbolDependenceGroup> DepGroups);
0653 
0654   /// Attempt to claim responsibility for new definitions. This method can be
0655   /// used to claim responsibility for symbols that are added to a
0656   /// materialization unit during the compilation process (e.g. literal pool
0657   /// symbols). Symbol linkage rules are the same as for symbols that are
0658   /// defined up front: duplicate strong definitions will result in errors.
0659   /// Duplicate weak definitions will be discarded (in which case they will
0660   /// not be added to this responsibility instance).
0661   ///
0662   ///   This method can be used by materialization units that want to add
0663   /// additional symbols at materialization time (e.g. stubs, compile
0664   /// callbacks, metadata).
0665   Error defineMaterializing(SymbolFlagsMap SymbolFlags);
0666 
0667   /// Notify all not-yet-emitted covered by this MaterializationResponsibility
0668   /// instance that an error has occurred.
0669   /// This will remove all symbols covered by this MaterializationResponsibility
0670   /// from the target JITDylib, and send an error to any queries waiting on
0671   /// these symbols.
0672   void failMaterialization();
0673 
0674   /// Transfers responsibility to the given MaterializationUnit for all
0675   /// symbols defined by that MaterializationUnit. This allows
0676   /// materializers to break up work based on run-time information (e.g.
0677   /// by introspecting which symbols have actually been looked up and
0678   /// materializing only those).
0679   Error replace(std::unique_ptr<MaterializationUnit> MU);
0680 
0681   /// Delegates responsibility for the given symbols to the returned
0682   /// materialization responsibility. Useful for breaking up work between
0683   /// threads, or different kinds of materialization processes.
0684   Expected<std::unique_ptr<MaterializationResponsibility>>
0685   delegate(const SymbolNameSet &Symbols);
0686 
0687 private:
0688   /// Create a MaterializationResponsibility for the given JITDylib and
0689   ///        initial symbols.
0690   MaterializationResponsibility(ResourceTrackerSP RT,
0691                                 SymbolFlagsMap SymbolFlags,
0692                                 SymbolStringPtr InitSymbol)
0693       : JD(RT->getJITDylib()), RT(std::move(RT)),
0694         SymbolFlags(std::move(SymbolFlags)), InitSymbol(std::move(InitSymbol)) {
0695     assert(!this->SymbolFlags.empty() && "Materializing nothing?");
0696   }
0697 
0698   JITDylib &JD;
0699   ResourceTrackerSP RT;
0700   SymbolFlagsMap SymbolFlags;
0701   SymbolStringPtr InitSymbol;
0702 };
0703 
0704 /// A materialization unit for symbol aliases. Allows existing symbols to be
0705 /// aliased with alternate flags.
0706 class ReExportsMaterializationUnit : public MaterializationUnit {
0707 public:
0708   /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
0709   /// taken to be whatever JITDylib these definitions are materialized in (and
0710   /// MatchNonExported has no effect). This is useful for defining aliases
0711   /// within a JITDylib.
0712   ///
0713   /// Note: Care must be taken that no sets of aliases form a cycle, as such
0714   ///       a cycle will result in a deadlock when any symbol in the cycle is
0715   ///       resolved.
0716   ReExportsMaterializationUnit(JITDylib *SourceJD,
0717                                JITDylibLookupFlags SourceJDLookupFlags,
0718                                SymbolAliasMap Aliases);
0719 
0720   StringRef getName() const override;
0721 
0722 private:
0723   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
0724   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
0725   static MaterializationUnit::Interface
0726   extractFlags(const SymbolAliasMap &Aliases);
0727 
0728   JITDylib *SourceJD = nullptr;
0729   JITDylibLookupFlags SourceJDLookupFlags;
0730   SymbolAliasMap Aliases;
0731 };
0732 
0733 /// Create a ReExportsMaterializationUnit with the given aliases.
0734 /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
0735 /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
0736 /// (for "bar") with: \code{.cpp}
0737 ///   SymbolStringPtr Baz = ...;
0738 ///   SymbolStringPtr Qux = ...;
0739 ///   if (auto Err = JD.define(symbolAliases({
0740 ///       {Baz, { Foo, JITSymbolFlags::Exported }},
0741 ///       {Qux, { Bar, JITSymbolFlags::Weak }}}))
0742 ///     return Err;
0743 /// \endcode
0744 inline std::unique_ptr<ReExportsMaterializationUnit>
0745 symbolAliases(SymbolAliasMap Aliases) {
0746   return std::make_unique<ReExportsMaterializationUnit>(
0747       nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
0748 }
0749 
0750 /// Create a materialization unit for re-exporting symbols from another JITDylib
0751 /// with alternative names/flags.
0752 /// SourceJD will be searched using the given JITDylibLookupFlags.
0753 inline std::unique_ptr<ReExportsMaterializationUnit>
0754 reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
0755           JITDylibLookupFlags SourceJDLookupFlags =
0756               JITDylibLookupFlags::MatchExportedSymbolsOnly) {
0757   return std::make_unique<ReExportsMaterializationUnit>(
0758       &SourceJD, SourceJDLookupFlags, std::move(Aliases));
0759 }
0760 
0761 /// Build a SymbolAliasMap for the common case where you want to re-export
0762 /// symbols from another JITDylib with the same linkage/flags.
0763 Expected<SymbolAliasMap>
0764 buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
0765 
0766 /// Represents the state that a symbol has reached during materialization.
0767 enum class SymbolState : uint8_t {
0768   Invalid,       /// No symbol should be in this state.
0769   NeverSearched, /// Added to the symbol table, never queried.
0770   Materializing, /// Queried, materialization begun.
0771   Resolved,      /// Assigned address, still materializing.
0772   Emitted,       /// Emitted to memory, but waiting on transitive dependencies.
0773   Ready = 0x3f   /// Ready and safe for clients to access.
0774 };
0775 
0776 /// A symbol query that returns results via a callback when results are
0777 ///        ready.
0778 ///
0779 /// makes a callback when all symbols are available.
0780 class AsynchronousSymbolQuery {
0781   friend class ExecutionSession;
0782   friend class InProgressFullLookupState;
0783   friend class JITDylib;
0784   friend class JITSymbolResolverAdapter;
0785   friend class MaterializationResponsibility;
0786 
0787 public:
0788   /// Create a query for the given symbols. The NotifyComplete
0789   /// callback will be called once all queried symbols reach the given
0790   /// minimum state.
0791   AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
0792                           SymbolState RequiredState,
0793                           SymbolsResolvedCallback NotifyComplete);
0794 
0795   /// Notify the query that a requested symbol has reached the required state.
0796   void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
0797                                     ExecutorSymbolDef Sym);
0798 
0799   /// Returns true if all symbols covered by this query have been
0800   ///        resolved.
0801   bool isComplete() const { return OutstandingSymbolsCount == 0; }
0802 
0803 
0804 private:
0805   void handleComplete(ExecutionSession &ES);
0806 
0807   SymbolState getRequiredState() { return RequiredState; }
0808 
0809   void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
0810 
0811   void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
0812 
0813   void dropSymbol(const SymbolStringPtr &Name);
0814 
0815   void handleFailed(Error Err);
0816 
0817   void detach();
0818 
0819   SymbolsResolvedCallback NotifyComplete;
0820   SymbolDependenceMap QueryRegistrations;
0821   SymbolMap ResolvedSymbols;
0822   size_t OutstandingSymbolsCount;
0823   SymbolState RequiredState;
0824 };
0825 
0826 /// Wraps state for a lookup-in-progress.
0827 /// DefinitionGenerators can optionally take ownership of a LookupState object
0828 /// to suspend a lookup-in-progress while they search for definitions.
0829 class LookupState {
0830   friend class OrcV2CAPIHelper;
0831   friend class ExecutionSession;
0832 
0833 public:
0834   LookupState();
0835   LookupState(LookupState &&);
0836   LookupState &operator=(LookupState &&);
0837   ~LookupState();
0838 
0839   /// Continue the lookup. This can be called by DefinitionGenerators
0840   /// to re-start a captured query-application operation.
0841   void continueLookup(Error Err);
0842 
0843 private:
0844   LookupState(std::unique_ptr<InProgressLookupState> IPLS);
0845 
0846   // For C API.
0847   void reset(InProgressLookupState *IPLS);
0848 
0849   std::unique_ptr<InProgressLookupState> IPLS;
0850 };
0851 
0852 /// Definition generators can be attached to JITDylibs to generate new
0853 /// definitions for otherwise unresolved symbols during lookup.
0854 class DefinitionGenerator {
0855   friend class ExecutionSession;
0856 
0857 public:
0858   virtual ~DefinitionGenerator();
0859 
0860   /// DefinitionGenerators should override this method to insert new
0861   /// definitions into the parent JITDylib. K specifies the kind of this
0862   /// lookup. JD specifies the target JITDylib being searched, and
0863   /// JDLookupFlags specifies whether the search should match against
0864   /// hidden symbols. Finally, Symbols describes the set of unresolved
0865   /// symbols and their associated lookup flags.
0866   virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
0867                               JITDylibLookupFlags JDLookupFlags,
0868                               const SymbolLookupSet &LookupSet) = 0;
0869 
0870 private:
0871   std::mutex M;
0872   bool InUse = false;
0873   std::deque<LookupState> PendingLookups;
0874 };
0875 
0876 /// Represents a JIT'd dynamic library.
0877 ///
0878 /// This class aims to mimic the behavior of a regular dylib or shared object,
0879 /// but without requiring the contained program representations to be compiled
0880 /// up-front. The JITDylib's content is defined by adding MaterializationUnits,
0881 /// and contained MaterializationUnits will typically rely on the JITDylib's
0882 /// links-against order to resolve external references (similar to a regular
0883 /// dylib).
0884 ///
0885 /// The JITDylib object is a thin wrapper that references state held by the
0886 /// ExecutionSession. JITDylibs can be removed, clearing this underlying state
0887 /// and leaving the JITDylib object in a defunct state. In this state the
0888 /// JITDylib's name is guaranteed to remain accessible. If the ExecutionSession
0889 /// is still alive then other operations are callable but will return an Error
0890 /// or null result (depending on the API). It is illegal to call any operation
0891 /// other than getName on a JITDylib after the ExecutionSession has been torn
0892 /// down.
0893 ///
0894 /// JITDylibs cannot be moved or copied. Their address is stable, and useful as
0895 /// a key in some JIT data structures.
0896 class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
0897                  public jitlink::JITLinkDylib {
0898   friend class AsynchronousSymbolQuery;
0899   friend class ExecutionSession;
0900   friend class Platform;
0901   friend class MaterializationResponsibility;
0902 public:
0903 
0904   JITDylib(const JITDylib &) = delete;
0905   JITDylib &operator=(const JITDylib &) = delete;
0906   JITDylib(JITDylib &&) = delete;
0907   JITDylib &operator=(JITDylib &&) = delete;
0908   ~JITDylib();
0909 
0910   /// Get a reference to the ExecutionSession for this JITDylib.
0911   ///
0912   /// It is legal to call this method on a defunct JITDylib, however the result
0913   /// will only usable if the ExecutionSession is still alive. If this JITDylib
0914   /// is held by an error that may have torn down the JIT then the result
0915   /// should not be used.
0916   ExecutionSession &getExecutionSession() const { return ES; }
0917 
0918   /// Dump current JITDylib state to OS.
0919   ///
0920   /// It is legal to call this method on a defunct JITDylib.
0921   void dump(raw_ostream &OS);
0922 
0923   /// Calls remove on all trackers currently associated with this JITDylib.
0924   /// Does not run static deinits.
0925   ///
0926   /// Note that removal happens outside the session lock, so new code may be
0927   /// added concurrently while the clear is underway, and the newly added
0928   /// code will *not* be cleared. Adding new code concurrently with a clear
0929   /// is usually a bug and should be avoided.
0930   ///
0931   /// It is illegal to call this method on a defunct JITDylib and the client
0932   /// is responsible for ensuring that they do not do so.
0933   Error clear();
0934 
0935   /// Get the default resource tracker for this JITDylib.
0936   ///
0937   /// It is illegal to call this method on a defunct JITDylib and the client
0938   /// is responsible for ensuring that they do not do so.
0939   ResourceTrackerSP getDefaultResourceTracker();
0940 
0941   /// Create a resource tracker for this JITDylib.
0942   ///
0943   /// It is illegal to call this method on a defunct JITDylib and the client
0944   /// is responsible for ensuring that they do not do so.
0945   ResourceTrackerSP createResourceTracker();
0946 
0947   /// Adds a definition generator to this JITDylib and returns a referenece to
0948   /// it.
0949   ///
0950   /// When JITDylibs are searched during lookup, if no existing definition of
0951   /// a symbol is found, then any generators that have been added are run (in
0952   /// the order that they were added) to potentially generate a definition.
0953   ///
0954   /// It is illegal to call this method on a defunct JITDylib and the client
0955   /// is responsible for ensuring that they do not do so.
0956   template <typename GeneratorT>
0957   GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
0958 
0959   /// Remove a definition generator from this JITDylib.
0960   ///
0961   /// The given generator must exist in this JITDylib's generators list (i.e.
0962   /// have been added and not yet removed).
0963   ///
0964   /// It is illegal to call this method on a defunct JITDylib and the client
0965   /// is responsible for ensuring that they do not do so.
0966   void removeGenerator(DefinitionGenerator &G);
0967 
0968   /// Set the link order to be used when fixing up definitions in JITDylib.
0969   /// This will replace the previous link order, and apply to any symbol
0970   /// resolutions made for definitions in this JITDylib after the call to
0971   /// setLinkOrder (even if the definition itself was added before the
0972   /// call).
0973   ///
0974   /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib
0975   /// will add itself to the beginning of the LinkOrder (Clients should not
0976   /// put this JITDylib in the list in this case, to avoid redundant lookups).
0977   ///
0978   /// If LinkAgainstThisJITDylibFirst is false then the link order will be used
0979   /// as-is. The primary motivation for this feature is to support deliberate
0980   /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
0981   /// the facade may resolve function names to stubs, and the stubs may compile
0982   /// lazily by looking up symbols in this dylib. Adding the facade dylib
0983   /// as the first in the link order (instead of this dylib) ensures that
0984   /// definitions within this dylib resolve to the lazy-compiling stubs,
0985   /// rather than immediately materializing the definitions in this dylib.
0986   ///
0987   /// It is illegal to call this method on a defunct JITDylib and the client
0988   /// is responsible for ensuring that they do not do so.
0989   void setLinkOrder(JITDylibSearchOrder NewSearchOrder,
0990                     bool LinkAgainstThisJITDylibFirst = true);
0991 
0992   /// Append the given JITDylibSearchOrder to the link order for this
0993   /// JITDylib (discarding any elements already present in this JITDylib's
0994   /// link order).
0995   void addToLinkOrder(const JITDylibSearchOrder &NewLinks);
0996 
0997   /// Add the given JITDylib to the link order for definitions in this
0998   /// JITDylib.
0999   ///
1000   /// It is illegal to call this method on a defunct JITDylib and the client
1001   /// is responsible for ensuring that they do not do so.
1002   void addToLinkOrder(JITDylib &JD,
1003                       JITDylibLookupFlags JDLookupFlags =
1004                           JITDylibLookupFlags::MatchExportedSymbolsOnly);
1005 
1006   /// Replace OldJD with NewJD in the link order if OldJD is present.
1007   /// Otherwise this operation is a no-op.
1008   ///
1009   /// It is illegal to call this method on a defunct JITDylib and the client
1010   /// is responsible for ensuring that they do not do so.
1011   void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1012                           JITDylibLookupFlags JDLookupFlags =
1013                               JITDylibLookupFlags::MatchExportedSymbolsOnly);
1014 
1015   /// Remove the given JITDylib from the link order for this JITDylib if it is
1016   /// present. Otherwise this operation is a no-op.
1017   ///
1018   /// It is illegal to call this method on a defunct JITDylib and the client
1019   /// is responsible for ensuring that they do not do so.
1020   void removeFromLinkOrder(JITDylib &JD);
1021 
1022   /// Do something with the link order (run under the session lock).
1023   ///
1024   /// It is illegal to call this method on a defunct JITDylib and the client
1025   /// is responsible for ensuring that they do not do so.
1026   template <typename Func>
1027   auto withLinkOrderDo(Func &&F)
1028       -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
1029 
1030   /// Define all symbols provided by the materialization unit to be part of this
1031   /// JITDylib.
1032   ///
1033   /// If RT is not specified then the default resource tracker will be used.
1034   ///
1035   /// This overload always takes ownership of the MaterializationUnit. If any
1036   /// errors occur, the MaterializationUnit consumed.
1037   ///
1038   /// It is illegal to call this method on a defunct JITDylib and the client
1039   /// is responsible for ensuring that they do not do so.
1040   template <typename MaterializationUnitType>
1041   Error define(std::unique_ptr<MaterializationUnitType> &&MU,
1042                ResourceTrackerSP RT = nullptr);
1043 
1044   /// Define all symbols provided by the materialization unit to be part of this
1045   /// JITDylib.
1046   ///
1047   /// This overload only takes ownership of the MaterializationUnit no error is
1048   /// generated. If an error occurs, ownership remains with the caller. This
1049   /// may allow the caller to modify the MaterializationUnit to correct the
1050   /// issue, then re-call define.
1051   ///
1052   /// It is illegal to call this method on a defunct JITDylib and the client
1053   /// is responsible for ensuring that they do not do so.
1054   template <typename MaterializationUnitType>
1055   Error define(std::unique_ptr<MaterializationUnitType> &MU,
1056                ResourceTrackerSP RT = nullptr);
1057 
1058   /// Tries to remove the given symbols.
1059   ///
1060   /// If any symbols are not defined in this JITDylib this method will return
1061   /// a SymbolsNotFound error covering the missing symbols.
1062   ///
1063   /// If all symbols are found but some symbols are in the process of being
1064   /// materialized this method will return a SymbolsCouldNotBeRemoved error.
1065   ///
1066   /// On success, all symbols are removed. On failure, the JITDylib state is
1067   /// left unmodified (no symbols are removed).
1068   ///
1069   /// It is illegal to call this method on a defunct JITDylib and the client
1070   /// is responsible for ensuring that they do not do so.
1071   Error remove(const SymbolNameSet &Names);
1072 
1073   /// Returns the given JITDylibs and all of their transitive dependencies in
1074   /// DFS order (based on linkage relationships). Each JITDylib will appear
1075   /// only once.
1076   ///
1077   /// If any JITDylib in the order is defunct then this method will return an
1078   /// error, otherwise returns the order.
1079   static Expected<std::vector<JITDylibSP>>
1080   getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1081 
1082   /// Returns the given JITDylibs and all of their transitive dependencies in
1083   /// reverse DFS order (based on linkage relationships). Each JITDylib will
1084   /// appear only once.
1085   ///
1086   /// If any JITDylib in the order is defunct then this method will return an
1087   /// error, otherwise returns the order.
1088   static Expected<std::vector<JITDylibSP>>
1089   getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1090 
1091   /// Return this JITDylib and its transitive dependencies in DFS order
1092   /// based on linkage relationships.
1093   ///
1094   /// If any JITDylib in the order is defunct then this method will return an
1095   /// error, otherwise returns the order.
1096   Expected<std::vector<JITDylibSP>> getDFSLinkOrder();
1097 
1098   /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
1099   /// based on linkage relationships.
1100   ///
1101   /// If any JITDylib in the order is defunct then this method will return an
1102   /// error, otherwise returns the order.
1103   Expected<std::vector<JITDylibSP>> getReverseDFSLinkOrder();
1104 
1105 private:
1106   using AsynchronousSymbolQuerySet =
1107     std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
1108 
1109   using AsynchronousSymbolQueryList =
1110       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
1111 
1112   struct UnmaterializedInfo {
1113     UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
1114                        ResourceTracker *RT)
1115         : MU(std::move(MU)), RT(RT) {}
1116 
1117     std::unique_ptr<MaterializationUnit> MU;
1118     ResourceTracker *RT;
1119   };
1120 
1121   using UnmaterializedInfosMap =
1122       DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
1123 
1124   using UnmaterializedInfosList =
1125       std::vector<std::shared_ptr<UnmaterializedInfo>>;
1126 
1127   struct EmissionDepUnit {
1128     EmissionDepUnit(JITDylib &JD) : JD(&JD) {}
1129 
1130     JITDylib *JD = nullptr;
1131     DenseMap<NonOwningSymbolStringPtr, JITSymbolFlags> Symbols;
1132     DenseMap<JITDylib *, DenseSet<NonOwningSymbolStringPtr>> Dependencies;
1133   };
1134 
1135   struct EmissionDepUnitInfo {
1136     std::shared_ptr<EmissionDepUnit> EDU;
1137     DenseSet<EmissionDepUnit *> IntraEmitUsers;
1138     DenseMap<JITDylib *, DenseSet<NonOwningSymbolStringPtr>> NewDeps;
1139   };
1140 
1141   // Information about not-yet-ready symbol.
1142   // * DefiningEDU will point to the EmissionDepUnit that defines the symbol.
1143   // * DependantEDUs will hold pointers to any EmissionDepUnits currently
1144   //   waiting on this symbol.
1145   // * Pending queries holds any not-yet-completed queries that include this
1146   //   symbol.
1147   struct MaterializingInfo {
1148     friend class ExecutionSession;
1149 
1150     std::shared_ptr<EmissionDepUnit> DefiningEDU;
1151     DenseSet<EmissionDepUnit *> DependantEDUs;
1152 
1153     void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
1154     void removeQuery(const AsynchronousSymbolQuery &Q);
1155     AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
1156     AsynchronousSymbolQueryList takeAllPendingQueries() {
1157       return std::move(PendingQueries);
1158     }
1159     bool hasQueriesPending() const { return !PendingQueries.empty(); }
1160     const AsynchronousSymbolQueryList &pendingQueries() const {
1161       return PendingQueries;
1162     }
1163   private:
1164     AsynchronousSymbolQueryList PendingQueries;
1165   };
1166 
1167   using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
1168 
1169   class SymbolTableEntry {
1170   public:
1171     SymbolTableEntry() = default;
1172     SymbolTableEntry(JITSymbolFlags Flags)
1173         : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
1174           MaterializerAttached(false) {}
1175 
1176     ExecutorAddr getAddress() const { return Addr; }
1177     JITSymbolFlags getFlags() const { return Flags; }
1178     SymbolState getState() const { return static_cast<SymbolState>(State); }
1179 
1180     bool hasMaterializerAttached() const { return MaterializerAttached; }
1181 
1182     void setAddress(ExecutorAddr Addr) { this->Addr = Addr; }
1183     void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; }
1184     void setState(SymbolState State) {
1185       assert(static_cast<uint8_t>(State) < (1 << 6) &&
1186              "State does not fit in bitfield");
1187       this->State = static_cast<uint8_t>(State);
1188     }
1189 
1190     void setMaterializerAttached(bool MaterializerAttached) {
1191       this->MaterializerAttached = MaterializerAttached;
1192     }
1193 
1194     ExecutorSymbolDef getSymbol() const { return {Addr, Flags}; }
1195 
1196   private:
1197     ExecutorAddr Addr;
1198     JITSymbolFlags Flags;
1199     uint8_t State : 7;
1200     uint8_t MaterializerAttached : 1;
1201   };
1202 
1203   using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
1204 
1205   JITDylib(ExecutionSession &ES, std::string Name);
1206 
1207   struct RemoveTrackerResult {
1208     AsynchronousSymbolQuerySet QueriesToFail;
1209     std::shared_ptr<SymbolDependenceMap> FailedSymbols;
1210     std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs;
1211   };
1212 
1213   RemoveTrackerResult IL_removeTracker(ResourceTracker &RT);
1214 
1215   void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1216 
1217   Error defineImpl(MaterializationUnit &MU);
1218 
1219   void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
1220                                   ResourceTracker &RT);
1221 
1222   void detachQueryHelper(AsynchronousSymbolQuery &Q,
1223                          const SymbolNameSet &QuerySymbols);
1224 
1225   void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
1226                                        const SymbolStringPtr &DependantName,
1227                                        MaterializingInfo &EmittedMI);
1228 
1229   Expected<SymbolFlagsMap>
1230   defineMaterializing(MaterializationResponsibility &FromMR,
1231                       SymbolFlagsMap SymbolFlags);
1232 
1233   Error replace(MaterializationResponsibility &FromMR,
1234                 std::unique_ptr<MaterializationUnit> MU);
1235 
1236   Expected<std::unique_ptr<MaterializationResponsibility>>
1237   delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
1238            SymbolStringPtr InitSymbol);
1239 
1240   SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
1241 
1242   void addDependencies(const SymbolStringPtr &Name,
1243                        const SymbolDependenceMap &Dependants);
1244 
1245   Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
1246 
1247   void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
1248 
1249   /// Attempt to reduce memory usage from empty \c UnmaterializedInfos and
1250   /// \c MaterializingInfos tables.
1251   void shrinkMaterializationInfoMemory();
1252 
1253   ExecutionSession &ES;
1254   enum { Open, Closing, Closed } State = Open;
1255   std::mutex GeneratorsMutex;
1256   SymbolTable Symbols;
1257   UnmaterializedInfosMap UnmaterializedInfos;
1258   MaterializingInfosMap MaterializingInfos;
1259   std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
1260   JITDylibSearchOrder LinkOrder;
1261   ResourceTrackerSP DefaultTracker;
1262 
1263   // Map trackers to sets of symbols tracked.
1264   DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
1265   DenseMap<ResourceTracker *, DenseSet<MaterializationResponsibility *>>
1266       TrackerMRs;
1267 };
1268 
1269 /// Platforms set up standard symbols and mediate interactions between dynamic
1270 /// initializers (e.g. C++ static constructors) and ExecutionSession state.
1271 /// Note that Platforms do not automatically run initializers: clients are still
1272 /// responsible for doing this.
1273 class Platform {
1274 public:
1275   virtual ~Platform();
1276 
1277   /// This method will be called outside the session lock each time a JITDylib
1278   /// is created (unless it is created with EmptyJITDylib set) to allow the
1279   /// Platform to install any JITDylib specific standard symbols (e.g
1280   /// __dso_handle).
1281   virtual Error setupJITDylib(JITDylib &JD) = 0;
1282 
1283   /// This method will be called outside the session lock each time a JITDylib
1284   /// is removed to allow the Platform to remove any JITDylib-specific data.
1285   virtual Error teardownJITDylib(JITDylib &JD) = 0;
1286 
1287   /// This method will be called under the ExecutionSession lock each time a
1288   /// MaterializationUnit is added to a JITDylib.
1289   virtual Error notifyAdding(ResourceTracker &RT,
1290                              const MaterializationUnit &MU) = 0;
1291 
1292   /// This method will be called under the ExecutionSession lock when a
1293   /// ResourceTracker is removed.
1294   virtual Error notifyRemoving(ResourceTracker &RT) = 0;
1295 
1296   /// A utility function for looking up initializer symbols. Performs a blocking
1297   /// lookup for the given symbols in each of the given JITDylibs.
1298   ///
1299   /// Note: This function is deprecated and will be removed in the near future.
1300   static Expected<DenseMap<JITDylib *, SymbolMap>>
1301   lookupInitSymbols(ExecutionSession &ES,
1302                     const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1303 
1304   /// Performs an async lookup for the given symbols in each of the given
1305   /// JITDylibs, calling the given handler once all lookups have completed.
1306   static void
1307   lookupInitSymbolsAsync(unique_function<void(Error)> OnComplete,
1308                          ExecutionSession &ES,
1309                          const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1310 };
1311 
1312 /// A materialization task.
1313 class MaterializationTask : public RTTIExtends<MaterializationTask, Task> {
1314 public:
1315   static char ID;
1316 
1317   MaterializationTask(std::unique_ptr<MaterializationUnit> MU,
1318                       std::unique_ptr<MaterializationResponsibility> MR)
1319       : MU(std::move(MU)), MR(std::move(MR)) {}
1320   ~MaterializationTask() override;
1321   void printDescription(raw_ostream &OS) override;
1322   void run() override;
1323 
1324 private:
1325   std::unique_ptr<MaterializationUnit> MU;
1326   std::unique_ptr<MaterializationResponsibility> MR;
1327 };
1328 
1329 /// Lookups are usually run on the current thread, but in some cases they may
1330 /// be run as tasks, e.g. if the lookup has been continued from a suspended
1331 /// state.
1332 class LookupTask : public RTTIExtends<LookupTask, Task> {
1333 public:
1334   static char ID;
1335 
1336   LookupTask(LookupState LS) : LS(std::move(LS)) {}
1337   void printDescription(raw_ostream &OS) override;
1338   void run() override;
1339 
1340 private:
1341   LookupState LS;
1342 };
1343 
1344 /// An ExecutionSession represents a running JIT program.
1345 class ExecutionSession {
1346   friend class InProgressLookupFlagsState;
1347   friend class InProgressFullLookupState;
1348   friend class JITDylib;
1349   friend class LookupState;
1350   friend class MaterializationResponsibility;
1351   friend class ResourceTracker;
1352 
1353 public:
1354   /// For reporting errors.
1355   using ErrorReporter = unique_function<void(Error)>;
1356 
1357   /// Send a result to the remote.
1358   using SendResultFunction = unique_function<void(shared::WrapperFunctionResult)>;
1359 
1360   /// An asynchronous wrapper-function callable from the executor via
1361   /// jit-dispatch.
1362   using JITDispatchHandlerFunction = unique_function<void(
1363       SendResultFunction SendResult,
1364       const char *ArgData, size_t ArgSize)>;
1365 
1366   /// A map associating tag names with asynchronous wrapper function
1367   /// implementations in the JIT.
1368   using JITDispatchHandlerAssociationMap =
1369       DenseMap<SymbolStringPtr, JITDispatchHandlerFunction>;
1370 
1371   /// Construct an ExecutionSession with the given ExecutorProcessControl
1372   /// object.
1373   ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC);
1374 
1375   /// Destroy an ExecutionSession. Verifies that endSession was called prior to
1376   /// destruction.
1377   ~ExecutionSession();
1378 
1379   /// End the session. Closes all JITDylibs and disconnects from the
1380   /// executor. Clients must call this method before destroying the session.
1381   Error endSession();
1382 
1383   /// Get the ExecutorProcessControl object associated with this
1384   /// ExecutionSession.
1385   ExecutorProcessControl &getExecutorProcessControl() { return *EPC; }
1386 
1387   /// Return the triple for the executor.
1388   const Triple &getTargetTriple() const { return EPC->getTargetTriple(); }
1389 
1390   // Return the page size for the executor.
1391   size_t getPageSize() const { return EPC->getPageSize(); }
1392 
1393   /// Get the SymbolStringPool for this instance.
1394   std::shared_ptr<SymbolStringPool> getSymbolStringPool() {
1395     return EPC->getSymbolStringPool();
1396   }
1397 
1398   /// Add a symbol name to the SymbolStringPool and return a pointer to it.
1399   SymbolStringPtr intern(StringRef SymName) { return EPC->intern(SymName); }
1400 
1401   /// Set the Platform for this ExecutionSession.
1402   void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
1403 
1404   /// Get the Platform for this session.
1405   /// Will return null if no Platform has been set for this ExecutionSession.
1406   Platform *getPlatform() { return P.get(); }
1407 
1408   /// Run the given lambda with the session mutex locked.
1409   template <typename Func> decltype(auto) runSessionLocked(Func &&F) {
1410     std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
1411     return F();
1412   }
1413 
1414   /// Register the given ResourceManager with this ExecutionSession.
1415   /// Managers will be notified of events in reverse order of registration.
1416   void registerResourceManager(ResourceManager &RM);
1417 
1418   /// Deregister the given ResourceManager with this ExecutionSession.
1419   /// Manager must have been previously registered.
1420   void deregisterResourceManager(ResourceManager &RM);
1421 
1422   /// Return a pointer to the "name" JITDylib.
1423   /// Ownership of JITDylib remains within Execution Session
1424   JITDylib *getJITDylibByName(StringRef Name);
1425 
1426   /// Add a new bare JITDylib to this ExecutionSession.
1427   ///
1428   /// The JITDylib Name is required to be unique. Clients should verify that
1429   /// names are not being re-used (E.g. by calling getJITDylibByName) if names
1430   /// are based on user input.
1431   ///
1432   /// This call does not install any library code or symbols into the newly
1433   /// created JITDylib. The client is responsible for all configuration.
1434   JITDylib &createBareJITDylib(std::string Name);
1435 
1436   /// Add a new JITDylib to this ExecutionSession.
1437   ///
1438   /// The JITDylib Name is required to be unique. Clients should verify that
1439   /// names are not being re-used (e.g. by calling getJITDylibByName) if names
1440   /// are based on user input.
1441   ///
1442   /// If a Platform is attached then Platform::setupJITDylib will be called to
1443   /// install standard platform symbols (e.g. standard library interposes).
1444   /// If no Platform is attached this call is equivalent to createBareJITDylib.
1445   Expected<JITDylib &> createJITDylib(std::string Name);
1446 
1447   /// Removes the given JITDylibs from the ExecutionSession.
1448   ///
1449   /// This method clears all resources held for the JITDylibs, puts them in the
1450   /// closed state, and clears all references to them that are held by the
1451   /// ExecutionSession or other JITDylibs. No further code can be added to the
1452   /// removed JITDylibs, and the JITDylib objects will be freed once any
1453   /// remaining JITDylibSPs pointing to them are destroyed.
1454   ///
1455   /// This method does *not* run static destructors for code contained in the
1456   /// JITDylibs, and each JITDylib can only be removed once.
1457   ///
1458   /// JITDylibs will be removed in the order given. Teardown is usually
1459   /// independent for each JITDylib, but not always. In particular, where the
1460   /// ORC runtime is used it is expected that teardown off all JITDylibs will
1461   /// depend on it, so the JITDylib containing the ORC runtime must be removed
1462   /// last. If the client has introduced any other dependencies they should be
1463   /// accounted for in the removal order too.
1464   Error removeJITDylibs(std::vector<JITDylibSP> JDsToRemove);
1465 
1466   /// Calls removeJTIDylibs on the gives JITDylib.
1467   Error removeJITDylib(JITDylib &JD) {
1468     return removeJITDylibs(std::vector<JITDylibSP>({&JD}));
1469   }
1470 
1471   /// Set the error reporter function.
1472   ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
1473     this->ReportError = std::move(ReportError);
1474     return *this;
1475   }
1476 
1477   /// Report a error for this execution session.
1478   ///
1479   /// Unhandled errors can be sent here to log them.
1480   void reportError(Error Err) { ReportError(std::move(Err)); }
1481 
1482   /// Search the given JITDylibs to find the flags associated with each of the
1483   /// given symbols.
1484   void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1485                    SymbolLookupSet Symbols,
1486                    unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1487 
1488   /// Blocking version of lookupFlags.
1489   Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
1490                                        JITDylibSearchOrder SearchOrder,
1491                                        SymbolLookupSet Symbols);
1492 
1493   /// Search the given JITDylibs for the given symbols.
1494   ///
1495   /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
1496   /// boolean indicates whether the search should match against non-exported
1497   /// (hidden visibility) symbols in that dylib (true means match against
1498   /// non-exported symbols, false means do not match).
1499   ///
1500   /// The NotifyComplete callback will be called once all requested symbols
1501   /// reach the required state.
1502   ///
1503   /// If all symbols are found, the RegisterDependencies function will be called
1504   /// while the session lock is held. This gives clients a chance to register
1505   /// dependencies for on the queried symbols for any symbols they are
1506   /// materializing (if a MaterializationResponsibility instance is present,
1507   /// this can be implemented by calling
1508   /// MaterializationResponsibility::addDependencies). If there are no
1509   /// dependenant symbols for this query (e.g. it is being made by a top level
1510   /// client to get an address to call) then the value NoDependenciesToRegister
1511   /// can be used.
1512   void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
1513               SymbolLookupSet Symbols, SymbolState RequiredState,
1514               SymbolsResolvedCallback NotifyComplete,
1515               RegisterDependenciesFunction RegisterDependencies);
1516 
1517   /// Blocking version of lookup above. Returns the resolved symbol map.
1518   /// If WaitUntilReady is true (the default), will not return until all
1519   /// requested symbols are ready (or an error occurs). If WaitUntilReady is
1520   /// false, will return as soon as all requested symbols are resolved,
1521   /// or an error occurs. If WaitUntilReady is false and an error occurs
1522   /// after resolution, the function will return a success value, but the
1523   /// error will be reported via reportErrors.
1524   Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
1525                              SymbolLookupSet Symbols,
1526                              LookupKind K = LookupKind::Static,
1527                              SymbolState RequiredState = SymbolState::Ready,
1528                              RegisterDependenciesFunction RegisterDependencies =
1529                                  NoDependenciesToRegister);
1530 
1531   /// Convenience version of blocking lookup.
1532   /// Searches each of the JITDylibs in the search order in turn for the given
1533   /// symbol.
1534   Expected<ExecutorSymbolDef>
1535   lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,
1536          SymbolState RequiredState = SymbolState::Ready);
1537 
1538   /// Convenience version of blocking lookup.
1539   /// Searches each of the JITDylibs in the search order in turn for the given
1540   /// symbol. The search will not find non-exported symbols.
1541   Expected<ExecutorSymbolDef>
1542   lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,
1543          SymbolState RequiredState = SymbolState::Ready);
1544 
1545   /// Convenience version of blocking lookup.
1546   /// Searches each of the JITDylibs in the search order in turn for the given
1547   /// symbol. The search will not find non-exported symbols.
1548   Expected<ExecutorSymbolDef>
1549   lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,
1550          SymbolState RequiredState = SymbolState::Ready);
1551 
1552   /// Materialize the given unit.
1553   void dispatchTask(std::unique_ptr<Task> T) {
1554     assert(T && "T must be non-null");
1555     DEBUG_WITH_TYPE("orc", dumpDispatchInfo(*T));
1556     EPC->getDispatcher().dispatch(std::move(T));
1557   }
1558 
1559   /// Returns the bootstrap map.
1560   const StringMap<std::vector<char>> &getBootstrapMap() const {
1561     return EPC->getBootstrapMap();
1562   }
1563 
1564   /// Look up and SPS-deserialize a bootstrap map value.
1565   template <typename T, typename SPSTagT>
1566   Error getBootstrapMapValue(StringRef Key, std::optional<T> &Val) const {
1567     return EPC->getBootstrapMapValue<T, SPSTagT>(Key, Val);
1568   }
1569 
1570   /// Returns the bootstrap symbol map.
1571   const StringMap<ExecutorAddr> &getBootstrapSymbolsMap() const {
1572     return EPC->getBootstrapSymbolsMap();
1573   }
1574 
1575   /// For each (ExecutorAddr&, StringRef) pair, looks up the string in the
1576   /// bootstrap symbols map and writes its address to the ExecutorAddr if
1577   /// found. If any symbol is not found then the function returns an error.
1578   Error getBootstrapSymbols(
1579       ArrayRef<std::pair<ExecutorAddr &, StringRef>> Pairs) const {
1580     return EPC->getBootstrapSymbols(Pairs);
1581   }
1582 
1583   /// Run a wrapper function in the executor.
1584   ///
1585   /// The wrapper function should be callable as:
1586   ///
1587   /// \code{.cpp}
1588   ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
1589   /// \endcode{.cpp}
1590   ///
1591   /// The given OnComplete function will be called to return the result.
1592   template <typename... ArgTs>
1593   void callWrapperAsync(ArgTs &&... Args) {
1594     EPC->callWrapperAsync(std::forward<ArgTs>(Args)...);
1595   }
1596 
1597   /// Run a wrapper function in the executor. The wrapper function should be
1598   /// callable as:
1599   ///
1600   /// \code{.cpp}
1601   ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
1602   /// \endcode{.cpp}
1603   shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr,
1604                                             ArrayRef<char> ArgBuffer) {
1605     return EPC->callWrapper(WrapperFnAddr, ArgBuffer);
1606   }
1607 
1608   /// Run a wrapper function using SPS to serialize the arguments and
1609   /// deserialize the results.
1610   template <typename SPSSignature, typename SendResultT, typename... ArgTs>
1611   void callSPSWrapperAsync(ExecutorAddr WrapperFnAddr, SendResultT &&SendResult,
1612                            const ArgTs &...Args) {
1613     EPC->callSPSWrapperAsync<SPSSignature, SendResultT, ArgTs...>(
1614         WrapperFnAddr, std::forward<SendResultT>(SendResult), Args...);
1615   }
1616 
1617   /// Run a wrapper function using SPS to serialize the arguments and
1618   /// deserialize the results.
1619   ///
1620   /// If SPSSignature is a non-void function signature then the second argument
1621   /// (the first in the Args list) should be a reference to a return value.
1622   template <typename SPSSignature, typename... WrapperCallArgTs>
1623   Error callSPSWrapper(ExecutorAddr WrapperFnAddr,
1624                        WrapperCallArgTs &&...WrapperCallArgs) {
1625     return EPC->callSPSWrapper<SPSSignature, WrapperCallArgTs...>(
1626         WrapperFnAddr, std::forward<WrapperCallArgTs>(WrapperCallArgs)...);
1627   }
1628 
1629   /// Wrap a handler that takes concrete argument types (and a sender for a
1630   /// concrete return type) to produce an AsyncHandlerWrapperFunction. Uses SPS
1631   /// to unpack the arguments and pack the result.
1632   ///
1633   /// This function is intended to support easy construction of
1634   /// AsyncHandlerWrapperFunctions that can be associated with a tag
1635   /// (using registerJITDispatchHandler) and called from the executor.
1636   template <typename SPSSignature, typename HandlerT>
1637   static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) {
1638     return [H = std::forward<HandlerT>(H)](
1639                SendResultFunction SendResult,
1640                const char *ArgData, size_t ArgSize) mutable {
1641       shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
1642                                                          std::move(SendResult));
1643     };
1644   }
1645 
1646   /// Wrap a class method that takes concrete argument types (and a sender for
1647   /// a concrete return type) to produce an AsyncHandlerWrapperFunction. Uses
1648   /// SPS to unpack the arguments and pack the result.
1649   ///
1650   /// This function is intended to support easy construction of
1651   /// AsyncHandlerWrapperFunctions that can be associated with a tag
1652   /// (using registerJITDispatchHandler) and called from the executor.
1653   template <typename SPSSignature, typename ClassT, typename... MethodArgTs>
1654   static JITDispatchHandlerFunction
1655   wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) {
1656     return wrapAsyncWithSPS<SPSSignature>(
1657         [Instance, Method](MethodArgTs &&...MethodArgs) {
1658           (Instance->*Method)(std::forward<MethodArgTs>(MethodArgs)...);
1659         });
1660   }
1661 
1662   /// For each tag symbol name, associate the corresponding
1663   /// AsyncHandlerWrapperFunction with the address of that symbol. The
1664   /// handler becomes callable from the executor using the ORC runtime
1665   /// __orc_rt_jit_dispatch function and the given tag.
1666   ///
1667   /// Tag symbols will be looked up in JD using LookupKind::Static,
1668   /// JITDylibLookupFlags::MatchAllSymbols (hidden tags will be found), and
1669   /// LookupFlags::WeaklyReferencedSymbol. Missing tag definitions will not
1670   /// cause an error, the handler will simply be dropped.
1671   Error registerJITDispatchHandlers(JITDylib &JD,
1672                                     JITDispatchHandlerAssociationMap WFs);
1673 
1674   /// Run a registered jit-side wrapper function.
1675   /// This should be called by the ExecutorProcessControl instance in response
1676   /// to incoming jit-dispatch requests from the executor.
1677   void runJITDispatchHandler(SendResultFunction SendResult,
1678                              ExecutorAddr HandlerFnTagAddr,
1679                              ArrayRef<char> ArgBuffer);
1680 
1681   /// Dump the state of all the JITDylibs in this session.
1682   void dump(raw_ostream &OS);
1683 
1684   /// Check the internal consistency of ExecutionSession data structures.
1685 #ifdef EXPENSIVE_CHECKS
1686   bool verifySessionState(Twine Phase);
1687 #endif
1688 
1689 private:
1690   static void logErrorsToStdErr(Error Err) {
1691     logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
1692   }
1693 
1694   void dispatchOutstandingMUs();
1695 
1696   static std::unique_ptr<MaterializationResponsibility>
1697   createMaterializationResponsibility(ResourceTracker &RT,
1698                                       SymbolFlagsMap Symbols,
1699                                       SymbolStringPtr InitSymbol) {
1700     auto &JD = RT.getJITDylib();
1701     std::unique_ptr<MaterializationResponsibility> MR(
1702         new MaterializationResponsibility(&RT, std::move(Symbols),
1703                                           std::move(InitSymbol)));
1704     JD.TrackerMRs[&RT].insert(MR.get());
1705     return MR;
1706   }
1707 
1708   Error removeResourceTracker(ResourceTracker &RT);
1709   void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1710   void destroyResourceTracker(ResourceTracker &RT);
1711 
1712   // State machine functions for query application..
1713 
1714   /// IL_updateCandidatesFor is called to remove already-defined symbols that
1715   /// match a given query from the set of candidate symbols to generate
1716   /// definitions for (no need to generate a definition if one already exists).
1717   Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
1718                                SymbolLookupSet &Candidates,
1719                                SymbolLookupSet *NonCandidates);
1720 
1721   /// Handle resumption of a lookup after entering a generator.
1722   void OL_resumeLookupAfterGeneration(InProgressLookupState &IPLS);
1723 
1724   /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
1725   /// definition generation. It is called when a lookup is performed, and again
1726   /// each time that LookupState::continueLookup is called.
1727   void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
1728                            Error Err);
1729 
1730   /// OL_completeLookup is run once phase 1 successfully completes for a lookup
1731   /// call. It attempts to attach the symbol to all symbol table entries and
1732   /// collect all MaterializationUnits to dispatch. If this method fails then
1733   /// all MaterializationUnits will be left un-materialized.
1734   void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
1735                          std::shared_ptr<AsynchronousSymbolQuery> Q,
1736                          RegisterDependenciesFunction RegisterDependencies);
1737 
1738   /// OL_completeLookupFlags is run once phase 1 successfully completes for a
1739   /// lookupFlags call.
1740   void OL_completeLookupFlags(
1741       std::unique_ptr<InProgressLookupState> IPLS,
1742       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1743 
1744   // State machine functions for MaterializationResponsibility.
1745   void OL_destroyMaterializationResponsibility(
1746       MaterializationResponsibility &MR);
1747   SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
1748   Error OL_notifyResolved(MaterializationResponsibility &MR,
1749                           const SymbolMap &Symbols);
1750 
1751   using EDUInfosMap =
1752       DenseMap<JITDylib::EmissionDepUnit *, JITDylib::EmissionDepUnitInfo>;
1753 
1754   template <typename HandleNewDepFn>
1755   void propagateExtraEmitDeps(std::deque<JITDylib::EmissionDepUnit *> Worklist,
1756                               EDUInfosMap &EDUInfos,
1757                               HandleNewDepFn HandleNewDep);
1758   EDUInfosMap simplifyDepGroups(MaterializationResponsibility &MR,
1759                                 ArrayRef<SymbolDependenceGroup> EmittedDeps);
1760   void IL_makeEDUReady(std::shared_ptr<JITDylib::EmissionDepUnit> EDU,
1761                        JITDylib::AsynchronousSymbolQuerySet &Queries);
1762   void IL_makeEDUEmitted(std::shared_ptr<JITDylib::EmissionDepUnit> EDU,
1763                          JITDylib::AsynchronousSymbolQuerySet &Queries);
1764   bool IL_removeEDUDependence(JITDylib::EmissionDepUnit &EDU, JITDylib &DepJD,
1765                               NonOwningSymbolStringPtr DepSym,
1766                               EDUInfosMap &EDUInfos);
1767 
1768   static Error makeJDClosedError(JITDylib::EmissionDepUnit &EDU,
1769                                  JITDylib &ClosedJD);
1770   static Error makeUnsatisfiedDepsError(JITDylib::EmissionDepUnit &EDU,
1771                                         JITDylib &BadJD, SymbolNameSet BadDeps);
1772 
1773   Expected<JITDylib::AsynchronousSymbolQuerySet>
1774   IL_emit(MaterializationResponsibility &MR, EDUInfosMap EDUInfos);
1775   Error OL_notifyEmitted(MaterializationResponsibility &MR,
1776                          ArrayRef<SymbolDependenceGroup> EmittedDeps);
1777 
1778   Error OL_defineMaterializing(MaterializationResponsibility &MR,
1779                                SymbolFlagsMap SymbolFlags);
1780 
1781   std::pair<JITDylib::AsynchronousSymbolQuerySet,
1782             std::shared_ptr<SymbolDependenceMap>>
1783   IL_failSymbols(JITDylib &JD, const SymbolNameVector &SymbolsToFail);
1784   void OL_notifyFailed(MaterializationResponsibility &MR);
1785   Error OL_replace(MaterializationResponsibility &MR,
1786                    std::unique_ptr<MaterializationUnit> MU);
1787   Expected<std::unique_ptr<MaterializationResponsibility>>
1788   OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols);
1789 
1790 #ifndef NDEBUG
1791   void dumpDispatchInfo(Task &T);
1792 #endif // NDEBUG
1793 
1794   mutable std::recursive_mutex SessionMutex;
1795   bool SessionOpen = true;
1796   std::unique_ptr<ExecutorProcessControl> EPC;
1797   std::unique_ptr<Platform> P;
1798   ErrorReporter ReportError = logErrorsToStdErr;
1799 
1800   std::vector<ResourceManager *> ResourceManagers;
1801 
1802   std::vector<JITDylibSP> JDs;
1803 
1804   // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
1805   //        with callbacks from asynchronous queries.
1806   mutable std::recursive_mutex OutstandingMUsMutex;
1807   std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
1808                         std::unique_ptr<MaterializationResponsibility>>>
1809       OutstandingMUs;
1810 
1811   mutable std::mutex JITDispatchHandlersMutex;
1812   DenseMap<ExecutorAddr, std::shared_ptr<JITDispatchHandlerFunction>>
1813       JITDispatchHandlers;
1814 };
1815 
1816 inline Expected<ExecutorSymbolDef> SymbolInstance::lookup() const {
1817   return JD->getExecutionSession().lookup({JD.get()}, Name);
1818 }
1819 
1820 template <typename Func> Error ResourceTracker::withResourceKeyDo(Func &&F) {
1821   return getJITDylib().getExecutionSession().runSessionLocked([&]() -> Error {
1822     if (isDefunct())
1823       return make_error<ResourceTrackerDefunct>(this);
1824     F(getKeyUnsafe());
1825     return Error::success();
1826   });
1827 }
1828 
1829 inline ExecutionSession &
1830 MaterializationResponsibility::getExecutionSession() const {
1831   return JD.getExecutionSession();
1832 }
1833 
1834 template <typename GeneratorT>
1835 GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
1836   auto &G = *DefGenerator;
1837   ES.runSessionLocked([&] {
1838     assert(State == Open && "Cannot add generator to closed JITDylib");
1839     DefGenerators.push_back(std::move(DefGenerator));
1840   });
1841   return G;
1842 }
1843 
1844 template <typename Func>
1845 auto JITDylib::withLinkOrderDo(Func &&F)
1846     -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
1847   assert(State == Open && "Cannot use link order of closed JITDylib");
1848   return ES.runSessionLocked([&]() { return F(LinkOrder); });
1849 }
1850 
1851 template <typename MaterializationUnitType>
1852 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
1853                        ResourceTrackerSP RT) {
1854   assert(MU && "Can not define with a null MU");
1855 
1856   if (MU->getSymbols().empty()) {
1857     // Empty MUs are allowable but pathological, so issue a warning.
1858     DEBUG_WITH_TYPE("orc", {
1859       dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for "
1860              << getName() << "\n";
1861     });
1862     return Error::success();
1863   } else
1864     DEBUG_WITH_TYPE("orc", {
1865       dbgs() << "Defining MU " << MU->getName() << " for " << getName()
1866              << " (tracker: ";
1867       if (RT == getDefaultResourceTracker())
1868         dbgs() << "default)";
1869       else if (RT)
1870         dbgs() << RT.get() << ")\n";
1871       else
1872         dbgs() << "0x0, default will be used)\n";
1873     });
1874 
1875   return ES.runSessionLocked([&, this]() -> Error {
1876     assert(State == Open && "JD is defunct");
1877 
1878     if (auto Err = defineImpl(*MU))
1879       return Err;
1880 
1881     if (!RT)
1882       RT = getDefaultResourceTracker();
1883 
1884     if (auto *P = ES.getPlatform()) {
1885       if (auto Err = P->notifyAdding(*RT, *MU))
1886         return Err;
1887     }
1888 
1889     installMaterializationUnit(std::move(MU), *RT);
1890     return Error::success();
1891   });
1892 }
1893 
1894 template <typename MaterializationUnitType>
1895 Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
1896                        ResourceTrackerSP RT) {
1897   assert(MU && "Can not define with a null MU");
1898 
1899   if (MU->getSymbols().empty()) {
1900     // Empty MUs are allowable but pathological, so issue a warning.
1901     DEBUG_WITH_TYPE("orc", {
1902       dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName()
1903              << "\n";
1904     });
1905     return Error::success();
1906   } else
1907     DEBUG_WITH_TYPE("orc", {
1908       dbgs() << "Defining MU " << MU->getName() << " for " << getName()
1909              << " (tracker: ";
1910       if (RT == getDefaultResourceTracker())
1911         dbgs() << "default)";
1912       else if (RT)
1913         dbgs() << RT.get() << ")\n";
1914       else
1915         dbgs() << "0x0, default will be used)\n";
1916     });
1917 
1918   return ES.runSessionLocked([&, this]() -> Error {
1919     assert(State == Open && "JD is defunct");
1920 
1921     if (auto Err = defineImpl(*MU))
1922       return Err;
1923 
1924     if (!RT)
1925       RT = getDefaultResourceTracker();
1926 
1927     if (auto *P = ES.getPlatform()) {
1928       if (auto Err = P->notifyAdding(*RT, *MU))
1929         return Err;
1930     }
1931 
1932     installMaterializationUnit(std::move(MU), *RT);
1933     return Error::success();
1934   });
1935 }
1936 
1937 /// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
1938 /// re-export a subset of the source JITDylib's symbols in the target.
1939 class ReexportsGenerator : public DefinitionGenerator {
1940 public:
1941   using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
1942 
1943   /// Create a reexports generator. If an Allow predicate is passed, only
1944   /// symbols for which the predicate returns true will be reexported. If no
1945   /// Allow predicate is passed, all symbols will be exported.
1946   ReexportsGenerator(JITDylib &SourceJD,
1947                      JITDylibLookupFlags SourceJDLookupFlags,
1948                      SymbolPredicate Allow = SymbolPredicate());
1949 
1950   Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
1951                       JITDylibLookupFlags JDLookupFlags,
1952                       const SymbolLookupSet &LookupSet) override;
1953 
1954 private:
1955   JITDylib &SourceJD;
1956   JITDylibLookupFlags SourceJDLookupFlags;
1957   SymbolPredicate Allow;
1958 };
1959 
1960 // --------------- IMPLEMENTATION --------------
1961 // Implementations for inline functions/methods.
1962 // ---------------------------------------------
1963 
1964 inline MaterializationResponsibility::~MaterializationResponsibility() {
1965   getExecutionSession().OL_destroyMaterializationResponsibility(*this);
1966 }
1967 
1968 inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
1969   return getExecutionSession().OL_getRequestedSymbols(*this);
1970 }
1971 
1972 inline Error MaterializationResponsibility::notifyResolved(
1973     const SymbolMap &Symbols) {
1974   return getExecutionSession().OL_notifyResolved(*this, Symbols);
1975 }
1976 
1977 inline Error MaterializationResponsibility::notifyEmitted(
1978     ArrayRef<SymbolDependenceGroup> EmittedDeps) {
1979   return getExecutionSession().OL_notifyEmitted(*this, EmittedDeps);
1980 }
1981 
1982 inline Error MaterializationResponsibility::defineMaterializing(
1983     SymbolFlagsMap SymbolFlags) {
1984   return getExecutionSession().OL_defineMaterializing(*this,
1985                                                       std::move(SymbolFlags));
1986 }
1987 
1988 inline void MaterializationResponsibility::failMaterialization() {
1989   getExecutionSession().OL_notifyFailed(*this);
1990 }
1991 
1992 inline Error MaterializationResponsibility::replace(
1993     std::unique_ptr<MaterializationUnit> MU) {
1994   return getExecutionSession().OL_replace(*this, std::move(MU));
1995 }
1996 
1997 inline Expected<std::unique_ptr<MaterializationResponsibility>>
1998 MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
1999   return getExecutionSession().OL_delegate(*this, Symbols);
2000 }
2001 
2002 } // End namespace orc
2003 } // End namespace llvm
2004 
2005 #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H