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