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