1 #include <wasmtime/func.hh>
2
3 #include <gtest/gtest.h>
4 #include <wasmtime.hh>
5
6 using namespace wasmtime;
7 using empty_t = std::tuple<>;
8
TEST(TypedFunc,Smoke)9 TEST(TypedFunc, Smoke) {
10 Engine engine;
11 Store store(engine);
12 Func thunk(
13 store, FuncType({}, {}),
14 [](auto caller, auto params, auto results) { return std::monostate(); });
15
16 EXPECT_FALSE((thunk.typed<int, int>(store)));
17 EXPECT_FALSE((thunk.typed<float, std::tuple<int32_t, uint32_t>>(store)));
18 EXPECT_FALSE((thunk.typed<float, empty_t>(store)));
19 EXPECT_TRUE((thunk.typed<empty_t, empty_t>(store)));
20
21 Func pi32(
22 store, FuncType({ValKind::I32}, {}),
23 [](auto caller, auto params, auto results) { return std::monostate(); });
24
25 EXPECT_FALSE((pi32.typed<float, empty_t>(store)));
26 EXPECT_TRUE((pi32.typed<std::tuple<int32_t>, empty_t>(store)));
27 EXPECT_TRUE((pi32.typed<int32_t, empty_t>(store)));
28 EXPECT_TRUE((pi32.typed<std::tuple<uint32_t>, empty_t>(store)));
29 EXPECT_TRUE((pi32.typed<uint32_t, empty_t>(store)));
30
31 Func rets(
32 store, FuncType({}, {ValKind::F32, ValKind::F64}),
33 [](auto caller, auto params, auto results) { return std::monostate(); });
34
35 EXPECT_FALSE((rets.typed<empty_t, std::tuple<int, int>>(store)));
36 EXPECT_FALSE((rets.typed<empty_t, empty_t>(store)));
37 EXPECT_TRUE((rets.typed<empty_t, std::tuple<float, double>>(store)));
38 }
39
TEST(TypedFunc,Call)40 TEST(TypedFunc, Call) {
41 Engine engine;
42 Store store(engine);
43
44 {
45 Func thunk(store, FuncType({}, {}),
46 [](auto caller, auto params, auto results) {
47 return std::monostate();
48 });
49 auto func = thunk.typed<empty_t, empty_t>(store).unwrap();
50 empty_t result = func.call(store, empty_t()).unwrap();
51 }
52
53 {
54 Func f(store, FuncType({ValKind::I32}, {}),
55 [](auto caller, auto params, auto results) {
56 EXPECT_EQ(params[0].i32(), 1);
57 return std::monostate();
58 });
59
60 f.typed<int32_t, empty_t>(store).unwrap().call(store, 1).unwrap();
61 f.typed<std::tuple<int32_t>, empty_t>(store)
62 .unwrap()
63 .call(store, {1})
64 .unwrap();
65 }
66 {
67 Func f(store,
68 FuncType({ValKind::F32, ValKind::I64}, {ValKind::I32, ValKind::F64}),
69 [](auto caller, auto params, auto results) {
70 EXPECT_EQ(params[0].f32(), 1);
71 EXPECT_EQ(params[1].i64(), 2);
72 results[0] = int32_t(3);
73 results[1] = double(4);
74 return std::monostate();
75 });
76
77 auto func =
78 f.typed<std::tuple<float, uint64_t>, std::tuple<uint32_t, double>>(
79 store)
80 .unwrap();
81 auto result = func.call(store, {1, 2}).unwrap();
82 EXPECT_EQ(std::get<0>(result), 3);
83 EXPECT_EQ(std::get<1>(result), 4);
84 }
85
86 {
87 FuncType ty({ValKind::ExternRef, ValKind::ExternRef},
88 {ValKind::ExternRef, ValKind::ExternRef});
89 Func f(store, ty, [](auto caller, auto params, auto results) {
90 caller.context().gc();
91 EXPECT_TRUE(params[0].externref());
92 EXPECT_EQ(std::any_cast<int>(params[0].externref()->data(caller)), 100);
93 EXPECT_FALSE(params[1].externref());
94 results[0] = ExternRef(caller, int(3));
95 results[1] = std::optional<ExternRef>(std::nullopt);
96 caller.context().gc();
97 return std::monostate();
98 });
99
100 using ExternRefPair =
101 std::tuple<std::optional<ExternRef>, std::optional<ExternRef>>;
102 auto func = f.typed<ExternRefPair, ExternRefPair>(store).unwrap();
103 auto result =
104 func.call(store, {ExternRef(store, int(100)), std::nullopt}).unwrap();
105 store.context().gc();
106 EXPECT_EQ(std::any_cast<int>(std::get<0>(result)->data(store)), 3);
107 EXPECT_EQ(std::get<1>(result), std::nullopt);
108 }
109
110 {
111 Func f2(store, FuncType({}, {}),
112 [](auto caller, auto params, auto results) {
113 return std::monostate();
114 });
115
116 FuncType ty({ValKind::FuncRef, ValKind::FuncRef},
117 {ValKind::FuncRef, ValKind::FuncRef});
118
119 Func f(store, ty, [&](auto caller, auto params, auto results) {
120 EXPECT_TRUE(params[0].funcref());
121 Func param = *params[0].funcref();
122 param.typed<empty_t, empty_t>(caller)
123 .unwrap()
124 .call(caller, empty_t())
125 .unwrap();
126 EXPECT_FALSE(params[1].funcref());
127 results[0] = f2;
128 results[1] = std::optional<Func>(std::nullopt);
129 return std::monostate();
130 });
131
132 using FuncPair = std::tuple<std::optional<Func>, std::optional<Func>>;
133 auto func = f.typed<FuncPair, FuncPair>(store).unwrap();
134 auto result = func.call(store, {f2, std::nullopt}).unwrap();
135 /* EXPECT_EQ(std::any_cast<int>(std::get<0>(result)->data()), 3); */
136 Func result_f = *std::get<0>(result);
137 result_f.typed<empty_t, empty_t>(store)
138 .unwrap()
139 .call(store, empty_t())
140 .unwrap();
141 EXPECT_EQ(std::get<1>(result), std::nullopt);
142 }
143
144 {
145 FuncType ty({ValKind::V128}, {ValKind::V128});
146
147 Func f(store, ty, [&](auto caller, auto params, auto results) {
148 V128 ret;
149 for (int i = 0; i < 16; i++) {
150 EXPECT_EQ(params[0].v128().v128[i], 1);
151 ret.v128[i] = 2;
152 }
153 results[0] = ret;
154 return std::monostate();
155 });
156
157 V128 param;
158 for (int i = 0; i < 16; i++) {
159 param.v128[i] = 1;
160 }
161 auto func = f.typed<V128, V128>(store).unwrap();
162 auto result = func.call(store, {param}).unwrap();
163 for (int i = 0; i < 16; i++) {
164 EXPECT_EQ(result.v128[i], 2);
165 }
166 }
167 }
168
assert_types_eq(ValType::ListRef actual,std::initializer_list<ValKind> expected)169 void assert_types_eq(ValType::ListRef actual,
170 std::initializer_list<ValKind> expected) {
171 EXPECT_EQ(expected.size(), actual.size());
172 std::vector<ValKind> actual_vec;
173 for (auto ty : actual) {
174 actual_vec.push_back(ty.kind());
175 }
176 std::vector<ValKind> expected_vec(expected);
177 EXPECT_EQ(actual_vec, expected_vec);
178 }
179
assert_func_type(FuncType actual,std::initializer_list<ValKind> params,std::initializer_list<ValKind> results)180 void assert_func_type(FuncType actual, std::initializer_list<ValKind> params,
181 std::initializer_list<ValKind> results) {
182 assert_types_eq(actual->params(), params);
183 assert_types_eq(actual->results(), results);
184 }
185
TEST(TypedFunc,WrapAndTypes)186 TEST(TypedFunc, WrapAndTypes) {
187 Engine engine;
188 Store store(engine);
189 Func f = Func::wrap(store, []() {});
190 assert_func_type(f.type(store), {}, {});
191 f = Func::wrap(store, []() { return int32_t(1); });
192 assert_func_type(f.type(store), {}, {ValKind::I32});
193 f = Func::wrap(store, []() { return int64_t(1); });
194 assert_func_type(f.type(store), {}, {ValKind::I64});
195 f = Func::wrap(store, []() { return float(1); });
196 assert_func_type(f.type(store), {}, {ValKind::F32});
197 f = Func::wrap(store, []() { return double(1); });
198 assert_func_type(f.type(store), {}, {ValKind::F64});
199 f = Func::wrap(store, []() { return V128(); });
200 assert_func_type(f.type(store), {}, {ValKind::V128});
201 f = Func::wrap(store,
202 []() { return std::make_tuple(int32_t(1), int32_t(2)); });
203 assert_func_type(f.type(store), {}, {ValKind::I32, ValKind::I32});
204 f = Func::wrap(store, []() { return std::optional<Func>(std::nullopt); });
205 assert_func_type(f.type(store), {}, {ValKind::FuncRef});
206 f = Func::wrap(store,
207 []() { return std::optional<ExternRef>(std::nullopt); });
208 assert_func_type(f.type(store), {}, {ValKind::ExternRef});
209 f = Func::wrap(
210 store, []() { return Result<std::monostate, Trap>(std::monostate()); });
211 assert_func_type(f.type(store), {}, {});
212 f = Func::wrap(store, []() { return Result<int32_t, Trap>(1); });
213 assert_func_type(f.type(store), {}, {ValKind::I32});
214 f = Func::wrap(store, []() { return Result<float, Trap>(1); });
215 assert_func_type(f.type(store), {}, {ValKind::F32});
216 f = Func::wrap(store, []() {
217 return Result<std::tuple<int32_t, int32_t>, Trap>({1, 2});
218 });
219 assert_func_type(f.type(store), {}, {ValKind::I32, ValKind::I32});
220
221 f = Func::wrap(store, [](int32_t a) {});
222 assert_func_type(f.type(store), {ValKind::I32}, {});
223 f = Func::wrap(store, [](int64_t a) {});
224 assert_func_type(f.type(store), {ValKind::I64}, {});
225 f = Func::wrap(store, [](float a) {});
226 assert_func_type(f.type(store), {ValKind::F32}, {});
227 f = Func::wrap(store, [](double a) {});
228 assert_func_type(f.type(store), {ValKind::F64}, {});
229 f = Func::wrap(store, [](V128 a) {});
230 assert_func_type(f.type(store), {ValKind::V128}, {});
231 f = Func::wrap(store, [](std::optional<Func> a) {});
232 assert_func_type(f.type(store), {ValKind::FuncRef}, {});
233 f = Func::wrap(store, [](std::optional<ExternRef> a) {});
234 assert_func_type(f.type(store), {ValKind::ExternRef}, {});
235 f = Func::wrap(store, [](Caller a) {});
236 assert_func_type(f.type(store), {}, {});
237 f = Func::wrap(store, [](Caller a, int32_t b) {});
238 assert_func_type(f.type(store), {ValKind::I32}, {});
239 }
240
TEST(TypedFunc,WrapRuntime)241 TEST(TypedFunc, WrapRuntime) {
242 Engine engine;
243 Store store(engine);
244 Func f = Func::wrap(store, []() {});
245 f.typed<empty_t, empty_t>(store).unwrap().call(store, empty_t()).unwrap();
246
247 f = Func::wrap(store, []() { return int32_t(1); });
248 int32_t i =
249 f.typed<empty_t, int32_t>(store).unwrap().call(store, empty_t()).unwrap();
250 EXPECT_EQ(i, 1);
251
252 f = Func::wrap(store, [](Caller cx, int32_t i) { EXPECT_EQ(i, 2); });
253 f.typed<int32_t, empty_t>(store).unwrap().call(store, 2).unwrap();
254
255 f = Func::wrap(store, [](Caller cx, int32_t i, int32_t j) { return i + j; });
256 auto ret = f.typed<std::tuple<int32_t, int32_t>, int32_t>(store)
257 .unwrap()
258 .call(store, {1, 2})
259 .unwrap();
260 EXPECT_EQ(ret, 3);
261 }
262