[llvm] [ORC] Add Executor Resolver Utility (PR #143654)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 10 21:28:21 PDT 2025


https://github.com/SahilPatidar created https://github.com/llvm/llvm-project/pull/143654

This patch adds the new **executor-side resolver API** as suggested by @lhames. It introduces a `DylibSymbolResolver` that helps resolve symbols for each loaded dylib.

Previously, we returned a `DylibHandle` to the controller. Now, we wrap the native handle inside `DylibSymbolResolver` and return a `ResolverHandle` instead. This makes the code cleaner and separates the symbol resolution logic from raw handle management.

>From 10c8bddc25df02c67525a2e517541f136f917861 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Wed, 4 Jun 2025 11:53:50 +0530
Subject: [PATCH 1/4] [ORC] Add `Resolver` API

---
 .../Orc/EPCGenericDylibManager.h              |  5 +-
 .../Orc/ExecutorResolutionGenerator.h         | 76 +++++++++++++++
 .../ExecutionEngine/Orc/Shared/OrcRTBridge.h  |  5 +
 .../Orc/Shared/TargetProcessControlTypes.h    |  4 +
 .../Orc/TargetProcess/ExecutorResolver.h      | 48 ++++++++++
 .../SimpleExecutorDylibManager.h              |  5 +
 llvm/lib/ExecutionEngine/Orc/CMakeLists.txt   |  1 +
 .../Orc/EPCDynamicLibrarySearchGenerator.cpp  | 27 ++++--
 .../Orc/EPCGenericDylibManager.cpp            | 15 +--
 .../Orc/ExecutorProcessControl.cpp            | 16 ++--
 .../Orc/ExecutorResolutionGenerator.cpp       | 96 +++++++++++++++++++
 .../Orc/Shared/OrcRTBridge.cpp                |  2 +
 .../Orc/TargetProcess/CMakeLists.txt          |  1 +
 .../Orc/TargetProcess/ExecutorResolver.cpp    | 47 +++++++++
 .../SimpleExecutorDylibManager.cpp            | 28 +++++-
 15 files changed, 346 insertions(+), 30 deletions(-)
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/ExecutorResolutionGenerator.h
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
 create mode 100644 llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp
 create mode 100644 llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
index 68bc54b89fe56..66073a8111f71 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
@@ -35,6 +35,7 @@ class EPCGenericDylibManager {
     ExecutorAddr Instance;
     ExecutorAddr Open;
     ExecutorAddr Lookup;
+    ExecutorAddr Resolve;
   };
 
   /// Create an EPCGenericMemoryAccess instance from a given set of
@@ -68,8 +69,8 @@ class EPCGenericDylibManager {
     return RF.get();
   }
 
-  using SymbolLookupCompleteFn =
-      unique_function<void(Expected<std::vector<ExecutorSymbolDef>>)>;
+  using SymbolLookupCompleteFn = unique_function<void(
+      Expected<std::vector<ExecutorSymbolDef>>)>;
 
   /// Looks up symbols within the given dylib.
   LLVM_ABI void lookupAsync(tpctypes::DylibHandle H,
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorResolutionGenerator.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorResolutionGenerator.h
new file mode 100644
index 0000000000000..987e5082597a4
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorResolutionGenerator.h
@@ -0,0 +1,76 @@
+
+// LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H
+//===----- ExecutorResolver.h - Resolve symbols in executor -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares ExecutorResolutionGenerator for symbol resolution,
+// dynamic library loading, and lookup in an executor process via
+// ExecutorResolver.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H
+#define LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+
+namespace llvm::orc {
+
+class ExecutorResolutionGenerator : public DefinitionGenerator {
+public:
+  using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>;
+  using AbsoluteSymbolsFn =
+      unique_function<std::unique_ptr<MaterializationUnit>(SymbolMap)>;
+
+  ExecutorResolutionGenerator(
+      ExecutionSession &ES, tpctypes::ResolverHandle H,
+      SymbolPredicate Allow = SymbolPredicate(),
+      AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols)
+      : EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)),
+        AbsoluteSymbols(std::move(AbsoluteSymbols)) {}
+
+  ExecutorResolutionGenerator(
+      ExecutionSession &ES, SymbolPredicate Allow = SymbolPredicate(),
+      AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols)
+      : EPC(ES.getExecutorProcessControl()), Allow(std::move(Allow)),
+        AbsoluteSymbols(std::move(AbsoluteSymbols)) {}
+
+  /// Permanently loads the library at the given path and, on success, returns
+  /// an ExecutorResolutionGenerator that will search it for symbol
+  /// definitions in the library. On failure returns the reason the library
+  /// failed to load.
+  static Expected<std::unique_ptr<ExecutorResolutionGenerator>>
+  Load(ExecutionSession &ES, const char *LibraryPath,
+       SymbolPredicate Allow = SymbolPredicate(),
+       AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols);
+
+  /// Creates a ExecutorResolutionGenerator that searches for symbols in
+  /// the target process.
+  static Expected<std::unique_ptr<ExecutorResolutionGenerator>>
+  GetForTargetProcess(ExecutionSession &ES,
+                      SymbolPredicate Allow = SymbolPredicate(),
+                      AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols) {
+    return Load(ES, nullptr, std::move(Allow), std::move(AbsoluteSymbols));
+  }
+
+  Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+                      JITDylibLookupFlags JDLookupFlags,
+                      const SymbolLookupSet &LookupSet) override;
+
+private:
+  ExecutorProcessControl &EPC;
+  tpctypes::ResolverHandle H;
+  SymbolPredicate Allow;
+  AbsoluteSymbolsFn AbsoluteSymbols;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
index 017ef70469e29..5431f385f9f24 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
@@ -26,6 +26,7 @@ namespace rt {
 LLVM_ABI extern const char *SimpleExecutorDylibManagerInstanceName;
 LLVM_ABI extern const char *SimpleExecutorDylibManagerOpenWrapperName;
 LLVM_ABI extern const char *SimpleExecutorDylibManagerLookupWrapperName;
+LLVM_ABI extern const char *SimpleExecutorDylibManagerResolveWrapperName;
 
 LLVM_ABI extern const char *SimpleExecutorMemoryManagerInstanceName;
 LLVM_ABI extern const char *SimpleExecutorMemoryManagerReserveWrapperName;
@@ -63,6 +64,10 @@ using SPSSimpleExecutorDylibManagerLookupSignature =
         shared::SPSExecutorAddr, shared::SPSExecutorAddr,
         shared::SPSRemoteSymbolLookupSet);
 
+using SPSSimpleExecutorDylibManagerResolveSignature =
+    shared::SPSExpected<shared::SPSSequence<shared::SPSExecutorSymbolDef>>(
+        shared::SPSExecutorAddr, shared::SPSRemoteSymbolLookupSet);
+
 using SPSSimpleExecutorMemoryManagerReserveSignature =
     shared::SPSExpected<shared::SPSExecutorAddr>(shared::SPSExecutorAddr,
                                                  uint64_t);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
index e91d8d926d88c..08b7164b2d099 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
@@ -114,6 +114,10 @@ struct PointerWrite {
 /// A handle used to represent a loaded dylib in the target process.
 using DylibHandle = ExecutorAddr;
 
+/// A handle used to reference the resolver associated with a loaded
+///  dylib in the target process.
+using ResolverHandle = ExecutorAddr;
+
 using LookupResult = std::vector<ExecutorSymbolDef>;
 
 } // end namespace tpctypes
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
new file mode 100644
index 0000000000000..45dbd753bac55
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
@@ -0,0 +1,48 @@
+//===----- ExecutorResolver.h - Symbol resolver -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Executor Symbol resolver.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORRESOLVER_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORRESOLVER_H
+
+#include "llvm/ADT/FunctionExtras.h"
+
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+
+namespace llvm::orc {
+
+class ExecutorResolver {
+public:
+  using ResolveResult = Expected<std::vector<ExecutorSymbolDef>>;
+  using YieldResolveResultFn = unique_function<void(ResolveResult)>;
+
+  virtual ~ExecutorResolver() = default;
+
+  virtual void resolveAsync(const RemoteSymbolLookupSet &L,
+                            YieldResolveResultFn &&OnResolve) = 0;
+};
+
+class DylibSymbolResolver : public ExecutorResolver {
+public:
+  DylibSymbolResolver(tpctypes::DylibHandle H)
+  : Handle(H) {}
+
+  void resolveAsync(const RemoteSymbolLookupSet &L,
+                    ExecutorResolver::YieldResolveResultFn &&OnResolve) override;
+
+private:
+  tpctypes::DylibHandle Handle;
+};
+
+} // end namespace llvm::orc
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORRESOLVER_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h
index 36a6f4bf6e193..e809d8c7fdee5 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h
@@ -23,6 +23,7 @@
 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/Error.h"
@@ -54,8 +55,12 @@ class LLVM_ABI SimpleExecutorDylibManager : public ExecutorBootstrapService {
   static llvm::orc::shared::CWrapperFunctionResult
   lookupWrapper(const char *ArgData, size_t ArgSize);
 
+  static llvm::orc::shared::CWrapperFunctionResult
+  resolveWrapper(const char *ArgData, size_t ArgSize);
+
   std::mutex M;
   DylibSet Dylibs;
+  std::vector<std::unique_ptr<ExecutorResolver>> Resolvers;
 };
 
 } // end namespace rt_bootstrap
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 6c86f252bf7ea..c242f051f5a68 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -24,6 +24,7 @@ add_llvm_component_library(LLVMOrcJIT
   EPCGenericRTDyldMemoryManager.cpp
   EPCIndirectionUtils.cpp
   ExecutionUtils.cpp
+  ExecutorResolutionGenerator.cpp
   ObjectFileInterface.cpp
   GetDylibInterface.cpp
   IndirectionUtils.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index 59d66b271bb09..702a91b755155 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -79,25 +79,32 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
     assert(Result->front().size() == LookupSymbols.size() &&
            "Result has incorrect number of elements");
 
-    SymbolMap NewSymbols;
-    auto ResultI = Result->front().begin();
-    for (auto &KV : LookupSymbols) {
-      if (ResultI->getAddress())
-        NewSymbols[KV.first] = *ResultI;
-      ++ResultI;
+    const std::vector<ExecutorSymbolDef> &Syms = Result->front();
+    size_t SymIdx = 0;
+    SymbolNameSet MissingSymbols;
+    SymbolMap NewSyms;
+    for (auto &[Name, Flags] : LookupSymbols) {
+      auto Sym = Syms[SymIdx++];
+      if (Sym.getAddress())
+        NewSyms[Name] = Sym;
+      else if (LLVM_UNLIKELY(Flags == SymbolLookupFlags::RequiredSymbol))
+        MissingSymbols.insert(Name);
     }
 
     LLVM_DEBUG({
       dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned "
-             << NewSymbols << "\n";
+             << NewSyms << "\n";
     });
 
-    // If there were no resolved symbols bail out.
-    if (NewSymbols.empty())
+    if (NewSyms.empty())
       return LS.continueLookup(Error::success());
 
+    if (LLVM_UNLIKELY(!MissingSymbols.empty()))
+      return LS.continueLookup(make_error<SymbolsNotFound>(
+          this->EPC.getSymbolStringPool(), std::move(MissingSymbols)));
+
     // Define resolved symbols.
-    Error Err = addAbsolutes(JD, std::move(NewSymbols));
+    Error Err = addAbsolutes(JD, std::move(NewSyms));
 
     LS.continueLookup(std::move(Err));
   });
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
index f98b18ccd0dc7..7c7335e6a3128 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
@@ -66,7 +66,8 @@ EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(
   if (auto Err = EPC.getBootstrapSymbols(
           {{SAs.Instance, rt::SimpleExecutorDylibManagerInstanceName},
            {SAs.Open, rt::SimpleExecutorDylibManagerOpenWrapperName},
-           {SAs.Lookup, rt::SimpleExecutorDylibManagerLookupWrapperName}}))
+           {SAs.Lookup, rt::SimpleExecutorDylibManagerLookupWrapperName},
+           {SAs.Resolve, rt::SimpleExecutorDylibManagerResolveWrapperName}}))
     return std::move(Err);
   return EPCGenericDylibManager(EPC, std::move(SAs));
 }
@@ -84,8 +85,8 @@ Expected<tpctypes::DylibHandle> EPCGenericDylibManager::open(StringRef Path,
 void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
                                          const SymbolLookupSet &Lookup,
                                          SymbolLookupCompleteFn Complete) {
-  EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
-      SAs.Lookup,
+  EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerResolveSignature>(
+      SAs.Resolve,
       [Complete = std::move(Complete)](
           Error SerializationErr,
           Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
@@ -96,14 +97,14 @@ void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
         }
         Complete(std::move(Result));
       },
-      SAs.Instance, H, Lookup);
+      H, Lookup);
 }
 
 void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
                                          const RemoteSymbolLookupSet &Lookup,
                                          SymbolLookupCompleteFn Complete) {
-  EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
-      SAs.Lookup,
+  EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerResolveSignature>(
+      SAs.Resolve,
       [Complete = std::move(Complete)](
           Error SerializationErr,
           Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
@@ -114,7 +115,7 @@ void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
         }
         Complete(std::move(Result));
       },
-      SAs.Instance, H, Lookup);
+      H, Lookup);
 }
 
 } // end namespace orc
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index 45cb28af56050..113215c3021bf 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -104,16 +104,12 @@ void SelfExecutorProcessControl::lookupSymbolsAsync(
       std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
                       (*Sym).size() - !!GlobalManglingPrefix);
       void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
-      if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
-        // FIXME: Collect all failing symbols before erroring out.
-        SymbolNameVector MissingSymbols;
-        MissingSymbols.push_back(Sym);
-        return Complete(
-            make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
-      }
-      // FIXME: determine accurate JITSymbolFlags.
-      R.back().push_back(
-          {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
+      if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol)
+        R.back().emplace_back();
+      else
+        // FIXME: determine accurate JITSymbolFlags.
+        R.back().push_back(
+            {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
     }
   }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp
new file mode 100644
index 0000000000000..c8f8257e23330
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp
@@ -0,0 +1,96 @@
+//===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/ExecutorResolutionGenerator.h"
+
+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
+#include "llvm/Support/Error.h"
+
+#define DEBUG_TYPE "orc"
+
+namespace llvm {
+namespace orc {
+
+Expected<std::unique_ptr<ExecutorResolutionGenerator>>
+ExecutorResolutionGenerator::Load(ExecutionSession &ES, const char *LibraryPath,
+                                  SymbolPredicate Allow,
+                                  AbsoluteSymbolsFn AbsoluteSymbols) {
+  auto H = ES.getExecutorProcessControl().getDylibMgr().loadDylib(LibraryPath);
+  if (H)
+    return H.takeError();
+  return std::make_unique<ExecutorResolutionGenerator>(
+      ES, *H, std::move(Allow), std::move(AbsoluteSymbols));
+}
+
+Error ExecutorResolutionGenerator::tryToGenerate(
+    LookupState &LS, LookupKind K, JITDylib &JD,
+    JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &LookupSet) {
+
+  if (LookupSet.empty())
+    return Error::success();
+
+  LLVM_DEBUG({
+    dbgs() << "ExecutorResolutionGenerator trying to generate " << LookupSet
+           << "\n";
+  });
+
+  SymbolLookupSet LookupSymbols;
+  for (auto &[Name, LookupFlag] : LookupSet) {
+    if (Allow && !Allow(Name))
+      continue;
+    LookupSymbols.add(Name, LookupFlag);
+  }
+
+  DylibManager::LookupRequest LR(H, LookupSymbols);
+  EPC.getDylibMgr().lookupSymbolsAsync(
+      LR, [this, LS = std::move(LS), JD = JITDylibSP(&JD),
+           LookupSymbols](auto Result) mutable {
+        if (Result) {
+          LLVM_DEBUG({
+            dbgs() << "ExecutorResolutionGenerator lookup failed due to error";
+          });
+          return LS.continueLookup(Result.takeError());
+        }
+        assert(Result->size() == 1 &&
+               "Results for more than one library returned");
+        assert(Result->front().size() == LookupSymbols.size() &&
+               "Result has incorrect number of elements");
+
+        const std::vector<ExecutorSymbolDef> &Syms = Result->front();
+        size_t SymIdx = 0;
+        SymbolNameSet MissingSymbols;
+        SymbolMap NewSyms;
+        for (auto &[Name, Flags] : LookupSymbols) {
+          auto Sym = Syms[SymIdx++];
+          if (Sym.getAddress())
+            NewSyms[Name] = Sym;
+          else if (LLVM_UNLIKELY(Flags == SymbolLookupFlags::RequiredSymbol))
+            MissingSymbols.insert(Name);
+        }
+
+        LLVM_DEBUG({
+          dbgs() << "ExecutorResolutionGenerator lookup returned " << NewSyms
+                 << "\n";
+        });
+
+        if (NewSyms.empty())
+          return LS.continueLookup(Error::success());
+
+        if (LLVM_UNLIKELY(!MissingSymbols.empty()))
+          return LS.continueLookup(make_error<SymbolsNotFound>(
+              this->EPC.getSymbolStringPool(), std::move(MissingSymbols)));
+
+        LS.continueLookup(JD->define(AbsoluteSymbols(std::move(NewSyms))));
+      });
+
+  return Error::success();
+}
+
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
index 4e5b800100b9c..f181894b95d95 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
@@ -18,6 +18,8 @@ const char *SimpleExecutorDylibManagerOpenWrapperName =
     "__llvm_orc_SimpleExecutorDylibManager_open_wrapper";
 const char *SimpleExecutorDylibManagerLookupWrapperName =
     "__llvm_orc_SimpleExecutorDylibManager_lookup_wrapper";
+const char *SimpleExecutorDylibManagerResolveWrapperName =
+    "__llvm_orc_SimpleExecutorDylibManager_resolve_wrapper";
 
 const char *SimpleExecutorMemoryManagerInstanceName =
     "__llvm_orc_SimpleExecutorMemoryManager_Instance";
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
index 9f3abac156adb..927558649eb4d 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
@@ -15,6 +15,7 @@ endif()
 add_llvm_component_library(LLVMOrcTargetProcess
   ExecutorSharedMemoryMapperService.cpp
   DefaultHostBootstrapValues.cpp
+  ExecutorResolver.cpp
   JITLoaderGDB.cpp
   JITLoaderPerf.cpp
   JITLoaderVTune.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
new file mode 100644
index 0000000000000..8ce4721caeeea
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
@@ -0,0 +1,47 @@
+
+#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h"
+
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm::orc {
+
+void DylibSymbolResolver::resolveAsync(
+    const RemoteSymbolLookupSet &L,
+    ExecutorResolver::YieldResolveResultFn &&OnResolve) {
+  std::vector<ExecutorSymbolDef> Result;
+  auto DL = sys::DynamicLibrary(Handle.toPtr<void *>());
+
+  for (const auto &E : L) {
+    if (E.Name.empty()) {
+      if (E.Required)
+        OnResolve(
+            make_error<StringError>("Required address for empty symbol \"\"",
+                                    inconvertibleErrorCode()));
+      else
+        Result.emplace_back();
+    } else {
+
+      const char *DemangledSymName = E.Name.c_str();
+#ifdef __APPLE__
+      if (E.Name.front() != '_')
+        OnResolve(make_error<StringError>(Twine("MachO symbol \"") + E.Name +
+                                              "\" missing leading '_'",
+                                          inconvertibleErrorCode()));
+      ++DemangledSymName;
+#endif
+
+      void *Addr = DL.getAddressOfSymbol(DemangledSymName);
+      if (!Addr && E.Required)
+        Result.emplace_back();
+      else
+        // FIXME: determine accurate JITSymbolFlags.
+        Result.emplace_back(ExecutorSymbolDef{ExecutorAddr::fromPtr(Addr),
+                                              JITSymbolFlags::Exported});
+    }
+  }
+
+  OnResolve(std::move(Result));
+}
+
+} // end namespace llvm::orc
\ No newline at end of file
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
index db6f20130db9e..877943f25ccfe 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
@@ -10,6 +10,10 @@
 
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
 
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+
+#include <future>
+
 #define DEBUG_TYPE "orc"
 
 namespace llvm {
@@ -35,8 +39,9 @@ SimpleExecutorDylibManager::open(const std::string &Path, uint64_t Mode) {
 
   std::lock_guard<std::mutex> Lock(M);
   auto H = ExecutorAddr::fromPtr(DL.getOSSpecificHandle());
+  Resolvers.push_back(std::make_unique<DylibSymbolResolver>(H));
   Dylibs.insert(DL.getOSSpecificHandle());
-  return H;
+  return ExecutorAddr::fromPtr(Resolvers.back().get());
 }
 
 Expected<std::vector<ExecutorSymbolDef>>
@@ -96,6 +101,8 @@ void SimpleExecutorDylibManager::addBootstrapSymbols(
       ExecutorAddr::fromPtr(&openWrapper);
   M[rt::SimpleExecutorDylibManagerLookupWrapperName] =
       ExecutorAddr::fromPtr(&lookupWrapper);
+  M[rt::SimpleExecutorDylibManagerResolveWrapperName] =
+      ExecutorAddr::fromPtr(&resolveWrapper);
 }
 
 llvm::orc::shared::CWrapperFunctionResult
@@ -118,6 +125,25 @@ SimpleExecutorDylibManager::lookupWrapper(const char *ArgData, size_t ArgSize) {
           .release();
 }
 
+llvm::orc::shared::CWrapperFunctionResult
+SimpleExecutorDylibManager::resolveWrapper(const char *ArgData,
+                                           size_t ArgSize) {
+  using ResolveResult = ExecutorResolver::ResolveResult;
+  return shared::WrapperFunction<
+             rt::SPSSimpleExecutorDylibManagerResolveSignature>::
+      handle(ArgData, ArgSize,
+             [](ExecutorAddr Obj, RemoteSymbolLookupSet L) -> ResolveResult {
+               using TmpResult = MSVCPExpected<std::vector<ExecutorSymbolDef>>;
+               std::promise<TmpResult> P;
+               auto F = P.get_future();
+               Obj.toPtr<ExecutorResolver *>()->resolveAsync(
+                   std::move(L),
+                   [&](TmpResult R) { P.set_value(std::move(R)); });
+               return F.get();
+             })
+          .release();
+}
+
 } // namespace rt_bootstrap
 } // end namespace orc
 } // end namespace llvm

>From b7d21b9f3a7aa87136c7778b351943b9556e31ab Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Thu, 5 Jun 2025 11:12:31 +0530
Subject: [PATCH 2/4] Fix format

---
 .../llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h     | 4 ++--
 .../ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h  | 8 ++++----
 .../Orc/EPCDynamicLibrarySearchGenerator.cpp              | 4 ++--
 .../Orc/TargetProcess/ExecutorResolver.cpp                | 4 ++--
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
index 66073a8111f71..d70592f61e12b 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
@@ -69,8 +69,8 @@ class EPCGenericDylibManager {
     return RF.get();
   }
 
-  using SymbolLookupCompleteFn = unique_function<void(
-      Expected<std::vector<ExecutorSymbolDef>>)>;
+  using SymbolLookupCompleteFn =
+      unique_function<void(Expected<std::vector<ExecutorSymbolDef>>)>;
 
   /// Looks up symbols within the given dylib.
   LLVM_ABI void lookupAsync(tpctypes::DylibHandle H,
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
index 45dbd753bac55..e09954444d6ab 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
@@ -34,11 +34,11 @@ class ExecutorResolver {
 
 class DylibSymbolResolver : public ExecutorResolver {
 public:
-  DylibSymbolResolver(tpctypes::DylibHandle H)
-  : Handle(H) {}
+  DylibSymbolResolver(tpctypes::DylibHandle H) : Handle(H) {}
 
-  void resolveAsync(const RemoteSymbolLookupSet &L,
-                    ExecutorResolver::YieldResolveResultFn &&OnResolve) override;
+  void
+  resolveAsync(const RemoteSymbolLookupSet &L,
+               ExecutorResolver::YieldResolveResultFn &&OnResolve) override;
 
 private:
   tpctypes::DylibHandle Handle;
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index 702a91b755155..1bb88491b6720 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -92,8 +92,8 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
     }
 
     LLVM_DEBUG({
-      dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned "
-             << NewSyms << "\n";
+      dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned " << NewSyms
+             << "\n";
     });
 
     if (NewSyms.empty())
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
index 8ce4721caeeea..b3a051be74aa1 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
@@ -36,8 +36,8 @@ void DylibSymbolResolver::resolveAsync(
         Result.emplace_back();
       else
         // FIXME: determine accurate JITSymbolFlags.
-        Result.emplace_back(ExecutorSymbolDef{ExecutorAddr::fromPtr(Addr),
-                                              JITSymbolFlags::Exported});
+        Result.push_back(
+            {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
     }
   }
 

>From 820cb109c9e169898e030a96c2233001cba09c74 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Fri, 6 Jun 2025 14:38:03 +0530
Subject: [PATCH 3/4] Fix minor issue

---
 .../Orc/EPCDynamicLibrarySearchGenerator.cpp  | 29 +++++++------------
 .../Orc/ExecutorProcessControl.cpp            | 16 ++++++----
 .../Orc/TargetProcess/ExecutorResolver.cpp    | 11 +++----
 3 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index 1bb88491b6720..59d66b271bb09 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -79,32 +79,25 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
     assert(Result->front().size() == LookupSymbols.size() &&
            "Result has incorrect number of elements");
 
-    const std::vector<ExecutorSymbolDef> &Syms = Result->front();
-    size_t SymIdx = 0;
-    SymbolNameSet MissingSymbols;
-    SymbolMap NewSyms;
-    for (auto &[Name, Flags] : LookupSymbols) {
-      auto Sym = Syms[SymIdx++];
-      if (Sym.getAddress())
-        NewSyms[Name] = Sym;
-      else if (LLVM_UNLIKELY(Flags == SymbolLookupFlags::RequiredSymbol))
-        MissingSymbols.insert(Name);
+    SymbolMap NewSymbols;
+    auto ResultI = Result->front().begin();
+    for (auto &KV : LookupSymbols) {
+      if (ResultI->getAddress())
+        NewSymbols[KV.first] = *ResultI;
+      ++ResultI;
     }
 
     LLVM_DEBUG({
-      dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned " << NewSyms
-             << "\n";
+      dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned "
+             << NewSymbols << "\n";
     });
 
-    if (NewSyms.empty())
+    // If there were no resolved symbols bail out.
+    if (NewSymbols.empty())
       return LS.continueLookup(Error::success());
 
-    if (LLVM_UNLIKELY(!MissingSymbols.empty()))
-      return LS.continueLookup(make_error<SymbolsNotFound>(
-          this->EPC.getSymbolStringPool(), std::move(MissingSymbols)));
-
     // Define resolved symbols.
-    Error Err = addAbsolutes(JD, std::move(NewSyms));
+    Error Err = addAbsolutes(JD, std::move(NewSymbols));
 
     LS.continueLookup(std::move(Err));
   });
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index 113215c3021bf..45cb28af56050 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -104,12 +104,16 @@ void SelfExecutorProcessControl::lookupSymbolsAsync(
       std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
                       (*Sym).size() - !!GlobalManglingPrefix);
       void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
-      if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol)
-        R.back().emplace_back();
-      else
-        // FIXME: determine accurate JITSymbolFlags.
-        R.back().push_back(
-            {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
+      if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
+        // FIXME: Collect all failing symbols before erroring out.
+        SymbolNameVector MissingSymbols;
+        MissingSymbols.push_back(Sym);
+        return Complete(
+            make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
+      }
+      // FIXME: determine accurate JITSymbolFlags.
+      R.back().push_back(
+          {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
     }
   }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
index b3a051be74aa1..c69ce86fb0787 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
@@ -33,11 +33,12 @@ void DylibSymbolResolver::resolveAsync(
 
       void *Addr = DL.getAddressOfSymbol(DemangledSymName);
       if (!Addr && E.Required)
-        Result.emplace_back();
-      else
-        // FIXME: determine accurate JITSymbolFlags.
-        Result.push_back(
-            {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
+        OnResolve(make_error<StringError>(Twine("Missing definition for ") +
+                                              DemangledSymName,
+                                          inconvertibleErrorCode()));
+
+      // FIXME: determine accurate JITSymbolFlags.
+      Result.push_back({ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
     }
   }
 

>From b3ac7cb4865d99831aee5b794299ae7e31b0bbc4 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Mon, 9 Jun 2025 09:36:56 +0530
Subject: [PATCH 4/4] Refactor code to return Optional<ExecutorSymbolDef>

---
 .../Orc/EPCGenericDylibManager.h               | 10 +++++-----
 .../ExecutionEngine/Orc/Shared/OrcRTBridge.h   |  6 +++---
 .../Orc/Shared/TargetProcessControlTypes.h     |  2 +-
 .../Orc/TargetProcess/ExecutorResolver.h       |  2 +-
 .../Orc/EPCDebugObjectRegistrar.cpp            |  4 +++-
 .../Orc/EPCDynamicLibrarySearchGenerator.cpp   | 17 ++++++++++++-----
 .../Orc/EPCGenericDylibManager.cpp             |  6 ++++--
 .../Orc/ExecutorProcessControl.cpp             | 18 +++++++-----------
 .../Orc/ExecutorResolutionGenerator.cpp        | 13 +++++++------
 .../Orc/LookupAndRecordAddrs.cpp               |  7 ++++---
 .../Orc/TargetProcess/ExecutorResolver.cpp     | 13 ++++++-------
 .../SimpleExecutorDylibManager.cpp             |  3 ++-
 llvm/tools/lli/ForwardingMemoryManager.h       |  7 +++++--
 .../Orc/ObjectLinkingLayerTest.cpp             |  4 ++--
 14 files changed, 62 insertions(+), 50 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
index d70592f61e12b..d64f7e7c0cb3b 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h
@@ -52,25 +52,25 @@ class EPCGenericDylibManager {
   LLVM_ABI Expected<tpctypes::DylibHandle> open(StringRef Path, uint64_t Mode);
 
   /// Looks up symbols within the given dylib.
-  Expected<std::vector<ExecutorSymbolDef>>
+  Expected<tpctypes::LookupResult>
   lookup(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup) {
-    std::promise<MSVCPExpected<std::vector<ExecutorSymbolDef>>> RP;
+    std::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
     auto RF = RP.get_future();
     lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
     return RF.get();
   }
 
   /// Looks up symbols within the given dylib.
-  Expected<std::vector<ExecutorSymbolDef>>
+  Expected<tpctypes::LookupResult>
   lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup) {
-    std::promise<MSVCPExpected<std::vector<ExecutorSymbolDef>>> RP;
+    std::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
     auto RF = RP.get_future();
     lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
     return RF.get();
   }
 
   using SymbolLookupCompleteFn =
-      unique_function<void(Expected<std::vector<ExecutorSymbolDef>>)>;
+      unique_function<void(Expected<tpctypes::LookupResult>)>;
 
   /// Looks up symbols within the given dylib.
   LLVM_ABI void lookupAsync(tpctypes::DylibHandle H,
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
index 5431f385f9f24..62f428f316915 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
@@ -64,9 +64,9 @@ using SPSSimpleExecutorDylibManagerLookupSignature =
         shared::SPSExecutorAddr, shared::SPSExecutorAddr,
         shared::SPSRemoteSymbolLookupSet);
 
-using SPSSimpleExecutorDylibManagerResolveSignature =
-    shared::SPSExpected<shared::SPSSequence<shared::SPSExecutorSymbolDef>>(
-        shared::SPSExecutorAddr, shared::SPSRemoteSymbolLookupSet);
+using SPSSimpleExecutorDylibManagerResolveSignature = shared::SPSExpected<
+    shared::SPSSequence<shared::SPSOptional<shared::SPSExecutorSymbolDef>>>(
+    shared::SPSExecutorAddr, shared::SPSRemoteSymbolLookupSet);
 
 using SPSSimpleExecutorMemoryManagerReserveSignature =
     shared::SPSExpected<shared::SPSExecutorAddr>(shared::SPSExecutorAddr,
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
index 08b7164b2d099..0637f33a464bc 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
@@ -118,7 +118,7 @@ using DylibHandle = ExecutorAddr;
 ///  dylib in the target process.
 using ResolverHandle = ExecutorAddr;
 
-using LookupResult = std::vector<ExecutorSymbolDef>;
+using LookupResult = std::vector<std::optional<ExecutorSymbolDef>>;
 
 } // end namespace tpctypes
 
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
index e09954444d6ab..2c5e98c7312b9 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h
@@ -23,7 +23,7 @@ namespace llvm::orc {
 
 class ExecutorResolver {
 public:
-  using ResolveResult = Expected<std::vector<ExecutorSymbolDef>>;
+  using ResolveResult = Expected<std::vector<std::optional<ExecutorSymbolDef>>>;
   using YieldResolveResultFn = unique_function<void(ResolveResult)>;
 
   virtual ~ExecutorResolver() = default;
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
index 9f7d517d481d4..c4517a8c82f14 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
@@ -41,8 +41,10 @@ Expected<std::unique_ptr<EPCDebugObjectRegistrar>> createJITLoaderGDBRegistrar(
   assert(Result->size() == 1 && "Unexpected number of dylibs in result");
   assert((*Result)[0].size() == 1 &&
          "Unexpected number of addresses in result");
+  assert((*Result)[0][0].has_value() &&
+         "Expected a valid address in the lookup result");
 
-  ExecutorAddr RegisterAddr = (*Result)[0][0].getAddress();
+  ExecutorAddr RegisterAddr = (*Result)[0][0]->getAddress();
   return std::make_unique<EPCDebugObjectRegistrar>(ES, RegisterAddr);
 }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index 59d66b271bb09..8177b5ed069b0 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -79,12 +79,15 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
     assert(Result->front().size() == LookupSymbols.size() &&
            "Result has incorrect number of elements");
 
+    auto SymsIt = Result->front().begin();
+    SymbolNameSet MissingSymbols;
     SymbolMap NewSymbols;
-    auto ResultI = Result->front().begin();
-    for (auto &KV : LookupSymbols) {
-      if (ResultI->getAddress())
-        NewSymbols[KV.first] = *ResultI;
-      ++ResultI;
+    for (auto &[Name, Flags] : LookupSymbols) {
+      const auto &Sym = *SymsIt++;
+      if (Sym && Sym->getAddress())
+        NewSymbols[Name] = *Sym;
+      else if (LLVM_UNLIKELY(!Sym && Flags == SymbolLookupFlags::RequiredSymbol))
+        MissingSymbols.insert(Name);
     }
 
     LLVM_DEBUG({
@@ -96,6 +99,10 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
     if (NewSymbols.empty())
       return LS.continueLookup(Error::success());
 
+    if (LLVM_UNLIKELY(!MissingSymbols.empty()))
+      return LS.continueLookup(make_error<SymbolsNotFound>(
+          this->EPC.getSymbolStringPool(), std::move(MissingSymbols)));
+
     // Define resolved symbols.
     Error Err = addAbsolutes(JD, std::move(NewSymbols));
 
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
index 7c7335e6a3128..ded9b93746317 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp
@@ -89,7 +89,8 @@ void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
       SAs.Resolve,
       [Complete = std::move(Complete)](
           Error SerializationErr,
-          Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
+          Expected<std::vector<std::optional<ExecutorSymbolDef>>>
+              Result) mutable {
         if (SerializationErr) {
           cantFail(Result.takeError());
           Complete(std::move(SerializationErr));
@@ -107,7 +108,8 @@ void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
       SAs.Resolve,
       [Complete = std::move(Complete)](
           Error SerializationErr,
-          Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
+          Expected<std::vector<std::optional<ExecutorSymbolDef>>>
+              Result) mutable {
         if (SerializationErr) {
           cantFail(Result.takeError());
           Complete(std::move(SerializationErr));
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index 45cb28af56050..bfa345a1d644a 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -98,22 +98,18 @@ void SelfExecutorProcessControl::lookupSymbolsAsync(
 
   for (auto &Elem : Request) {
     sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());
-    R.push_back(std::vector<ExecutorSymbolDef>());
+    R.push_back(tpctypes::LookupResult());
     for (auto &KV : Elem.Symbols) {
       auto &Sym = KV.first;
       std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
                       (*Sym).size() - !!GlobalManglingPrefix);
       void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
-      if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
-        // FIXME: Collect all failing symbols before erroring out.
-        SymbolNameVector MissingSymbols;
-        MissingSymbols.push_back(Sym);
-        return Complete(
-            make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
-      }
-      // FIXME: determine accurate JITSymbolFlags.
-      R.back().push_back(
-          {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
+      if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol)
+        R.back().emplace_back();
+      else
+        // FIXME: determine accurate JITSymbolFlags.
+        R.back().emplace_back(ExecutorSymbolDef(ExecutorAddr::fromPtr(Addr),
+                                                JITSymbolFlags::Exported));
     }
   }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp
index c8f8257e23330..15cebb273558b 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorResolutionGenerator.cpp
@@ -62,15 +62,16 @@ Error ExecutorResolutionGenerator::tryToGenerate(
         assert(Result->front().size() == LookupSymbols.size() &&
                "Result has incorrect number of elements");
 
-        const std::vector<ExecutorSymbolDef> &Syms = Result->front();
-        size_t SymIdx = 0;
+        // const tpctypes::LookupResult &Syms = Result->front();
+        // size_t SymIdx = 0;
+        auto Syms = Result->front().begin();
         SymbolNameSet MissingSymbols;
         SymbolMap NewSyms;
         for (auto &[Name, Flags] : LookupSymbols) {
-          auto Sym = Syms[SymIdx++];
-          if (Sym.getAddress())
-            NewSyms[Name] = Sym;
-          else if (LLVM_UNLIKELY(Flags == SymbolLookupFlags::RequiredSymbol))
+          const auto &Sym = *Syms++;
+          if (Sym && Sym->getAddress())
+            NewSyms[Name] = *Sym;
+          else if (LLVM_UNLIKELY(!Sym && Flags == SymbolLookupFlags::RequiredSymbol))
             MissingSymbols.insert(Name);
         }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp b/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
index 78169a28ed63b..42d630d690864 100644
--- a/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
@@ -72,9 +72,10 @@ Error lookupAndRecordAddrs(
     return make_error<StringError>("Error in lookup result elements",
                                    inconvertibleErrorCode());
 
-  for (unsigned I = 0; I != Pairs.size(); ++I)
-    *Pairs[I].second = Result->front()[I].getAddress();
-
+  for (unsigned I = 0; I != Pairs.size(); ++I) {
+    if (Result->front()[I])
+      *Pairs[I].second = Result->front()[I]->getAddress();
+  }
   return Error::success();
 }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
index c69ce86fb0787..6054d8673036a 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.cpp
@@ -9,7 +9,7 @@ namespace llvm::orc {
 void DylibSymbolResolver::resolveAsync(
     const RemoteSymbolLookupSet &L,
     ExecutorResolver::YieldResolveResultFn &&OnResolve) {
-  std::vector<ExecutorSymbolDef> Result;
+  std::vector<std::optional<ExecutorSymbolDef>> Result;
   auto DL = sys::DynamicLibrary(Handle.toPtr<void *>());
 
   for (const auto &E : L) {
@@ -33,12 +33,11 @@ void DylibSymbolResolver::resolveAsync(
 
       void *Addr = DL.getAddressOfSymbol(DemangledSymName);
       if (!Addr && E.Required)
-        OnResolve(make_error<StringError>(Twine("Missing definition for ") +
-                                              DemangledSymName,
-                                          inconvertibleErrorCode()));
-
-      // FIXME: determine accurate JITSymbolFlags.
-      Result.push_back({ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
+        Result.emplace_back();
+      else
+        // FIXME: determine accurate JITSymbolFlags.
+        Result.emplace_back(ExecutorSymbolDef(ExecutorAddr::fromPtr(Addr),
+                                              JITSymbolFlags::Exported));
     }
   }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
index 877943f25ccfe..5458b49dbf5d6 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.cpp
@@ -133,7 +133,8 @@ SimpleExecutorDylibManager::resolveWrapper(const char *ArgData,
              rt::SPSSimpleExecutorDylibManagerResolveSignature>::
       handle(ArgData, ArgSize,
              [](ExecutorAddr Obj, RemoteSymbolLookupSet L) -> ResolveResult {
-               using TmpResult = MSVCPExpected<std::vector<ExecutorSymbolDef>>;
+               using TmpResult =
+                   MSVCPExpected<std::vector<std::optional<ExecutorSymbolDef>>>;
                std::promise<TmpResult> P;
                auto F = P.get_future();
                Obj.toPtr<ExecutorResolver *>()->resolveAsync(
diff --git a/llvm/tools/lli/ForwardingMemoryManager.h b/llvm/tools/lli/ForwardingMemoryManager.h
index e5c10d672ccfb..d193befc0682d 100644
--- a/llvm/tools/lli/ForwardingMemoryManager.h
+++ b/llvm/tools/lli/ForwardingMemoryManager.h
@@ -109,8 +109,11 @@ class RemoteResolver : public LegacyJITSymbolResolver {
       if (Syms->size() != 1)
         return make_error<StringError>("Unexpected remote lookup result",
                                        inconvertibleErrorCode());
-      return JITSymbol(Syms->front().getAddress().getValue(),
-                       Syms->front().getFlags());
+      if (!Syms->front())
+        return make_error<StringError>("Expected valid address",
+                                       inconvertibleErrorCode());
+      return JITSymbol(Syms->front()->getAddress().getValue(),
+                       Syms->front()->getFlags());
     } else
       return Syms.takeError();
   }
diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
index 0c2c06ec75d6e..89aabdab385ad 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
@@ -299,7 +299,7 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {
 
     void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
                             SymbolLookupCompleteFn Complete) override {
-      std::vector<ExecutorSymbolDef> Result;
+      std::vector<std::optional<ExecutorSymbolDef>> Result;
       EXPECT_EQ(Request.size(), 1u);
       for (auto &LR : Request) {
         EXPECT_EQ(LR.Symbols.size(), 1u);
@@ -307,7 +307,7 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {
           if (*Sym.first == "_testFunc") {
             ExecutorSymbolDef Def{ExecutorAddr::fromPtr((void *)0x1000),
                                   JITSymbolFlags::Exported};
-            Result.push_back(Def);
+            Result.emplace_back(Def);
           } else {
             ADD_FAILURE() << "unexpected symbol request " << *Sym.first;
           }



More information about the llvm-commits mailing list