[llvm] [ORC] Generalize RTBridge Callers to any runtime function (PR #213526)
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 2 03:47:47 PDT 2026
https://github.com/lhames created https://github.com/llvm/llvm-project/pull/213526
An RTBridge Caller is a controller-side handle for calling a function in the runtime. Until now the abstraction assumed every such function was a trampoline -- a runtime function whose job is to invoke *another* function at an address the controller supplies (run-as-main, run-as-int, etc.) -- so every Caller carried a dedicated ExecutorAddr parameter for that target.
Generalize Callers to call runtime functions of any shape. Invoking a supplied target is now just one kind of call, with the target address an ordinary leading argument rather than a built-in parameter: e.g. MainCaller becomes Caller<int64_t(ExecutorAddr, ArrayRef<std::string>)>.
The SPS signatures already led with an SPSExecutorAddr for the target, so this is a pure interface change -- the SPS wrappers and all call sites are unaffected. It lets Callers model runtime functions that do the work themselves, such as the memory-access wrappers, rather than only those that dispatch to another function.
>From 42fea0be3ef6cc0709c064fc867f3c6620082616 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Sun, 2 Aug 2026 20:37:35 +1000
Subject: [PATCH] [ORC] Generalize RTBridge Callers to any runtime function
An RTBridge Caller is a controller-side handle for calling a function in
the runtime. Until now the abstraction assumed every such function was a
trampoline -- a runtime function whose job is to invoke *another* function
at an address the controller supplies (run-as-main, run-as-int, etc.) -- so
every Caller carried a dedicated ExecutorAddr parameter for that target.
Generalize Callers to call runtime functions of any shape. Invoking a
supplied target is now just one kind of call, with the target address an
ordinary leading argument rather than a built-in parameter: e.g. MainCaller
becomes Caller<int64_t(ExecutorAddr, ArrayRef<std::string>)>.
The SPS signatures already led with an SPSExecutorAddr for the target, so
this is a pure interface change -- the SPS wrappers and all call sites are
unaffected. It lets Callers model runtime functions that do the work
themselves, such as the memory-access wrappers, rather than only those that
dispatch to another function.
---
.../llvm/ExecutionEngine/Orc/RTBridge/Calls.h | 31 +++++++++----------
.../ExecutionEngine/Orc/RTBridge/SPS/Calls.h | 17 +++++-----
2 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Calls.h b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Calls.h
index 29cf268c71803..b49e6457754bf 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Calls.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/Calls.h
@@ -35,11 +35,9 @@ template <typename FnT> class Caller;
/// Runtime-agnostic interface for invoking an executor-side operation with the
/// signature RetT(ArgTs...).
///
-/// The operation is identified by an ExecutorAddr (the address of the
-/// executor-side function to invoke) and takes ArgTs... as arguments. Two call
-/// operators are provided: an asynchronous form that delivers the result to an
-/// OnComplete continuation, and a synchronous form that blocks until the result
-/// is available.
+/// Two call operators are provided: an asynchronous form that delivers the
+/// result to an OnComplete continuation, and a synchronous form that blocks
+/// until the result is available.
///
/// A Caller abstracts over how the operation is dispatched to the executor.
/// Concrete implementations (e.g. rt::sps::Caller) supply the dispatch
@@ -58,21 +56,21 @@ template <typename RetT, typename... ArgTs> class Caller<RetT(ArgTs...)> {
virtual ~Caller() = default;
- /// Asynchronously invoke the executor-side function at FnAddr with the given
- /// Args, delivering its result (or an error) to OnComplete.
+ /// Asynchronously invoke the operation with the given Args, delivering its
+ /// result (or an error) to OnComplete.
virtual void operator()(unique_function<void(ErrorRetT)> OnComplete,
- ExecutorAddr FnAddr, ArgTs... Args) = 0;
+ ArgTs... Args) = 0;
- /// Invoke the executor-side function at FnAddr with the given Args, blocking
- /// until its result (or an error) is available.
- ErrorRetT operator()(ExecutorAddr FnAddr, ArgTs &&...Args) {
+ /// Invoke the operation with the given Args, blocking until its result (or an
+ /// error) is available.
+ ErrorRetT operator()(ArgTs... Args) {
using PromiseValT = std::conditional_t<std::is_void_v<RetT>, MSVCPError,
MSVCPExpected<RetT>>;
std::promise<PromiseValT> P;
auto F = P.get_future();
this->operator()(
[P = std::move(P)](ErrorRetT R) mutable { P.set_value(std::move(R)); },
- FnAddr, std::forward<ArgTs>(Args)...);
+ std::move(Args)...);
return F.get();
}
};
@@ -82,14 +80,15 @@ template <typename RetT, typename... ArgTs> class Caller<RetT(ArgTs...)> {
///
/// The function to run is given by its ExecutorAddr, its arguments as an
/// argument vector, and its int64_t result is returned.
-class MainCaller : public Caller<int64_t(ArrayRef<std::string>)> {};
+class MainCaller : public Caller<int64_t(ExecutorAddr, ArrayRef<std::string>)> {
+};
/// Runtime-agnostic interface for running a void() function in the executor.
///
/// The function to run is given by its ExecutorAddr.
///
/// WARNING: This Caller is experimental and may be removed.
-class VoidVoidCaller : public Caller<void()> {};
+class VoidVoidCaller : public Caller<void(ExecutorAddr)> {};
/// Runtime-agnostic interface for running an int32_t() function in the
/// executor.
@@ -97,7 +96,7 @@ class VoidVoidCaller : public Caller<void()> {};
/// The function to run is given by its ExecutorAddr.
///
/// WARNING: This Caller is experimental and may be removed.
-class Int32VoidCaller : public Caller<int32_t()> {};
+class Int32VoidCaller : public Caller<int32_t(ExecutorAddr)> {};
/// Runtime-agnostic interface for running an int32_t(int32_t) function in the
/// executor.
@@ -105,7 +104,7 @@ class Int32VoidCaller : public Caller<int32_t()> {};
/// The function to run is given by its ExecutorAddr.
///
/// WARNING: This Caller is experimental and may be removed.
-class Int32Int32Caller : public Caller<int32_t(int32_t)> {};
+class Int32Int32Caller : public Caller<int32_t(ExecutorAddr, int32_t)> {};
} // namespace llvm::orc::rt
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/Calls.h b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/Calls.h
index d11cc16a7b7e7..4102327f5d394 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/Calls.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/RTBridge/SPS/Calls.h
@@ -64,13 +64,12 @@ class Caller<BaseT, SPSSigT, CINameV, RetT(ArgTs...)> : public BaseT {
return CallerSym.takeError();
}
- /// Asynchronously call the SPS wrapper at CallerFnAddr to invoke the
- /// executor-side function at FnAddr with the given Args, delivering the
- /// result (or an error) to OnComplete. Serialization failures are reported
- /// through OnComplete's error channel.
+ /// Asynchronously call the SPS wrapper at CallerFnAddr with the given Args,
+ /// delivering the result (or an error) to OnComplete. Serialization failures
+ /// are reported through OnComplete's error channel.
static void callAsync(unique_function<void(ErrorRetT)> OnComplete,
ExecutionSession &ES, ExecutorAddr CallerFnAddr,
- ExecutorAddr FnAddr, const ArgTs &...Args) {
+ const ArgTs &...Args) {
using namespace llvm::orc::shared;
if constexpr (std::is_void_v<CalleeRetT>) {
// Void result: the executor-side function produces no value, so the only
@@ -80,7 +79,7 @@ class Caller<BaseT, SPSSigT, CINameV, RetT(ArgTs...)> : public BaseT {
[OnComplete = std::move(OnComplete)](Error SerErr) mutable {
OnComplete(std::move(SerErr));
},
- FnAddr, Args...);
+ Args...);
} else {
ES.callSPSWrapperAsync<SPSSigT>(
CallerFnAddr,
@@ -91,13 +90,13 @@ class Caller<BaseT, SPSSigT, CINameV, RetT(ArgTs...)> : public BaseT {
else
return OnComplete(std::move(Result));
},
- FnAddr, Args...);
+ Args...);
}
}
void operator()(unique_function<void(ErrorRetT)> OnComplete,
- ExecutorAddr FnAddr, ArgTs... Args) override {
- callAsync(std::move(OnComplete), ES, CallerFnAddr, FnAddr, Args...);
+ ArgTs... Args) override {
+ callAsync(std::move(OnComplete), ES, CallerFnAddr, Args...);
}
using BaseT::operator();
More information about the llvm-commits
mailing list