[llvm] r337595 - [ORC] Add new symbol lookup methods to ExecutionSessionBase in preparation for

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 20 13:27:57 PDT 2018


I had to revert this in r337608 because it broke the
LLVM_ENABLE_THREADS=OFF build. Unfortunately, the two code paths are very
different, and I couldn't find a quick fix.

On Fri, Jul 20, 2018 at 11:37 AM Lang Hames via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: lhames
> Date: Fri Jul 20 11:31:53 2018
> New Revision: 337595
>
> URL: http://llvm.org/viewvc/llvm-project?rev=337595&view=rev
> Log:
> [ORC] Add new symbol lookup methods to ExecutionSessionBase in preparation
> for
> deprecating SymbolResolver and AsynchronousSymbolQuery.
>
> Both lookup overloads take a VSO search order to perform the lookup. The
> first
> overload is non-blocking and takes OnResolved and OnReady callbacks. The
> second
> is blocking, takes a boolean flag to indicate whether to wait until all
> symbols
> are ready, and returns a SymbolMap. Both overloads take a
> RegisterDependencies
> function to register symbol dependencies (if any) on the query.
>
> Modified:
>     llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h
>     llvm/trunk/include/llvm/ExecutionEngine/Orc/Legacy.h
>     llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp
>     llvm/trunk/lib/ExecutionEngine/Orc/Legacy.cpp
>     llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
>     llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
>     llvm/trunk/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
>     llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
>     llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp
>
> Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h (original)
> +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h Fri Jul 20 11:31:53
> 2018
> @@ -69,8 +69,23 @@ raw_ostream &operator<<(raw_ostream &OS,
>  /// A list of VSO pointers.
>  using VSOList = std::vector<VSO *>;
>
> +/// Render a VSOList.
>  raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs);
>
> +/// Callback to notify client that symbols have been resolved.
> +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.
> +using RegisterDependenciesFunction =
> +    std::function<void(const SymbolDependenceMap &)>;
> +
> +/// This can be used as the value for a RegisterDependenciesFunction if
> there
> +/// are no dependants to register with.
> +extern RegisterDependenciesFunction NoDependenciesToRegister;
> +
>  /// Used to notify a VSO that the given set of symbols failed to
> materialize.
>  class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
>  public:
> @@ -122,6 +137,9 @@ public:
>    ///        into.
>    VSO &getTargetVSO() const { return V; }
>
> +  /// Returns the symbol flags map for this responsibility instance.
> +  SymbolFlagsMap getSymbols() { return SymbolFlags; }
> +
>    /// Returns the names of any symbols covered by this
>    /// MaterializationResponsibility object that have queries pending. This
>    /// information can be used to return responsibility for unrequested
> symbols
> @@ -223,6 +241,9 @@ private:
>    virtual void discard(const VSO &V, SymbolStringPtr Name) = 0;
>  };
>
> +using MaterializationUnitList =
> +    std::vector<std::unique_ptr<MaterializationUnit>>;
> +
>  /// A MaterializationUnit implementation for pre-existing absolute
> symbols.
>  ///
>  /// All symbols will be resolved and marked ready as soon as the unit is
> @@ -322,6 +343,9 @@ buildSimpleReexportsAliasMap(VSO &Source
>
>  /// Base utilities for ExecutionSession.
>  class ExecutionSessionBase {
> +  // FIXME: Remove this when we remove the old ORC layers.
> +  friend class VSO;
> +
>  public:
>    /// For reporting errors.
>    using ErrorReporter = std::function<void(Error)>;
> @@ -372,11 +396,50 @@ public:
>    void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
>    }
>
> -  /// Cause the given query to fail with the given Error.
> -  ///
> -  /// This should only be used by legacy APIs and will be deprecated in
> the
> -  /// future.
> -  void failQuery(AsynchronousSymbolQuery &Q, Error Err);
> +  void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
> +
> +  using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
> +      std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
> +
> +  /// A legacy lookup function for JITSymbolResolverAdapter.
> +  /// Do not use -- this will be removed soon.
> +  Expected<SymbolMap>
> +  legacyLookup(ExecutionSessionBase &ES, LegacyAsyncLookupFunction
> AsyncLookup,
> +               SymbolNameSet Names, bool WaiUntilReady,
> +               RegisterDependenciesFunction RegisterDependencies);
> +
> +  /// Search the given VSO list for the given symbols.
> +  ///
> +  ///
> +  /// 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.
> +  ///
> +  /// If all symbols are found, the RegisterDependencies function will be
> called
> +  /// while the session lock is held. This gives clients a chance to
> register
> +  /// dependencies for on the queried symbols for any symbols they are
> +  /// materializing (if a MaterializationResponsibility instance is
> present,
> +  /// this can be implemented by calling
> +  /// MaterializationResponsibility::addDependencies). If there are no
> +  /// dependenant symbols for this query (e.g. it is being made by a top
> level
> +  /// client to get an address to call) then the value
> NoDependenciesToRegister
> +  /// can be used.
> +  void lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
> +              SymbolsResolvedCallback OnResolve, SymbolsReadyCallback
> OnReady,
> +              RegisterDependenciesFunction RegisterDependencies);
> +
> +  /// Blocking version of lookup above. Returns the resolved symbol map.
> +  /// If WaitUntilReady is true (the default), will not return until all
> +  /// requested symbols are ready (or an error occurs). If WaitUntilReady
> is
> +  /// false, will return as soon as all requested symbols are resolved,
> +  /// or an error occurs. If WaitUntilReady is false and an error occurs
> +  /// after resolution, the function will return a success value, but the
> +  /// error will be reported via reportErrors.
> +  Expected<SymbolMap> lookup(const VSOList &VSOs, const SymbolNameSet
> &Symbols,
> +                             RegisterDependenciesFunction
> RegisterDependencies,
> +                             bool WaitUntilReady = true);
>
>    /// Materialize the given unit.
>    void dispatchMaterialization(VSO &V,
> @@ -394,12 +457,20 @@ private:
>      MU->doMaterialize(V);
>    }
>
> +  void runOutstandingMUs();
> +
>    mutable std::recursive_mutex SessionMutex;
>    std::shared_ptr<SymbolStringPool> SSP;
>    VModuleKey LastKey = 0;
>    ErrorReporter ReportError = logErrorsToStdErr;
>    DispatchMaterializationFunction DispatchMaterialization =
>        materializeOnCurrentThread;
> +
> +  // FIXME: Remove this (and runOutstandingMUs) once the linking layer
> works
> +  //        with callbacks from asynchronous queries.
> +  mutable std::recursive_mutex OutstandingMUsMutex;
> +  std::vector<std::pair<VSO *, std::unique_ptr<MaterializationUnit>>>
> +      OutstandingMUs;
>  };
>
>  /// A symbol query that returns results via a callback when results are
> @@ -411,21 +482,6 @@ class AsynchronousSymbolQuery {
>    friend class VSO;
>
>  public:
> -  class ResolutionResult {
> -  public:
> -    ResolutionResult(SymbolMap Symbols, const SymbolDependenceMap
> &Dependencies)
> -        : Symbols(std::move(Symbols)), Dependencies(Dependencies) {}
> -
> -    SymbolMap Symbols;
> -    const SymbolDependenceMap &Dependencies;
> -  };
> -
> -  /// Callback to notify client that symbols have been resolved.
> -  using SymbolsResolvedCallback =
> -      std::function<void(Expected<ResolutionResult>)>;
> -
> -  /// Callback to notify client that symbols are ready for execution.
> -  using SymbolsReadyCallback = std::function<void(Error)>;
>
>    /// Create a query for the given symbols, notify-resolved and
>    ///        notify-ready callbacks.
> @@ -485,6 +541,7 @@ private:
>  class VSO {
>    friend class AsynchronousSymbolQuery;
>    friend class ExecutionSession;
> +  friend class ExecutionSessionBase;
>    friend class MaterializationResponsibility;
>  public:
>    using FallbackDefinitionGeneratorFunction =
> @@ -493,9 +550,6 @@ public:
>    using AsynchronousSymbolQuerySet =
>        std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
>
> -  using MaterializationUnitList =
> -      std::vector<std::unique_ptr<MaterializationUnit>>;
> -
>    VSO(const VSO &) = delete;
>    VSO &operator=(const VSO &) = delete;
>    VSO(VSO &&) = delete;
> @@ -547,8 +601,10 @@ public:
>    void removeFromSearchOrder(VSO &V);
>
>    /// Do something with the search order (run under the session lock).
> -  template <typename Func> void withSearchOrderDo(Func F) {
> -    ES.runSessionLocked([&]() { F(SearchOrder); });
> +  template <typename Func>
> +  auto withSearchOrderDo(Func &&F)
> +      -> decltype(F(std::declval<const VSOList &>())) {
> +    return ES.runSessionLocked([&]() { return F(SearchOrder); });
>    }
>
>    /// Define all symbols provided by the materialization unit to be part
> @@ -579,6 +635,10 @@ public:
>    ///        the flags for each symbol in Flags. Returns any unresolved
> symbols.
>    SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
>
> +  /// Dump current VSO state to OS.
> +  void dump(raw_ostream &OS);
> +
> +  /// FIXME: Remove this when we remove the old ORC layers.
>    /// Search the given VSOs in order for the symbols in Symbols. Results
>    ///        (once they become available) will be returned via the given
> Query.
>    ///
> @@ -586,11 +646,8 @@ public:
>    /// and the query will not be applied. The Query is not failed and can
> be
>    /// re-used in a subsequent lookup once the symbols have been added, or
>    /// manually failed.
> -  SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
> -                       SymbolNameSet Names);
> -
> -  /// Dump current VSO state to OS.
> -  void dump(raw_ostream &OS);
> +  SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
> +                             SymbolNameSet Names);
>
>  private:
>    using AsynchronousSymbolQueryList =
> @@ -629,6 +686,12 @@ private:
>    SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
>                                  const SymbolNameSet &Names);
>
> +  void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
> +                  SymbolNameSet &Unresolved, MaterializationUnitList
> &MUs);
> +
> +  void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
> +                      SymbolNameSet &Unresolved, MaterializationUnitList
> &MUs);
> +
>    LookupImplActionFlags
>    lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
>               std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
> @@ -647,8 +710,8 @@ private:
>
>    SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
>
> -  void addDependencies(const SymbolFlagsMap &Dependents,
> -                       const SymbolDependenceMap &Dependencies);
> +  void addDependencies(const SymbolStringPtr &Name,
> +                       const SymbolDependenceMap &Dependants);
>
>    void resolve(const SymbolMap &Resolved);
>
> @@ -656,8 +719,6 @@ private:
>
>    void notifyFailed(const SymbolNameSet &FailedSymbols);
>
> -  void runOutstandingMUs();
> -
>    ExecutionSessionBase &ES;
>    std::string VSOName;
>    SymbolMap Symbols;
> @@ -665,11 +726,6 @@ private:
>    MaterializingInfosMap MaterializingInfos;
>    FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
>    VSOList SearchOrder;
> -
> -  // FIXME: Remove this (and runOutstandingMUs) once the linking layer
> works
> -  //        with callbacks from asynchronous queries.
> -  mutable std::recursive_mutex OutstandingMUsMutex;
> -  std::vector<std::unique_ptr<MaterializationUnit>> OutstandingMUs;
>  };
>
>  /// An ExecutionSession represents a running JIT program.
> @@ -693,15 +749,6 @@ private:
>    std::vector<std::unique_ptr<VSO>> VSOs;
>  };
>
> -using AsynchronousLookupFunction = std::function<SymbolNameSet(
> -    std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
> -
> -/// Perform a blocking lookup on the given symbols.
> -Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES,
> -                                   AsynchronousLookupFunction AsyncLookup,
> -                                   SymbolNameSet Names, bool
> WaiUntilReady,
> -                                   MaterializationResponsibility *MR =
> nullptr);
> -
>  /// Look up the given names in the given VSOs.
>  /// VSOs will be searched in order and no VSO pointer may be null.
>  /// All symbols must be found within the given VSOs or an error
>
> Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/Legacy.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/Legacy.h?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ExecutionEngine/Orc/Legacy.h (original)
> +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/Legacy.h Fri Jul 20
> 11:31:53 2018
> @@ -146,11 +146,11 @@ lookupWithLegacyFn(ExecutionSession &ES,
>          Query.notifySymbolReady();
>          NewSymbolsResolved = true;
>        } else {
> -        ES.failQuery(Query, Addr.takeError());
> +        ES.legacyFailQuery(Query, Addr.takeError());
>          return SymbolNameSet();
>        }
>      } else if (auto Err = Sym.takeError()) {
> -      ES.failQuery(Query, std::move(Err));
> +      ES.legacyFailQuery(Query, std::move(Err));
>        return SymbolNameSet();
>      } else
>        SymbolsNotFound.insert(S);
>
> Modified: llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp (original)
> +++ llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp Fri Jul 20 11:31:53 2018
> @@ -23,6 +23,9 @@ namespace orc {
>  char FailedToMaterialize::ID = 0;
>  char SymbolsNotFound::ID = 0;
>
> +RegisterDependenciesFunction NoDependenciesToRegister =
> +    RegisterDependenciesFunction();
> +
>  void MaterializationUnit::anchor() {}
>
>  raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
> @@ -138,20 +141,361 @@ void SymbolsNotFound::log(raw_ostream &O
>    OS << "Symbols not found: " << Symbols;
>  }
>
> -void ExecutionSessionBase::failQuery(AsynchronousSymbolQuery &Q, Error
> Err) {
> -  bool DeliveredError = true;
> -  runSessionLocked([&]() -> void {
> +void ExecutionSessionBase::legacyFailQuery(AsynchronousSymbolQuery &Q,
> +                                           Error Err) {
> +  assert(!!Err && "Error should be in failure state");
> +
> +  bool SendErrorToQuery;
> +  runSessionLocked([&]() {
>      Q.detach();
> -    if (Q.canStillFail())
> -      Q.handleFailed(std::move(Err));
> -    else
> -      DeliveredError = false;
> +    SendErrorToQuery = Q.canStillFail();
>    });
>
> -  if (!DeliveredError)
> +  if (SendErrorToQuery)
> +    Q.handleFailed(std::move(Err));
> +  else
>      reportError(std::move(Err));
>  }
>
> +Expected<SymbolMap> ExecutionSessionBase::legacyLookup(
> +    ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup,
> +    SymbolNameSet Names, bool WaitUntilReady,
> +    RegisterDependenciesFunction RegisterDependencies) {
> +#if LLVM_ENABLE_THREADS
> +  // In the threaded case we use promises to return the results.
> +  std::promise<SymbolMap> PromisedResult;
> +  std::mutex ErrMutex;
> +  Error ResolutionError = Error::success();
> +  std::promise<void> PromisedReady;
> +  Error ReadyError = Error::success();
> +  auto OnResolve = [&](Expected<SymbolMap> R) {
> +    if (R)
> +      PromisedResult.set_value(std::move(*R));
> +    else {
> +      {
> +        ErrorAsOutParameter _(&ResolutionError);
> +        std::lock_guard<std::mutex> Lock(ErrMutex);
> +        ResolutionError = R.takeError();
> +      }
> +      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)
> +        ES.reportError(std::move(Err));
> +    };
> +  }
> +
> +#else
> +  SymbolMap Result;
> +  Error ResolutionError = Error::success();
> +  Error ReadyError = Error::success();
> +
> +  auto OnResolve = [&](Expected<SymbolMap> R) {
> +    ErrorAsOutParameter _(&ResolutionError);
> +    if (R)
> +      Result = std::move(*R);
> +    else
> +      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)
> +        ES.reportError(std::move(Err));
> +    };
> +  }
> +#endif
> +
> +  auto Query = std::make_shared<AsynchronousSymbolQuery>(
> +      Names, std::move(OnResolve), std::move(OnReady));
> +  // FIXME: This should be run session locked along with the registration
> code
> +  // and error reporting below.
> +  SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
> +
> +  // If the query was lodged successfully then register the dependencies,
> +  // otherwise fail it with an error.
> +  if (UnresolvedSymbols.empty())
> +    RegisterDependencies(Query->QueryRegistrations);
> +  else {
> +    bool DeliverError = runSessionLocked([&]() {
> +      Query->detach();
> +      return Query->canStillFail();
> +    });
> +    auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
> +    if (DeliverError)
> +      Query->handleFailed(std::move(Err));
> +    else
> +      ES.reportError(std::move(Err));
> +  }
> +
> +#if LLVM_ENABLE_THREADS
> +  auto ResultFuture = PromisedResult.get_future();
> +  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));
> +
> +  return std::move(Result);
> +
> +#else
> +  if (ResolutionError) {
> +    // ReadyError will never be assigned. Consume the success value.
> +    cantFail(std::move(ReadyError));
> +    return std::move(ResolutionError);
> +  }
> +
> +  if (ReadyError)
> +    return std::move(ReadyError);
> +
> +  return Result;
> +#endif
> +}
> +
> +void ExecutionSessionBase::lookup(
> +    const VSOList &VSOs, const SymbolNameSet &Symbols,
> +    SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
> +    RegisterDependenciesFunction RegisterDependencies) {
> +
> +  // lookup can be re-entered recursively if running on a single thread.
> Run any
> +  // outstanding MUs in case this query depends on them, otherwise the
> main
> +  // thread will starve waiting for a result from an MU that it failed to
> run.
> +  runOutstandingMUs();
> +
> +  auto Unresolved = std::move(Symbols);
> +  std::map<VSO *, MaterializationUnitList> MUsMap;
> +  auto Q = std::make_shared<AsynchronousSymbolQuery>(
> +      Symbols, std::move(OnResolve), std::move(OnReady));
> +  bool QueryIsFullyResolved = false;
> +  bool QueryIsFullyReady = false;
> +  bool QueryFailed = false;
> +
> +  runSessionLocked([&]() {
> +    for (auto *V : VSOs) {
> +      assert(V && "VSOList entries must not be null");
> +      assert(!MUsMap.count(V) &&
> +             "VSOList should not contain duplicate entries");
> +      V->lodgeQuery(Q, Unresolved, MUsMap[V]);
> +    }
> +
> +    if (Unresolved.empty()) {
> +      // Query lodged successfully.
> +
> +      // Record whether this query is fully ready / resolved. We will use
> +      // this to call handleFullyResolved/handleFullyReady outside the
> session
> +      // lock.
> +      QueryIsFullyResolved = Q->isFullyResolved();
> +      QueryIsFullyReady = Q->isFullyReady();
> +
> +      // Call the register dependencies function.
> +      if (RegisterDependencies && !Q->QueryRegistrations.empty())
> +        RegisterDependencies(Q->QueryRegistrations);
> +    } else {
> +      // Query failed due to unresolved symbols.
> +      QueryFailed = true;
> +
> +      // Disconnect the query from its dependencies.
> +      Q->detach();
> +
> +      // Replace the MUs.
> +      for (auto &KV : MUsMap)
> +        for (auto &MU : KV.second)
> +          KV.first->replace(std::move(MU));
> +    }
> +  });
> +
> +  if (QueryFailed) {
> +    Q->handleFailed(make_error<SymbolsNotFound>(std::move(Unresolved)));
> +    return;
> +  } else {
> +    if (QueryIsFullyResolved)
> +      Q->handleFullyResolved();
> +    if (QueryIsFullyReady)
> +      Q->handleFullyReady();
> +  }
> +
> +  // Move the MUs to the OutstandingMUs list, then materialize.
> +  {
> +    std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
> +
> +    for (auto &KV : MUsMap)
> +      for (auto &MU : KV.second)
> +        OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU)));
> +  }
> +
> +  runOutstandingMUs();
> +}
> +
> +Expected<SymbolMap>
> +ExecutionSessionBase::lookup(const VSOList &VSOs, const SymbolNameSet
> &Symbols,
> +                             RegisterDependenciesFunction
> RegisterDependencies,
> +                             bool WaitUntilReady) {
> +#if LLVM_ENABLE_THREADS
> +  // In the threaded case we use promises to return the results.
> +  std::promise<SymbolMap> PromisedResult;
> +  std::mutex ErrMutex;
> +  Error ResolutionError = Error::success();
> +  std::promise<void> PromisedReady;
> +  Error ReadyError = Error::success();
> +  auto OnResolve = [&](Expected<SymbolMap> R) {
> +    if (R)
> +      PromisedResult.set_value(std::move(*R));
> +    else {
> +      {
> +        ErrorAsOutParameter _(&ResolutionError);
> +        std::lock_guard<std::mutex> Lock(ErrMutex);
> +        ResolutionError = R.takeError();
> +      }
> +      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
> +  SymbolMap Result;
> +  Error ResolutionError = Error::success();
> +  Error ReadyError = Error::success();
> +
> +  auto OnResolve = [&](Expected<SymbolMap> R) {
> +    ErrorAsOutParameter _(&ResolutionError);
> +    if (R)
> +      Result = std::move(R->Symbols);
> +    else
> +      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
> +
> +  // Perform the asynchronous lookup.
> +  lookup(VSOs, Symbols, OnResolve, OnReady, RegisterDependencies);
> +
> +#if LLVM_ENABLE_THREADS
> +  auto ResultFuture = PromisedResult.get_future();
> +  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));
> +
> +  return std::move(Result);
> +
> +#else
> +  if (ResolutionError) {
> +    // ReadyError will never be assigned. Consume the success value.
> +    cantFail(std::move(ReadyError));
> +    return std::move(ResolutionError);
> +  }
> +
> +  if (ReadyError)
> +    return std::move(ReadyError);
> +
> +  return Result;
> +#endif
> +}
> +
> +void ExecutionSessionBase::runOutstandingMUs() {
> +  while (1) {
> +    std::pair<VSO *, std::unique_ptr<MaterializationUnit>> VSOAndMU;
> +
> +    {
> +      std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
> +      if (!OutstandingMUs.empty()) {
> +        VSOAndMU = std::move(OutstandingMUs.back());
> +        OutstandingMUs.pop_back();
> +      }
> +    }
> +
> +    if (VSOAndMU.first) {
> +      assert(VSOAndMU.second && "VSO, but no MU?");
> +      dispatchMaterialization(*VSOAndMU.first,
> std::move(VSOAndMU.second));
> +    } else
> +      break;
> +  }
> +}
> +
>  AsynchronousSymbolQuery::AsynchronousSymbolQuery(
>      const SymbolNameSet &Symbols, SymbolsResolvedCallback
> NotifySymbolsResolved,
>      SymbolsReadyCallback NotifySymbolsReady)
> @@ -161,12 +505,6 @@ AsynchronousSymbolQuery::AsynchronousSym
>
>    for (auto &S : Symbols)
>      ResolvedSymbols[S] = nullptr;
> -
> -  // If the query is empty it is trivially resolved/ready.
> -  if (Symbols.empty()) {
> -    handleFullyResolved();
> -    handleFullyReady();
> -  }
>  }
>
>  void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name,
> @@ -183,8 +521,7 @@ void AsynchronousSymbolQuery::handleFull
>    assert(NotYetResolvedCount == 0 && "Not fully resolved?");
>    assert(NotifySymbolsResolved &&
>           "NotifySymbolsResolved already called or error occurred");
> -  NotifySymbolsResolved(
> -      ResolutionResult(std::move(ResolvedSymbols), QueryRegistrations));
> +  NotifySymbolsResolved(std::move(ResolvedSymbols));
>    NotifySymbolsResolved = SymbolsResolvedCallback();
>  }
>
> @@ -349,7 +686,8 @@ MaterializationResponsibility::delegate(
>
>  void MaterializationResponsibility::addDependencies(
>      const SymbolDependenceMap &Dependencies) {
> -  V.addDependencies(SymbolFlags, Dependencies);
> +  for (auto &KV : SymbolFlags)
> +    V.addDependencies(KV.first, Dependencies);
>  }
>
>  AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
> @@ -384,8 +722,9 @@ ReExportsMaterializationUnit::ReExportsM
>  void ReExportsMaterializationUnit::materialize(
>      MaterializationResponsibility R) {
>
> -  VSO &SrcV = SourceVSO ? *SourceVSO : R.getTargetVSO();
> -  auto &ES = SrcV.getExecutionSession();
> +  auto &ES = R.getTargetVSO().getExecutionSession();
> +  VSO &TgtV = R.getTargetVSO();
> +  VSO &SrcV = SourceVSO ? *SourceVSO : TgtV;
>
>    // Find the set of requested aliases and aliasees. Return any
> unrequested
>    // aliases back to the VSO so as to not prematurely materialize any
> aliasees.
> @@ -434,9 +773,8 @@ void ReExportsMaterializationUnit::mater
>        auto Tmp = I++;
>
>        // Chain detected. Skip this symbol for this round.
> -      if (&SrcV == &R.getTargetVSO() &&
> -          (QueryAliases.count(Tmp->second.Aliasee) ||
> -           RequestedAliases.count(Tmp->second.Aliasee)))
> +      if (&SrcV == &TgtV && (QueryAliases.count(Tmp->second.Aliasee) ||
> +                             RequestedAliases.count(Tmp->second.Aliasee)))
>          continue;
>
>        ResponsibilitySymbols.insert(Tmp->first);
> @@ -459,49 +797,32 @@ void ReExportsMaterializationUnit::mater
>
>      QueryInfos.pop_back();
>
> -    auto OnResolve =
> -        [QueryInfo,
> -         &SrcV](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
> -          if (RR) {
> -            SymbolMap ResolutionMap;
> -            SymbolNameSet Resolved;
> -            for (auto &KV : QueryInfo->Aliases) {
> -              assert(RR->Symbols.count(KV.second.Aliasee) &&
> -                     "Result map missing entry?");
> -              ResolutionMap[KV.first] = JITEvaluatedSymbol(
> -                  RR->Symbols[KV.second.Aliasee].getAddress(),
> -                  KV.second.AliasFlags);
> -
> -              // FIXME: We're creating a SymbolFlagsMap and a std::map of
> -              // std::sets just to add one dependency here. This needs a
> -              // re-think.
> -              Resolved.insert(KV.first);
> -            }
> -            QueryInfo->R.resolve(ResolutionMap);
> +    auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
> +      R.addDependencies(Deps);
> +    };
>
> -            SymbolDependenceMap Deps;
> -            Deps[&SrcV] = std::move(Resolved);
> -            QueryInfo->R.addDependencies(Deps);
> -
> -            QueryInfo->R.finalize();
> -          } else {
> -            auto &ES = QueryInfo->R.getTargetVSO().getExecutionSession();
> -            ES.reportError(RR.takeError());
> -            QueryInfo->R.failMaterialization();
> -          }
> -        };
> +    auto OnResolve = [QueryInfo](Expected<SymbolMap> Result) {
> +      if (Result) {
> +        SymbolMap ResolutionMap;
> +        for (auto &KV : QueryInfo->Aliases) {
> +          assert(Result->count(KV.second.Aliasee) &&
> +                 "Result map missing entry?");
> +          ResolutionMap[KV.first] = JITEvaluatedSymbol(
> +              (*Result)[KV.second.Aliasee].getAddress(),
> KV.second.AliasFlags);
> +        }
> +        QueryInfo->R.resolve(ResolutionMap);
> +        QueryInfo->R.finalize();
> +      } else {
> +        auto &ES = QueryInfo->R.getTargetVSO().getExecutionSession();
> +        ES.reportError(Result.takeError());
> +        QueryInfo->R.failMaterialization();
> +      }
> +    };
>
>      auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
>
> -    auto Q = std::make_shared<AsynchronousSymbolQuery>(
> -        QuerySymbols, std::move(OnResolve), std::move(OnReady));
> -
> -    auto Unresolved = SrcV.lookup(Q, std::move(QuerySymbols));
> -
> -    if (!Unresolved.empty()) {
> -      ES.failQuery(*Q,
> make_error<SymbolsNotFound>(std::move(Unresolved)));
> -      return;
> -    }
> +    ES.lookup({&SrcV}, QuerySymbols, std::move(OnResolve),
> std::move(OnReady),
> +              std::move(RegisterDependencies));
>    }
>  }
>
> @@ -642,40 +963,35 @@ SymbolNameSet VSO::getRequestedSymbols(c
>    });
>  }
>
> -void VSO::addDependencies(const SymbolFlagsMap &Dependants,
> +void VSO::addDependencies(const SymbolStringPtr &Name,
>                            const SymbolDependenceMap &Dependencies) {
> -  ES.runSessionLocked([&, this]() {
> -    for (auto &KV : Dependants) {
> -      const auto &Name = KV.first;
> -      assert(Symbols.count(Name) && "Name not in symbol table");
> -      assert((Symbols[Name].getFlags().isLazy() ||
> -              Symbols[Name].getFlags().isMaterializing()) &&
> -             "Symbol is not lazy or materializing");
> -
> -      auto &MI = MaterializingInfos[Name];
> -      assert(!MI.IsFinalized && "Can not add dependencies to finalized
> symbol");
> -
> -      for (auto &KV : Dependencies) {
> -        assert(KV.first && "Null VSO in dependency?");
> -        auto &OtherVSO = *KV.first;
> -        auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO];
> -
> -        for (auto &OtherSymbol : KV.second) {
> -          auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol];
> -
> -          if (OtherMI.IsFinalized)
> -            transferFinalizedNodeDependencies(MI, Name, OtherMI);
> -          else if (&OtherVSO != this || OtherSymbol != Name) {
> -            OtherMI.Dependants[this].insert(Name);
> -            DepsOnOtherVSO.insert(OtherSymbol);
> -          }
> -        }
> -
> -        if (DepsOnOtherVSO.empty())
> -          MI.UnfinalizedDependencies.erase(&OtherVSO);
> +  assert(Symbols.count(Name) && "Name not in symbol table");
> +  assert((Symbols[Name].getFlags().isLazy() ||
> +          Symbols[Name].getFlags().isMaterializing()) &&
> +         "Symbol is not lazy or materializing");
> +
> +  auto &MI = MaterializingInfos[Name];
> +  assert(!MI.IsFinalized && "Can not add dependencies to finalized
> symbol");
> +
> +  for (auto &KV : Dependencies) {
> +    assert(KV.first && "Null VSO in dependency?");
> +    auto &OtherVSO = *KV.first;
> +    auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO];
> +
> +    for (auto &OtherSymbol : KV.second) {
> +      auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol];
> +
> +      if (OtherMI.IsFinalized)
> +        transferFinalizedNodeDependencies(MI, Name, OtherMI);
> +      else if (&OtherVSO != this || OtherSymbol != Name) {
> +        OtherMI.Dependants[this].insert(Name);
> +        DepsOnOtherVSO.insert(OtherSymbol);
>        }
>      }
> -  });
> +
> +    if (DepsOnOtherVSO.empty())
> +      MI.UnfinalizedDependencies.erase(&OtherVSO);
> +  }
>  }
>
>  void VSO::resolve(const SymbolMap &Resolved) {
> @@ -856,25 +1172,6 @@ void VSO::notifyFailed(const SymbolNameS
>      Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
>  }
>
> -void VSO::runOutstandingMUs() {
> -  while (1) {
> -    std::unique_ptr<MaterializationUnit> MU;
> -
> -    {
> -      std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
> -      if (!OutstandingMUs.empty()) {
> -        MU = std::move(OutstandingMUs.back());
> -        OutstandingMUs.pop_back();
> -      }
> -    }
> -
> -    if (MU)
> -      ES.dispatchMaterialization(*this, std::move(MU));
> -    else
> -      break;
> -  }
> -}
> -
>  void VSO::setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst)
> {
>    if (SearchThisVSOFirst && NewSearchOrder.front() != this)
>      NewSearchOrder.insert(NewSearchOrder.begin(), this);
> @@ -939,11 +1236,89 @@ SymbolNameSet VSO::lookupFlagsImpl(Symbo
>    return Unresolved;
>  }
>
> -SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
> -                          SymbolNameSet Names) {
> +void VSO::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
> +                     SymbolNameSet &Unresolved, MaterializationUnitList
> &MUs) {
>    assert(Q && "Query can not be null");
>
> -  runOutstandingMUs();
> +  lodgeQueryImpl(Q, Unresolved, MUs);
> +  if (FallbackDefinitionGenerator && !Unresolved.empty()) {
> +    auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
> +    if (!FallbackDefs.empty()) {
> +      for (auto &D : FallbackDefs)
> +        Unresolved.erase(D);
> +      lodgeQueryImpl(Q, FallbackDefs, MUs);
> +      assert(FallbackDefs.empty() &&
> +             "All fallback defs should have been found by lookupImpl");
> +    }
> +  }
> +}
> +
> +void VSO::lodgeQueryImpl(
> +    std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet
> &Unresolved,
> +    std::vector<std::unique_ptr<MaterializationUnit>> &MUs) {
> +  for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
> +    auto TmpI = I++;
> +    auto Name = *TmpI;
> +
> +    // Search for the name in Symbols. Skip it if not found.
> +    auto SymI = Symbols.find(Name);
> +    if (SymI == Symbols.end())
> +      continue;
> +
> +    // If we found Name in V, remove it frome the Unresolved set and add
> it
> +    // to the added set.
> +    Unresolved.erase(TmpI);
> +
> +    // If the symbol has an address then resolve it.
> +    if (SymI->second.getAddress() != 0)
> +      Q->resolve(Name, SymI->second);
> +
> +    // If the symbol is lazy, get the MaterialiaztionUnit for it.
> +    if (SymI->second.getFlags().isLazy()) {
> +      assert(SymI->second.getAddress() == 0 &&
> +             "Lazy symbol should not have a resolved address");
> +      assert(!SymI->second.getFlags().isMaterializing() &&
> +             "Materializing and lazy should not both be set");
> +      auto UMII = UnmaterializedInfos.find(Name);
> +      assert(UMII != UnmaterializedInfos.end() &&
> +             "Lazy symbol should have UnmaterializedInfo");
> +      auto MU = std::move(UMII->second->MU);
> +      assert(MU != nullptr && "Materializer should not be null");
> +
> +      // Move all symbols associated with this MaterializationUnit into
> +      // materializing state.
> +      for (auto &KV : MU->getSymbols()) {
> +        auto SymK = Symbols.find(KV.first);
> +        auto Flags = SymK->second.getFlags();
> +        Flags &= ~JITSymbolFlags::Lazy;
> +        Flags |= JITSymbolFlags::Materializing;
> +        SymK->second.setFlags(Flags);
> +        UnmaterializedInfos.erase(KV.first);
> +      }
> +
> +      // Add MU to the list of MaterializationUnits to be materialized.
> +      MUs.push_back(std::move(MU));
> +    } else if (!SymI->second.getFlags().isMaterializing()) {
> +      // The symbol is neither lazy nor materializing. Finalize it and
> +      // continue.
> +      Q->notifySymbolReady();
> +      continue;
> +    }
> +
> +    // Add the query to the PendingQueries list.
> +    assert(SymI->second.getFlags().isMaterializing() &&
> +           "By this line the symbol should be materializing");
> +    auto &MI = MaterializingInfos[Name];
> +    MI.PendingQueries.push_back(Q);
> +    Q->addQueryDependence(*this, Name);
> +  }
> +}
> +
> +SymbolNameSet VSO::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery>
> Q,
> +                                SymbolNameSet Names) {
> +  assert(Q && "Query can not be null");
> +
> +  ES.runOutstandingMUs();
>
>    LookupImplActionFlags ActionFlags = None;
>    std::vector<std::unique_ptr<MaterializationUnit>> MUs;
> @@ -978,11 +1353,11 @@ SymbolNameSet VSO::lookup(std::shared_pt
>    //        callbacks from asynchronous queries.
>    // Add MUs to the OutstandingMUs list.
>    {
> -    std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
> +    std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
>      for (auto &MU : MUs)
> -      OutstandingMUs.push_back(std::move(MU));
> +      ES.OutstandingMUs.push_back(make_pair(this, std::move(MU)));
>    }
> -  runOutstandingMUs();
> +  ES.runOutstandingMUs();
>
>    // Dispatch any required MaterializationUnits for materialization.
>    // for (auto &MU : MUs)
> @@ -1243,133 +1618,6 @@ VSO &ExecutionSession::createVSO(std::st
>    });
>  }
>
> -Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES,
> -                                   AsynchronousLookupFunction AsyncLookup,
> -                                   SymbolNameSet Names, bool
> WaitUntilReady,
> -                                   MaterializationResponsibility *MR) {
> -
> -#if LLVM_ENABLE_THREADS
> -  // In the threaded case we use promises to return the results.
> -  std::promise<SymbolMap> PromisedResult;
> -  std::mutex ErrMutex;
> -  Error ResolutionError = Error::success();
> -  std::promise<void> PromisedReady;
> -  Error ReadyError = Error::success();
> -  auto OnResolve =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        if (Result) {
> -          if (MR)
> -            MR->addDependencies(Result->Dependencies);
> -          PromisedResult.set_value(std::move(Result->Symbols));
> -        } else {
> -          {
> -            ErrorAsOutParameter _(&ResolutionError);
> -            std::lock_guard<std::mutex> Lock(ErrMutex);
> -            ResolutionError = Result.takeError();
> -          }
> -          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)
> -        ES.reportError(std::move(Err));
> -    };
> -  }
> -
> -#else
> -  SymbolMap Result;
> -  Error ResolutionError = Error::success();
> -  Error ReadyError = Error::success();
> -
> -  auto OnResolve =
> [&](Expected<AsynchronousSymbolQuery::ResolutionResult> R) {
> -    ErrorAsOutParameter _(&ResolutionError);
> -    if (R) {
> -      if (MR)
> -        MR->addDependencies(R->Dependencies);
> -      Result = std::move(R->Symbols);
> -    } else
> -      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)
> -        ES.reportError(std::move(Err));
> -    };
> -  }
> -#endif
> -
> -  auto Query = std::make_shared<AsynchronousSymbolQuery>(
> -      Names, std::move(OnResolve), std::move(OnReady));
> -
> -  SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
> -
> -  // If there are unresolved symbols then the query will never return.
> -  // Fail it with ES.failQuery.
> -  if (!UnresolvedSymbols.empty())
> -    ES.failQuery(*Query,
> -
>  make_error<SymbolsNotFound>(std::move(UnresolvedSymbols)));
> -
> -#if LLVM_ENABLE_THREADS
> -  auto ResultFuture = PromisedResult.get_future();
> -  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));
> -
> -  return std::move(Result);
> -
> -#else
> -  if (ResolutionError) {
> -    // ReadyError will never be assigned. Consume the success value.
> -    cantFail(std::move(ReadyError));
> -    return std::move(ResolutionError);
> -  }
> -
> -  if (ReadyError)
> -    return std::move(ReadyError);
> -
> -  return Result;
> -#endif
> -}
> -
>  Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names) {
>
>    if (VSOs.empty())
> @@ -1377,18 +1625,7 @@ Expected<SymbolMap> lookup(const VSOList
>
>    auto &ES = (*VSOs.begin())->getExecutionSession();
>
> -  auto LookupFn = [&](std::shared_ptr<AsynchronousSymbolQuery> Q,
> -                      SymbolNameSet Unresolved) {
> -    for (auto *V : VSOs) {
> -      assert(V && "VSOs entries must not be null");
> -      if (Unresolved.empty())
> -        break;
> -      Unresolved = V->lookup(Q, std::move(Unresolved));
> -    }
> -    return Unresolved;
> -  };
> -
> -  return blockingLookup(ES, std::move(LookupFn), Names, true);
> +  return ES.lookup(VSOs, Names, NoDependenciesToRegister, true);
>  }
>
>  /// Look up a symbol by searching a list of VSOs.
>
> Modified: llvm/trunk/lib/ExecutionEngine/Orc/Legacy.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/Legacy.cpp?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/Orc/Legacy.cpp (original)
> +++ llvm/trunk/lib/ExecutionEngine/Orc/Legacy.cpp Fri Jul 20 11:31:53 2018
> @@ -29,8 +29,14 @@ JITSymbolResolverAdapter::lookup(const L
>      return R.lookup(std::move(Q), std::move(Unresolved));
>    };
>
> -  auto InternedResult = blockingLookup(ES, std::move(LookupFn),
> -                                       std::move(InternedSymbols), false,
> MR);
> +  auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
> +    if (MR)
> +      MR->addDependencies(Deps);
> +  };
> +
> +  auto InternedResult =
> +      ES.legacyLookup(ES, std::move(LookupFn), std::move(InternedSymbols),
> +                      false, RegisterDependencies);
>
>    if (!InternedResult)
>      return InternedResult.takeError();
>
> Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.h?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.h (original)
> +++ llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.h Fri Jul 20
> 11:31:53 2018
> @@ -156,11 +156,11 @@ private:
>              Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
>              Query->notifySymbolReady();
>            } else {
> -            Stack.ES.failQuery(*Query, Addr.takeError());
> +            Stack.ES.legacyFailQuery(*Query, Addr.takeError());
>              return orc::SymbolNameSet();
>            }
>          } else if (auto Err = Sym.takeError()) {
> -          Stack.ES.failQuery(*Query, std::move(Err));
> +          Stack.ES.legacyFailQuery(*Query, std::move(Err));
>            return orc::SymbolNameSet();
>          } else
>            UnresolvedSymbols.insert(S);
>
> Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h (original)
> +++ llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h Fri Jul 20
> 11:31:53 2018
> @@ -178,11 +178,11 @@ class OrcMCJITReplacement : public Execu
>              Query->notifySymbolReady();
>              NewSymbolsResolved = true;
>            } else {
> -            M.ES.failQuery(*Query, Addr.takeError());
> +            M.ES.legacyFailQuery(*Query, Addr.takeError());
>              return SymbolNameSet();
>            }
>          } else if (auto Err = Sym.takeError()) {
> -          M.ES.failQuery(*Query, std::move(Err));
> +          M.ES.legacyFailQuery(*Query, std::move(Err));
>            return SymbolNameSet();
>          } else {
>            if (auto Sym2 = M.ClientResolver->findSymbol(*S)) {
> @@ -191,11 +191,11 @@ class OrcMCJITReplacement : public Execu
>                Query->notifySymbolReady();
>                NewSymbolsResolved = true;
>              } else {
> -              M.ES.failQuery(*Query, Addr.takeError());
> +              M.ES.legacyFailQuery(*Query, Addr.takeError());
>                return SymbolNameSet();
>              }
>            } else if (auto Err = Sym2.takeError()) {
> -            M.ES.failQuery(*Query, std::move(Err));
> +            M.ES.legacyFailQuery(*Query, std::move(Err));
>              return SymbolNameSet();
>            } else
>              UnresolvedSymbols.insert(S);
>
> Modified: llvm/trunk/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
> (original)
> +++ llvm/trunk/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp Fri
> Jul 20 11:31:53 2018
> @@ -16,30 +16,23 @@ using namespace llvm::orc;
>
>  class VSOSearchOrderResolver : public JITSymbolResolver {
>  public:
> -  VSOSearchOrderResolver(ExecutionSession &ES,
> -                         MaterializationResponsibility &MR)
> -      : ES(ES), MR(MR) {}
> +  VSOSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
>
>    Expected<LookupResult> lookup(const LookupSet &Symbols) {
> +    auto &ES = MR.getTargetVSO().getExecutionSession();
>      SymbolNameSet InternedSymbols;
>
>      for (auto &S : Symbols)
>        InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
>
> -    auto AsyncLookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Q,
> -                           SymbolNameSet Names) {
> -      SymbolNameSet Unresolved = std::move(Names);
> -      MR.getTargetVSO().withSearchOrderDo([&](const VSOList &SearchOrder)
> {
> -        for (auto *V : SearchOrder) {
> -          assert(V && "VSOList entry can not be null");
> -          Unresolved = V->lookup(Q, std::move(Unresolved));
> -        }
> -      });
> -      return Unresolved;
> +    auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
> +      MR.addDependencies(Deps);
>      };
>
> -    auto InternedResult = blockingLookup(
> -        ES, std::move(AsyncLookup), std::move(InternedSymbols), false,
> &MR);
> +    auto InternedResult =
> +        MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) {
> +          return ES.lookup(VSOs, InternedSymbols, RegisterDependencies,
> false);
> +        });
>
>      if (!InternedResult)
>        return InternedResult.takeError();
> @@ -52,6 +45,8 @@ public:
>    }
>
>    Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) {
> +    auto &ES = MR.getTargetVSO().getExecutionSession();
> +
>      SymbolNameSet InternedSymbols;
>
>      for (auto &S : Symbols)
> @@ -75,7 +70,6 @@ public:
>    }
>
>  private:
> -  ExecutionSession &ES;
>    MaterializationResponsibility &MR;
>  };
>
> @@ -106,7 +100,7 @@ void RTDyldObjectLinkingLayer2::emit(Mat
>
>    auto MemoryManager = GetMemoryManager(K);
>
> -  VSOSearchOrderResolver Resolver(ES, R);
> +  VSOSearchOrderResolver Resolver(R);
>    auto RTDyld = llvm::make_unique<RuntimeDyld>(*MemoryManager, Resolver);
>    RTDyld->setProcessAllSections(ProcessAllSections);
>
>
> Modified: llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp (original)
> +++ llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp Fri Jul 20
> 11:31:53 2018
> @@ -59,51 +59,57 @@ private:
>    DestructorFunction Destructor;
>  };
>
> -
> -TEST_F(CoreAPIsStandardTest,
> AsynchronousSymbolQuerySuccessfulResolutionOnly) {
> +TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
>    bool OnResolutionRun = false;
>    bool OnReadyRun = false;
> -  auto OnResolution =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
> -        auto &Resolved = Result->Symbols;
> -        auto I = Resolved.find(Foo);
> -        EXPECT_NE(I, Resolved.end()) << "Could not find symbol
> definition";
> -        EXPECT_EQ(I->second.getAddress(), FooAddr)
> -            << "Resolution returned incorrect result";
> -        OnResolutionRun = true;
> -      };
> +
> +  auto OnResolution = [&](Expected<SymbolMap> Result) {
> +    EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
> +    auto &Resolved = *Result;
> +    auto I = Resolved.find(Foo);
> +    EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition";
> +    EXPECT_EQ(I->second.getAddress(), FooAddr)
> +        << "Resolution returned incorrect result";
> +    OnResolutionRun = true;
> +  };
>    auto OnReady = [&](Error Err) {
>      cantFail(std::move(Err));
>      OnReadyRun = true;
>    };
>
> -  AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), OnResolution, OnReady);
> +  std::shared_ptr<MaterializationResponsibility> FooMR;
>
> -  Q.resolve(Foo, FooSym);
> +  cantFail(V.define(llvm::make_unique<SimpleMaterializationUnit>(
> +      SymbolFlagsMap({{Foo, FooSym.getFlags()}}),
> +      [&](MaterializationResponsibility R) {
> +        FooMR =
> std::make_shared<MaterializationResponsibility>(std::move(R));
> +      })));
>
> -  EXPECT_TRUE(Q.isFullyResolved()) << "Expected query to be fully
> resolved";
> +  ES.lookup({&V}, {Foo}, OnResolution, OnReady, NoDependenciesToRegister);
>
> -  if (!Q.isFullyResolved())
> -    return;
> +  EXPECT_FALSE(OnResolutionRun) << "Should not have been resolved yet";
> +  EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet";
>
> -  Q.handleFullyResolved();
> +  FooMR->resolve({{Foo, FooSym}});
>
> -  EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
> -  EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run";
> +  EXPECT_TRUE(OnResolutionRun) << "Should have been resolved";
> +  EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet";
> +
> +  FooMR->finalize();
> +
> +  EXPECT_TRUE(OnReadyRun) << "Should have been marked ready";
>  }
>
>  TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) {
>    bool OnResolutionRun = false;
>    bool OnReadyRun = false;
>
> -  auto OnResolution =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned
> success";
> -        auto Msg = toString(Result.takeError());
> -        EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result";
> -        OnResolutionRun = true;
> -      };
> +  auto OnResolution = [&](Expected<SymbolMap> Result) {
> +    EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success";
> +    auto Msg = toString(Result.takeError());
> +    EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result";
> +    OnResolutionRun = true;
> +  };
>    auto OnReady = [&](Error Err) {
>      cantFail(std::move(Err));
>      OnReadyRun = true;
> @@ -111,62 +117,28 @@ TEST_F(CoreAPIsStandardTest, ExecutionSe
>
>    AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), OnResolution, OnReady);
>
> -  ES.failQuery(Q, make_error<StringError>("xyz",
> inconvertibleErrorCode()));
> +  ES.legacyFailQuery(Q,
> +                     make_error<StringError>("xyz",
> inconvertibleErrorCode()));
>
>    EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
>    EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run";
>  }
>
> -TEST_F(CoreAPIsStandardTest, SimpleAsynchronousSymbolQueryAgainstVSO) {
> -  bool OnResolutionRun = false;
> +TEST_F(CoreAPIsStandardTest, EmptyLookup) {
> +  bool OnResolvedRun = false;
>    bool OnReadyRun = false;
>
> -  auto OnResolution =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        EXPECT_TRUE(!!Result) << "Query unexpectedly returned error";
> -        auto &Resolved = Result->Symbols;
> -        auto I = Resolved.find(Foo);
> -        EXPECT_NE(I, Resolved.end()) << "Could not find symbol
> definition";
> -        EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
> -            << "Resolution returned incorrect result";
> -        OnResolutionRun = true;
> -      };
> +  auto OnResolution = [&](Expected<SymbolMap> Result) {
> +    cantFail(std::move(Result));
> +    OnResolvedRun = true;
> +  };
>
>    auto OnReady = [&](Error Err) {
>      cantFail(std::move(Err));
>      OnReadyRun = true;
>    };
>
> -  SymbolNameSet Names({Foo});
> -
> -  auto Q =
> -      std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution,
> OnReady);
> -
> -  auto Defs = absoluteSymbols({{Foo, FooSym}});
> -  cantFail(V.define(Defs));
> -  assert(Defs == nullptr && "Defs should have been accepted");
> -  V.lookup(Q, Names);
> -
> -  EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
> -  EXPECT_TRUE(OnReadyRun) << "OnReady was not run";
> -}
> -
> -TEST_F(CoreAPIsStandardTest, EmptyVSOAndQueryLookup) {
> -  bool OnResolvedRun = false;
> -  bool OnReadyRun = false;
> -
> -  auto Q = std::make_shared<AsynchronousSymbolQuery>(
> -      SymbolNameSet(),
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
> -        cantFail(std::move(RR));
> -        OnResolvedRun = true;
> -      },
> -      [&](Error Err) {
> -        cantFail(std::move(Err));
> -        OnReadyRun = true;
> -      });
> -
> -  V.lookup(std::move(Q), {});
> +  ES.lookup({&V}, {}, OnResolution, OnReady, NoDependenciesToRegister);
>
>    EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
>    EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
> @@ -182,8 +154,8 @@ TEST_F(CoreAPIsStandardTest, ChainedVSOL
>
>    auto Q = std::make_shared<AsynchronousSymbolQuery>(
>        SymbolNameSet({Foo}),
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
> -        cantFail(std::move(RR));
> +      [&](Expected<SymbolMap> Result) {
> +        cantFail(std::move(Result));
>          OnResolvedRun = true;
>        },
>        [&](Error Err) {
> @@ -191,7 +163,7 @@ TEST_F(CoreAPIsStandardTest, ChainedVSOL
>          OnReadyRun = true;
>        });
>
> -  V2.lookup(Q, V.lookup(Q, {Foo}));
> +  V2.legacyLookup(Q, V.legacyLookup(Q, {Foo}));
>
>    EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
>    EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
> @@ -268,20 +240,15 @@ TEST_F(CoreAPIsStandardTest, TestTrivial
>    cantFail(V.define(FooMU));
>
>    bool FooReady = false;
> -  auto Q =
> -    std::make_shared<AsynchronousSymbolQuery>(
> -      SymbolNameSet({ Foo }),
> -      [](Expected<AsynchronousSymbolQuery::ResolutionResult> R) {
> -        cantFail(std::move(R));
> -      },
> -      [&](Error Err) {
> -        cantFail(std::move(Err));
> -        FooReady = true;
> -      });
> +  auto OnResolution = [](Expected<SymbolMap> R) { cantFail(std::move(R));
> };
> +  auto OnReady = [&](Error Err) {
> +    cantFail(std::move(Err));
> +    FooReady = true;
> +  };
>
> -  V.lookup(std::move(Q), { Foo });
> +  ES.lookup({&V}, {Foo}, std::move(OnResolution), std::move(OnReady),
> +            NoDependenciesToRegister);
>
> -  FooR->addDependencies({{&V, {Foo}}});
>    FooR->resolve({{Foo, FooSym}});
>    FooR->finalize();
>
> @@ -323,54 +290,52 @@ TEST_F(CoreAPIsStandardTest, TestCircula
>    // Query each of the symbols to trigger materialization.
>    bool FooResolved = false;
>    bool FooReady = false;
> -  auto FooQ = std::make_shared<AsynchronousSymbolQuery>(
> -      SymbolNameSet({Foo}),
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
> -        cantFail(std::move(RR));
> -        FooResolved = true;
> -      },
> -      [&](Error Err) {
> -        cantFail(std::move(Err));
> -        FooReady = true;
> -      });
> -  {
> -    auto Unresolved = V.lookup(FooQ, {Foo});
> -    EXPECT_TRUE(Unresolved.empty()) << "Failed to resolve \"Foo\"";
> -  }
> +
> +  auto OnFooResolution = [&](Expected<SymbolMap> Result) {
> +    cantFail(std::move(Result));
> +    FooResolved = true;
> +  };
> +
> +  auto OnFooReady = [&](Error Err) {
> +    cantFail(std::move(Err));
> +    FooReady = true;
> +  };
> +
> +  // Issue a lookup for Foo. Use NoDependenciesToRegister: We're going to
> add
> +  // the dependencies manually below.
> +  ES.lookup({&V}, {Foo}, std::move(OnFooResolution),
> std::move(OnFooReady),
> +            NoDependenciesToRegister);
>
>    bool BarResolved = false;
>    bool BarReady = false;
> -  auto BarQ = std::make_shared<AsynchronousSymbolQuery>(
> -      SymbolNameSet({Bar}),
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
> -        cantFail(std::move(RR));
> -        BarResolved = true;
> -      },
> -      [&](Error Err) {
> -        cantFail(std::move(Err));
> -        BarReady = true;
> -      });
> -  {
> -    auto Unresolved = V.lookup(BarQ, {Bar});
> -    EXPECT_TRUE(Unresolved.empty()) << "Failed to resolve \"Bar\"";
> -  }
> +  auto OnBarResolution = [&](Expected<SymbolMap> Result) {
> +    cantFail(std::move(Result));
> +    BarResolved = true;
> +  };
> +
> +  auto OnBarReady = [&](Error Err) {
> +    cantFail(std::move(Err));
> +    BarReady = true;
> +  };
> +
> +  ES.lookup({&V}, {Bar}, std::move(OnBarResolution),
> std::move(OnBarReady),
> +            NoDependenciesToRegister);
>
>    bool BazResolved = false;
>    bool BazReady = false;
> -  auto BazQ = std::make_shared<AsynchronousSymbolQuery>(
> -      SymbolNameSet({Baz}),
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
> -        cantFail(std::move(RR));
> -        BazResolved = true;
> -      },
> -      [&](Error Err) {
> -        cantFail(std::move(Err));
> -        BazReady = true;
> -      });
> -  {
> -    auto Unresolved = V.lookup(BazQ, {Baz});
> -    EXPECT_TRUE(Unresolved.empty()) << "Failed to resolve \"Baz\"";
> -  }
> +
> +  auto OnBazResolution = [&](Expected<SymbolMap> Result) {
> +    cantFail(std::move(Result));
> +    BazResolved = true;
> +  };
> +
> +  auto OnBazReady = [&](Error Err) {
> +    cantFail(std::move(Err));
> +    BazReady = true;
> +  };
> +
> +  ES.lookup({&V}, {Baz}, std::move(OnBazResolution),
> std::move(OnBazReady),
> +            NoDependenciesToRegister);
>
>    // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo.
>    FooR->addDependencies({{&V, SymbolNameSet({Bar})}});
> @@ -478,28 +443,23 @@ TEST_F(CoreAPIsStandardTest, AddAndMater
>    bool OnResolutionRun = false;
>    bool OnReadyRun = false;
>
> -  auto OnResolution =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
> -        auto I = Result->Symbols.find(Foo);
> -        EXPECT_NE(I, Result->Symbols.end())
> -            << "Could not find symbol definition";
> -        EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
> -            << "Resolution returned incorrect result";
> -        OnResolutionRun = true;
> -      };
> +  auto OnResolution = [&](Expected<SymbolMap> Result) {
> +    EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error";
> +    auto I = Result->find(Foo);
> +    EXPECT_NE(I, Result->end()) << "Could not find symbol definition";
> +    EXPECT_EQ(I->second.getAddress(), FooSym.getAddress())
> +        << "Resolution returned incorrect result";
> +    OnResolutionRun = true;
> +  };
>
>    auto OnReady = [&](Error Err) {
>      cantFail(std::move(Err));
>      OnReadyRun = true;
>    };
>
> -  auto Q =
> -      std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution,
> OnReady);
> +  ES.lookup({&V}, Names, std::move(OnResolution), std::move(OnReady),
> +            NoDependenciesToRegister);
>
> -  auto Unresolved = V.lookup(std::move(Q), Names);
> -
> -  EXPECT_TRUE(Unresolved.empty()) << "Could not find Foo in dylib";
>    EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
>    EXPECT_TRUE(BarDiscarded) << "Bar was not discarded";
>    EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
> @@ -714,13 +674,14 @@ TEST_F(CoreAPIsStandardTest, TestMateria
>        });
>
>    cantFail(V.define(MU));
> -  auto Q = std::make_shared<AsynchronousSymbolQuery>(
> -      SymbolNameSet({Foo}),
> -      [](Expected<AsynchronousSymbolQuery::ResolutionResult> R) {
> -        cantFail(std::move(R));
> -      },
> -      [](Error Err) { cantFail(std::move(Err)); });
> -  V.lookup(std::move(Q), SymbolNameSet({Foo}));
> +  auto OnResolution = [](Expected<SymbolMap> Result) {
> +    cantFail(std::move(Result));
> +  };
> +
> +  auto OnReady = [](Error Err) { cantFail(std::move(Err)); };
> +
> +  ES.lookup({&V}, {Foo}, std::move(OnResolution), std::move(OnReady),
> +            NoDependenciesToRegister);
>
>    auto MU2 = llvm::make_unique<SimpleMaterializationUnit>(
>        SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
>
> Modified: llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp?rev=337595&r1=337594&r2=337595&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp
> (original)
> +++ llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp Fri
> Jul 20 11:31:53 2018
> @@ -24,7 +24,7 @@ TEST_F(LegacyAPIsStandardTest, TestLambd
>    auto Resolver = createSymbolResolver(
>        [&](const SymbolNameSet &Symbols) { return V.lookupFlags(Symbols);
> },
>        [&](std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet
> Symbols) {
> -        return V.lookup(std::move(Q), Symbols);
> +        return V.legacyLookup(std::move(Q), Symbols);
>        });
>
>    SymbolNameSet Symbols({Foo, Bar, Baz});
> @@ -42,21 +42,17 @@ TEST_F(LegacyAPIsStandardTest, TestLambd
>
>    bool OnResolvedRun = false;
>
> -  auto OnResolved =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        OnResolvedRun = true;
> -        EXPECT_TRUE(!!Result) << "Unexpected error";
> -        EXPECT_EQ(Result->Symbols.size(), 2U)
> -            << "Unexpected number of resolved symbols";
> -        EXPECT_EQ(Result->Symbols.count(Foo), 1U)
> -            << "Missing lookup result for foo";
> -        EXPECT_EQ(Result->Symbols.count(Bar), 1U)
> -            << "Missing lookup result for bar";
> -        EXPECT_EQ(Result->Symbols[Foo].getAddress(), FooSym.getAddress())
> -            << "Incorrect address for foo";
> -        EXPECT_EQ(Result->Symbols[Bar].getAddress(), BarSym.getAddress())
> -            << "Incorrect address for bar";
> -      };
> +  auto OnResolved = [&](Expected<SymbolMap> Result) {
> +    OnResolvedRun = true;
> +    EXPECT_TRUE(!!Result) << "Unexpected error";
> +    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(Bar), 1U) << "Missing lookup result for bar";
> +    EXPECT_EQ((*Result)[Foo].getAddress(), FooSym.getAddress())
> +        << "Incorrect address for foo";
> +    EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress())
> +        << "Incorrect address for bar";
> +  };
>    auto OnReady = [&](Error Err) {
>      EXPECT_FALSE(!!Err) << "Finalization should never fail in this test";
>    };
> @@ -85,7 +81,7 @@ TEST(LegacyAPIInteropTest, QueryAgainstV
>
>    auto Lookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
>                      SymbolNameSet Symbols) {
> -    return V.lookup(std::move(Query), Symbols);
> +    return V.legacyLookup(std::move(Query), Symbols);
>    };
>
>    auto UnderlyingResolver =
> @@ -158,22 +154,18 @@ TEST(LegacyAPIInteropTset, LegacyLookupH
>
>    bool OnResolvedRun = false;
>    bool OnReadyRun = false;
> -  auto OnResolved =
> -      [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
> -        OnResolvedRun = true;
> -        EXPECT_TRUE(!!Result) << "lookuWithLegacy failed to resolve";
> -
> -        auto &Resolved = Result->Symbols;
> -        EXPECT_EQ(Resolved.size(), 2U) << "Wrong number of symbols
> resolved";
> -        EXPECT_EQ(Resolved.count(Foo), 1U) << "Result for foo missing";
> -        EXPECT_EQ(Resolved.count(Bar), 1U) << "Result for bar missing";
> -        EXPECT_EQ(Resolved[Foo].getAddress(), FooAddr)
> -            << "Wrong address for foo";
> -        EXPECT_EQ(Resolved[Foo].getFlags(), FooFlags) << "
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180720/cda5b172/attachment.html>


More information about the llvm-commits mailing list