[orc-rt] Add C API for Session::callController. (#212204)

Add orc-rt-c/Session.h with a C API, orc_rt_Session_callController,
wrapping the C++ Session::callController method.
This commit is contained in:
Lang Hames 2026-07-27 21:06:19 +10:00 committed by GitHub
parent 9facc23846
commit cd653d5916
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 99 additions and 0 deletions

View file

@ -0,0 +1,34 @@
/*===----------- Session.h - ORC Runtime Session C APIs -----------*- 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 *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* ORC Runtime Session C APIs. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef ORC_RT_C_SESSION_H
#define ORC_RT_C_SESSION_H
#include "orc-rt-c/Compiler.h"
#include "orc-rt-c/CoreTypes.h"
#include "orc-rt-c/WrapperFunction.h"
ORC_RT_C_EXTERN_C_BEGIN
typedef void (*orc_rt_Session_CallControllerReturn)(
orc_rt_SessionRef S, orc_rt_WrapperFunctionBuffer ResultBytes, void *Ctx);
void orc_rt_Session_callController(orc_rt_SessionRef S,
orc_rt_ControllerHandlerTag T,
orc_rt_WrapperFunctionBuffer ArgBytes,
orc_rt_Session_CallControllerReturn Return,
void *ReturnCtx);
ORC_RT_C_EXTERN_C_END
#endif /* ORC_RT_C_SESSION_H */

View file

@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "orc-rt/Session.h"
#include "orc-rt-c/Session.h"
namespace orc_rt {
@ -370,4 +371,17 @@ void Session::wrapperReturn(orc_rt_SessionRef S, uint64_t CallId,
unwrap(S)->sendWrapperResult(CallId, WrapperFunctionBuffer(ResultBytes));
}
// --- C API Implementation ---
extern "C" void orc_rt_Session_callController(
orc_rt_SessionRef S, orc_rt_ControllerHandlerTag T,
orc_rt_WrapperFunctionBuffer ArgBytes,
orc_rt_Session_CallControllerReturn Return, void *ReturnCtx) {
unwrap(S)->callController(
[S, Return, ReturnCtx](WrapperFunctionBuffer ResultBytes) {
Return(S, ResultBytes.release(), ReturnCtx);
},
T, WrapperFunctionBuffer(ArgBytes));
}
} // namespace orc_rt

View file

@ -14,6 +14,8 @@
#include "orc-rt/QueueingRunner.h"
#include "orc-rt/SPSWrapperFunction.h"
#include "orc-rt-c/Session.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@ -674,6 +676,55 @@ static void add_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,
});
}
// Wrapper handler that echoes its argument bytes straight back as the result.
// Used to exercise the C callController entry point without pulling in SPS
// (de)serialization -- the payload is opaque to the code under test.
static void echo_wrapper(orc_rt_SessionRef S, uint64_t CallId,
orc_rt_WrapperFunctionReturn Return,
orc_rt_WrapperFunctionBuffer ArgBytes) {
Return(S, CallId, ArgBytes);
}
// Captures what orc_rt_Session_callController threads back to its C return
// function, so the test can inspect it after the call completes.
struct CAPICallControllerResult {
bool Ran = false;
orc_rt_SessionRef S = nullptr;
std::string Result;
};
static void capiCallControllerReturn(orc_rt_SessionRef S,
orc_rt_WrapperFunctionBuffer ResultBytes,
void *Ctx) {
auto &R = *static_cast<CAPICallControllerResult *>(Ctx);
R.Ran = true;
R.S = S;
WrapperFunctionBuffer Result(ResultBytes);
R.Result.assign(Result.data(), Result.size());
}
TEST(ControllerAccessTest, CAPICallControllerRoundTrip) {
// Drive a controller call through the C API entry point
// (orc_rt_Session_callController) and confirm that the result bytes, the
// session handle, and the caller-supplied context are all threaded back to
// the C return function.
QueueingRunner<>::WorkQueue Tasks;
Session S(mockExecutorProcessInfo(), QueueingRunner(Tasks), noErrors);
S.attach<MockControllerAccess>(BootstrapInfo(S), postOnto(Tasks));
CAPICallControllerResult R;
orc_rt_Session_callController(
wrap(&S), reinterpret_cast<orc_rt_ControllerHandlerTag>(&echo_wrapper),
WrapperFunctionBuffer::copyFrom("hello", 5).release(),
&capiCallControllerReturn, &R);
QueueingRunner<>::runFIFOUntilEmpty(Tasks);
EXPECT_TRUE(R.Ran) << "C return function never fired";
EXPECT_EQ(R.S, wrap(&S)) << "Session handle not threaded through";
EXPECT_EQ(R.Result, "hello") << "Result bytes not round-tripped";
}
TEST(ControllerAccessTest, ValidCallToController) {
// Simulate a call to a controller handler.
QueueingRunner<>::WorkQueue Tasks;