[ORC] Replace SymbolResolvers in the new ORC layers with search orders on VSOs.

A search order is a list of VSOs to be searched linearly to find symbols. Each
VSO now has a search order that will be used when fixing up definitions in that
VSO. Each VSO's search order defaults to just that VSO itself.

This is a first step towards removing symbol resolvers from ORC altogether. In
practice symbol resolvers tended to be used to implement a search order anyway,
sometimes with additional programatic generation of symbols. Now that VSOs
support programmatic generation of definitions via fallback generators, search
orders provide a cleaner way to achieve the desired effect (while removing a lot
of boilerplate).

llvm-svn: 337593
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
index ebd8d43..d42e7b0 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
@@ -130,21 +130,18 @@
 
 class ExtractingIRMaterializationUnit : public IRMaterializationUnit {
 public:
-  ExtractingIRMaterializationUnit(
-      ExecutionSession &ES, CompileOnDemandLayer2 &Parent,
-      std::unique_ptr<Module> M,
-      std::shared_ptr<SymbolResolver> BackingResolver)
-      : IRMaterializationUnit(ES, std::move(M)), Parent(Parent),
-        BackingResolver(std::move(BackingResolver)) {}
+  ExtractingIRMaterializationUnit(ExecutionSession &ES,
+                                  CompileOnDemandLayer2 &Parent,
+                                  std::unique_ptr<Module> M)
+      : IRMaterializationUnit(ES, std::move(M)), Parent(Parent) {}
 
-  ExtractingIRMaterializationUnit(
-      std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
-      SymbolNameToDefinitionMap SymbolToDefinition,
-      CompileOnDemandLayer2 &Parent,
-      std::shared_ptr<SymbolResolver> BackingResolver)
+  ExtractingIRMaterializationUnit(std::unique_ptr<Module> M,
+                                  SymbolFlagsMap SymbolFlags,
+                                  SymbolNameToDefinitionMap SymbolToDefinition,
+                                  CompileOnDemandLayer2 &Parent)
       : IRMaterializationUnit(std::move(M), std::move(SymbolFlags),
                               std::move(SymbolToDefinition)),
-        Parent(Parent), BackingResolver(std::move(BackingResolver)) {}
+        Parent(Parent) {}
 
 private:
   void materialize(MaterializationResponsibility R) override {
@@ -153,10 +150,6 @@
     //        together. This could be used, for example, to provide a specific
     //        memory manager instance to the linking layer.
 
-    // FIXME: The derived constructor should *only* look for the names of
-    //        original function definitions in the target VSO. All other
-    //        symbols should be looked up in the backing resolver.
-
     auto RequestedSymbols = R.getRequestedSymbols();
 
     // Extract the requested functions into a new module.
@@ -201,12 +194,12 @@
              "of entries");
       R.replace(llvm::make_unique<ExtractingIRMaterializationUnit>(
           std::move(M), std::move(DelegatedSymbolFlags),
-          std::move(DelegatedSymbolToDefinition), Parent, BackingResolver));
+          std::move(DelegatedSymbolToDefinition), Parent));
     }
 
     if (ExtractedFunctionsModule)
-      Parent.emitExtractedFunctionsModule(
-          std::move(R), std::move(ExtractedFunctionsModule), BackingResolver);
+      Parent.emitExtractedFunctionsModule(std::move(R),
+                                          std::move(ExtractedFunctionsModule));
   }
 
   void discard(const VSO &V, SymbolStringPtr Name) override {
@@ -218,19 +211,14 @@
 
   mutable std::mutex SourceModuleMutex;
   CompileOnDemandLayer2 &Parent;
-  std::shared_ptr<SymbolResolver> BackingResolver;
 };
 
 CompileOnDemandLayer2::CompileOnDemandLayer2(
     ExecutionSession &ES, IRLayer &BaseLayer, JITCompileCallbackManager &CCMgr,
     IndirectStubsManagerBuilder BuildIndirectStubsManager,
-    GetSymbolResolverFunction GetSymbolResolver,
-    SetSymbolResolverFunction SetSymbolResolver,
     GetAvailableContextFunction GetAvailableContext)
     : IRLayer(ES), BaseLayer(BaseLayer), CCMgr(CCMgr),
       BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)),
-      GetSymbolResolver(std::move(GetSymbolResolver)),
-      SetSymbolResolver(std::move(SetSymbolResolver)),
       GetAvailableContext(std::move(GetAvailableContext)) {}
 
 Error CompileOnDemandLayer2::add(VSO &V, VModuleKey K,
@@ -306,19 +294,14 @@
     StubInits[*KV.first] = KV.second;
 
   // Build the function-body-extracting materialization unit.
-  auto SR = GetSymbolResolver(K);
   if (auto Err = R.getTargetVSO().define(
-          llvm::make_unique<ExtractingIRMaterializationUnit>(
-              ES, *this, std::move(M), SR))) {
+          llvm::make_unique<ExtractingIRMaterializationUnit>(ES, *this,
+                                                             std::move(M)))) {
     ES.reportError(std::move(Err));
     R.failMaterialization();
     return;
   }
 
-  // Replace the fallback symbol resolver: We will re-use M's VModuleKey for
-  // the GlobalsModule.
-  SetSymbolResolver(K, SR);
-
   // Build the stubs.
   // FIXME: Remove function bodies materialization unit if stub creation fails.
   auto &StubsMgr = getStubsManager(TargetVSO);
@@ -351,22 +334,8 @@
 }
 
 void CompileOnDemandLayer2::emitExtractedFunctionsModule(
-    MaterializationResponsibility R, std::unique_ptr<Module> M,
-    std::shared_ptr<SymbolResolver> Resolver) {
-  auto &TargetVSO = R.getTargetVSO();
+    MaterializationResponsibility R, std::unique_ptr<Module> M) {
   auto K = getExecutionSession().allocateVModule();
-
-  auto ExtractedFunctionsResolver = createSymbolResolver(
-      [=](SymbolFlagsMap &Flags, const SymbolNameSet &Symbols) {
-        return Resolver->lookupFlags(Flags, Symbols);
-      },
-      [=, &TargetVSO](std::shared_ptr<AsynchronousSymbolQuery> Query,
-                      SymbolNameSet Symbols) {
-        auto RemainingSymbols = TargetVSO.lookup(Query, std::move(Symbols));
-        return Resolver->lookup(std::move(Query), std::move(RemainingSymbols));
-      });
-
-  SetSymbolResolver(K, std::move(ExtractedFunctionsResolver));
   BaseLayer.emit(std::move(R), std::move(K), std::move(M));
 }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index 38f2213..9275bb8 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -24,7 +24,6 @@
 char SymbolsNotFound::ID = 0;
 
 void MaterializationUnit::anchor() {}
-void SymbolResolver::anchor() {}
 
 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
   if (Flags.isWeak())
@@ -99,6 +98,20 @@
   return OS;
 }
 
+raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs) {
+  OS << "[";
+  if (!VSOs.empty()) {
+    assert(VSOs.front() && "VSOList entries must not be null");
+    OS << " " << VSOs.front()->getName();
+    for (auto *V : make_range(std::next(VSOs.begin()), VSOs.end())) {
+      assert(V && "VSOList entries must not be null");
+      OS << ", " << V->getName();
+    }
+  }
+  OS << " ]";
+  return OS;
+}
+
 FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
     : Symbols(std::move(Symbols)) {
   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
@@ -859,6 +872,34 @@
   }
 }
 
+void VSO::setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst) {
+  if (SearchThisVSOFirst && NewSearchOrder.front() != this)
+    NewSearchOrder.insert(NewSearchOrder.begin(), this);
+
+  ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); });
+}
+
+void VSO::addToSearchOrder(VSO &V) {
+  ES.runSessionLocked([&]() { SearchOrder.push_back(&V); });
+}
+
+void VSO::replaceInSearchOrder(VSO &OldV, VSO &NewV) {
+  ES.runSessionLocked([&]() {
+    auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &OldV);
+
+    if (I != SearchOrder.end())
+      *I = &NewV;
+  });
+}
+
+void VSO::removeFromSearchOrder(VSO &V) {
+  ES.runSessionLocked([&]() {
+    auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &V);
+    if (I != SearchOrder.end())
+      SearchOrder.erase(I);
+  });
+}
+
 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,
                                const SymbolNameSet &Names) {
   return ES.runSessionLocked([&, this]() {
@@ -1066,6 +1107,11 @@
   });
 }
 
+VSO::VSO(ExecutionSessionBase &ES, std::string Name)
+    : ES(ES), VSOName(std::move(Name)) {
+  SearchOrder.push_back(this);
+}
+
 Error VSO::defineImpl(MaterializationUnit &MU) {
   SymbolNameSet Duplicates;
   SymbolNameSet MUDefsOverridden;
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 059fba2..52ff4ef 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -35,7 +35,6 @@
     return Err;
 
   auto K = ES->allocateVModule();
-  Resolvers[K] = createResolverFor(V);
   return CompileLayer.add(V, K, std::move(M));
 }
 
@@ -49,23 +48,13 @@
     : ES(std::move(ES)), Main(this->ES->createVSO("main")), TM(std::move(TM)),
       DL(std::move(DL)),
       ObjLinkingLayer(*this->ES,
-                      [this](VModuleKey K) { return getRTDyldResources(K); }),
+                      [this](VModuleKey K) { return getMemoryManager(K); }),
       CompileLayer(*this->ES, ObjLinkingLayer, SimpleCompiler(*this->TM)),
-      CtorRunner(Main), DtorRunner(Main) {
-  VSOLookupOrder[&Main] = VSOList({&Main});
-}
+      CtorRunner(Main), DtorRunner(Main) {}
 
-std::shared_ptr<SymbolResolver> LLJIT::takeSymbolResolver(VModuleKey K) {
-  auto ResolverI = Resolvers.find(K);
-  assert(ResolverI != Resolvers.end() && "Missing resolver");
-  auto Resolver = std::move(ResolverI->second);
-  Resolvers.erase(ResolverI);
-  return Resolver;
-}
-
-RTDyldObjectLinkingLayer2::Resources LLJIT::getRTDyldResources(VModuleKey K) {
-  return orc::RTDyldObjectLinkingLayer2::Resources(
-      {llvm::make_unique<SectionMemoryManager>(), takeSymbolResolver(K)});
+std::shared_ptr<RuntimeDyld::MemoryManager>
+LLJIT::getMemoryManager(VModuleKey K) {
+  return llvm::make_unique<SectionMemoryManager>();
 }
 
 std::string LLJIT::mangle(StringRef UnmangledName) {
@@ -77,21 +66,6 @@
   return MangledName;
 }
 
-std::unique_ptr<SymbolResolver> LLJIT::createResolverFor(VSO &V) {
-  return createSymbolResolver(
-      [&](SymbolFlagsMap &Flags, const SymbolNameSet &Symbols) {
-        return V.lookupFlags(Flags, Symbols);
-      },
-      [&, this](std::shared_ptr<AsynchronousSymbolQuery> Q,
-                SymbolNameSet Symbols) {
-        assert(VSOLookupOrder.count(&V) && "No VSO lookup order for V");
-        SymbolNameSet Unresolved = std::move(Symbols);
-        for (auto *LV : VSOLookupOrder[&V])
-          Unresolved = LV->lookup(Q, std::move(Unresolved));
-        return Unresolved;
-      });
-}
-
 Error LLJIT::applyDataLayout(Module &M) {
   if (M.getDataLayout().isDefault())
     M.setDataLayout(DL);
@@ -143,7 +117,6 @@
   recordCtorDtors(*M);
 
   auto K = ES->allocateVModule();
-  setSymbolResolver(K, createResolverFor(V));
   return CODLayer.add(V, K, std::move(M));
 }
 
@@ -155,17 +128,7 @@
     : LLJIT(std::move(ES), std::move(TM), std::move(DL)),
       CCMgr(std::move(CCMgr)), TransformLayer(*this->ES, CompileLayer),
       CODLayer(*this->ES, TransformLayer, *this->CCMgr, std::move(ISMBuilder),
-               [this](VModuleKey K) { return takeSymbolResolver(K); },
-               [this](VModuleKey K, std::shared_ptr<SymbolResolver> R) {
-                 setSymbolResolver(K, std::move(R));
-               },
                [&]() -> LLVMContext & { return Ctx; }) {}
 
-void LLLazyJIT::setSymbolResolver(VModuleKey K,
-                                  std::shared_ptr<SymbolResolver> R) {
-  assert(!Resolvers.count(K) && "Resolver already present for VModule K");
-  Resolvers[K] = std::move(R);
-}
-
 } // End namespace orc.
 } // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp
index 795ddd5..79525ba 100644
--- a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp
@@ -12,6 +12,8 @@
 namespace llvm {
 namespace orc {
 
+void SymbolResolver::anchor() {}
+
 JITSymbolResolverAdapter::JITSymbolResolverAdapter(
     ExecutionSession &ES, SymbolResolver &R, MaterializationResponsibility *MR)
     : ES(ES), R(R), MR(MR) {}
diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
index 61e8ee8..8c53b4f 100644
--- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
@@ -9,13 +9,85 @@
 
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
 
+namespace {
+
+using namespace llvm;
+using namespace llvm::orc;
+
+class VSOSearchOrderResolver : public JITSymbolResolver {
+public:
+  VSOSearchOrderResolver(ExecutionSession &ES,
+                         MaterializationResponsibility &MR)
+      : ES(ES), MR(MR) {}
+
+  Expected<LookupResult> lookup(const LookupSet &Symbols) {
+    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 InternedResult = blockingLookup(
+        ES, std::move(AsyncLookup), std::move(InternedSymbols), false, &MR);
+
+    if (!InternedResult)
+      return InternedResult.takeError();
+
+    LookupResult Result;
+    for (auto &KV : *InternedResult)
+      Result[*KV.first] = std::move(KV.second);
+
+    return Result;
+  }
+
+  Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) {
+    SymbolNameSet InternedSymbols;
+
+    for (auto &S : Symbols)
+      InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
+
+    SymbolFlagsMap InternedResult;
+    MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) {
+      // An empty search order is pathalogical, but allowed.
+      if (VSOs.empty())
+        return;
+
+      assert(VSOs.front() && "VSOList entry can not be null");
+      VSOs.front()->lookupFlags(InternedResult, InternedSymbols);
+    });
+
+    LookupFlagsResult Result;
+    for (auto &KV : InternedResult)
+      Result[*KV.first] = std::move(KV.second);
+
+    return Result;
+  }
+
+private:
+  ExecutionSession &ES;
+  MaterializationResponsibility &MR;
+};
+
+} // end anonymous namespace
+
 namespace llvm {
 namespace orc {
 
 RTDyldObjectLinkingLayer2::RTDyldObjectLinkingLayer2(
-    ExecutionSession &ES, ResourcesGetterFunction GetResources,
+    ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
     NotifyLoadedFunction NotifyLoaded, NotifyFinalizedFunction NotifyFinalized)
-    : ObjectLayer(ES), GetResources(std::move(GetResources)),
+    : ObjectLayer(ES), GetMemoryManager(GetMemoryManager),
       NotifyLoaded(std::move(NotifyLoaded)),
       NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {}
 
@@ -32,11 +104,10 @@
     R.failMaterialization();
   }
 
-  auto Resources = GetResources(K);
+  auto MemoryManager = GetMemoryManager(K);
 
-  JITSymbolResolverAdapter ResolverAdapter(ES, *Resources.Resolver, &R);
-  auto RTDyld =
-      llvm::make_unique<RuntimeDyld>(*Resources.MemMgr, ResolverAdapter);
+  VSOSearchOrderResolver Resolver(ES, R);
+  auto RTDyld = llvm::make_unique<RuntimeDyld>(*MemoryManager, Resolver);
   RTDyld->setProcessAllSections(ProcessAllSections);
 
   {
@@ -48,7 +119,7 @@
 
     assert(!MemMgrs.count(K) &&
            "A memory manager already exists for this key?");
-    MemMgrs[K] = Resources.MemMgr;
+    MemMgrs[K] = std::move(MemoryManager);
   }
 
   auto Info = RTDyld->loadObject(**ObjFile);