Skip to content

Commit c9ebc89

Browse files
authored
[ORC] Add void function support to CallViaEPC, CallSPSViaEPC. (#170800)
Adds support for calling void functions. Calls to void functions return Error to capture any IPC/RPC failure.
1 parent 7220268 commit c9ebc89

File tree

3 files changed

+80
-20
lines changed

3 files changed

+80
-20
lines changed

llvm/include/llvm/ExecutionEngine/Orc/CallSPSViaEPC.h

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,13 @@
2020
namespace llvm::orc {
2121

2222
namespace detail {
23-
template <typename RetT, typename... ArgTs> struct SPSCallSerializationImpl {
24-
using RetSerialization = shared::SPSArgList<RetT>;
25-
using ArgSerialization = shared::SPSArgList<ArgTs...>;
26-
};
27-
} // namespace detail
28-
29-
template <typename SPSSig>
30-
struct SPSCallSerialization
31-
: public CallableTraitsHelper<detail::SPSCallSerializationImpl, SPSSig> {};
23+
template <typename SPSRetT, typename... SPSArgTs>
24+
struct SPSCallSerializationImpl {
25+
using RetSerialization = shared::SPSArgList<SPSRetT>;
26+
using ArgSerialization = shared::SPSArgList<SPSArgTs...>;
3227

33-
template <typename SPSSig> class SPSCallSerializer {
34-
public:
3528
template <typename... ArgTs>
3629
Expected<shared::WrapperFunctionResult> serialize(ArgTs &&...Args) {
37-
using ArgSerialization =
38-
typename SPSCallSerialization<SPSSig>::ArgSerialization;
3930
auto Buffer = shared::WrapperFunctionResult::allocate(
4031
ArgSerialization::size(Args...));
4132
shared::SPSOutputBuffer OB(Buffer.data(), Buffer.size());
@@ -44,11 +35,22 @@ template <typename SPSSig> class SPSCallSerializer {
4435
inconvertibleErrorCode());
4536
return std::move(Buffer);
4637
}
38+
};
39+
40+
template <typename SPSSig>
41+
struct SPSCallSerialization
42+
: public CallableTraitsHelper<detail::SPSCallSerializationImpl, SPSSig> {};
43+
44+
} // namespace detail
45+
46+
/// SPS serialization for non-void calls.
47+
template <typename SPSSig>
48+
struct SPSCallSerializer : public detail::SPSCallSerialization<SPSSig> {
4749

4850
template <typename RetT>
4951
Expected<RetT> deserialize(shared::WrapperFunctionResult ResultBytes) {
5052
using RetDeserialization =
51-
typename SPSCallSerialization<SPSSig>::RetSerialization;
53+
typename detail::SPSCallSerialization<SPSSig>::RetSerialization;
5254
shared::SPSInputBuffer IB(ResultBytes.data(), ResultBytes.size());
5355
RetT ReturnValue;
5456
if (!RetDeserialization::deserialize(IB, ReturnValue))
@@ -58,6 +60,20 @@ template <typename SPSSig> class SPSCallSerializer {
5860
}
5961
};
6062

63+
/// SPS serialization for void calls.
64+
template <typename... SPSArgTs>
65+
struct SPSCallSerializer<void(SPSArgTs...)>
66+
: public detail::SPSCallSerialization<void(SPSArgTs...)> {
67+
template <typename RetT>
68+
std::enable_if_t<std::is_void_v<RetT>, Error>
69+
deserialize(shared::WrapperFunctionResult ResultBytes) {
70+
if (!ResultBytes.empty())
71+
return make_error<StringError>("Could not deserialize return value",
72+
inconvertibleErrorCode());
73+
return Error::success();
74+
}
75+
};
76+
6177
template <typename SPSSig>
6278
class SPSEPCCaller : public EPCCaller<SPSCallSerializer<SPSSig>> {
6379
public:

llvm/include/llvm/ExecutionEngine/Orc/CallViaEPC.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,33 @@ namespace llvm::orc {
2525

2626
namespace detail {
2727

28-
// Helper to extract the Expected<T> argument type from a handler callable.
29-
template <typename HandlerT> struct HandlerTraits {
28+
template <typename HandlerArgT> struct CallViaEPCRetValueTraits;
29+
30+
template <typename RetT> struct CallViaEPCRetValueTraits<Expected<RetT>> {
31+
using value_type = RetT;
32+
};
33+
34+
template <> struct CallViaEPCRetValueTraits<Error> {
35+
using value_type = void;
36+
};
37+
38+
template <typename RetT> struct CallViaEPCRetValueTraits<MSVCPExpected<RetT>> {
39+
using value_type = RetT;
40+
};
41+
42+
template <> struct CallViaEPCRetValueTraits<MSVCPError> {
43+
using value_type = void;
44+
};
45+
46+
// Helper to extract the argument type from a handler callable.
47+
template <typename HandlerT> struct CallViaEPCHandlerTraits {
3048
using ArgInfo = CallableArgInfo<HandlerT>;
3149
using ArgsTuple = typename ArgInfo::ArgsTupleType;
3250
static_assert(std::tuple_size_v<ArgsTuple> == 1,
3351
"Handler must take exactly one argument");
34-
using ExpectedArgType = std::tuple_element_t<0, ArgsTuple>;
35-
using RetT = typename std::remove_cv_t<
36-
std::remove_reference_t<ExpectedArgType>>::value_type;
52+
using HandlerArgT = std::tuple_element_t<0, ArgsTuple>;
53+
using RetT = typename CallViaEPCRetValueTraits<
54+
std::remove_cv_t<std::remove_reference_t<HandlerArgT>>>::value_type;
3755
};
3856

3957
} // namespace detail
@@ -43,7 +61,7 @@ template <typename HandlerFn, typename Serializer, typename... ArgTs>
4361
std::enable_if_t<std::is_invocable_v<HandlerFn, Error>>
4462
callViaEPC(HandlerFn &&H, ExecutorProcessControl &EPC, Serializer S,
4563
ExecutorSymbolDef Fn, ArgTs &&...Args) {
46-
using RetT = typename detail::HandlerTraits<HandlerFn>::RetT;
64+
using RetT = typename detail::CallViaEPCHandlerTraits<HandlerFn>::RetT;
4765

4866
if (auto ArgBytes = S.serialize(std::forward<ArgTs>(Args)...))
4967
EPC.callWrapperAsync(

llvm/unittests/ExecutionEngine/Orc/CallSPSViaEPCTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ using namespace llvm;
1919
using namespace llvm::orc;
2020
using namespace llvm::orc::shared;
2121

22+
static CWrapperFunctionResult voidWrapper(const char *ArgData, size_t ArgSize) {
23+
return WrapperFunction<void()>::handle(ArgData, ArgSize, []() {}).release();
24+
}
25+
2226
static CWrapperFunctionResult mainWrapper(const char *ArgData, size_t ArgSize) {
2327
return WrapperFunction<int32_t(SPSSequence<SPSString>)>::handle(
2428
ArgData, ArgSize,
@@ -28,6 +32,28 @@ static CWrapperFunctionResult mainWrapper(const char *ArgData, size_t ArgSize) {
2832
.release();
2933
}
3034

35+
TEST(CallSPSViaEPCTest, CallVoidViaCallerAsync) {
36+
auto EPC = cantFail(SelfExecutorProcessControl::Create());
37+
SPSEPCCaller<void()> C(*EPC);
38+
39+
Error Err = Error::success();
40+
{
41+
ErrorAsOutParameter _(Err);
42+
C([&](Error E) { Err = std::move(E); },
43+
ExecutorSymbolDef::fromPtr(voidWrapper));
44+
}
45+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
46+
}
47+
48+
TEST(CallSPSViaEPCTest, CallVoidViaCallerSync) {
49+
auto EPC = cantFail(SelfExecutorProcessControl::Create());
50+
SPSEPCCaller<void()> C(*EPC);
51+
52+
Error Err =
53+
C(std::promise<MSVCPError>(), ExecutorSymbolDef::fromPtr(voidWrapper));
54+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
55+
}
56+
3157
TEST(CallSPSViaEPCTest, CallMainViaCallerAsync) {
3258
auto EPC = cantFail(SelfExecutorProcessControl::Create());
3359
SPSEPCCaller<int32_t(SPSSequence<SPSString>)> C(*EPC);

0 commit comments

Comments
 (0)