xref: /wasmtime-44.0.1/crates/c-api/tests/func.cc (revision adff9d9d)
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