1da592413SLang Hames //===-- wrapper_function_utils_test.cpp -----------------------------------===//
2da592413SLang Hames //
3da592413SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4da592413SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5da592413SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6da592413SLang Hames //
7da592413SLang Hames //===----------------------------------------------------------------------===//
8da592413SLang Hames //
9da592413SLang Hames // This file is a part of the ORC runtime.
10da592413SLang Hames //
11da592413SLang Hames //===----------------------------------------------------------------------===//
12da592413SLang Hames
13da592413SLang Hames #include "wrapper_function_utils.h"
14da592413SLang Hames #include "gtest/gtest.h"
15da592413SLang Hames
16da592413SLang Hames using namespace __orc_rt;
17da592413SLang Hames
18da592413SLang Hames namespace {
19da592413SLang Hames constexpr const char *TestString = "test string";
20da592413SLang Hames } // end anonymous namespace
21da592413SLang Hames
TEST(WrapperFunctionUtilsTest,DefaultWrapperFunctionResult)22da592413SLang Hames TEST(WrapperFunctionUtilsTest, DefaultWrapperFunctionResult) {
23da592413SLang Hames WrapperFunctionResult R;
24da592413SLang Hames EXPECT_TRUE(R.empty());
25da592413SLang Hames EXPECT_EQ(R.size(), 0U);
26da592413SLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
27da592413SLang Hames }
28da592413SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromCStruct)29da592413SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCStruct) {
30da592413SLang Hames __orc_rt_CWrapperFunctionResult CR =
31da592413SLang Hames __orc_rt_CreateCWrapperFunctionResultFromString(TestString);
32da592413SLang Hames WrapperFunctionResult R(CR);
33da592413SLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
34da592413SLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
35da592413SLang Hames EXPECT_FALSE(R.empty());
36da592413SLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
37da592413SLang Hames }
38da592413SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromRange)39da592413SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromRange) {
40da592413SLang Hames auto R = WrapperFunctionResult::copyFrom(TestString, strlen(TestString) + 1);
41da592413SLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
42da592413SLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
43da592413SLang Hames EXPECT_FALSE(R.empty());
44da592413SLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
45da592413SLang Hames }
46da592413SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromCString)47da592413SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCString) {
48da592413SLang Hames auto R = WrapperFunctionResult::copyFrom(TestString);
49da592413SLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
50da592413SLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
51da592413SLang Hames EXPECT_FALSE(R.empty());
52da592413SLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
53da592413SLang Hames }
54da592413SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromStdString)55da592413SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromStdString) {
56da592413SLang Hames auto R = WrapperFunctionResult::copyFrom(std::string(TestString));
57da592413SLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
58da592413SLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
59da592413SLang Hames EXPECT_FALSE(R.empty());
60da592413SLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
61da592413SLang Hames }
62da592413SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromOutOfBandError)63da592413SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromOutOfBandError) {
64da592413SLang Hames auto R = WrapperFunctionResult::createOutOfBandError(TestString);
65da592413SLang Hames EXPECT_FALSE(R.empty());
66da592413SLang Hames EXPECT_TRUE(strcmp(R.getOutOfBandError(), TestString) == 0);
67da592413SLang Hames }
68da592413SLang Hames
voidNoop()6968c16109SLang Hames static void voidNoop() {}
7068c16109SLang Hames
voidNoopWrapper(const char * ArgData,size_t ArgSize)7168c16109SLang Hames static __orc_rt_CWrapperFunctionResult voidNoopWrapper(const char *ArgData,
7268c16109SLang Hames size_t ArgSize) {
7368c16109SLang Hames return WrapperFunction<void()>::handle(ArgData, ArgSize, voidNoop).release();
7468c16109SLang Hames }
7568c16109SLang Hames
addWrapper(const char * ArgData,size_t ArgSize)76da592413SLang Hames static __orc_rt_CWrapperFunctionResult addWrapper(const char *ArgData,
77da592413SLang Hames size_t ArgSize) {
78da592413SLang Hames return WrapperFunction<int32_t(int32_t, int32_t)>::handle(
79da592413SLang Hames ArgData, ArgSize,
80da592413SLang Hames [](int32_t X, int32_t Y) -> int32_t { return X + Y; })
81da592413SLang Hames .release();
82da592413SLang Hames }
83da592413SLang Hames
84da592413SLang Hames extern "C" __orc_rt_Opaque __orc_rt_jit_dispatch_ctx{};
85da592413SLang Hames
86da592413SLang Hames extern "C" __orc_rt_CWrapperFunctionResult
__orc_rt_jit_dispatch(__orc_rt_Opaque * Ctx,const void * FnTag,const char * ArgData,size_t ArgSize)87da592413SLang Hames __orc_rt_jit_dispatch(__orc_rt_Opaque *Ctx, const void *FnTag,
88da592413SLang Hames const char *ArgData, size_t ArgSize) {
89da592413SLang Hames using WrapperFunctionType =
90da592413SLang Hames __orc_rt_CWrapperFunctionResult (*)(const char *, size_t);
91da592413SLang Hames
92da592413SLang Hames return reinterpret_cast<WrapperFunctionType>(const_cast<void *>(FnTag))(
93da592413SLang Hames ArgData, ArgSize);
94da592413SLang Hames }
95da592413SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallVoidNoopAndHandle)9668c16109SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallVoidNoopAndHandle) {
9768c16109SLang Hames EXPECT_FALSE(!!WrapperFunction<void()>::call((void *)&voidNoopWrapper));
9868c16109SLang Hames }
9968c16109SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallAddWrapperAndHandle)10068c16109SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAddWrapperAndHandle) {
101da592413SLang Hames int32_t Result;
102da592413SLang Hames EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call(
103da592413SLang Hames (void *)&addWrapper, Result, 1, 2));
104da592413SLang Hames EXPECT_EQ(Result, (int32_t)3);
105da592413SLang Hames }
106b574c52dSLang Hames
107b574c52dSLang Hames class AddClass {
108b574c52dSLang Hames public:
AddClass(int32_t X)109b574c52dSLang Hames AddClass(int32_t X) : X(X) {}
addMethod(int32_t Y)110b574c52dSLang Hames int32_t addMethod(int32_t Y) { return X + Y; }
111b574c52dSLang Hames
112b574c52dSLang Hames private:
113b574c52dSLang Hames int32_t X;
114b574c52dSLang Hames };
115b574c52dSLang Hames
addMethodWrapper(const char * ArgData,size_t ArgSize)116b574c52dSLang Hames static __orc_rt_CWrapperFunctionResult addMethodWrapper(const char *ArgData,
117b574c52dSLang Hames size_t ArgSize) {
118b574c52dSLang Hames return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle(
119b574c52dSLang Hames ArgData, ArgSize, makeMethodWrapperHandler(&AddClass::addMethod))
120b574c52dSLang Hames .release();
121b574c52dSLang Hames }
122b574c52dSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionMethodCallAndHandleRet)123b574c52dSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionMethodCallAndHandleRet) {
124b574c52dSLang Hames int32_t Result;
125b574c52dSLang Hames AddClass AddObj(1);
126b574c52dSLang Hames EXPECT_FALSE(!!WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::call(
127b574c52dSLang Hames (void *)&addMethodWrapper, Result, ExecutorAddr::fromPtr(&AddObj), 2));
128b574c52dSLang Hames EXPECT_EQ(Result, (int32_t)3);
129b574c52dSLang Hames }
130dc8e5e1dSLang Hames
sumArrayWrapper(const char * ArgData,size_t ArgSize)131*0ede1b90SLang Hames static __orc_rt_CWrapperFunctionResult sumArrayWrapper(const char *ArgData,
132dc8e5e1dSLang Hames size_t ArgSize) {
133*0ede1b90SLang Hames return WrapperFunction<int8_t(SPSExecutorAddrRange)>::handle(
134*0ede1b90SLang Hames ArgData, ArgSize,
135*0ede1b90SLang Hames [](ExecutorAddrRange R) {
136*0ede1b90SLang Hames int8_t Sum = 0;
137*0ede1b90SLang Hames for (char C : R.toSpan<char>())
138*0ede1b90SLang Hames Sum += C;
139*0ede1b90SLang Hames return Sum;
140*0ede1b90SLang Hames })
141*0ede1b90SLang Hames .release();
142dc8e5e1dSLang Hames }
143dc8e5e1dSLang Hames
TEST(WrapperFunctionUtilsTest,SerializedWrapperFunctionCallTest)144dc8e5e1dSLang Hames TEST(WrapperFunctionUtilsTest, SerializedWrapperFunctionCallTest) {
145dc8e5e1dSLang Hames {
146*0ede1b90SLang Hames // Check wrapper function calls.
147dc8e5e1dSLang Hames char A[] = {1, 2, 3, 4};
148dc8e5e1dSLang Hames
149*0ede1b90SLang Hames auto WFC =
150*0ede1b90SLang Hames cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
151*0ede1b90SLang Hames ExecutorAddr::fromPtr(sumArrayWrapper),
152dc8e5e1dSLang Hames ExecutorAddrRange(ExecutorAddr::fromPtr(A),
153*0ede1b90SLang Hames ExecutorAddrDiff(sizeof(A)))));
154dc8e5e1dSLang Hames
155dc8e5e1dSLang Hames WrapperFunctionResult WFR(WFC.run());
156dc8e5e1dSLang Hames EXPECT_EQ(WFR.size(), 1U);
157dc8e5e1dSLang Hames EXPECT_EQ(WFR.data()[0], 10);
158dc8e5e1dSLang Hames }
159dc8e5e1dSLang Hames
160dc8e5e1dSLang Hames {
161dc8e5e1dSLang Hames // Check calls to void functions.
162*0ede1b90SLang Hames auto WFC =
163*0ede1b90SLang Hames cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
164*0ede1b90SLang Hames ExecutorAddr::fromPtr(voidNoopWrapper), ExecutorAddrRange()));
165*0ede1b90SLang Hames auto Err = WFC.runWithSPSRet<void>();
166dc8e5e1dSLang Hames EXPECT_FALSE(!!Err);
167dc8e5e1dSLang Hames }
168dc8e5e1dSLang Hames
169dc8e5e1dSLang Hames {
170dc8e5e1dSLang Hames // Check calls with arguments and return values.
171*0ede1b90SLang Hames auto WFC =
172*0ede1b90SLang Hames cantFail(WrapperFunctionCall::Create<SPSArgList<int32_t, int32_t>>(
173*0ede1b90SLang Hames ExecutorAddr::fromPtr(addWrapper), 2, 4));
174dc8e5e1dSLang Hames
175dc8e5e1dSLang Hames int32_t Result = 0;
176dc8e5e1dSLang Hames auto Err = WFC.runWithSPSRet<int32_t>(Result);
177dc8e5e1dSLang Hames EXPECT_FALSE(!!Err);
178dc8e5e1dSLang Hames EXPECT_EQ(Result, 6);
179dc8e5e1dSLang Hames }
180dc8e5e1dSLang Hames }
181