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