Ver Fonte

[ORC] Update symbol lookup to use a single callback with a required symbol state
rather than two callbacks.

The asynchronous lookup API (which the synchronous lookup API wraps for
convenience) used to take two callbacks: OnResolved (called once all requested
symbols had an address assigned) and OnReady to be called once all requested
symbols were safe to access). This patch updates the asynchronous lookup API to
take a single 'OnComplete' callback and a required state (SymbolState) to
determine when the callback should be made. This simplifies the common use case
(where the client is interested in a specific state) and will generalize neatly
as new states are introduced to track runtime initialization of symbols.

Clients who were making use of both callbacks in a single query will now need to
issue two queries (one for SymbolState::Resolved and another for
SymbolState::Ready). Synchronous lookup API clients who were explicitly passing
the WaitOnReady argument will now need neeed to pass a SymbolState instead (for
'WaitOnReady == true' use SymbolState::Ready, for 'WaitOnReady == false' use
SymbolState::Resolved). Synchronous lookup API clients who were using default
arugment values should see no change.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362832 91177308-0d34-0410-b5e6-96231b3b80d8

Lang Hames há 6 anos atrás
pai
commit
883ef72f22

+ 71 - 74
include/llvm/ExecutionEngine/Orc/Core.h

@@ -33,6 +33,7 @@ class ExecutionSession;
 class MaterializationUnit;
 class MaterializationUnit;
 class MaterializationResponsibility;
 class MaterializationResponsibility;
 class JITDylib;
 class JITDylib;
+enum class SymbolState : uint8_t;
 
 
 /// VModuleKey provides a unique identifier (allocated and managed by
 /// VModuleKey provides a unique identifier (allocated and managed by
 /// ExecutionSessions) for a module added to the JIT.
 /// ExecutionSessions) for a module added to the JIT.
@@ -56,6 +57,18 @@ using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
 /// A list of (JITDylib*, bool) pairs.
 /// A list of (JITDylib*, bool) pairs.
 using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
 using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
 
 
+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>;
+
 /// Render a SymbolStringPtr.
 /// Render a SymbolStringPtr.
 raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
 raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
 
 
@@ -87,12 +100,15 @@ raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
 /// Render a JITDylibSearchList.
 /// Render a JITDylibSearchList.
 raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
 raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
 
 
+/// Render a SymbolAliasMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases);
+
+/// Render a SymbolState.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S);
+
 /// Callback to notify client that symbols have been resolved.
 /// Callback to notify client that symbols have been resolved.
 using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
 using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
 
 
-/// Callback to notify client that symbols are ready for execution.
-using SymbolsReadyCallback = std::function<void(Error)>;
-
 /// Callback to register the dependencies for a given query.
 /// Callback to register the dependencies for a given query.
 using RegisterDependenciesFunction =
 using RegisterDependenciesFunction =
     std::function<void(const SymbolDependenceMap &)>;
     std::function<void(const SymbolDependenceMap &)>;
@@ -333,18 +349,6 @@ absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) {
       std::move(Symbols), std::move(K));
       std::move(Symbols), std::move(K));
 }
 }
 
 
-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>;
-
 /// A materialization unit for symbol aliases. Allows existing symbols to be
 /// A materialization unit for symbol aliases. Allows existing symbols to be
 /// aliased with alternate flags.
 /// aliased with alternate flags.
 class ReExportsMaterializationUnit : public MaterializationUnit {
 class ReExportsMaterializationUnit : public MaterializationUnit {
@@ -426,6 +430,15 @@ private:
   SymbolPredicate Allow;
   SymbolPredicate Allow;
 };
 };
 
 
+/// 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.
+  Ready = 0x3f   /// Ready and safe for clients to access.
+};
+
 /// A symbol query that returns results via a callback when results are
 /// A symbol query that returns results via a callback when results are
 ///        ready.
 ///        ready.
 ///
 ///
@@ -436,38 +449,30 @@ class AsynchronousSymbolQuery {
   friend class JITSymbolResolverAdapter;
   friend class JITSymbolResolverAdapter;
 
 
 public:
 public:
-
-  /// Create a query for the given symbols, notify-resolved and
-  ///        notify-ready callbacks.
+  /// Create a query for the given symbols. The NotifyComplete
+  /// callback will be called once all queried symbols reach the given
+  /// minimum state.
   AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
   AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
-                          SymbolsResolvedCallback NotifySymbolsResolved,
-                          SymbolsReadyCallback NotifySymbolsReady);
+                          SymbolState RequiredState,
+                          SymbolsResolvedCallback NotifyComplete);
 
 
-  /// Set the resolved symbol information for the given symbol name.
-  void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
+  /// 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
   /// Returns true if all symbols covered by this query have been
   ///        resolved.
   ///        resolved.
-  bool isFullyResolved() const { return NotYetResolvedCount == 0; }
-
-  /// Call the NotifySymbolsResolved callback.
-  ///
-  /// This should only be called if all symbols covered by the query have been
-  /// resolved.
-  void handleFullyResolved();
-
-  /// Notify the query that a requested symbol is ready for execution.
-  void notifySymbolReady();
+  bool isComplete() const { return OutstandingSymbolsCount == 0; }
 
 
-  /// Returns true if all symbols covered by this query are ready.
-  bool isFullyReady() const { return NotYetReadyCount == 0; }
-
-  /// Calls the NotifySymbolsReady callback.
+  /// Call the NotifyComplete callback.
   ///
   ///
-  /// This should only be called if all symbols covered by this query are ready.
-  void handleFullyReady();
+  /// This should only be called if all symbols covered by the query have
+  /// reached the specified state.
+  void handleComplete();
 
 
 private:
 private:
+  SymbolState getRequiredState() { return RequiredState; }
+
   void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
   void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
 
 
   void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
   void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
@@ -478,12 +483,11 @@ private:
 
 
   void detach();
   void detach();
 
 
-  SymbolsResolvedCallback NotifySymbolsResolved;
-  SymbolsReadyCallback NotifySymbolsReady;
+  SymbolsResolvedCallback NotifyComplete;
   SymbolDependenceMap QueryRegistrations;
   SymbolDependenceMap QueryRegistrations;
   SymbolMap ResolvedSymbols;
   SymbolMap ResolvedSymbols;
-  size_t NotYetResolvedCount;
-  size_t NotYetReadyCount;
+  size_t OutstandingSymbolsCount;
+  SymbolState RequiredState;
 };
 };
 
 
 /// A symbol table that supports asynchoronous symbol queries.
 /// A symbol table that supports asynchoronous symbol queries.
@@ -626,28 +630,24 @@ private:
       DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
       DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
 
 
   struct MaterializingInfo {
   struct MaterializingInfo {
-    AsynchronousSymbolQueryList PendingQueries;
     SymbolDependenceMap Dependants;
     SymbolDependenceMap Dependants;
     SymbolDependenceMap UnemittedDependencies;
     SymbolDependenceMap UnemittedDependencies;
     bool IsEmitted = false;
     bool IsEmitted = false;
-  };
 
 
-  using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
+    void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
+    void removeQuery(const AsynchronousSymbolQuery &Q);
+    AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
+    AsynchronousSymbolQueryList takeAllQueries();
+    bool hasQueriesPending() const { return !PendingQueries.empty(); }
+    const AsynchronousSymbolQueryList &pendingQueries() const {
+      return PendingQueries;
+    }
 
 
-  using LookupImplActionFlags = enum {
-    None = 0,
-    NotifyFullyResolved = 1 << 0U,
-    NotifyFullyReady = 1 << 1U,
-    LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
+  private:
+    AsynchronousSymbolQueryList PendingQueries;
   };
   };
 
 
-  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.
-    Ready = 0x3f   // Ready and safe for clients to access.
-  };
+  using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
 
 
   class SymbolTableEntry {
   class SymbolTableEntry {
   public:
   public:
@@ -713,10 +713,9 @@ private:
                       SymbolNameSet &Unresolved, bool MatchNonExported,
                       SymbolNameSet &Unresolved, bool MatchNonExported,
                       MaterializationUnitList &MUs);
                       MaterializationUnitList &MUs);
 
 
-  LookupImplActionFlags
-  lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
-             std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
-             SymbolNameSet &Unresolved);
+  bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+                  std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
+                  SymbolNameSet &Unresolved);
 
 
   void detachQueryHelper(AsynchronousSymbolQuery &Q,
   void detachQueryHelper(AsynchronousSymbolQuery &Q,
                          const SymbolNameSet &QuerySymbols);
                          const SymbolNameSet &QuerySymbols);
@@ -833,7 +832,7 @@ public:
   /// Do not use -- this will be removed soon.
   /// Do not use -- this will be removed soon.
   Expected<SymbolMap>
   Expected<SymbolMap>
   legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
   legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
-               bool WaiUntilReady,
+               SymbolState RequiredState,
                RegisterDependenciesFunction RegisterDependencies);
                RegisterDependenciesFunction RegisterDependencies);
 
 
   /// Search the given JITDylib list for the given symbols.
   /// Search the given JITDylib list for the given symbols.
@@ -843,11 +842,8 @@ public:
   /// (hidden visibility) symbols in that dylib (true means match against
   /// (hidden visibility) symbols in that dylib (true means match against
   /// non-exported symbols, false means do not match).
   /// non-exported symbols, false means do not match).
   ///
   ///
-  /// The OnResolve callback will be called once all requested symbols are
-  /// resolved, or if an error occurs prior to resolution.
-  ///
-  /// The OnReady callback will be called once all requested symbols are ready,
-  /// or if an error occurs after resolution but before all symbols are ready.
+  /// 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
   /// If all symbols are found, the RegisterDependencies function will be called
   /// while the session lock is held. This gives clients a chance to register
   /// while the session lock is held. This gives clients a chance to register
@@ -859,7 +855,7 @@ public:
   /// client to get an address to call) then the value NoDependenciesToRegister
   /// client to get an address to call) then the value NoDependenciesToRegister
   /// can be used.
   /// can be used.
   void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
   void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
-              SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
+              SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete,
               RegisterDependenciesFunction RegisterDependencies);
               RegisterDependenciesFunction RegisterDependencies);
 
 
   /// Blocking version of lookup above. Returns the resolved symbol map.
   /// Blocking version of lookup above. Returns the resolved symbol map.
@@ -871,9 +867,9 @@ public:
   /// error will be reported via reportErrors.
   /// error will be reported via reportErrors.
   Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder,
   Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder,
                              const SymbolNameSet &Symbols,
                              const SymbolNameSet &Symbols,
+                             SymbolState RequiredState = SymbolState::Ready,
                              RegisterDependenciesFunction RegisterDependencies =
                              RegisterDependenciesFunction RegisterDependencies =
-                                 NoDependenciesToRegister,
-                             bool WaitUntilReady = true);
+                                 NoDependenciesToRegister);
 
 
   /// Convenience version of blocking lookup.
   /// Convenience version of blocking lookup.
   /// Searches each of the JITDylibs in the search order in turn for the given
   /// Searches each of the JITDylibs in the search order in turn for the given
@@ -896,10 +892,11 @@ public:
   /// Materialize the given unit.
   /// Materialize the given unit.
   void dispatchMaterialization(JITDylib &JD,
   void dispatchMaterialization(JITDylib &JD,
                                std::unique_ptr<MaterializationUnit> MU) {
                                std::unique_ptr<MaterializationUnit> MU) {
-    LLVM_DEBUG(runSessionLocked([&]() {
-                 dbgs() << "Compiling, for " << JD.getName() << ", " << *MU
-                        << "\n";
-               }););
+    LLVM_DEBUG({
+      runSessionLocked([&]() {
+        dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n";
+      });
+    });
     DispatchMaterialization(JD, std::move(MU));
     DispatchMaterialization(JD, std::move(MU));
   }
   }
 
 

+ 4 - 7
include/llvm/ExecutionEngine/Orc/Legacy.h

@@ -148,8 +148,8 @@ lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
   for (auto &S : Symbols) {
   for (auto &S : Symbols) {
     if (JITSymbol Sym = FindSymbol(*S)) {
     if (JITSymbol Sym = FindSymbol(*S)) {
       if (auto Addr = Sym.getAddress()) {
       if (auto Addr = Sym.getAddress()) {
-        Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
-        Query.notifySymbolReady();
+        Query.notifySymbolMetRequiredState(
+            S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
         NewSymbolsResolved = true;
         NewSymbolsResolved = true;
       } else {
       } else {
         ES.legacyFailQuery(Query, Addr.takeError());
         ES.legacyFailQuery(Query, Addr.takeError());
@@ -162,11 +162,8 @@ lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
       SymbolsNotFound.insert(S);
       SymbolsNotFound.insert(S);
   }
   }
 
 
-  if (NewSymbolsResolved && Query.isFullyResolved())
-    Query.handleFullyResolved();
-
-  if (NewSymbolsResolved && Query.isFullyReady())
-    Query.handleFullyReady();
+  if (NewSymbolsResolved && Query.isComplete())
+    Query.handleComplete();
 
 
   return SymbolsNotFound;
   return SymbolsNotFound;
 }
 }

+ 230 - 337
lib/ExecutionEngine/Orc/Core.cpp

@@ -219,6 +219,31 @@ raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs) {
   return OS;
   return OS;
 }
 }
 
 
+raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
+  OS << "{";
+  for (auto &KV : Aliases)
+    OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
+       << KV.second.AliasFlags;
+  OS << " }\n";
+  return OS;
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
+  switch (S) {
+  case SymbolState::Invalid:
+    return OS << "Invalid";
+  case SymbolState::NeverSearched:
+    return OS << "Never-Searched";
+  case SymbolState::Materializing:
+    return OS << "Materializing";
+  case SymbolState::Resolved:
+    return OS << "Resolved";
+  case SymbolState::Ready:
+    return OS << "Ready";
+  }
+  llvm_unreachable("Invalid state");
+}
+
 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
     : Symbols(std::move(Symbols)) {
     : Symbols(std::move(Symbols)) {
   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
@@ -259,85 +284,46 @@ void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const {
 }
 }
 
 
 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
-    const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
-    SymbolsReadyCallback NotifySymbolsReady)
-    : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
-      NotifySymbolsReady(std::move(NotifySymbolsReady)) {
-  NotYetResolvedCount = NotYetReadyCount = Symbols.size();
+    const SymbolNameSet &Symbols, SymbolState RequiredState,
+    SymbolsResolvedCallback NotifyComplete)
+    : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) {
+  assert(RequiredState >= SymbolState::Resolved &&
+         "Cannot query for a symbols that have not reached the resolve state "
+         "yet");
+
+  OutstandingSymbolsCount = Symbols.size();
 
 
   for (auto &S : Symbols)
   for (auto &S : Symbols)
     ResolvedSymbols[S] = nullptr;
     ResolvedSymbols[S] = nullptr;
 }
 }
 
 
-void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
-                                      JITEvaluatedSymbol Sym) {
+void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
+    const SymbolStringPtr &Name, JITEvaluatedSymbol Sym) {
   auto I = ResolvedSymbols.find(Name);
   auto I = ResolvedSymbols.find(Name);
   assert(I != ResolvedSymbols.end() &&
   assert(I != ResolvedSymbols.end() &&
          "Resolving symbol outside the requested set");
          "Resolving symbol outside the requested set");
   assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
   assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
   I->second = std::move(Sym);
   I->second = std::move(Sym);
-  --NotYetResolvedCount;
+  --OutstandingSymbolsCount;
 }
 }
 
 
-void AsynchronousSymbolQuery::handleFullyResolved() {
-  assert(NotYetResolvedCount == 0 && "Not fully resolved?");
+void AsynchronousSymbolQuery::handleComplete() {
+  assert(OutstandingSymbolsCount == 0 &&
+         "Symbols remain, handleComplete called prematurely");
 
 
-  if (!NotifySymbolsResolved) {
-    // handleFullyResolved may be called by handleFullyReady (see comments in
-    // that method), in which case this is a no-op, so bail out.
-    assert(!NotifySymbolsReady &&
-           "NotifySymbolsResolved already called or an error occurred");
-    return;
-  }
-
-  auto TmpNotifySymbolsResolved = std::move(NotifySymbolsResolved);
-  NotifySymbolsResolved = SymbolsResolvedCallback();
-  TmpNotifySymbolsResolved(std::move(ResolvedSymbols));
+  auto TmpNotifyComplete = std::move(NotifyComplete);
+  NotifyComplete = SymbolsResolvedCallback();
+  TmpNotifyComplete(std::move(ResolvedSymbols));
 }
 }
 
 
-void AsynchronousSymbolQuery::notifySymbolReady() {
-  assert(NotYetReadyCount != 0 && "All symbols already emitted");
-  --NotYetReadyCount;
-}
-
-void AsynchronousSymbolQuery::handleFullyReady() {
-  assert(NotifySymbolsReady &&
-         "NotifySymbolsReady already called or an error occurred");
-
-  auto TmpNotifySymbolsReady = std::move(NotifySymbolsReady);
-  NotifySymbolsReady = SymbolsReadyCallback();
-
-  if (NotYetResolvedCount == 0 && NotifySymbolsResolved) {
-    // The NotifyResolved callback of one query must have caused this query to
-    // become ready (i.e. there is still a handleFullyResolved callback waiting
-    // to be made back up the stack). Fold the handleFullyResolved call into
-    // this one before proceeding. This will cause the call further up the
-    // stack to become a no-op.
-    handleFullyResolved();
-  }
-
-  assert(QueryRegistrations.empty() &&
-         "Query is still registered with some symbols");
-  assert(!NotifySymbolsResolved && "Resolution not applied yet");
-  TmpNotifySymbolsReady(Error::success());
-}
-
-bool AsynchronousSymbolQuery::canStillFail() {
-  return (NotifySymbolsResolved || NotifySymbolsReady);
-}
+bool AsynchronousSymbolQuery::canStillFail() { return !!NotifyComplete; }
 
 
 void AsynchronousSymbolQuery::handleFailed(Error Err) {
 void AsynchronousSymbolQuery::handleFailed(Error Err) {
   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
   assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
-         NotYetResolvedCount == 0 && NotYetReadyCount == 0 &&
+         OutstandingSymbolsCount == 0 &&
          "Query should already have been abandoned");
          "Query should already have been abandoned");
-  if (NotifySymbolsResolved) {
-    NotifySymbolsResolved(std::move(Err));
-    NotifySymbolsResolved = SymbolsResolvedCallback();
-  } else {
-    assert(NotifySymbolsReady && "Failed after both callbacks issued?");
-    NotifySymbolsReady(std::move(Err));
-  }
-  NotifySymbolsReady = SymbolsReadyCallback();
+  NotifyComplete(std::move(Err));
+  NotifyComplete = SymbolsResolvedCallback();
 }
 }
 
 
 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
 void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD,
@@ -360,8 +346,7 @@ void AsynchronousSymbolQuery::removeQueryDependence(
 
 
 void AsynchronousSymbolQuery::detach() {
 void AsynchronousSymbolQuery::detach() {
   ResolvedSymbols.clear();
   ResolvedSymbols.clear();
-  NotYetResolvedCount = 0;
-  NotYetReadyCount = 0;
+  OutstandingSymbolsCount = 0;
   for (auto &KV : QueryRegistrations)
   for (auto &KV : QueryRegistrations)
     KV.first->detachQueryHelper(*this, KV.second);
     KV.first->detachQueryHelper(*this, KV.second);
   QueryRegistrations.clear();
   QueryRegistrations.clear();
@@ -548,6 +533,14 @@ void ReExportsMaterializationUnit::materialize(
     Aliases.erase(I);
     Aliases.erase(I);
   }
   }
 
 
+  LLVM_DEBUG({
+    ES.runSessionLocked([&]() {
+      dbgs() << "materializing reexports: target = " << TgtJD.getName()
+             << ", source = " << SrcJD.getName() << " " << RequestedAliases
+             << "\n";
+    });
+  });
+
   if (!Aliases.empty()) {
   if (!Aliases.empty()) {
     if (SourceJD)
     if (SourceJD)
       R.replace(reexports(*SourceJD, std::move(Aliases), MatchNonExported));
       R.replace(reexports(*SourceJD, std::move(Aliases), MatchNonExported));
@@ -630,7 +623,7 @@ void ReExportsMaterializationUnit::materialize(
         }
         }
     };
     };
 
 
-    auto OnResolve = [QueryInfo](Expected<SymbolMap> Result) {
+    auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
       if (Result) {
       if (Result) {
         SymbolMap ResolutionMap;
         SymbolMap ResolutionMap;
         for (auto &KV : QueryInfo->Aliases) {
         for (auto &KV : QueryInfo->Aliases) {
@@ -648,10 +641,8 @@ void ReExportsMaterializationUnit::materialize(
       }
       }
     };
     };
 
 
-    auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
-
     ES.lookup(JITDylibSearchList({{&SrcJD, MatchNonExported}}), QuerySymbols,
     ES.lookup(JITDylibSearchList({{&SrcJD, MatchNonExported}}), QuerySymbols,
-              std::move(OnResolve), std::move(OnReady),
+              SymbolState::Resolved, std::move(OnComplete),
               std::move(RegisterDependencies));
               std::move(RegisterDependencies));
   }
   }
 }
 }
@@ -776,7 +767,7 @@ void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
         for (auto &KV : MU->getSymbols()) {
         for (auto &KV : MU->getSymbols()) {
           auto MII = MaterializingInfos.find(KV.first);
           auto MII = MaterializingInfos.find(KV.first);
           if (MII != MaterializingInfos.end()) {
           if (MII != MaterializingInfos.end()) {
-            if (!MII->second.PendingQueries.empty())
+            if (MII->second.hasQueriesPending())
               return std::move(MU);
               return std::move(MU);
           }
           }
         }
         }
@@ -817,7 +808,7 @@ JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const {
       if (I == MaterializingInfos.end())
       if (I == MaterializingInfos.end())
         continue;
         continue;
 
 
-      if (!I->second.PendingQueries.empty())
+      if (I->second.hasQueriesPending())
         RequestedSymbols.insert(KV.first);
         RequestedSymbols.insert(KV.first);
     }
     }
 
 
@@ -864,8 +855,8 @@ void JITDylib::addDependencies(const SymbolStringPtr &Name,
 }
 }
 
 
 void JITDylib::resolve(const SymbolMap &Resolved) {
 void JITDylib::resolve(const SymbolMap &Resolved) {
-  auto FullyResolvedQueries = ES.runSessionLocked([&, this]() {
-    AsynchronousSymbolQuerySet FullyResolvedQueries;
+  auto CompletedQueries = ES.runSessionLocked([&, this]() {
+    AsynchronousSymbolQuerySet CompletedQueries;
     for (const auto &KV : Resolved) {
     for (const auto &KV : Resolved) {
       auto &Name = KV.first;
       auto &Name = KV.first;
       auto Sym = KV.second;
       auto Sym = KV.second;
@@ -891,25 +882,25 @@ void JITDylib::resolve(const SymbolMap &Resolved) {
       I->second.setState(SymbolState::Resolved);
       I->second.setState(SymbolState::Resolved);
 
 
       auto &MI = MaterializingInfos[Name];
       auto &MI = MaterializingInfos[Name];
-      for (auto &Q : MI.PendingQueries) {
-        Q->resolve(Name, Sym);
-        if (Q->isFullyResolved())
-          FullyResolvedQueries.insert(Q);
+      for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
+        Q->notifySymbolMetRequiredState(Name, Sym);
+        if (Q->isComplete())
+          CompletedQueries.insert(std::move(Q));
       }
       }
     }
     }
 
 
-    return FullyResolvedQueries;
+    return CompletedQueries;
   });
   });
 
 
-  for (auto &Q : FullyResolvedQueries) {
-    assert(Q->isFullyResolved() && "Q not fully resolved");
-    Q->handleFullyResolved();
+  for (auto &Q : CompletedQueries) {
+    assert(Q->isComplete() && "Q not completed");
+    Q->handleComplete();
   }
   }
 }
 }
 
 
 void JITDylib::emit(const SymbolFlagsMap &Emitted) {
 void JITDylib::emit(const SymbolFlagsMap &Emitted) {
-  auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
-    AsynchronousSymbolQuerySet ReadyQueries;
+  auto CompletedQueries = ES.runSessionLocked([&, this]() {
+    AsynchronousSymbolQuerySet CompletedQueries;
 
 
     for (const auto &KV : Emitted) {
     for (const auto &KV : Emitted) {
       const auto &Name = KV.first;
       const auto &Name = KV.first;
@@ -951,18 +942,22 @@ void JITDylib::emit(const SymbolFlagsMap &Emitted) {
               DependantMI.UnemittedDependencies.empty()) {
               DependantMI.UnemittedDependencies.empty()) {
             assert(DependantMI.Dependants.empty() &&
             assert(DependantMI.Dependants.empty() &&
                    "Dependants should be empty by now");
                    "Dependants should be empty by now");
-            for (auto &Q : DependantMI.PendingQueries) {
-              Q->notifySymbolReady();
-              if (Q->isFullyReady())
-                ReadyQueries.insert(Q);
-              Q->removeQueryDependence(DependantJD, DependantName);
-            }
 
 
             // Since this dependant is now ready, we erase its MaterializingInfo
             // Since this dependant is now ready, we erase its MaterializingInfo
             // and update its materializing state.
             // and update its materializing state.
-            assert(DependantJD.Symbols.count(DependantName) &&
+            auto DependantSymI = DependantJD.Symbols.find(DependantName);
+            assert(DependantSymI != DependantJD.Symbols.end() &&
                    "Dependant has no entry in the Symbols table");
                    "Dependant has no entry in the Symbols table");
-            DependantJD.Symbols[DependantName].setState(SymbolState::Ready);
+            DependantSymI->second.setState(SymbolState::Ready);
+
+            for (auto &Q : DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
+              Q->notifySymbolMetRequiredState(
+                  DependantName, DependantSymI->second.getSymbol());
+              if (Q->isComplete())
+                CompletedQueries.insert(Q);
+              Q->removeQueryDependence(DependantJD, DependantName);
+            }
+
             DependantJD.MaterializingInfos.erase(DependantMII);
             DependantJD.MaterializingInfos.erase(DependantMII);
           }
           }
         }
         }
@@ -971,25 +966,25 @@ void JITDylib::emit(const SymbolFlagsMap &Emitted) {
       MI.IsEmitted = true;
       MI.IsEmitted = true;
 
 
       if (MI.UnemittedDependencies.empty()) {
       if (MI.UnemittedDependencies.empty()) {
-        for (auto &Q : MI.PendingQueries) {
-          Q->notifySymbolReady();
-          if (Q->isFullyReady())
-            ReadyQueries.insert(Q);
+        auto SymI = Symbols.find(Name);
+        assert(SymI != Symbols.end() && "Symbol has no entry in Symbols table");
+        SymI->second.setState(SymbolState::Ready);
+        for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
+          Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
+          if (Q->isComplete())
+            CompletedQueries.insert(Q);
           Q->removeQueryDependence(*this, Name);
           Q->removeQueryDependence(*this, Name);
         }
         }
-        assert(Symbols.count(Name) &&
-               "Symbol has no entry in the Symbols table");
-        Symbols[Name].setState(SymbolState::Ready);
         MaterializingInfos.erase(MII);
         MaterializingInfos.erase(MII);
       }
       }
     }
     }
 
 
-    return ReadyQueries;
+    return CompletedQueries;
   });
   });
 
 
-  for (auto &Q : FullyReadyQueries) {
-    assert(Q->isFullyReady() && "Q is not fully ready");
-    Q->handleFullyReady();
+  for (auto &Q : CompletedQueries) {
+    assert(Q->isComplete() && "Q is not complete");
+    Q->handleComplete();
   }
   }
 }
 }
 
 
@@ -999,6 +994,7 @@ void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) {
 
 
   auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
   auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
     AsynchronousSymbolQuerySet FailedQueries;
     AsynchronousSymbolQuerySet FailedQueries;
+    std::vector<MaterializingInfosMap::iterator> MIIsToRemove;
 
 
     for (auto &Name : FailedSymbols) {
     for (auto &Name : FailedSymbols) {
       auto I = Symbols.find(Name);
       auto I = Symbols.find(Name);
@@ -1033,13 +1029,19 @@ void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) {
       // This has to be a copy, and the copy has to come before the abandon
       // This has to be a copy, and the copy has to come before the abandon
       // operation: Each Q.detach() call will reach back into this
       // operation: Each Q.detach() call will reach back into this
       // PendingQueries list to remove Q.
       // PendingQueries list to remove Q.
-      for (auto &Q : MII->second.PendingQueries)
+      for (auto &Q : MII->second.pendingQueries())
         FailedQueries.insert(Q);
         FailedQueries.insert(Q);
 
 
-      for (auto &Q : FailedQueries)
-        Q->detach();
+      MIIsToRemove.push_back(std::move(MII));
+    }
+
+    // Detach failed queries.
+    for (auto &Q : FailedQueries)
+      Q->detach();
 
 
-      assert(MII->second.PendingQueries.empty() &&
+    // Remove the MaterializingInfos.
+    for (auto &MII : MIIsToRemove) {
+      assert(!MII->second.hasQueriesPending() &&
              "Queries remain after symbol was failed");
              "Queries remain after symbol was failed");
 
 
       MaterializingInfos.erase(MII);
       MaterializingInfos.erase(MII);
@@ -1228,19 +1230,20 @@ void JITDylib::lodgeQueryImpl(
     if (!SymI->second.getFlags().isExported() && !MatchNonExported)
     if (!SymI->second.getFlags().isExported() && !MatchNonExported)
       continue;
       continue;
 
 
-    // If we matched against Name in JD, mark it to be removed from the Unresolved
-    // set.
+    // If we matched against Name in JD, mark it to be removed from the
+    // Unresolved set.
     ToRemove.push_back(Name);
     ToRemove.push_back(Name);
 
 
-    if (SymI->second.getState() >= SymbolState::Resolved) {
-      assert(!SymI->second.hasMaterializerAttached() &&
-             "Resolved symbols should not have materializers attached");
-      Q->resolve(Name, SymI->second.getSymbol());
-      if (SymI->second.getState() == SymbolState::Ready) {
-        Q->notifySymbolReady();
-        continue;
-      }
-    } else if (SymI->second.hasMaterializerAttached()) {
+    // If this symbol already meets the required state for then notify the
+    // query and continue.
+    if (SymI->second.getState() >= Q->getRequiredState()) {
+      Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
+      continue;
+    }
+
+    // Otherwise this symbol does not yet meet the required state. Check whether
+    // it has a materializer attached, and if so prepare to run it.
+    if (SymI->second.hasMaterializerAttached()) {
       assert(SymI->second.getAddress() == 0 &&
       assert(SymI->second.getAddress() == 0 &&
              "Symbol not resolved but already has address?");
              "Symbol not resolved but already has address?");
       auto UMII = UnmaterializedInfos.find(Name);
       auto UMII = UnmaterializedInfos.find(Name);
@@ -1266,7 +1269,7 @@ void JITDylib::lodgeQueryImpl(
     assert(SymI->second.isInMaterializationPhase() &&
     assert(SymI->second.isInMaterializationPhase() &&
            "By this line the symbol should be materializing");
            "By this line the symbol should be materializing");
     auto &MI = MaterializingInfos[Name];
     auto &MI = MaterializingInfos[Name];
-    MI.PendingQueries.push_back(Q);
+    MI.addQuery(Q);
     Q->addQueryDependence(*this, Name);
     Q->addQueryDependence(*this, Name);
   }
   }
 
 
@@ -1282,22 +1285,21 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
 
 
   ES.runOutstandingMUs();
   ES.runOutstandingMUs();
 
 
-  LookupImplActionFlags ActionFlags = None;
+  bool QueryComplete = false;
   std::vector<std::unique_ptr<MaterializationUnit>> MUs;
   std::vector<std::unique_ptr<MaterializationUnit>> MUs;
 
 
   SymbolNameSet Unresolved = std::move(Names);
   SymbolNameSet Unresolved = std::move(Names);
   auto Err = ES.runSessionLocked([&, this]() -> Error {
   auto Err = ES.runSessionLocked([&, this]() -> Error {
-    ActionFlags = lookupImpl(Q, MUs, Unresolved);
+    QueryComplete = lookupImpl(Q, MUs, Unresolved);
     if (DefGenerator && !Unresolved.empty()) {
     if (DefGenerator && !Unresolved.empty()) {
-      assert(ActionFlags == None &&
-             "ActionFlags set but unresolved symbols remain?");
+      assert(!QueryComplete && "query complete but unresolved symbols remain?");
       auto NewDefs = DefGenerator(*this, Unresolved);
       auto NewDefs = DefGenerator(*this, Unresolved);
       if (!NewDefs)
       if (!NewDefs)
         return NewDefs.takeError();
         return NewDefs.takeError();
       if (!NewDefs->empty()) {
       if (!NewDefs->empty()) {
         for (auto &D : *NewDefs)
         for (auto &D : *NewDefs)
           Unresolved.erase(D);
           Unresolved.erase(D);
-        ActionFlags = lookupImpl(Q, MUs, *NewDefs);
+        QueryComplete = lookupImpl(Q, MUs, *NewDefs);
         assert(NewDefs->empty() &&
         assert(NewDefs->empty() &&
                "All fallback defs should have been found by lookupImpl");
                "All fallback defs should have been found by lookupImpl");
       }
       }
@@ -1308,14 +1310,11 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
   if (Err)
   if (Err)
     return std::move(Err);
     return std::move(Err);
 
 
-  assert((MUs.empty() || ActionFlags == None) &&
+  assert((MUs.empty() || !QueryComplete) &&
          "If action flags are set, there should be no work to do (so no MUs)");
          "If action flags are set, there should be no work to do (so no MUs)");
 
 
-  if (ActionFlags & NotifyFullyResolved)
-    Q->handleFullyResolved();
-
-  if (ActionFlags & NotifyFullyReady)
-    Q->handleFullyReady();
+  if (QueryComplete)
+    Q->handleComplete();
 
 
   // FIXME: Swap back to the old code below once RuntimeDyld works with
   // FIXME: Swap back to the old code below once RuntimeDyld works with
   //        callbacks from asynchronous queries.
   //        callbacks from asynchronous queries.
@@ -1334,13 +1333,13 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
   return Unresolved;
   return Unresolved;
 }
 }
 
 
-JITDylib::LookupImplActionFlags
-JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
-                     std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
-                     SymbolNameSet &Unresolved) {
-  LookupImplActionFlags ActionFlags = None;
-  std::vector<SymbolStringPtr> ToRemove;
+bool JITDylib::lookupImpl(
+    std::shared_ptr<AsynchronousSymbolQuery> &Q,
+    std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
+    SymbolNameSet &Unresolved) {
+  bool QueryComplete = false;
 
 
+  std::vector<SymbolStringPtr> ToRemove;
   for (auto Name : Unresolved) {
   for (auto Name : Unresolved) {
 
 
     // Search for the name in Symbols. Skip it if not found.
     // Search for the name in Symbols. Skip it if not found.
@@ -1351,11 +1350,11 @@ JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
     // If we found Name, mark it to be removed from the Unresolved set.
     // If we found Name, mark it to be removed from the Unresolved set.
     ToRemove.push_back(Name);
     ToRemove.push_back(Name);
 
 
-    // If the symbol has an address then resolve it.
-    if (SymI->second.getAddress() != 0) {
-      Q->resolve(Name, SymI->second.getSymbol());
-      if (Q->isFullyResolved())
-        ActionFlags |= NotifyFullyResolved;
+    if (SymI->second.getState() >= Q->getRequiredState()) {
+      Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
+      if (Q->isComplete())
+        QueryComplete = true;
+      continue;
     }
     }
 
 
     // If the symbol is lazy, get the MaterialiaztionUnit for it.
     // If the symbol is lazy, get the MaterialiaztionUnit for it.
@@ -1380,18 +1379,13 @@ JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
 
 
       // Add MU to the list of MaterializationUnits to be materialized.
       // Add MU to the list of MaterializationUnits to be materialized.
       MUs.push_back(std::move(MU));
       MUs.push_back(std::move(MU));
-    } else if (SymI->second.getState() == SymbolState::Ready) {
-      Q->notifySymbolReady();
-      if (Q->isFullyReady())
-        ActionFlags |= NotifyFullyReady;
-      continue;
     }
     }
 
 
     // Add the query to the PendingQueries list.
     // Add the query to the PendingQueries list.
     assert(SymI->second.isInMaterializationPhase() &&
     assert(SymI->second.isInMaterializationPhase() &&
            "By this line the symbol should be materializing");
            "By this line the symbol should be materializing");
     auto &MI = MaterializingInfos[Name];
     auto &MI = MaterializingInfos[Name];
-    MI.PendingQueries.push_back(Q);
+    MI.addQuery(Q);
     Q->addQueryDependence(*this, Name);
     Q->addQueryDependence(*this, Name);
   }
   }
 
 
@@ -1399,7 +1393,7 @@ JITDylib::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
   for (auto &Name : ToRemove)
   for (auto &Name : ToRemove)
     Unresolved.erase(Name);
     Unresolved.erase(Name);
 
 
-  return ActionFlags;
+  return QueryComplete;
 }
 }
 
 
 void JITDylib::dump(raw_ostream &OS) {
 void JITDylib::dump(raw_ostream &OS) {
@@ -1421,24 +1415,7 @@ void JITDylib::dump(raw_ostream &OS) {
       else
       else
         OS << "<not resolved> ";
         OS << "<not resolved> ";
 
 
-      switch (KV.second.getState()) {
-      case SymbolState::Invalid:
-        OS << "Invalid";
-        break;
-      case SymbolState::NeverSearched:
-        OS << "Never-Searched";
-        break;
-      case SymbolState::Materializing:
-        OS << "Materializing";
-        break;
-      case SymbolState::Resolved:
-        OS << "Resolved";
-        break;
-      case SymbolState::Ready:
-        OS << "Ready";
-        break;
-        // default: llvm_unreachable("Invalid state"); break;
-      }
+      OS << KV.second.getState();
 
 
       if (KV.second.hasMaterializerAttached()) {
       if (KV.second.hasMaterializerAttached()) {
         OS << " (Materializer ";
         OS << " (Materializer ";
@@ -1456,10 +1433,10 @@ void JITDylib::dump(raw_ostream &OS) {
       OS << "    \"" << *KV.first << "\":\n"
       OS << "    \"" << *KV.first << "\":\n"
          << "      IsEmitted = " << (KV.second.IsEmitted ? "true" : "false")
          << "      IsEmitted = " << (KV.second.IsEmitted ? "true" : "false")
          << "\n"
          << "\n"
-         << "      " << KV.second.PendingQueries.size()
+         << "      " << KV.second.pendingQueries().size()
          << " pending queries: { ";
          << " pending queries: { ";
-      for (auto &Q : KV.second.PendingQueries)
-        OS << Q.get() << " ";
+      for (const auto &Q : KV.second.pendingQueries())
+        OS << Q.get() << " (" << Q->getRequiredState() << ") ";
       OS << "}\n      Dependants:\n";
       OS << "}\n      Dependants:\n";
       for (auto &KV2 : KV.second.Dependants)
       for (auto &KV2 : KV.second.Dependants)
         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
         OS << "        " << KV2.first->getName() << ": " << KV2.second << "\n";
@@ -1470,6 +1447,51 @@ void JITDylib::dump(raw_ostream &OS) {
   });
   });
 }
 }
 
 
+void JITDylib::MaterializingInfo::addQuery(
+    std::shared_ptr<AsynchronousSymbolQuery> Q) {
+
+  auto I = std::lower_bound(
+      PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(),
+      [](const std::shared_ptr<AsynchronousSymbolQuery> &V, SymbolState S) {
+        return V->getRequiredState() <= S;
+      });
+  PendingQueries.insert(I.base(), std::move(Q));
+}
+
+void JITDylib::MaterializingInfo::removeQuery(
+    const AsynchronousSymbolQuery &Q) {
+  // FIXME: Implement 'find_as' for shared_ptr<T>/T*.
+  auto I =
+      std::find_if(PendingQueries.begin(), PendingQueries.end(),
+                   [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
+                     return V.get() == &Q;
+                   });
+  assert(I != PendingQueries.end() &&
+         "Query is not attached to this MaterializingInfo");
+  PendingQueries.erase(I);
+}
+
+JITDylib::AsynchronousSymbolQueryList
+JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) {
+  AsynchronousSymbolQueryList Result;
+  while (!PendingQueries.empty()) {
+    if (PendingQueries.back()->getRequiredState() > RequiredState)
+      break;
+
+    Result.push_back(std::move(PendingQueries.back()));
+    PendingQueries.pop_back();
+  }
+
+  return Result;
+}
+
+JITDylib::AsynchronousSymbolQueryList
+JITDylib::MaterializingInfo::takeAllQueries() {
+  AsynchronousSymbolQueryList Result;
+  std::swap(Result, PendingQueries);
+  return Result;
+}
+
 JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
 JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
     : ES(ES), JITDylibName(std::move(Name)) {
     : ES(ES), JITDylibName(std::move(Name)) {
   SearchOrder.push_back({this, true});
   SearchOrder.push_back({this, true});
@@ -1533,17 +1555,7 @@ void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
     assert(MaterializingInfos.count(QuerySymbol) &&
     assert(MaterializingInfos.count(QuerySymbol) &&
            "QuerySymbol does not have MaterializingInfo");
            "QuerySymbol does not have MaterializingInfo");
     auto &MI = MaterializingInfos[QuerySymbol];
     auto &MI = MaterializingInfos[QuerySymbol];
-
-    auto IdenticalQuery =
-        [&](const std::shared_ptr<AsynchronousSymbolQuery> &R) {
-          return R.get() == &Q;
-        };
-
-    auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(),
-                          IdenticalQuery);
-    assert(I != MI.PendingQueries.end() &&
-           "Query Q should be in the PendingQueries list for QuerySymbol");
-    MI.PendingQueries.erase(I);
+    MI.removeQuery(Q);
   }
   }
 }
 }
 
 
@@ -1621,74 +1633,36 @@ void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {
 
 
 Expected<SymbolMap> ExecutionSession::legacyLookup(
 Expected<SymbolMap> ExecutionSession::legacyLookup(
     LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
     LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
-    bool WaitUntilReady, RegisterDependenciesFunction RegisterDependencies) {
+    SymbolState RequiredState,
+    RegisterDependenciesFunction RegisterDependencies) {
 #if LLVM_ENABLE_THREADS
 #if LLVM_ENABLE_THREADS
   // In the threaded case we use promises to return the results.
   // In the threaded case we use promises to return the results.
   std::promise<SymbolMap> PromisedResult;
   std::promise<SymbolMap> PromisedResult;
-  std::mutex ErrMutex;
   Error ResolutionError = Error::success();
   Error ResolutionError = Error::success();
-  std::promise<void> PromisedReady;
-  Error ReadyError = Error::success();
-  auto OnResolve = [&](Expected<SymbolMap> R) {
+  auto NotifyComplete = [&](Expected<SymbolMap> R) {
     if (R)
     if (R)
       PromisedResult.set_value(std::move(*R));
       PromisedResult.set_value(std::move(*R));
     else {
     else {
-      {
-        ErrorAsOutParameter _(&ResolutionError);
-        std::lock_guard<std::mutex> Lock(ErrMutex);
-        ResolutionError = R.takeError();
-      }
+      ErrorAsOutParameter _(&ResolutionError);
+      ResolutionError = R.takeError();
       PromisedResult.set_value(SymbolMap());
       PromisedResult.set_value(SymbolMap());
     }
     }
   };
   };
-
-  std::function<void(Error)> OnReady;
-  if (WaitUntilReady) {
-    OnReady = [&](Error Err) {
-      if (Err) {
-        ErrorAsOutParameter _(&ReadyError);
-        std::lock_guard<std::mutex> Lock(ErrMutex);
-        ReadyError = std::move(Err);
-      }
-      PromisedReady.set_value();
-    };
-  } else {
-    OnReady = [&](Error Err) {
-      if (Err)
-        reportError(std::move(Err));
-    };
-  }
-
 #else
 #else
   SymbolMap Result;
   SymbolMap Result;
   Error ResolutionError = Error::success();
   Error ResolutionError = Error::success();
-  Error ReadyError = Error::success();
 
 
-  auto OnResolve = [&](Expected<SymbolMap> R) {
+  auto NotifyComplete = [&](Expected<SymbolMap> R) {
     ErrorAsOutParameter _(&ResolutionError);
     ErrorAsOutParameter _(&ResolutionError);
     if (R)
     if (R)
       Result = std::move(*R);
       Result = std::move(*R);
     else
     else
       ResolutionError = R.takeError();
       ResolutionError = R.takeError();
   };
   };
-
-  std::function<void(Error)> OnReady;
-  if (WaitUntilReady) {
-    OnReady = [&](Error Err) {
-      ErrorAsOutParameter _(&ReadyError);
-      if (Err)
-        ReadyError = std::move(Err);
-    };
-  } else {
-    OnReady = [&](Error Err) {
-      if (Err)
-        reportError(std::move(Err));
-    };
-  }
 #endif
 #endif
 
 
   auto Query = std::make_shared<AsynchronousSymbolQuery>(
   auto Query = std::make_shared<AsynchronousSymbolQuery>(
-      Names, std::move(OnResolve), std::move(OnReady));
+      Names, RequiredState, std::move(NotifyComplete));
   // FIXME: This should be run session locked along with the registration code
   // FIXME: This should be run session locked along with the registration code
   // and error reporting below.
   // and error reporting below.
   SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
   SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
@@ -1712,39 +1686,13 @@ Expected<SymbolMap> ExecutionSession::legacyLookup(
 #if LLVM_ENABLE_THREADS
 #if LLVM_ENABLE_THREADS
   auto ResultFuture = PromisedResult.get_future();
   auto ResultFuture = PromisedResult.get_future();
   auto Result = ResultFuture.get();
   auto Result = ResultFuture.get();
-
-  {
-    std::lock_guard<std::mutex> Lock(ErrMutex);
-    if (ResolutionError) {
-      // ReadyError will never be assigned. Consume the success value.
-      cantFail(std::move(ReadyError));
-      return std::move(ResolutionError);
-    }
-  }
-
-  if (WaitUntilReady) {
-    auto ReadyFuture = PromisedReady.get_future();
-    ReadyFuture.get();
-
-    {
-      std::lock_guard<std::mutex> Lock(ErrMutex);
-      if (ReadyError)
-        return std::move(ReadyError);
-    }
-  } else
-    cantFail(std::move(ReadyError));
-
+  if (ResolutionError)
+    return std::move(ResolutionError);
   return std::move(Result);
   return std::move(Result);
 
 
 #else
 #else
-  if (ResolutionError) {
-    // ReadyError will never be assigned. Consume the success value.
-    cantFail(std::move(ReadyError));
+  if (ResolutionError)
     return std::move(ResolutionError);
     return std::move(ResolutionError);
-  }
-
-  if (ReadyError)
-    return std::move(ReadyError);
 
 
   return Result;
   return Result;
 #endif
 #endif
@@ -1752,9 +1700,16 @@ Expected<SymbolMap> ExecutionSession::legacyLookup(
 
 
 void ExecutionSession::lookup(
 void ExecutionSession::lookup(
     const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
     const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
-    SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
+    SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete,
     RegisterDependenciesFunction RegisterDependencies) {
     RegisterDependenciesFunction RegisterDependencies) {
 
 
+  LLVM_DEBUG({
+    runSessionLocked([&]() {
+      dbgs() << "Looking up " << Symbols << " in " << SearchOrder
+             << " (required state: " << RequiredState << ")\n";
+    });
+  });
+
   // lookup can be re-entered recursively if running on a single thread. Run any
   // lookup can be re-entered recursively if running on a single thread. Run any
   // outstanding MUs in case this query depends on them, otherwise this lookup
   // outstanding MUs in case this query depends on them, otherwise this lookup
   // will starve waiting for a result from an MU that is stuck in the queue.
   // will starve waiting for a result from an MU that is stuck in the queue.
@@ -1762,10 +1717,9 @@ void ExecutionSession::lookup(
 
 
   auto Unresolved = std::move(Symbols);
   auto Unresolved = std::move(Symbols);
   std::map<JITDylib *, MaterializationUnitList> CollectedMUsMap;
   std::map<JITDylib *, MaterializationUnitList> CollectedMUsMap;
-  auto Q = std::make_shared<AsynchronousSymbolQuery>(
-      Unresolved, std::move(OnResolve), std::move(OnReady));
-  bool QueryIsFullyResolved = false;
-  bool QueryIsFullyReady = false;
+  auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
+                                                     std::move(NotifyComplete));
+  bool QueryComplete = false;
 
 
   auto LodgingErr = runSessionLocked([&]() -> Error {
   auto LodgingErr = runSessionLocked([&]() -> Error {
     auto LodgeQuery = [&]() -> Error {
     auto LodgeQuery = [&]() -> Error {
@@ -1806,8 +1760,7 @@ void ExecutionSession::lookup(
     // Record whether this query is fully ready / resolved. We will use
     // Record whether this query is fully ready / resolved. We will use
     // this to call handleFullyResolved/handleFullyReady outside the session
     // this to call handleFullyResolved/handleFullyReady outside the session
     // lock.
     // lock.
-    QueryIsFullyResolved = Q->isFullyResolved();
-    QueryIsFullyReady = Q->isFullyReady();
+    QueryComplete = Q->isComplete();
 
 
     // Call the register dependencies function.
     // Call the register dependencies function.
     if (RegisterDependencies && !Q->QueryRegistrations.empty())
     if (RegisterDependencies && !Q->QueryRegistrations.empty())
@@ -1819,13 +1772,11 @@ void ExecutionSession::lookup(
   if (LodgingErr) {
   if (LodgingErr) {
     Q->handleFailed(std::move(LodgingErr));
     Q->handleFailed(std::move(LodgingErr));
     return;
     return;
-  } else {
-    if (QueryIsFullyResolved)
-      Q->handleFullyResolved();
-    if (QueryIsFullyReady)
-      Q->handleFullyReady();
   }
   }
 
 
+  if (QueryComplete)
+    Q->handleComplete();
+
   // Move the MUs to the OutstandingMUs list, then materialize.
   // Move the MUs to the OutstandingMUs list, then materialize.
   {
   {
     std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
     std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
@@ -1838,113 +1789,55 @@ void ExecutionSession::lookup(
   runOutstandingMUs();
   runOutstandingMUs();
 }
 }
 
 
-Expected<SymbolMap> ExecutionSession::lookup(
-    const JITDylibSearchList &SearchOrder, const SymbolNameSet &Symbols,
-    RegisterDependenciesFunction RegisterDependencies, bool WaitUntilReady) {
+Expected<SymbolMap>
+ExecutionSession::lookup(const JITDylibSearchList &SearchOrder,
+                         const SymbolNameSet &Symbols,
+                         SymbolState RequiredState,
+                         RegisterDependenciesFunction RegisterDependencies) {
 #if LLVM_ENABLE_THREADS
 #if LLVM_ENABLE_THREADS
   // In the threaded case we use promises to return the results.
   // In the threaded case we use promises to return the results.
   std::promise<SymbolMap> PromisedResult;
   std::promise<SymbolMap> PromisedResult;
-  std::mutex ErrMutex;
   Error ResolutionError = Error::success();
   Error ResolutionError = Error::success();
-  std::promise<void> PromisedReady;
-  Error ReadyError = Error::success();
-  auto OnResolve = [&](Expected<SymbolMap> R) {
+
+  auto NotifyComplete = [&](Expected<SymbolMap> R) {
     if (R)
     if (R)
       PromisedResult.set_value(std::move(*R));
       PromisedResult.set_value(std::move(*R));
     else {
     else {
-      {
-        ErrorAsOutParameter _(&ResolutionError);
-        std::lock_guard<std::mutex> Lock(ErrMutex);
-        ResolutionError = R.takeError();
-      }
+      ErrorAsOutParameter _(&ResolutionError);
+      ResolutionError = R.takeError();
       PromisedResult.set_value(SymbolMap());
       PromisedResult.set_value(SymbolMap());
     }
     }
   };
   };
 
 
-  std::function<void(Error)> OnReady;
-  if (WaitUntilReady) {
-    OnReady = [&](Error Err) {
-      if (Err) {
-        ErrorAsOutParameter _(&ReadyError);
-        std::lock_guard<std::mutex> Lock(ErrMutex);
-        ReadyError = std::move(Err);
-      }
-      PromisedReady.set_value();
-    };
-  } else {
-    OnReady = [&](Error Err) {
-      if (Err)
-        reportError(std::move(Err));
-    };
-  }
-
 #else
 #else
   SymbolMap Result;
   SymbolMap Result;
   Error ResolutionError = Error::success();
   Error ResolutionError = Error::success();
-  Error ReadyError = Error::success();
 
 
-  auto OnResolve = [&](Expected<SymbolMap> R) {
+  auto NotifyComplete = [&](Expected<SymbolMap> R) {
     ErrorAsOutParameter _(&ResolutionError);
     ErrorAsOutParameter _(&ResolutionError);
     if (R)
     if (R)
       Result = std::move(*R);
       Result = std::move(*R);
     else
     else
       ResolutionError = R.takeError();
       ResolutionError = R.takeError();
   };
   };
-
-  std::function<void(Error)> OnReady;
-  if (WaitUntilReady) {
-    OnReady = [&](Error Err) {
-      ErrorAsOutParameter _(&ReadyError);
-      if (Err)
-        ReadyError = std::move(Err);
-    };
-  } else {
-    OnReady = [&](Error Err) {
-      if (Err)
-        reportError(std::move(Err));
-    };
-  }
 #endif
 #endif
 
 
   // Perform the asynchronous lookup.
   // Perform the asynchronous lookup.
-  lookup(SearchOrder, Symbols, OnResolve, OnReady, RegisterDependencies);
+  lookup(SearchOrder, Symbols, RequiredState, NotifyComplete,
+         RegisterDependencies);
 
 
 #if LLVM_ENABLE_THREADS
 #if LLVM_ENABLE_THREADS
   auto ResultFuture = PromisedResult.get_future();
   auto ResultFuture = PromisedResult.get_future();
   auto Result = ResultFuture.get();
   auto Result = ResultFuture.get();
 
 
-  {
-    std::lock_guard<std::mutex> Lock(ErrMutex);
-    if (ResolutionError) {
-      // ReadyError will never be assigned. Consume the success value.
-      cantFail(std::move(ReadyError));
-      return std::move(ResolutionError);
-    }
-  }
-
-  if (WaitUntilReady) {
-    auto ReadyFuture = PromisedReady.get_future();
-    ReadyFuture.get();
-
-    {
-      std::lock_guard<std::mutex> Lock(ErrMutex);
-      if (ReadyError)
-        return std::move(ReadyError);
-    }
-  } else
-    cantFail(std::move(ReadyError));
+  if (ResolutionError)
+    return std::move(ResolutionError);
 
 
   return std::move(Result);
   return std::move(Result);
 
 
 #else
 #else
-  if (ResolutionError) {
-    // ReadyError will never be assigned. Consume the success value.
-    cantFail(std::move(ReadyError));
+  if (ResolutionError)
     return std::move(ResolutionError);
     return std::move(ResolutionError);
-  }
-
-  if (ReadyError)
-    return std::move(ReadyError);
 
 
   return Result;
   return Result;
 #endif
 #endif
@@ -1955,8 +1848,8 @@ ExecutionSession::lookup(const JITDylibSearchList &SearchOrder,
                          SymbolStringPtr Name) {
                          SymbolStringPtr Name) {
   SymbolNameSet Names({Name});
   SymbolNameSet Names({Name});
 
 
-  if (auto ResultMap = lookup(SearchOrder, std::move(Names),
-                              NoDependenciesToRegister, true)) {
+  if (auto ResultMap = lookup(SearchOrder, std::move(Names), SymbolState::Ready,
+                              NoDependenciesToRegister)) {
     assert(ResultMap->size() == 1 && "Unexpected number of results");
     assert(ResultMap->size() == 1 && "Unexpected number of results");
     assert(ResultMap->count(Name) && "Missing result for symbol");
     assert(ResultMap->count(Name) && "Missing result for symbol");
     return std::move(ResultMap->begin()->second);
     return std::move(ResultMap->begin()->second);

+ 1 - 2
lib/ExecutionEngine/Orc/ExecutionUtils.cpp

@@ -129,8 +129,7 @@ Error CtorDtorRunner::run() {
 
 
   auto &ES = JD.getExecutionSession();
   auto &ES = JD.getExecutionSession();
   if (auto CtorDtorMap =
   if (auto CtorDtorMap =
-          ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names),
-                    NoDependenciesToRegister, true)) {
+          ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names))) {
     for (auto &KV : CtorDtorsByPriority) {
     for (auto &KV : CtorDtorsByPriority) {
       for (auto &Name : KV.second) {
       for (auto &Name : KV.second) {
         assert(CtorDtorMap->count(Name) && "No entry for Name");
         assert(CtorDtorMap->count(Name) && "No entry for Name");

+ 3 - 6
lib/ExecutionEngine/Orc/LazyReexports.cpp

@@ -51,18 +51,15 @@ LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
     SymbolName = I->second.second;
     SymbolName = I->second.second;
   }
   }
 
 
-  auto LookupResult = ES.lookup(JITDylibSearchList({{SourceJD, true}}),
-                                {SymbolName}, NoDependenciesToRegister, true);
+  auto LookupResult =
+      ES.lookup(JITDylibSearchList({{SourceJD, true}}), SymbolName);
 
 
   if (!LookupResult) {
   if (!LookupResult) {
     ES.reportError(LookupResult.takeError());
     ES.reportError(LookupResult.takeError());
     return ErrorHandlerAddr;
     return ErrorHandlerAddr;
   }
   }
 
 
-  assert(LookupResult->size() == 1 && "Unexpected number of results");
-  assert(LookupResult->count(SymbolName) && "Unexpected result");
-
-  auto ResolvedAddr = LookupResult->begin()->second.getAddress();
+  auto ResolvedAddr = LookupResult->getAddress();
 
 
   std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
   std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
   {
   {

+ 1 - 2
lib/ExecutionEngine/Orc/Legacy.cpp

@@ -36,8 +36,7 @@ void JITSymbolResolverAdapter::lookup(const LookupSet &Symbols,
   };
   };
 
 
   auto Q = std::make_shared<AsynchronousSymbolQuery>(
   auto Q = std::make_shared<AsynchronousSymbolQuery>(
-      InternedSymbols, OnResolvedWithUnwrap,
-      [this](Error Err) { ES.reportError(std::move(Err)); });
+      InternedSymbols, SymbolState::Resolved, OnResolvedWithUnwrap);
 
 
   auto Unresolved = R.lookup(Q, InternedSymbols);
   auto Unresolved = R.lookup(Q, InternedSymbols);
   if (Unresolved.empty()) {
   if (Unresolved.empty()) {

+ 4 - 8
lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp

@@ -69,14 +69,10 @@ public:
       }
       }
     };
     };
 
 
-    ES.lookup(
-        SearchOrder, std::move(InternedSymbols), std::move(OnResolve),
-        // OnReady:
-        [&ES](Error Err) { ES.reportError(std::move(Err)); },
-        // RegisterDependencies:
-        [this](const SymbolDependenceMap &Deps) {
-          registerDependencies(Deps);
-        });
+    ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
+              std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
+                registerDependencies(Deps);
+              });
   }
   }
 
 
   void notifyResolved(AtomGraph &G) override {
   void notifyResolved(AtomGraph &G) override {

+ 4 - 7
lib/ExecutionEngine/Orc/OrcCBindingsStack.h

@@ -153,8 +153,8 @@ private:
       for (auto &S : Symbols) {
       for (auto &S : Symbols) {
         if (auto Sym = findSymbol(*S)) {
         if (auto Sym = findSymbol(*S)) {
           if (auto Addr = Sym.getAddress()) {
           if (auto Addr = Sym.getAddress()) {
-            Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
-            Query->notifySymbolReady();
+            Query->notifySymbolMetRequiredState(
+                S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
           } else {
           } else {
             Stack.ES.legacyFailQuery(*Query, Addr.takeError());
             Stack.ES.legacyFailQuery(*Query, Addr.takeError());
             return orc::SymbolNameSet();
             return orc::SymbolNameSet();
@@ -166,11 +166,8 @@ private:
           UnresolvedSymbols.insert(S);
           UnresolvedSymbols.insert(S);
       }
       }
 
 
-      if (Query->isFullyResolved())
-        Query->handleFullyResolved();
-
-      if (Query->isFullyReady())
-        Query->handleFullyReady();
+      if (Query->isComplete())
+        Query->handleComplete();
 
 
       return UnresolvedSymbols;
       return UnresolvedSymbols;
     }
     }

+ 6 - 9
lib/ExecutionEngine/Orc/OrcMCJITReplacement.h

@@ -176,8 +176,8 @@ class OrcMCJITReplacement : public ExecutionEngine {
       for (auto &S : Symbols) {
       for (auto &S : Symbols) {
         if (auto Sym = M.findMangledSymbol(*S)) {
         if (auto Sym = M.findMangledSymbol(*S)) {
           if (auto Addr = Sym.getAddress()) {
           if (auto Addr = Sym.getAddress()) {
-            Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
-            Query->notifySymbolReady();
+            Query->notifySymbolMetRequiredState(
+                S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
             NewSymbolsResolved = true;
             NewSymbolsResolved = true;
           } else {
           } else {
             M.ES.legacyFailQuery(*Query, Addr.takeError());
             M.ES.legacyFailQuery(*Query, Addr.takeError());
@@ -189,8 +189,8 @@ class OrcMCJITReplacement : public ExecutionEngine {
         } else {
         } else {
           if (auto Sym2 = M.ClientResolver->findSymbol(*S)) {
           if (auto Sym2 = M.ClientResolver->findSymbol(*S)) {
             if (auto Addr = Sym2.getAddress()) {
             if (auto Addr = Sym2.getAddress()) {
-              Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym2.getFlags()));
-              Query->notifySymbolReady();
+              Query->notifySymbolMetRequiredState(
+                  S, JITEvaluatedSymbol(*Addr, Sym2.getFlags()));
               NewSymbolsResolved = true;
               NewSymbolsResolved = true;
             } else {
             } else {
               M.ES.legacyFailQuery(*Query, Addr.takeError());
               M.ES.legacyFailQuery(*Query, Addr.takeError());
@@ -204,11 +204,8 @@ class OrcMCJITReplacement : public ExecutionEngine {
         }
         }
       }
       }
 
 
-      if (NewSymbolsResolved && Query->isFullyResolved())
-        Query->handleFullyResolved();
-
-      if (NewSymbolsResolved && Query->isFullyReady())
-        Query->handleFullyReady();
+      if (NewSymbolsResolved && Query->isComplete())
+        Query->handleComplete();
 
 
       return UnresolvedSymbols;
       return UnresolvedSymbols;
     }
     }

+ 2 - 5
lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp

@@ -41,9 +41,6 @@ public:
           OnResolved(Result);
           OnResolved(Result);
         };
         };
 
 
-    // We're not waiting for symbols to be ready. Just log any errors.
-    auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
-
     // Register dependencies for all symbols contained in this set.
     // Register dependencies for all symbols contained in this set.
     auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
     auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
       MR.addDependenciesForAll(Deps);
       MR.addDependenciesForAll(Deps);
@@ -52,8 +49,8 @@ public:
     JITDylibSearchList SearchOrder;
     JITDylibSearchList SearchOrder;
     MR.getTargetJITDylib().withSearchOrderDo(
     MR.getTargetJITDylib().withSearchOrderDo(
         [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
         [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
-    ES.lookup(SearchOrder, InternedSymbols, OnResolvedWithUnwrap, OnReady,
-              RegisterDependencies);
+    ES.lookup(SearchOrder, InternedSymbols, SymbolState::Resolved,
+              OnResolvedWithUnwrap, RegisterDependencies);
   }
   }
 
 
   Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
   Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {

+ 80 - 119
unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp

@@ -23,21 +23,16 @@ class CoreAPIsStandardTest : public CoreAPIsBasedStandardTest {};
 namespace {
 namespace {
 
 
 TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
 TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
-  bool OnResolutionRun = false;
-  bool OnReadyRun = false;
+  bool OnCompletionRun = false;
 
 
-  auto OnResolution = [&](Expected<SymbolMap> Result) {
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
     auto &Resolved = *Result;
     auto &Resolved = *Result;
     auto I = Resolved.find(Foo);
     auto I = Resolved.find(Foo);
     EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition";
     EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition";
     EXPECT_EQ(I->second.getAddress(), FooAddr)
     EXPECT_EQ(I->second.getAddress(), FooAddr)
         << "Resolution returned incorrect result";
         << "Resolution returned incorrect result";
-    OnResolutionRun = true;
-  };
-  auto OnReady = [&](Error Err) {
-    cantFail(std::move(Err));
-    OnReadyRun = true;
+    OnCompletionRun = true;
   };
   };
 
 
   std::shared_ptr<MaterializationResponsibility> FooMR;
   std::shared_ptr<MaterializationResponsibility> FooMR;
@@ -48,65 +43,51 @@ TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
         FooMR = std::make_shared<MaterializationResponsibility>(std::move(R));
         FooMR = std::make_shared<MaterializationResponsibility>(std::move(R));
       })));
       })));
 
 
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, OnResolution, OnReady,
-            NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
+            OnCompletion, NoDependenciesToRegister);
 
 
-  EXPECT_FALSE(OnResolutionRun) << "Should not have been resolved yet";
-  EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet";
+  EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet";
 
 
   FooMR->resolve({{Foo, FooSym}});
   FooMR->resolve({{Foo, FooSym}});
 
 
-  EXPECT_TRUE(OnResolutionRun) << "Should have been resolved";
-  EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet";
+  EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet";
 
 
   FooMR->emit();
   FooMR->emit();
 
 
-  EXPECT_TRUE(OnReadyRun) << "Should have been marked ready";
+  EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready";
 }
 }
 
 
 TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) {
 TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) {
-  bool OnResolutionRun = false;
-  bool OnReadyRun = false;
+  bool OnCompletionRun = false;
 
 
-  auto OnResolution = [&](Expected<SymbolMap> Result) {
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
     EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success";
     EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success";
     auto Msg = toString(Result.takeError());
     auto Msg = toString(Result.takeError());
     EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result";
     EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result";
-    OnResolutionRun = true;
-  };
-  auto OnReady = [&](Error Err) {
-    cantFail(std::move(Err));
-    OnReadyRun = true;
+    OnCompletionRun = true;
   };
   };
 
 
-  AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), OnResolution, OnReady);
+  AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), SymbolState::Ready,
+                            OnCompletion);
 
 
   ES.legacyFailQuery(Q,
   ES.legacyFailQuery(Q,
                      make_error<StringError>("xyz", inconvertibleErrorCode()));
                      make_error<StringError>("xyz", inconvertibleErrorCode()));
 
 
-  EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
-  EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletionCallback was not run";
 }
 }
 
 
 TEST_F(CoreAPIsStandardTest, EmptyLookup) {
 TEST_F(CoreAPIsStandardTest, EmptyLookup) {
-  bool OnResolvedRun = false;
-  bool OnReadyRun = false;
+  bool OnCompletionRun = false;
 
 
-  auto OnResolution = [&](Expected<SymbolMap> Result) {
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
     cantFail(std::move(Result));
     cantFail(std::move(Result));
-    OnResolvedRun = true;
-  };
-
-  auto OnReady = [&](Error Err) {
-    cantFail(std::move(Err));
-    OnReadyRun = true;
+    OnCompletionRun = true;
   };
   };
 
 
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {}, OnResolution, OnReady,
-            NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {}, SymbolState::Ready,
+            OnCompletion, NoDependenciesToRegister);
 
 
-  EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
-  EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query";
 }
 }
 
 
 TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
 TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
@@ -148,20 +129,14 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
         ADD_FAILURE() << "\"Baz\" discarded unexpectedly";
         ADD_FAILURE() << "\"Baz\" discarded unexpectedly";
       })));
       })));
 
 
-  bool OnResolvedRun = false;
-  bool OnReadyRun = false;
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Baz},
-            [&](Expected<SymbolMap> Result) {
-              EXPECT_TRUE(!!Result) << "OnResolved failed unexpectedly";
-              consumeError(Result.takeError());
-              OnResolvedRun = true;
-            },
-            [&](Error Err) {
-              EXPECT_FALSE(!!Err) << "OnReady failed unexpectedly";
-              consumeError(std::move(Err));
-              OnReadyRun = true;
-            },
-            NoDependenciesToRegister);
+  bool OnCompletionRun = false;
+  ES.lookup(
+      JITDylibSearchList({{&JD, false}}), {Foo, Baz}, SymbolState::Ready,
+      [&](Expected<SymbolMap> Result) {
+        cantFail(Result.takeError());
+        OnCompletionRun = true;
+      },
+      NoDependenciesToRegister);
 
 
   {
   {
     // Attempt 1: Search for a missing symbol, Qux.
     // Attempt 1: Search for a missing symbol, Qux.
@@ -193,8 +168,7 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
   EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded";
   EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded";
   EXPECT_TRUE(BarMaterializerDestructed)
   EXPECT_TRUE(BarMaterializerDestructed)
       << "\"Bar\"'s materializer should have been destructed";
       << "\"Bar\"'s materializer should have been destructed";
-  EXPECT_TRUE(OnResolvedRun) << "OnResolved should have been run";
-  EXPECT_TRUE(OnReadyRun) << "OnReady should have been run";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletion should have been run";
 }
 }
 
 
 TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) {
 TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) {
@@ -202,24 +176,18 @@ TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) {
 
 
   auto &JD2 = ES.createJITDylib("JD2");
   auto &JD2 = ES.createJITDylib("JD2");
 
 
-  bool OnResolvedRun = false;
-  bool OnReadyRun = false;
+  bool OnCompletionRun = false;
 
 
   auto Q = std::make_shared<AsynchronousSymbolQuery>(
   auto Q = std::make_shared<AsynchronousSymbolQuery>(
-      SymbolNameSet({Foo}),
+      SymbolNameSet({Foo}), SymbolState::Ready,
       [&](Expected<SymbolMap> Result) {
       [&](Expected<SymbolMap> Result) {
         cantFail(std::move(Result));
         cantFail(std::move(Result));
-        OnResolvedRun = true;
-      },
-      [&](Error Err) {
-        cantFail(std::move(Err));
-        OnReadyRun = true;
+        OnCompletionRun = true;
       });
       });
 
 
   cantFail(JD2.legacyLookup(Q, cantFail(JD.legacyLookup(Q, {Foo}))));
   cantFail(JD2.legacyLookup(Q, cantFail(JD.legacyLookup(Q, {Foo}))));
 
 
-  EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
-  EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query";
 }
 }
 
 
 TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) {
 TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) {
@@ -396,14 +364,13 @@ TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) {
   cantFail(JD.define(FooMU));
   cantFail(JD.define(FooMU));
 
 
   bool FooReady = false;
   bool FooReady = false;
-  auto OnResolution = [](Expected<SymbolMap> R) { cantFail(std::move(R)); };
-  auto OnReady = [&](Error Err) {
-    cantFail(std::move(Err));
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
+    cantFail(std::move(Result));
     FooReady = true;
     FooReady = true;
   };
   };
 
 
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, std::move(OnResolution),
-            std::move(OnReady), NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
+            OnCompletion, NoDependenciesToRegister);
 
 
   FooR->resolve({{Foo, FooSym}});
   FooR->resolve({{Foo, FooSym}});
   FooR->emit();
   FooR->emit();
@@ -452,16 +419,18 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
     FooResolved = true;
     FooResolved = true;
   };
   };
 
 
-  auto OnFooReady = [&](Error Err) {
-    cantFail(std::move(Err));
+  auto OnFooReady = [&](Expected<SymbolMap> Result) {
+    cantFail(std::move(Result));
     FooReady = true;
     FooReady = true;
   };
   };
 
 
-  // Issue a lookup for Foo. Use NoDependenciesToRegister: We're going to add
+  // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add
   // the dependencies manually below.
   // the dependencies manually below.
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo},
-            std::move(OnFooResolution), std::move(OnFooReady),
-            NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
+            std::move(OnFooResolution), NoDependenciesToRegister);
+
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
+            std::move(OnFooReady), NoDependenciesToRegister);
 
 
   bool BarResolved = false;
   bool BarResolved = false;
   bool BarReady = false;
   bool BarReady = false;
@@ -470,14 +439,16 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
     BarResolved = true;
     BarResolved = true;
   };
   };
 
 
-  auto OnBarReady = [&](Error Err) {
-    cantFail(std::move(Err));
+  auto OnBarReady = [&](Expected<SymbolMap> Result) {
+    cantFail(std::move(Result));
     BarReady = true;
     BarReady = true;
   };
   };
 
 
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar},
-            std::move(OnBarResolution), std::move(OnBarReady),
-            NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Resolved,
+            std::move(OnBarResolution), NoDependenciesToRegister);
+
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready,
+            std::move(OnBarReady), NoDependenciesToRegister);
 
 
   bool BazResolved = false;
   bool BazResolved = false;
   bool BazReady = false;
   bool BazReady = false;
@@ -487,14 +458,16 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
     BazResolved = true;
     BazResolved = true;
   };
   };
 
 
-  auto OnBazReady = [&](Error Err) {
-    cantFail(std::move(Err));
+  auto OnBazReady = [&](Expected<SymbolMap> Result) {
+    cantFail(std::move(Result));
     BazReady = true;
     BazReady = true;
   };
   };
 
 
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz},
-            std::move(OnBazResolution), std::move(OnBazReady),
-            NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Resolved,
+            std::move(OnBazResolution), NoDependenciesToRegister);
+
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Ready,
+            std::move(OnBazReady), NoDependenciesToRegister);
 
 
   // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo.
   // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo.
   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
   FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
@@ -599,30 +572,23 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) {
 
 
   SymbolNameSet Names({Foo});
   SymbolNameSet Names({Foo});
 
 
-  bool OnResolutionRun = false;
-  bool OnReadyRun = false;
+  bool OnCompletionRun = false;
 
 
-  auto OnResolution = [&](Expected<SymbolMap> Result) {
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
     EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
     auto I = Result->find(Foo);
     auto I = Result->find(Foo);
     EXPECT_NE(I, Result->end()) << "Could not find symbol definition";
     EXPECT_NE(I, Result->end()) << "Could not find symbol definition";
     EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
     EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
         << "Resolution returned incorrect result";
         << "Resolution returned incorrect result";
-    OnResolutionRun = true;
-  };
-
-  auto OnReady = [&](Error Err) {
-    cantFail(std::move(Err));
-    OnReadyRun = true;
+    OnCompletionRun = true;
   };
   };
 
 
-  ES.lookup(JITDylibSearchList({{&JD, false}}), Names, std::move(OnResolution),
-            std::move(OnReady), NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), Names, SymbolState::Ready,
+            std::move(OnCompletion), NoDependenciesToRegister);
 
 
   EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
   EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
   EXPECT_TRUE(BarDiscarded) << "Bar was not discarded";
   EXPECT_TRUE(BarDiscarded) << "Bar was not discarded";
-  EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
-  EXPECT_TRUE(OnReadyRun) << "OnReady was not run";
+  EXPECT_TRUE(OnCompletionRun) << "OnResolutionCallback was not run";
 }
 }
 
 
 TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {
 TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {
@@ -652,24 +618,17 @@ TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {
   cantFail(JD.define(MU1));
   cantFail(JD.define(MU1));
   cantFail(JD.define(MU2));
   cantFail(JD.define(MU2));
 
 
-  bool OnResolvedRun = false;
-  bool OnReadyRun = false;
+  bool OnCompletionRun = false;
 
 
-  auto OnResolution = [&](Expected<SymbolMap> Result) {
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
     cantFail(std::move(Result));
     cantFail(std::move(Result));
-    OnResolvedRun = true;
+    OnCompletionRun = true;
   };
   };
 
 
-  auto OnReady = [&](Error Err) {
-    cantFail(std::move(Err));
-    OnReadyRun = true;
-  };
-
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, std::move(OnResolution),
-            std::move(OnReady), NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready,
+            std::move(OnCompletion), NoDependenciesToRegister);
 
 
-  EXPECT_TRUE(OnResolvedRun) << "OnResolved not run";
-  EXPECT_TRUE(OnReadyRun) << "OnReady not run";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run";
   EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all";
   EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all";
   EXPECT_TRUE(DuplicateBarDiscarded)
   EXPECT_TRUE(DuplicateBarDiscarded)
       << "Duplicate bar definition not discarded";
       << "Duplicate bar definition not discarded";
@@ -725,7 +684,11 @@ TEST_F(CoreAPIsStandardTest, FailResolution) {
   auto MU = llvm::make_unique<SimpleMaterializationUnit>(
   auto MU = llvm::make_unique<SimpleMaterializationUnit>(
       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak},
       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak},
                       {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}),
                       {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}),
-      [&](MaterializationResponsibility R) { R.failMaterialization(); });
+      [&](MaterializationResponsibility R) {
+        dbgs() << "Before failMat:\n";
+        ES.dump(dbgs());
+        R.failMaterialization();
+      });
 
 
   cantFail(JD.define(MU));
   cantFail(JD.define(MU));
 
 
@@ -763,6 +726,7 @@ TEST_F(CoreAPIsStandardTest, FailEmissionEarly) {
 
 
         ES.lookup(
         ES.lookup(
             JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}),
             JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}),
+            SymbolState::Resolved,
             [&R](Expected<SymbolMap> Result) {
             [&R](Expected<SymbolMap> Result) {
               // Called when "baz" is resolved. We don't actually depend
               // Called when "baz" is resolved. We don't actually depend
               // on or care about baz, but use it to trigger failure of
               // on or care about baz, but use it to trigger failure of
@@ -772,7 +736,6 @@ TEST_F(CoreAPIsStandardTest, FailEmissionEarly) {
               cantFail(std::move(Result));
               cantFail(std::move(Result));
               R.failMaterialization();
               R.failMaterialization();
             },
             },
-            [](Error Err) { cantFail(std::move(Err)); },
             [&](const SymbolDependenceMap &Deps) {
             [&](const SymbolDependenceMap &Deps) {
               R.addDependenciesForAll(Deps);
               R.addDependenciesForAll(Deps);
             });
             });
@@ -923,14 +886,12 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) {
       });
       });
 
 
   cantFail(JD.define(MU));
   cantFail(JD.define(MU));
-  auto OnResolution = [](Expected<SymbolMap> Result) {
+  auto OnCompletion = [](Expected<SymbolMap> Result) {
     cantFail(std::move(Result));
     cantFail(std::move(Result));
   };
   };
 
 
-  auto OnReady = [](Error Err) { cantFail(std::move(Err)); };
-
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, std::move(OnResolution),
-            std::move(OnReady), NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready,
+            std::move(OnCompletion), NoDependenciesToRegister);
 
 
   auto MU2 = llvm::make_unique<SimpleMaterializationUnit>(
   auto MU2 = llvm::make_unique<SimpleMaterializationUnit>(
       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
       SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),

+ 11 - 20
unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp

@@ -42,10 +42,10 @@ TEST_F(LegacyAPIsStandardTest, TestLambdaSymbolResolver) {
   EXPECT_EQ(RS.count(Bar), 1U)
   EXPECT_EQ(RS.count(Bar), 1U)
       << "getResponsibilitySet result incorrect. Should be {'bar'}";
       << "getResponsibilitySet result incorrect. Should be {'bar'}";
 
 
-  bool OnResolvedRun = false;
+  bool OnCompletionRun = false;
 
 
-  auto OnResolved = [&](Expected<SymbolMap> Result) {
-    OnResolvedRun = true;
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
+    OnCompletionRun = true;
     EXPECT_TRUE(!!Result) << "Unexpected error";
     EXPECT_TRUE(!!Result) << "Unexpected error";
     EXPECT_EQ(Result->size(), 2U) << "Unexpected number of resolved symbols";
     EXPECT_EQ(Result->size(), 2U) << "Unexpected number of resolved symbols";
     EXPECT_EQ(Result->count(Foo), 1U) << "Missing lookup result for foo";
     EXPECT_EQ(Result->count(Foo), 1U) << "Missing lookup result for foo";
@@ -55,18 +55,15 @@ TEST_F(LegacyAPIsStandardTest, TestLambdaSymbolResolver) {
     EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress())
     EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress())
         << "Incorrect address for bar";
         << "Incorrect address for bar";
   };
   };
-  auto OnReady = [&](Error Err) {
-    EXPECT_FALSE(!!Err) << "Finalization should never fail in this test";
-  };
 
 
-  auto Q = std::make_shared<AsynchronousSymbolQuery>(SymbolNameSet({Foo, Bar}),
-                                                     OnResolved, OnReady);
+  auto Q = std::make_shared<AsynchronousSymbolQuery>(
+      SymbolNameSet({Foo, Bar}), SymbolState::Resolved, OnCompletion);
   auto Unresolved =
   auto Unresolved =
       Resolver->lookup(std::move(Q), SymbolNameSet({Foo, Bar, Baz}));
       Resolver->lookup(std::move(Q), SymbolNameSet({Foo, Bar, Baz}));
 
 
   EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol";
   EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol";
   EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to not be resolved";
   EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to not be resolved";
-  EXPECT_TRUE(OnResolvedRun) << "OnResolved was never run";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletion was never run";
 }
 }
 
 
 TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) {
 TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) {
@@ -98,10 +95,9 @@ TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) {
   EXPECT_FALSE(BarMaterialized)
   EXPECT_FALSE(BarMaterialized)
       << "lookupFlags should not have materialized bar";
       << "lookupFlags should not have materialized bar";
 
 
-  bool OnResolvedRun = false;
-  bool OnReadyRun = false;
-  auto OnResolved = [&](Expected<SymbolMap> Result) {
-    OnResolvedRun = true;
+  bool OnCompletionRun = false;
+  auto OnCompletion = [&](Expected<SymbolMap> Result) {
+    OnCompletionRun = true;
     EXPECT_TRUE(!!Result) << "lookuWithLegacy failed to resolve";
     EXPECT_TRUE(!!Result) << "lookuWithLegacy failed to resolve";
 
 
     EXPECT_EQ(Result->size(), 2U) << "Wrong number of symbols resolved";
     EXPECT_EQ(Result->size(), 2U) << "Wrong number of symbols resolved";
@@ -114,17 +110,12 @@ TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) {
     EXPECT_EQ((*Result)[Bar].getFlags(), BarSym.getFlags())
     EXPECT_EQ((*Result)[Bar].getFlags(), BarSym.getFlags())
         << "Wrong flags for bar";
         << "Wrong flags for bar";
   };
   };
-  auto OnReady = [&](Error Err) {
-    EXPECT_FALSE(!!Err) << "Finalization unexpectedly failed";
-    OnReadyRun = true;
-  };
 
 
-  AsynchronousSymbolQuery Q({Foo, Bar}, OnResolved, OnReady);
+  AsynchronousSymbolQuery Q({Foo, Bar}, SymbolState::Resolved, OnCompletion);
   auto Unresolved =
   auto Unresolved =
       lookupWithLegacyFn(ES, Q, SymbolNameSet({Foo, Bar, Baz}), LegacyLookup);
       lookupWithLegacyFn(ES, Q, SymbolNameSet({Foo, Bar, Baz}), LegacyLookup);
 
 
-  EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run";
-  EXPECT_TRUE(OnReadyRun) << "OnReady was not run";
+  EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run";
   EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol";
   EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol";
   EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to be unresolved";
   EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to be unresolved";
 }
 }

+ 11 - 12
unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp

@@ -61,12 +61,11 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
     cantFail(std::move(R));
     cantFail(std::move(R));
   };
   };
 
 
-  auto OnReadyDoNothing = [](Error Err) { cantFail(std::move(Err)); };
-
   ObjLayer.setProcessAllSections(ProcessAllSections);
   ObjLayer.setProcessAllSections(ProcessAllSections);
   cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule()));
   cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule()));
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, OnResolveDoNothing,
-            OnReadyDoNothing, NoDependenciesToRegister);
+  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
+            OnResolveDoNothing, NoDependenciesToRegister);
+
   return DebugSectionSeen;
   return DebugSectionSeen;
 }
 }
 
 
@@ -160,10 +159,10 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
   ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
   ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
 
 
   cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
   cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo},
-            [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
-            [](Error Err) { cantFail(std::move(Err)); },
-            NoDependenciesToRegister);
+  ES.lookup(
+      JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
+      [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
+      NoDependenciesToRegister);
 }
 }
 
 
 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
@@ -225,10 +224,10 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
   ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
   ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
 
 
   cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
   cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
-  ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo},
-            [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
-            [](Error Err) { cantFail(std::move(Err)); },
-            NoDependenciesToRegister);
+  ES.lookup(
+      JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
+      [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
+      NoDependenciesToRegister);
 }
 }
 
 
 } // end anonymous namespace
 } // end anonymous namespace