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

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 20 14:31:35 PDT 2018


Hi Reid,

No worries. Thanks for doing that!

I'll investigate and re-apply once I have a fix.

Cheers,
Lang.

On Fri, Jul 20, 2018 at 1:28 PM Reid Kleckner <rnk at google.com> wrote:

> 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/987eedab/attachment-0001.html>


More information about the llvm-commits mailing list