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