Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/c-api/tests/func.cc
1692 views
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
264