xref: /wasmtime-44.0.1/crates/c-api/tests/func.cc (revision b3fa9bfa)
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 
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 
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(caller));
92       EXPECT_EQ(std::any_cast<int>(params[0].externref(caller)->data(caller)),
93                 100);
94       EXPECT_FALSE(params[1].externref(caller));
95       results[0] = ExternRef(caller, int(3));
96       results[1] = std::optional<ExternRef>(std::nullopt);
97       caller.context().gc();
98       return std::monostate();
99     });
100 
101     using ExternRefPair =
102         std::tuple<std::optional<ExternRef>, std::optional<ExternRef>>;
103     auto func = f.typed<ExternRefPair, ExternRefPair>(store).unwrap();
104     auto result =
105         func.call(store, {ExternRef(store, int(100)), std::nullopt}).unwrap();
106     store.context().gc();
107     EXPECT_EQ(std::any_cast<int>(std::get<0>(result)->data(store)), 3);
108     EXPECT_EQ(std::get<1>(result), std::nullopt);
109   }
110 
111   {
112     Func f2(store, FuncType({}, {}),
113             [](auto caller, auto params, auto results) {
114               return std::monostate();
115             });
116 
117     FuncType ty({ValKind::FuncRef, ValKind::FuncRef},
118                 {ValKind::FuncRef, ValKind::FuncRef});
119 
120     Func f(store, ty, [&](auto caller, auto params, auto results) {
121       EXPECT_TRUE(params[0].funcref());
122       Func param = *params[0].funcref();
123       param.typed<empty_t, empty_t>(caller)
124           .unwrap()
125           .call(caller, empty_t())
126           .unwrap();
127       EXPECT_FALSE(params[1].funcref());
128       results[0] = f2;
129       results[1] = std::optional<Func>(std::nullopt);
130       return std::monostate();
131     });
132 
133     using FuncPair = std::tuple<std::optional<Func>, std::optional<Func>>;
134     auto func = f.typed<FuncPair, FuncPair>(store).unwrap();
135     auto result = func.call(store, {f2, std::nullopt}).unwrap();
136     /* EXPECT_EQ(std::any_cast<int>(std::get<0>(result)->data()), 3); */
137     Func result_f = *std::get<0>(result);
138     result_f.typed<empty_t, empty_t>(store)
139         .unwrap()
140         .call(store, empty_t())
141         .unwrap();
142     EXPECT_EQ(std::get<1>(result), std::nullopt);
143   }
144 
145   {
146     FuncType ty({ValKind::V128}, {ValKind::V128});
147 
148     Func f(store, ty, [&](auto caller, auto params, auto results) {
149       V128 ret;
150       for (int i = 0; i < 16; i++) {
151         EXPECT_EQ(params[0].v128().v128[i], 1);
152         ret.v128[i] = 2;
153       }
154       results[0] = ret;
155       return std::monostate();
156     });
157 
158     V128 param;
159     for (int i = 0; i < 16; i++) {
160       param.v128[i] = 1;
161     }
162     auto func = f.typed<V128, V128>(store).unwrap();
163     auto result = func.call(store, {param}).unwrap();
164     for (int i = 0; i < 16; i++) {
165       EXPECT_EQ(result.v128[i], 2);
166     }
167   }
168 }
169 
170 void assert_types_eq(ValType::ListRef actual,
171                      std::initializer_list<ValKind> expected) {
172   EXPECT_EQ(expected.size(), actual.size());
173   std::vector<ValKind> actual_vec;
174   for (auto ty : actual) {
175     actual_vec.push_back(ty.kind());
176   }
177   std::vector<ValKind> expected_vec(expected);
178   EXPECT_EQ(actual_vec, expected_vec);
179 }
180 
181 void assert_func_type(FuncType actual, std::initializer_list<ValKind> params,
182                       std::initializer_list<ValKind> results) {
183   assert_types_eq(actual->params(), params);
184   assert_types_eq(actual->results(), results);
185 }
186 
187 TEST(TypedFunc, WrapAndTypes) {
188   Engine engine;
189   Store store(engine);
190   Func f = Func::wrap(store, []() {});
191   assert_func_type(f.type(store), {}, {});
192   f = Func::wrap(store, []() { return int32_t(1); });
193   assert_func_type(f.type(store), {}, {ValKind::I32});
194   f = Func::wrap(store, []() { return int64_t(1); });
195   assert_func_type(f.type(store), {}, {ValKind::I64});
196   f = Func::wrap(store, []() { return float(1); });
197   assert_func_type(f.type(store), {}, {ValKind::F32});
198   f = Func::wrap(store, []() { return double(1); });
199   assert_func_type(f.type(store), {}, {ValKind::F64});
200   f = Func::wrap(store, []() { return V128(); });
201   assert_func_type(f.type(store), {}, {ValKind::V128});
202   f = Func::wrap(store,
203                  []() { return std::make_tuple(int32_t(1), int32_t(2)); });
204   assert_func_type(f.type(store), {}, {ValKind::I32, ValKind::I32});
205   f = Func::wrap(store, []() { return std::optional<Func>(std::nullopt); });
206   assert_func_type(f.type(store), {}, {ValKind::FuncRef});
207   f = Func::wrap(store,
208                  []() { return std::optional<ExternRef>(std::nullopt); });
209   assert_func_type(f.type(store), {}, {ValKind::ExternRef});
210   f = Func::wrap(
211       store, []() { return Result<std::monostate, Trap>(std::monostate()); });
212   assert_func_type(f.type(store), {}, {});
213   f = Func::wrap(store, []() { return Result<int32_t, Trap>(1); });
214   assert_func_type(f.type(store), {}, {ValKind::I32});
215   f = Func::wrap(store, []() { return Result<float, Trap>(1); });
216   assert_func_type(f.type(store), {}, {ValKind::F32});
217   f = Func::wrap(store, []() {
218     return Result<std::tuple<int32_t, int32_t>, Trap>({1, 2});
219   });
220   assert_func_type(f.type(store), {}, {ValKind::I32, ValKind::I32});
221 
222   f = Func::wrap(store, [](int32_t a) {});
223   assert_func_type(f.type(store), {ValKind::I32}, {});
224   f = Func::wrap(store, [](int64_t a) {});
225   assert_func_type(f.type(store), {ValKind::I64}, {});
226   f = Func::wrap(store, [](float a) {});
227   assert_func_type(f.type(store), {ValKind::F32}, {});
228   f = Func::wrap(store, [](double a) {});
229   assert_func_type(f.type(store), {ValKind::F64}, {});
230   f = Func::wrap(store, [](V128 a) {});
231   assert_func_type(f.type(store), {ValKind::V128}, {});
232   f = Func::wrap(store, [](std::optional<Func> a) {});
233   assert_func_type(f.type(store), {ValKind::FuncRef}, {});
234   f = Func::wrap(store, [](std::optional<ExternRef> a) {});
235   assert_func_type(f.type(store), {ValKind::ExternRef}, {});
236   f = Func::wrap(store, [](Caller a) {});
237   assert_func_type(f.type(store), {}, {});
238   f = Func::wrap(store, [](Caller a, int32_t b) {});
239   assert_func_type(f.type(store), {ValKind::I32}, {});
240 }
241 
242 TEST(TypedFunc, WrapRuntime) {
243   Engine engine;
244   Store store(engine);
245   Func f = Func::wrap(store, []() {});
246   f.typed<empty_t, empty_t>(store).unwrap().call(store, empty_t()).unwrap();
247 
248   f = Func::wrap(store, []() { return int32_t(1); });
249   int32_t i =
250       f.typed<empty_t, int32_t>(store).unwrap().call(store, empty_t()).unwrap();
251   EXPECT_EQ(i, 1);
252 
253   f = Func::wrap(store, [](Caller cx, int32_t i) { EXPECT_EQ(i, 2); });
254   f.typed<int32_t, empty_t>(store).unwrap().call(store, 2).unwrap();
255 
256   f = Func::wrap(store, [](Caller cx, int32_t i, int32_t j) { return i + j; });
257   auto ret = f.typed<std::tuple<int32_t, int32_t>, int32_t>(store)
258                  .unwrap()
259                  .call(store, {1, 2})
260                  .unwrap();
261   EXPECT_EQ(ret, 3);
262 }
263