[llvm] [ORC] Add lookupAndApply, replacing buildProxies (PR #216658)
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 17 02:40:44 PDT 2026
https://github.com/lhames updated https://github.com/llvm/llvm-project/pull/216658
>From 288d819a35c3ce9262ed84e0f4757eb3dac7af7a Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Mon, 17 Aug 2026 13:57:12 +1000
Subject: [PATCH] [ORC] Add lookupAndApply, replacing buildProxies
lookupAndApply composes a single atomic lookup from independent
operations, each contributing symbols and returning a handler to run on
the result. Two gains over buildProxies:
- One lookup binds everything, so every handler sees a consistent view
of the JITDylib. (buildProxies did a separate lookup per proxy)
- Each name sits next to the variable it binds, rather than going into a
lookup set in one place and coming back out of a SymbolMap elsewhere.
recordAddr and recordProxy cover the cases we have; recordProxy is in
its own header so holding a Proxy doesn't pull in the machinery to build
one. Prepare functions are independent, so two may request the same
symbol: the composed set goes through SymbolLookupSet::mergeEntries.
Proxy::Create, ProxyInit and proxyInit are removed. ProxySpecs stay
public, so operations can still be resolved under non-default names. The
asynchronous form has no in-tree callers yet.
---
.../Orc/EPCGenericDylibManagerSPS.h | 2 +-
.../Orc/EPCGenericJITLinkMemoryManagerSPS.h | 2 +-
.../Orc/EPCGenericMemoryAccessSPS.h | 2 +-
.../llvm/ExecutionEngine/Orc/LookupAndApply.h | 111 ++++++++++++++
llvm/include/llvm/ExecutionEngine/Orc/Proxy.h | 67 --------
.../llvm/ExecutionEngine/Orc/RecordProxy.h | 65 ++++++++
llvm/lib/ExecutionEngine/Orc/CMakeLists.txt | 1 +
llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp | 10 +-
.../Orc/COFFVCRuntimeSupport.cpp | 9 +-
.../Orc/EPCGenericDylibManagerSPS.cpp | 19 ++-
.../Orc/EPCGenericJITLinkMemoryManagerSPS.cpp | 24 ++-
.../Orc/EPCGenericMemoryAccessSPS.cpp | 30 ++--
.../ExecutionEngine/Orc/LookupAndApply.cpp | 70 +++++++++
.../ExecutionEngine/Orc/CMakeLists.txt | 1 +
.../Orc/LookupAndApplyTest.cpp | 145 ++++++++++++++++++
.../ExecutionEngine/Orc/ProxyTest.cpp | 116 +++++---------
.../llvm/lib/ExecutionEngine/Orc/BUILD.gn | 1 +
.../unittests/ExecutionEngine/Orc/BUILD.gn | 1 +
18 files changed, 489 insertions(+), 187 deletions(-)
create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/LookupAndApply.h
create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/RecordProxy.h
create mode 100644 llvm/lib/ExecutionEngine/Orc/LookupAndApply.cpp
create mode 100644 llvm/unittests/ExecutionEngine/Orc/LookupAndApplyTest.cpp
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h
index 46c180eda17e5..3b01da8b93300 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h
@@ -14,7 +14,7 @@
// controller-interface descriptor in Shared/SPSCI/NativeDylibManagerSPSCI.h,
// which supplies the wrapper name and wire signature. The specs are public so
// that clients can resolve the operations under non-default names, using
-// proxyInit<Spec>(&P, Name) with buildProxies.
+// recordProxy<Spec>(&P, Name) with lookupAndApply.
//
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
index c6978f5765616..1da5bc0e5c186 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h
@@ -14,7 +14,7 @@
// controller-interface descriptor in Shared/SPSCI/SimpleNativeMemoryMapSPSCI.h,
// which supplies the wrapper name and wire signature. The specs are public so
// that clients can resolve the operations under non-default names, using
-// proxyInit<Spec>(&P, Name) with buildProxies.
+// recordProxy<Spec>(&P, Name) with lookupAndApply.
//
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h
index 21d0efa539360..f55796aaa9256 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h
@@ -14,7 +14,7 @@
// controller-interface descriptor in Shared/SPSCI/MemoryAccessSPSCI.h, which
// supplies the wrapper name and wire signature. The specs are public so that
// clients can resolve the operations under non-default names, using
-// proxyInit<Spec>(&P, Name) with buildProxies.
+// recordProxy<Spec>(&P, Name) with lookupAndApply.
//
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LookupAndApply.h b/llvm/include/llvm/ExecutionEngine/Orc/LookupAndApply.h
new file mode 100644
index 0000000000000..8ab5b3273aadf
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LookupAndApply.h
@@ -0,0 +1,111 @@
+//===- LookupAndApply.h - Compose a lookup from handlers --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Compose an ExecutionSession lookup out of independent operations, each of
+// which contributes symbols to the lookup and then acts on the addresses those
+// symbols resolve to.
+//
+// The motivating use is binding a small, fixed set of controller-side variables
+// -- e.g. the proxies and instance address that make up an executor-side
+// service's handle -- with a single atomic lookup. Handlers are not limited to
+// that: they receive the whole result map and may do as they please with it.
+// Either way the operations do all the work, and the return path only signals
+// success or failure.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKUPANDAPPLY_H
+#define LLVM_EXECUTIONENGINE_ORC_LOOKUPANDAPPLY_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm::orc {
+
+/// Acts on the result of a completed lookup.
+///
+/// Produced by a LookupPrepareFn once it has added its symbols, so that it can
+/// capture their interned names rather than re-interning them here.
+using LookupApplyFn = unique_function<void(const SymbolMap &M)>;
+
+/// Contributes symbols to a lookup, and returns the function that will act on
+/// the result.
+///
+/// A prepare function may contribute any number of symbols, so one of them can
+/// stand for a whole service's worth of bindings. The applicator it returns
+/// runs only if the lookup succeeds.
+///
+/// The call operator is const so that these can be passed as a braced list (see
+/// lookupAndApply): they hold no mutable state.
+using LookupPrepareFn = unique_function<LookupApplyFn(
+ SymbolLookupSet &LS, ExecutionSession &ES) const>;
+
+/// Resolve the symbols contributed by every prepare function with a single
+/// lookup, then let each of their applicators act on the result.
+///
+/// Because one lookup covers them all, every applicator observes a single
+/// consistent view of the search order.
+///
+/// Prepare functions need not coordinate: if two of them ask for the same
+/// symbol the contributed entries are merged (see
+/// SymbolLookupSet::mergeEntries), and each applicator still reads its own
+/// value out of the result.
+///
+/// Asynchronous version: OnApplied is called once every applicator has run, or
+/// with an error if the lookup failed (in which case none of them run).
+///
+/// The prepare functions are only used during this call -- they are asked for
+/// their symbols up front, and only their applicators are retained -- so a
+/// braced list or other temporary is safe here.
+LLVM_ABI void lookupAndApply(unique_function<void(Error)> OnApplied,
+ ExecutionSession &ES, LookupKind K,
+ const JITDylibSearchOrder &SearchOrder,
+ ArrayRef<LookupPrepareFn> PrepareFns);
+
+/// Blocking version of lookupAndApply above.
+LLVM_ABI Error lookupAndApply(ExecutionSession &ES, LookupKind K,
+ const JITDylibSearchOrder &SearchOrder,
+ ArrayRef<LookupPrepareFn> PrepareFns);
+
+/// lookupAndApply with a static lookup in the given JITDylib.
+LLVM_ABI void lookupAndApply(unique_function<void(Error)> OnApplied,
+ JITDylib &JD,
+ ArrayRef<LookupPrepareFn> PrepareFns);
+
+/// lookupAndApply with a static lookup in the given JITDylib. Blocking
+/// version.
+LLVM_ABI Error lookupAndApply(JITDylib &JD,
+ ArrayRef<LookupPrepareFn> PrepareFns);
+
+/// Records the address of the symbol with the given name.
+///
+/// If the symbol is weakly referenced and not found then *A is set to null.
+///
+/// Name must remain valid until the lookupAndApply call it is passed to has
+/// collected its symbols: it is interned up front, and only the interned name
+/// is retained.
+inline LookupPrepareFn
+recordAddr(StringRef Name, ExecutorAddr *A,
+ SymbolLookupFlags LF = SymbolLookupFlags::RequiredSymbol) {
+ return [Name, A, LF](SymbolLookupSet &LS,
+ ExecutionSession &ES) -> LookupApplyFn {
+ auto N = ES.intern(Name);
+ LS.add(N, LF);
+ return [A, N = std::move(N)](const SymbolMap &M) {
+ *A = M.lookup(N).getAddress();
+ };
+ };
+}
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LOOKUPANDAPPLY_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Proxy.h b/llvm/include/llvm/ExecutionEngine/Orc/Proxy.h
index 2504f6217620c..0d994ad0562d6 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Proxy.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Proxy.h
@@ -115,24 +115,6 @@ class Proxy<RetT(ArgTs...)> : public ProxyBase {
Proxy(DispatchFn Dispatch, ExecutorAddr CalleeAddr)
: ProxyBase(CalleeAddr), Dispatch(Dispatch) {}
- static Expected<Proxy> Create(DispatchFn Dispatch, JITDylib &JD,
- StringRef Name, SymbolLookupFlags LF) {
- auto &ES = JD.getExecutionSession();
- if (auto CalleeSyms = ES.lookup(makeJITDylibSearchOrder(&JD),
- SymbolLookupSet{ES.intern(Name), LF})) {
- if (!CalleeSyms->empty())
- return Proxy(Dispatch, CalleeSyms->begin()->second.getAddress());
- assert(LF == SymbolLookupFlags::WeaklyReferencedSymbol);
- return Proxy();
- } else
- return CalleeSyms.takeError();
- }
-
- static Expected<Proxy> Create(DispatchFn Dispatch, ExecutionSession &ES,
- StringRef Name, SymbolLookupFlags LF) {
- return Create(Dispatch, ES.getBootstrapJITDylib(), Name, LF);
- }
-
/// Asynchronously invoke the operation with the given Args, delivering its
/// result (or an error) to OnComplete.
void operator()(unique_function<void(ErrorRetT)> OnComplete,
@@ -156,55 +138,6 @@ class Proxy<RetT(ArgTs...)> : public ProxyBase {
DispatchFn Dispatch = nullptr;
};
-template <typename FnT> struct ProxyInit {
- Proxy<FnT> *P = nullptr;
- typename Proxy<FnT>::DispatchFn Dispatch = nullptr;
- StringRef Name;
- SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol;
-};
-
-template <typename FnT>
-ProxyInit<FnT>
-proxyInit(Proxy<FnT> *P, typename Proxy<FnT>::DispatchFn Dispatch,
- StringRef Name,
- SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol) {
- return {P, Dispatch, Name, LookupFlags};
-}
-
-template <typename ProxySpecT, typename FnT>
-ProxyInit<FnT>
-proxyInit(Proxy<FnT> *P,
- SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol) {
- return {P, ProxySpecT::dispatch, ProxySpecT::Name, LookupFlags};
-}
-
-template <typename ProxySpecT, typename FnT>
-ProxyInit<FnT>
-proxyInit(Proxy<FnT> *P, StringRef Name,
- SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol) {
- return {P, ProxySpecT::dispatch, Name, LookupFlags};
-}
-
-/// buildProxies base case.
-inline Error buildProxies(JITDylib &JD) { return Error::success(); }
-
-/// buildProxies: Given an ExecutionSession, use BootstrapJITDylib.
-template <typename... FnTs>
-Error buildProxies(ExecutionSession &ES, ProxyInit<FnTs>... PIs) {
- return buildProxies(ES.getBootstrapJITDylib(), PIs...);
-}
-
-/// Build a sequence of proxies from their respective specs.
-template <typename FnT, typename... FnTs>
-Error buildProxies(JITDylib &JD, ProxyInit<FnT> PI, ProxyInit<FnTs>... PIs) {
- if (auto POrErr =
- Proxy<FnT>::Create(PI.Dispatch, JD, PI.Name, PI.LookupFlags))
- *PI.P = std::move(*POrErr);
- else
- return POrErr.takeError();
- return buildProxies(JD, PIs...);
-}
-
} // namespace llvm::orc
#endif // LLVM_EXECUTIONENGINE_ORC_PROXY_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RecordProxy.h b/llvm/include/llvm/ExecutionEngine/Orc/RecordProxy.h
new file mode 100644
index 0000000000000..6f4c8cdb2a672
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/RecordProxy.h
@@ -0,0 +1,65 @@
+//===- RecordProxy.h - Build a Proxy from a lookup --------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// lookupAndApply operations that build Proxy objects over the symbols they
+// resolve.
+//
+// This is kept out of Proxy.h so that clients holding or calling a Proxy do not
+// have to see the lookup machinery used to build one.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_RECORDPROXY_H
+#define LLVM_EXECUTIONENGINE_ORC_RECORDPROXY_H
+
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
+#include "llvm/ExecutionEngine/Orc/Proxy.h"
+
+namespace llvm::orc {
+
+/// Builds P over the symbol with the given name, dispatching through Dispatch.
+///
+/// If the symbol is weakly referenced and not found then P is left null.
+template <typename FnT>
+LookupPrepareFn
+recordProxy(Proxy<FnT> *P, typename Proxy<FnT>::DispatchFn Dispatch,
+ StringRef Name,
+ SymbolLookupFlags LF = SymbolLookupFlags::RequiredSymbol) {
+ return [P, Dispatch, Name, LF](SymbolLookupSet &LS,
+ ExecutionSession &ES) -> LookupApplyFn {
+ auto N = ES.intern(Name);
+ LS.add(N, LF);
+ return [P, Dispatch, N = std::move(N)](const SymbolMap &M) {
+ auto Sym = M.lookup(N);
+ *P = Sym.getAddress() ? Proxy<FnT>(Dispatch, Sym.getAddress())
+ : Proxy<FnT>();
+ };
+ };
+}
+
+/// Builds P from the given spec, using the spec's default controller-interface
+/// name.
+template <typename ProxySpecT, typename FnT>
+LookupPrepareFn
+recordProxy(Proxy<FnT> *P,
+ SymbolLookupFlags LF = SymbolLookupFlags::RequiredSymbol) {
+ return recordProxy(P, ProxySpecT::dispatch, ProxySpecT::Name, LF);
+}
+
+/// Builds P from the given spec, but resolves it under Name rather than the
+/// spec's default controller-interface name.
+template <typename ProxySpecT, typename FnT>
+LookupPrepareFn
+recordProxy(Proxy<FnT> *P, StringRef Name,
+ SymbolLookupFlags LF = SymbolLookupFlags::RequiredSymbol) {
+ return recordProxy(P, ProxySpecT::dispatch, Name, LF);
+}
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_RECORDPROXY_H
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 26306f36fbdaf..134a4ebea2b1c 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -43,6 +43,7 @@ add_llvm_component_library(LLVMOrcJIT
LinkGraphLayer.cpp
LinkGraphLinkingLayer.cpp
LoadLinkableFile.cpp
+ LookupAndApply.cpp
LookupAndRecordAddrs.cpp
LLJIT.cpp
MachO.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
index ca62be4bb44ad..ff342cb03ddf7 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/COFFPlatform.cpp
@@ -12,8 +12,10 @@
#include "llvm/ExecutionEngine/Orc/COFF.h"
#include "llvm/ExecutionEngine/Orc/CallProxiesSPS.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/Object/COFF.h"
@@ -664,8 +666,9 @@ Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
StringRef Start,
StringRef End) {
CallInt32VoidProxy CallInitializer;
- if (auto Err = buildProxies(
- ES, proxyInit<sps::CallInt32VoidProxySpec>(&CallInitializer)))
+ if (auto Err = lookupAndApply(
+ ES.getBootstrapJITDylib(),
+ {recordProxy<sps::CallInt32VoidProxySpec>(&CallInitializer)}))
return Err;
for (auto &Initializer : BState.Initializers)
if (Initializer.first >= Start && Initializer.first <= End &&
@@ -738,7 +741,8 @@ Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
if (!AfterCLookupErr) {
CallInt32VoidProxy CallFn;
if (auto Err =
- buildProxies(ES, proxyInit<sps::CallInt32VoidProxySpec>(&CallFn)))
+ lookupAndApply(ES.getBootstrapJITDylib(),
+ {recordProxy<sps::CallInt32VoidProxySpec>(&CallFn)}))
return Err;
auto Res = CallFn(ES, jit_function);
if (!Res)
diff --git a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
index a9010a3fc76f7..08159e5647b81 100644
--- a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
@@ -11,7 +11,9 @@
#include "llvm/ExecutionEngine/Orc/COFF.h"
#include "llvm/ExecutionEngine/Orc/CallProxiesSPS.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/WindowsDriver/MSVCPaths.h"
@@ -126,9 +128,10 @@ Error COFFVCRuntimeBootstrapper::initializeStaticVCRuntime(JITDylib &JD) {
CallInt32VoidProxy CallInt32Void;
CallInt32Int32Proxy CallInt32Int32;
- if (auto Err = buildProxies(
- ES, proxyInit<sps::CallInt32VoidProxySpec>(&CallInt32Void),
- proxyInit<sps::CallInt32Int32ProxySpec>(&CallInt32Int32)))
+ if (auto Err = lookupAndApply(
+ ES.getBootstrapJITDylib(),
+ {recordProxy<sps::CallInt32VoidProxySpec>(&CallInt32Void),
+ recordProxy<sps::CallInt32Int32ProxySpec>(&CallInt32Int32)}))
return Err;
auto R = CallInt32Int32(ES, jit_scrt_initialize, 0);
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp
index c9c44998bdcb3..eeab5d1da8de2 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.cpp
@@ -9,7 +9,8 @@
#include "llvm/ExecutionEngine/Orc/EPCGenericDylibManagerSPS.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
namespace llvm::orc::shared {
@@ -48,15 +49,13 @@ createEPCGenericDylibManager(JITDylib &JD) {
auto &ES = JD.getExecutionSession();
EPCGenericDylibManager::Bindings B;
// Instance is the executor-side manager object -- a data symbol passed as the
- // first argument to each call, not a wrapper to proxy.
- if (auto Err = lookupAndRecordAddrs(
- ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}),
- {{ES.intern(rt::sps_ci::NativeDylibManagerInstanceName),
- &B.Instance}}))
- return std::move(Err);
- // The proxies resolve to the specs' default (NativeDylibManager) names.
- if (auto Err = buildProxies(JD, proxyInit<DylibMgrOpenProxySpec>(&B.Open),
- proxyInit<DylibMgrResolveProxySpec>(&B.Resolve)))
+ // first argument to each call, not a wrapper to proxy. The proxies resolve to
+ // the specs' default (NativeDylibManager) names.
+ if (auto Err = lookupAndApply(
+ JD,
+ {recordAddr(rt::sps_ci::NativeDylibManagerInstanceName, &B.Instance),
+ recordProxy<DylibMgrOpenProxySpec>(&B.Open),
+ recordProxy<DylibMgrResolveProxySpec>(&B.Resolve)}))
return std::move(Err);
return std::make_unique<EPCGenericDylibManager>(ES, std::move(B));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
index e57d704ebafd6..a36b756e2403d 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.cpp
@@ -9,7 +9,8 @@
#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerSPS.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
namespace llvm::orc::sps {
@@ -18,18 +19,15 @@ createEPCGenericJITLinkMemoryManager(JITDylib &JD) {
auto &ES = JD.getExecutionSession();
EPCGenericJITLinkMemoryManager::Bindings B;
// Instance is the executor-side allocator object -- a data symbol passed as
- // the first argument to each call, not a wrapper to proxy.
- if (auto Err = lookupAndRecordAddrs(
- ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}),
- {{ES.intern(rt::sps_ci::SimpleNativeMemoryMapInstanceName),
- &B.Instance}}))
- return std::move(Err);
- // The proxies resolve to the specs' default (SimpleNativeMemoryMap) names.
- if (auto Err =
- buildProxies(JD, proxyInit<MemMgrReserveProxySpec>(&B.Reserve),
- proxyInit<MemMgrInitializeProxySpec>(&B.Initialize),
- proxyInit<MemMgrDeinitializeProxySpec>(&B.Deinitialize),
- proxyInit<MemMgrReleaseProxySpec>(&B.Release)))
+ // the first argument to each call, not a wrapper to proxy. The proxies
+ // resolve to the specs' default (SimpleNativeMemoryMap) names.
+ if (auto Err = lookupAndApply(
+ JD, {recordAddr(rt::sps_ci::SimpleNativeMemoryMapInstanceName,
+ &B.Instance),
+ recordProxy<MemMgrReserveProxySpec>(&B.Reserve),
+ recordProxy<MemMgrInitializeProxySpec>(&B.Initialize),
+ recordProxy<MemMgrDeinitializeProxySpec>(&B.Deinitialize),
+ recordProxy<MemMgrReleaseProxySpec>(&B.Release)}))
return std::move(Err);
return std::make_unique<EPCGenericJITLinkMemoryManager>(ES, std::move(B));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp b/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp
index 8c5f305c78e94..c061ab841191c 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.cpp
@@ -9,6 +9,8 @@
#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccessSPS.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
namespace llvm::orc::sps {
@@ -17,20 +19,20 @@ createEPCGenericMemoryAccess(JITDylib &JD) {
auto &ES = JD.getExecutionSession();
EPCGenericMemoryAccess::Funcs Fns;
// The proxies resolve to the specs' default controller-interface names.
- if (auto Err =
- buildProxies(JD, proxyInit<MemWriteUInt8sProxySpec>(&Fns.WriteUInt8s),
- proxyInit<MemWriteUInt16sProxySpec>(&Fns.WriteUInt16s),
- proxyInit<MemWriteUInt32sProxySpec>(&Fns.WriteUInt32s),
- proxyInit<MemWriteUInt64sProxySpec>(&Fns.WriteUInt64s),
- proxyInit<MemWritePointersProxySpec>(&Fns.WritePointers),
- proxyInit<MemWriteBuffersProxySpec>(&Fns.WriteBuffers),
- proxyInit<MemReadUInt8sProxySpec>(&Fns.ReadUInt8s),
- proxyInit<MemReadUInt16sProxySpec>(&Fns.ReadUInt16s),
- proxyInit<MemReadUInt32sProxySpec>(&Fns.ReadUInt32s),
- proxyInit<MemReadUInt64sProxySpec>(&Fns.ReadUInt64s),
- proxyInit<MemReadPointersProxySpec>(&Fns.ReadPointers),
- proxyInit<MemReadBuffersProxySpec>(&Fns.ReadBuffers),
- proxyInit<MemReadStringsProxySpec>(&Fns.ReadStrings)))
+ if (auto Err = lookupAndApply(
+ JD, {recordProxy<MemWriteUInt8sProxySpec>(&Fns.WriteUInt8s),
+ recordProxy<MemWriteUInt16sProxySpec>(&Fns.WriteUInt16s),
+ recordProxy<MemWriteUInt32sProxySpec>(&Fns.WriteUInt32s),
+ recordProxy<MemWriteUInt64sProxySpec>(&Fns.WriteUInt64s),
+ recordProxy<MemWritePointersProxySpec>(&Fns.WritePointers),
+ recordProxy<MemWriteBuffersProxySpec>(&Fns.WriteBuffers),
+ recordProxy<MemReadUInt8sProxySpec>(&Fns.ReadUInt8s),
+ recordProxy<MemReadUInt16sProxySpec>(&Fns.ReadUInt16s),
+ recordProxy<MemReadUInt32sProxySpec>(&Fns.ReadUInt32s),
+ recordProxy<MemReadUInt64sProxySpec>(&Fns.ReadUInt64s),
+ recordProxy<MemReadPointersProxySpec>(&Fns.ReadPointers),
+ recordProxy<MemReadBuffersProxySpec>(&Fns.ReadBuffers),
+ recordProxy<MemReadStringsProxySpec>(&Fns.ReadStrings)}))
return std::move(Err);
return std::make_unique<EPCGenericMemoryAccess>(ES, std::move(Fns));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/LookupAndApply.cpp b/llvm/lib/ExecutionEngine/Orc/LookupAndApply.cpp
new file mode 100644
index 0000000000000..da0d2c20820db
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/LookupAndApply.cpp
@@ -0,0 +1,70 @@
+//===- LookupAndApply.cpp - Compose a lookup from handlers ----------------===//
+//
+// 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/LookupAndApply.h"
+
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+
+#include <future>
+
+namespace llvm::orc {
+
+void lookupAndApply(unique_function<void(Error)> OnApplied,
+ ExecutionSession &ES, LookupKind K,
+ const JITDylibSearchOrder &SearchOrder,
+ ArrayRef<LookupPrepareFn> PrepareFns) {
+ // Collect the symbols to look up. Each prepare function hands back the
+ // applicator that will act on the result; the prepare functions themselves
+ // are not needed beyond this point.
+ SymbolLookupSet Symbols;
+ std::vector<LookupApplyFn> Applies;
+ Applies.reserve(PrepareFns.size());
+ for (const auto &PF : PrepareFns)
+ Applies.push_back(PF(Symbols, ES));
+
+ // PrepareFns are independent, so two of them may legitimately ask for the
+ // same symbol. ExecutionSession::lookup requires a duplicate-free set, and
+ // the applicators read the result by name, so merging here is invisible to
+ // them.
+ Symbols.mergeEntries();
+
+ ES.lookup(
+ K, SearchOrder, std::move(Symbols), SymbolState::Ready,
+ [Applies = std::move(Applies),
+ OnApplied = std::move(OnApplied)](Expected<SymbolMap> Result) mutable {
+ if (!Result)
+ return OnApplied(Result.takeError());
+ for (auto &Apply : Applies)
+ Apply(*Result);
+ OnApplied(Error::success());
+ },
+ NoDependenciesToRegister);
+}
+
+Error lookupAndApply(ExecutionSession &ES, LookupKind K,
+ const JITDylibSearchOrder &SearchOrder,
+ ArrayRef<LookupPrepareFn> PrepareFns) {
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ lookupAndApply([&](Error Err) { ResultP.set_value(std::move(Err)); }, ES, K,
+ SearchOrder, PrepareFns);
+ return ResultF.get();
+}
+
+void lookupAndApply(unique_function<void(Error)> OnApplied, JITDylib &JD,
+ ArrayRef<LookupPrepareFn> PrepareFns) {
+ lookupAndApply(std::move(OnApplied), JD.getExecutionSession(),
+ LookupKind::Static, makeJITDylibSearchOrder(&JD), PrepareFns);
+}
+
+Error lookupAndApply(JITDylib &JD, ArrayRef<LookupPrepareFn> PrepareFns) {
+ return lookupAndApply(JD.getExecutionSession(), LookupKind::Static,
+ makeJITDylibSearchOrder(&JD), PrepareFns);
+}
+
+} // namespace llvm::orc
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index ac648b3f420bf..798c7426e373b 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -31,6 +31,7 @@ add_llvm_unittest(OrcJITTests
LazyCallThroughAndReexportsTest.cpp
LibraryResolverTest.cpp
LinkGraphLinkingLayerTest.cpp
+ LookupAndApplyTest.cpp
LookupAndRecordAddrsTest.cpp
MachOBuilderTest.cpp
MangleAndInternerTest.cpp
diff --git a/llvm/unittests/ExecutionEngine/Orc/LookupAndApplyTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LookupAndApplyTest.cpp
new file mode 100644
index 0000000000000..5b29e0f65823b
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/Orc/LookupAndApplyTest.cpp
@@ -0,0 +1,145 @@
+//===- LookupAndApplyTest.cpp - Test lookupAndApply -----------------------===//
+//
+// 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/LookupAndApply.h"
+
+#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
+#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include <future>
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+// Two arbitrary, distinct addresses to resolve symbols to.
+constexpr uint64_t AddrAValue = 0x1000;
+constexpr uint64_t AddrBValue = 0x2000;
+
+// Define Name -> Addr in JD as an exported absolute symbol.
+static void defineAddr(JITDylib &JD, StringRef Name, ExecutorAddr Addr) {
+ auto &ES = JD.getExecutionSession();
+ cantFail(JD.define(
+ absoluteSymbols({{ES.intern(Name), {Addr, JITSymbolFlags::Exported}}})));
+}
+
+} // namespace
+
+// recordAddr writes the resolved address of a required symbol.
+TEST(LookupAndApplyTest, RecordAddr) {
+ ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
+ auto &JD = ES.getBootstrapJITDylib();
+ defineAddr(JD, "addr_a", ExecutorAddr(AddrAValue));
+
+ ExecutorAddr A;
+ cantFail(lookupAndApply(JD, {recordAddr("addr_a", &A)}));
+ EXPECT_EQ(A, ExecutorAddr(AddrAValue));
+
+ cantFail(ES.endSession());
+}
+
+// A required symbol that is missing fails the lookup.
+TEST(LookupAndApplyTest, RecordAddrRequiredAbsentFails) {
+ ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
+
+ ExecutorAddr A(AddrAValue);
+ EXPECT_THAT_ERROR(
+ lookupAndApply(ES.getBootstrapJITDylib(), {recordAddr("absent", &A)}),
+ Failed());
+
+ cantFail(ES.endSession());
+}
+
+// A weakly-referenced symbol that is missing records a null address, rather
+// than failing the lookup.
+TEST(LookupAndApplyTest, RecordAddrWeaklyReferencedAbsent) {
+ ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
+
+ ExecutorAddr A(AddrAValue);
+ cantFail(lookupAndApply(
+ ES.getBootstrapJITDylib(),
+ {recordAddr("absent", &A, SymbolLookupFlags::WeaklyReferencedSymbol)}));
+ EXPECT_EQ(A, ExecutorAddr());
+
+ cantFail(ES.endSession());
+}
+
+// Several prepare functions in one call are all applied, and a single one may
+// contribute more than one symbol.
+TEST(LookupAndApplyTest, MultiplePrepareFns) {
+ ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
+ auto &JD = ES.getBootstrapJITDylib();
+ defineAddr(JD, "addr_a", ExecutorAddr(AddrAValue));
+ defineAddr(JD, "addr_b", ExecutorAddr(AddrBValue));
+
+ ExecutorAddr A, B, C, D;
+
+ // A composite prepare fn: contributes both names, records both results.
+ auto RecordBoth = [&C, &D](SymbolLookupSet &LS,
+ ExecutionSession &ES) -> LookupApplyFn {
+ auto NA = ES.intern("addr_a");
+ auto NB = ES.intern("addr_b");
+ LS.add(NA);
+ LS.add(NB);
+ return
+ [&C, &D, NA = std::move(NA), NB = std::move(NB)](const SymbolMap &M) {
+ C = M.lookup(NA).getAddress();
+ D = M.lookup(NB).getAddress();
+ };
+ };
+
+ cantFail(lookupAndApply(
+ JD, {recordAddr("addr_a", &A), recordAddr("addr_b", &B), RecordBoth}));
+
+ EXPECT_EQ(A, ExecutorAddr(AddrAValue));
+ EXPECT_EQ(B, ExecutorAddr(AddrBValue));
+ EXPECT_EQ(C, ExecutorAddr(AddrAValue));
+ EXPECT_EQ(D, ExecutorAddr(AddrBValue));
+
+ cantFail(ES.endSession());
+}
+
+// If the lookup fails then no applicator runs: a failed lookup must not
+// leave some variables written and others not.
+TEST(LookupAndApplyTest, NoApplyOnLookupFailure) {
+ ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
+ auto &JD = ES.getBootstrapJITDylib();
+ defineAddr(JD, "addr_a", ExecutorAddr(AddrAValue));
+
+ ExecutorAddr A, B;
+ // "addr_a" resolves, "absent" does not, so the whole lookup fails.
+ EXPECT_THAT_ERROR(
+ lookupAndApply(JD, {recordAddr("addr_a", &A), recordAddr("absent", &B)}),
+ Failed());
+ EXPECT_EQ(A, ExecutorAddr());
+ EXPECT_EQ(B, ExecutorAddr());
+
+ cantFail(ES.endSession());
+}
+
+// The asynchronous form delivers success once every applicator has run.
+TEST(LookupAndApplyTest, Async) {
+ ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
+ auto &JD = ES.getBootstrapJITDylib();
+ defineAddr(JD, "addr_a", ExecutorAddr(AddrAValue));
+
+ ExecutorAddr A;
+ std::promise<MSVCPError> P;
+ auto F = P.get_future();
+ lookupAndApply([&](Error Err) { P.set_value(std::move(Err)); }, JD,
+ {recordAddr("addr_a", &A)});
+ EXPECT_THAT_ERROR(F.get(), Succeeded());
+ EXPECT_EQ(A, ExecutorAddr(AddrAValue));
+
+ cantFail(ES.endSession());
+}
diff --git a/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp
index 21c2e10c12c22..76ca030412048 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ProxyTest.cpp
@@ -16,6 +16,8 @@
#include "llvm/ExecutionEngine/Orc/Proxy.h"
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
+#include "llvm/ExecutionEngine/Orc/RecordProxy.h"
#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Testing/Support/Error.h"
@@ -88,7 +90,7 @@ static_assert(
std::is_same_v<Proxy<Expected<int>(int)>::ErrorRetT, Expected<int>>);
// A minimal ProxySpec-shaped type (static dispatch + Name) for exercising the
-// proxyInit / buildProxies client path without depending on a protocol.
+// recordProxy client path without depending on a protocol.
struct AddOneSpec {
static constexpr const char *Name = "add_one";
static void dispatch(unique_function<void(Expected<int32_t>)> OnComplete,
@@ -138,58 +140,22 @@ TEST(ProxyTest, OperatorBoolAndAccessors) {
cantFail(ES.endSession());
}
-// Create looks the callee up by name in the bootstrap JITDylib and binds a
-// usable proxy to it (required-symbol, present).
-TEST(ProxyTest, CreateRequiredPresent) {
+// A required (default) recordProxy against a missing symbol fails the whole
+// lookup, rather than yielding a null proxy as the weakly-referenced form does.
+TEST(ProxyTest, RecordProxyRequiredAbsentFails) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
- auto &JD = ES.getBootstrapJITDylib();
- cantFail(JD.define(absoluteSymbols(
- {{ES.intern(AddOneSpec::Name),
- {ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
-
- Expected<AddOneProxy> Call = AddOneProxy::Create(
- AddOneDispatch, ES, AddOneSpec::Name, SymbolLookupFlags::RequiredSymbol);
- ASSERT_THAT_EXPECTED(Call, Succeeded());
- EXPECT_TRUE(static_cast<bool>(*Call));
-
- Expected<int32_t> R = (*Call)(ES, 41);
- ASSERT_THAT_EXPECTED(R, Succeeded());
- EXPECT_EQ(*R, 42);
-
- cantFail(ES.endSession());
-}
-
-// A required (default) Create against a missing symbol fails, rather than
-// yielding a null proxy as the weakly-referenced form does.
-TEST(ProxyTest, CreateRequiredAbsentFails) {
- ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
-
- Expected<AddOneProxy> Call = AddOneProxy::Create(
- AddOneDispatch, ES, AddOneSpec::Name, SymbolLookupFlags::RequiredSymbol);
- EXPECT_THAT_EXPECTED(Call, Failed());
-
- cantFail(ES.endSession());
-}
-
-// A weakly-referenced Create against a missing symbol succeeds, yielding a
-// proxy with a null callee (falsey) rather than an error.
-TEST(ProxyTest, CreateWeaklyReferencedAbsent) {
- ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
-
- Expected<AddOneProxy> Call =
- AddOneProxy::Create(AddOneDispatch, ES, AddOneSpec::Name,
- SymbolLookupFlags::WeaklyReferencedSymbol);
- ASSERT_THAT_EXPECTED(Call, Succeeded());
- EXPECT_FALSE(static_cast<bool>(*Call));
- EXPECT_EQ(Call->calleeAddr(), ExecutorAddr());
+ AddOneProxy Call;
+ EXPECT_THAT_ERROR(lookupAndApply(ES.getBootstrapJITDylib(),
+ {recordProxy<AddOneSpec>(&Call)}),
+ Failed());
cantFail(ES.endSession());
}
-// A weakly-referenced Create against a present symbol resolves it, yielding a
-// usable proxy (truthy) bound to the registered address.
-TEST(ProxyTest, CreateWeaklyReferencedPresent) {
+// A weakly-referenced recordProxy against a present symbol resolves it,
+// yielding a usable proxy (truthy) bound to the registered address.
+TEST(ProxyTest, RecordProxyWeaklyReferencedPresent) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
auto &JD = ES.getBootstrapJITDylib();
@@ -198,19 +164,19 @@ TEST(ProxyTest, CreateWeaklyReferencedPresent) {
JD.define(absoluteSymbols({{ES.intern(AddOneSpec::Name),
{CalleeAddr, JITSymbolFlags::Exported}}})));
- Expected<AddOneProxy> Call =
- AddOneProxy::Create(AddOneDispatch, ES, AddOneSpec::Name,
- SymbolLookupFlags::WeaklyReferencedSymbol);
- ASSERT_THAT_EXPECTED(Call, Succeeded());
- EXPECT_TRUE(static_cast<bool>(*Call));
- EXPECT_EQ(Call->calleeAddr(), CalleeAddr);
+ AddOneProxy Call;
+ cantFail(lookupAndApply(
+ JD, {recordProxy<AddOneSpec>(
+ &Call, SymbolLookupFlags::WeaklyReferencedSymbol)}));
+ EXPECT_TRUE(static_cast<bool>(Call));
+ EXPECT_EQ(Call.calleeAddr(), CalleeAddr);
cantFail(ES.endSession());
}
-// buildProxies resolves a set of proxies from the bootstrap JITDylib via their
-// specs, exercising the proxyInit / buildProxies client entry point.
-TEST(ProxyTest, BuildProxies) {
+// recordProxy resolves a proxy from the bootstrap JITDylib via its spec,
+// exercising the recordProxy / lookupAndApply client entry point.
+TEST(ProxyTest, RecordProxy) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
auto &JD = ES.getBootstrapJITDylib();
@@ -219,7 +185,7 @@ TEST(ProxyTest, BuildProxies) {
{ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
AddOneProxy Call;
- cantFail(buildProxies(ES, proxyInit<AddOneSpec>(&Call)));
+ cantFail(lookupAndApply(JD, {recordProxy<AddOneSpec>(&Call)}));
ASSERT_TRUE(static_cast<bool>(Call));
Expected<int32_t> R = Call(ES, 41);
@@ -229,9 +195,9 @@ TEST(ProxyTest, BuildProxies) {
cantFail(ES.endSession());
}
-// buildProxies with an explicitly-supplied dispatch function and name -- the
-// proxyInit overload that takes no spec type.
-TEST(ProxyTest, BuildProxiesExplicitDispatch) {
+// recordProxy with an explicitly-supplied dispatch function and name -- the
+// overload that takes no spec type.
+TEST(ProxyTest, RecordProxyExplicitDispatch) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
auto &JD = ES.getBootstrapJITDylib();
@@ -240,8 +206,8 @@ TEST(ProxyTest, BuildProxiesExplicitDispatch) {
{ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
AddOneProxy Call;
- cantFail(
- buildProxies(ES, proxyInit(&Call, AddOneDispatch, AddOneSpec::Name)));
+ cantFail(lookupAndApply(
+ JD, {recordProxy(&Call, AddOneDispatch, AddOneSpec::Name)}));
ASSERT_TRUE(static_cast<bool>(Call));
Expected<int32_t> R = Call(ES, 41);
@@ -251,11 +217,11 @@ TEST(ProxyTest, BuildProxiesExplicitDispatch) {
cantFail(ES.endSession());
}
-// buildProxies with a spec but an overridden lookup name -- the proxyInit
-// overload that takes a spec type plus an explicit name. The symbol is defined
-// only under the override name, so resolving against the spec's default Name
-// would fail; success proves the override is used.
-TEST(ProxyTest, BuildProxiesSpecNameOverride) {
+// recordProxy with a spec but an overridden lookup name -- the overload that
+// takes a spec type plus an explicit name. The symbol is defined only under the
+// override name, so resolving against the spec's default Name would fail;
+// success proves the override is used.
+TEST(ProxyTest, RecordProxySpecNameOverride) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
auto &JD = ES.getBootstrapJITDylib();
@@ -264,7 +230,8 @@ TEST(ProxyTest, BuildProxiesSpecNameOverride) {
{ExecutorAddr::fromPtr(addOne), JITSymbolFlags::Exported}}})));
AddOneProxy Call;
- cantFail(buildProxies(ES, proxyInit<AddOneSpec>(&Call, "add_one_alias")));
+ cantFail(
+ lookupAndApply(JD, {recordProxy<AddOneSpec>(&Call, "add_one_alias")}));
ASSERT_TRUE(static_cast<bool>(Call));
Expected<int32_t> R = Call(ES, 41);
@@ -274,15 +241,16 @@ TEST(ProxyTest, BuildProxiesSpecNameOverride) {
cantFail(ES.endSession());
}
-// buildProxies propagates the lookup flags: a weakly-referenced proxyInit for a
-// missing symbol yields a null proxy rather than failing the whole build.
-TEST(ProxyTest, BuildProxiesWeaklyReferencedAbsent) {
+// lookupAndApply propagates the lookup flags: a weakly-referenced recordProxy
+// for a missing symbol yields a null proxy rather than failing the lookup.
+TEST(ProxyTest, RecordProxyWeaklyReferencedAbsent) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
AddOneProxy Call;
- cantFail(buildProxies(
- ES,
- proxyInit<AddOneSpec>(&Call, SymbolLookupFlags::WeaklyReferencedSymbol)));
+ cantFail(
+ lookupAndApply(ES.getBootstrapJITDylib(),
+ {recordProxy<AddOneSpec>(
+ &Call, SymbolLookupFlags::WeaklyReferencedSymbol)}));
EXPECT_FALSE(static_cast<bool>(Call));
cantFail(ES.endSession());
diff --git a/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
index 723b65337ba61..c1e51983f8950 100644
--- a/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/ExecutionEngine/Orc/BUILD.gn
@@ -54,6 +54,7 @@ static_library("Orc") {
"LinkGraphLayer.cpp",
"LinkGraphLinkingLayer.cpp",
"LoadLinkableFile.cpp",
+ "LookupAndApply.cpp",
"LookupAndRecordAddrs.cpp",
"MachO.cpp",
"MachOPlatform.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
index 5659ddfea45e0..285d2dcffb6fa 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
@@ -29,6 +29,7 @@ unittest("OrcJITTests") {
"LazyCallThroughAndReexportsTest.cpp",
"LibraryResolverTest.cpp",
"LinkGraphLinkingLayerTest.cpp",
+ "LookupAndApplyTest.cpp",
"LookupAndRecordAddrsTest.cpp",
"MachOBuilderTest.cpp",
"MachOPlatformTest.cpp",
More information about the llvm-commits
mailing list