diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index c694c70e1..47a0790b3 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -454,29 +454,30 @@ inline bool invoke_function(const FuncType& func_type, uint32_t func_idx, Instan OperandStack& stack, int depth) noexcept { const auto func = [func_idx](Instance& _instance, span args, int _depth) noexcept { - return execute(_instance, func_idx, args, _depth); + return execute(_instance, func_idx, args.data(), _depth); }; return invoke_function(func_type, func, instance, stack, depth); } } // namespace -ExecutionResult execute( - Instance& instance, FuncIdx func_idx, span args, int depth) noexcept +ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, int depth) noexcept { assert(depth >= 0); if (depth > CallStackLimit) return Trap; - assert(args.size() == instance.module.get_function_type(func_idx).inputs.size()); + const auto& func_type = instance.module.get_function_type(func_idx); assert(instance.module.imported_function_types.size() == instance.imported_functions.size()); if (func_idx < instance.imported_functions.size()) - return instance.imported_functions[func_idx].function(instance, args, depth); + return instance.imported_functions[func_idx].function( + instance, {args, func_type.inputs.size()}, depth); const auto& code = instance.module.get_code(func_idx); auto* const memory = instance.memory.get(); - OperandStack stack(args, code.local_count, static_cast(code.max_stack_height)); + OperandStack stack(args, func_type.inputs.size(), code.local_count, + static_cast(code.max_stack_height)); const Instr* pc = code.instructions.data(); const uint8_t* immediates = code.immediates.data(); diff --git a/lib/fizzy/execute.hpp b/lib/fizzy/execute.hpp index a71e67cab..66c3d9a4b 100644 --- a/lib/fizzy/execute.hpp +++ b/lib/fizzy/execute.hpp @@ -38,11 +38,12 @@ constexpr ExecutionResult Trap{false}; // Execute a function on an instance. ExecutionResult execute( - Instance& instance, FuncIdx func_idx, span args, int depth = 0) noexcept; + Instance& instance, FuncIdx func_idx, const Value* args, int depth = 0) noexcept; inline ExecutionResult execute( Instance& instance, FuncIdx func_idx, std::initializer_list args) noexcept { - return execute(instance, func_idx, span{args}); + assert(args.size() == instance.module.get_function_type(func_idx).inputs.size()); + return execute(instance, func_idx, args.begin()); } } // namespace fizzy diff --git a/lib/fizzy/instantiate.cpp b/lib/fizzy/instantiate.cpp index 4353803db..2b2a32a4e 100644 --- a/lib/fizzy/instantiate.cpp +++ b/lib/fizzy/instantiate.cpp @@ -328,7 +328,7 @@ std::unique_ptr instantiate(Module module, for (const auto idx : instance->module.elementsec[i].init) { auto func = [idx, &instance_ref = *instance](fizzy::Instance&, span args, - int depth) { return execute(instance_ref, idx, args, depth); }; + int depth) { return execute(instance_ref, idx, args.data(), depth); }; *it_table++ = ExternalFunction{std::move(func), instance->module.get_function_type(idx)}; @@ -433,7 +433,7 @@ std::optional find_exported_function(Instance& instance, std:: const auto idx = *opt_index; auto func = [idx, &instance](fizzy::Instance&, span args, int depth) { - return execute(instance, idx, args, depth); + return execute(instance, idx, args.data(), depth); }; return ExternalFunction{std::move(func), instance.module.get_function_type(idx)}; diff --git a/lib/fizzy/stack.hpp b/lib/fizzy/stack.hpp index 2da812c94..5b11b78e2 100644 --- a/lib/fizzy/stack.hpp +++ b/lib/fizzy/stack.hpp @@ -4,8 +4,8 @@ #pragma once -#include "cxx20/span.hpp" #include "value.hpp" +#include #include #include #include @@ -96,9 +96,9 @@ class OperandStack /// after the arguments. /// @param max_stack_height The maximum operand stack height in the function. This excludes /// args and num_local_variables. - OperandStack(span args, size_t num_local_variables, size_t max_stack_height) + OperandStack( + const Value* args, size_t num_args, size_t num_local_variables, size_t max_stack_height) { - const auto num_args = args.size(); const auto storage_size_required = num_args + num_local_variables + max_stack_height; if (storage_size_required <= small_storage_size) @@ -114,8 +114,8 @@ class OperandStack m_bottom = m_locals + num_args + num_local_variables; m_top = m_bottom - 1; - std::copy(std::begin(args), std::end(args), m_locals); - std::fill_n(m_locals + num_args, num_local_variables, 0); + const auto local_variables = std::copy_n(args, num_args, m_locals); + std::fill_n(local_variables, num_local_variables, 0); } OperandStack(const OperandStack&) = delete; diff --git a/test/spectests/spectests.cpp b/test/spectests/spectests.cpp index f1e14bd24..96dfd0da7 100644 --- a/test/spectests/spectests.cpp +++ b/test/spectests/spectests.cpp @@ -480,7 +480,8 @@ class test_runner args.push_back(*arg_value); } - return fizzy::execute(*instance, *func_idx, args); + assert(args.size() == instance->module.get_function_type(*func_idx).inputs.size()); + return fizzy::execute(*instance, *func_idx, args.data()); } bool check_integer_result(fizzy::Value actual_value, const json& expected) diff --git a/test/testfloat/testfloat.cpp b/test/testfloat/testfloat.cpp index 2b9924f4d..e68b950c2 100644 --- a/test/testfloat/testfloat.cpp +++ b/test/testfloat/testfloat.cpp @@ -336,8 +336,7 @@ bool check(const FunctionDescription& func, fizzy::Instance& instance, const uin for (size_t i = 0; i < func.num_arguments; ++i) args[i] = make_value(func.param_types[i], inputs[i]); - const auto r = fizzy::execute( - instance, func.idx, fizzy::span(args, func.num_arguments)); + const auto r = fizzy::execute(instance, func.idx, args); if (func.options == Options::TrapIsInvalidOperation) { diff --git a/test/unittests/api_test.cpp b/test/unittests/api_test.cpp index 5a913ed54..f1a6fa58b 100644 --- a/test/unittests/api_test.cpp +++ b/test/unittests/api_test.cpp @@ -99,8 +99,8 @@ TEST(api, resolve_imported_functions) module, external_functions, {}, {}, std::vector(external_globals)); EXPECT_THAT(execute(*instance, 0, {}), Result(0)); - EXPECT_THAT(execute(*instance, 1, {0}), Result(1)); - EXPECT_THAT(execute(*instance, 2, {0}), Result(2)); + EXPECT_THAT(execute(*instance, 1, {Value{0}}), Result(1)); + EXPECT_THAT(execute(*instance, 2, {Value{0}}), Result(2)); EXPECT_THAT(execute(*instance, 3, {0, 0}), Result()); @@ -119,8 +119,8 @@ TEST(api, resolve_imported_functions) std::vector(external_globals)); EXPECT_THAT(execute(*instance_reordered, 0, {}), Result(0)); - EXPECT_THAT(execute(*instance_reordered, 1, {0}), Result(1)); - EXPECT_THAT(execute(*instance_reordered, 2, {0}), Result(2)); + EXPECT_THAT(execute(*instance_reordered, 1, {Value{0}}), Result(1)); + EXPECT_THAT(execute(*instance_reordered, 2, {Value{0}}), Result(2)); EXPECT_THAT(execute(*instance_reordered, 3, {0, 0}), Result()); @@ -141,8 +141,8 @@ TEST(api, resolve_imported_functions) module, external_functions_extra, {}, {}, std::vector(external_globals)); EXPECT_THAT(execute(*instance_extra, 0, {}), Result(0)); - EXPECT_THAT(execute(*instance_extra, 1, {0}), Result(1)); - EXPECT_THAT(execute(*instance_extra, 2, {0}), Result(2)); + EXPECT_THAT(execute(*instance_extra, 1, {Value{0}}), Result(1)); + EXPECT_THAT(execute(*instance_extra, 2, {Value{0}}), Result(2)); EXPECT_THAT(execute(*instance_extra, 3, {0, 0}), Result()); diff --git a/test/unittests/execute_call_test.cpp b/test/unittests/execute_call_test.cpp index a338459df..285479303 100644 --- a/test/unittests/execute_call_test.cpp +++ b/test/unittests/execute_call_test.cpp @@ -338,7 +338,7 @@ TEST(execute_call, imported_function_from_another_module) ASSERT_TRUE(func_idx.has_value()); auto sub = [&instance1, func_idx](Instance&, span args, int) -> ExecutionResult { - return fizzy::execute(*instance1, *func_idx, args); + return fizzy::execute(*instance1, *func_idx, args.data()); }; auto instance2 = instantiate(module2, {{sub, module1.typesec[0]}}); diff --git a/test/unittests/execute_floating_point_test.cpp b/test/unittests/execute_floating_point_test.cpp index 99f9d1af3..4802d0670 100644 --- a/test/unittests/execute_floating_point_test.cpp +++ b/test/unittests/execute_floating_point_test.cpp @@ -1893,7 +1893,7 @@ TEST(execute_floating_point, f32_load_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -1966,7 +1966,7 @@ TEST(execute_floating_point, f64_load_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -2043,7 +2043,7 @@ TEST(execute_floating_point, f32_store_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -2120,7 +2120,7 @@ TEST(execute_floating_point, f64_store_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 diff --git a/test/unittests/execute_test.cpp b/test/unittests/execute_test.cpp index af6e79713..79b0b37b2 100644 --- a/test/unittests/execute_test.cpp +++ b/test/unittests/execute_test.cpp @@ -340,7 +340,7 @@ TEST(execute, i32_load_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -362,7 +362,7 @@ TEST(execute, i64_load_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -486,7 +486,7 @@ TEST(execute, i32_store_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -510,7 +510,7 @@ TEST(execute, i64_store_overflow) auto instance = instantiate(parse(wasm)); // Offset is 0x7fffffff + 0 => 0x7fffffff - EXPECT_THAT(execute(*instance, 0, {0}), Traps()); + EXPECT_THAT(execute(*instance, 0, {Value{0}}), Traps()); // Offset is 0x7fffffff + 0x80000000 => 0xffffffff EXPECT_THAT(execute(*instance, 0, {0x80000000}), Traps()); // Offset is 0x7fffffff + 0x80000001 => 0x100000000 @@ -980,7 +980,7 @@ TEST(execute, reuse_args) const std::vector args{20, 3}; const auto expected = args[0].i64 % (args[0].i64 / args[1].i64); - EXPECT_THAT(execute(*instance, 0, args), Result(expected)); + EXPECT_THAT(execute(*instance, 0, args.data()), Result(expected)); EXPECT_THAT(args[0].i64, 20); EXPECT_THAT(args[1].i64, 3); diff --git a/test/unittests/span_test.cpp b/test/unittests/span_test.cpp index 512a45e0e..f4aa83983 100644 --- a/test/unittests/span_test.cpp +++ b/test/unittests/span_test.cpp @@ -50,7 +50,7 @@ TEST(span, array) TEST(span, stack) { - OperandStack stack({}, 0, 4); + OperandStack stack(nullptr, 0, 0, 4); stack.push(10); stack.push(11); stack.push(12); diff --git a/test/unittests/stack_test.cpp b/test/unittests/stack_test.cpp index 853ab9cdb..429009594 100644 --- a/test/unittests/stack_test.cpp +++ b/test/unittests/stack_test.cpp @@ -123,13 +123,13 @@ TEST(stack, struct_item) TEST(operand_stack, construct) { - OperandStack stack({}, 0, 0); + OperandStack stack(nullptr, 0, 0, 0); EXPECT_EQ(stack.size(), 0); } TEST(operand_stack, top) { - OperandStack stack({}, 0, 1); + OperandStack stack(nullptr, 0, 0, 1); EXPECT_EQ(stack.size(), 0); stack.push(1); @@ -158,7 +158,7 @@ TEST(operand_stack, top) TEST(operand_stack, small) { - OperandStack stack({}, 0, 3); + OperandStack stack(nullptr, 0, 0, 3); ASSERT_LT(address_diff(&stack, stack.rbegin()), 100) << "not allocated on the system stack"; EXPECT_EQ(stack.size(), 0); @@ -189,7 +189,7 @@ TEST(operand_stack, small) TEST(operand_stack, small_with_locals) { const fizzy::Value args[] = {0xa1, 0xa2}; - OperandStack stack(args, 3, 1); + OperandStack stack(args, std::size(args), 3, 1); ASSERT_LT(address_diff(&stack, stack.rbegin()), 100) << "not allocated on the system stack"; EXPECT_EQ(stack.size(), 0); @@ -229,7 +229,7 @@ TEST(operand_stack, small_with_locals) TEST(operand_stack, large) { constexpr auto max_height = 33; - OperandStack stack({}, 0, max_height); + OperandStack stack(nullptr, 0, 0, max_height); ASSERT_GT(address_diff(&stack, stack.rbegin()), 100) << "not allocated on the heap"; for (unsigned i = 0; i < max_height; ++i) @@ -247,7 +247,7 @@ TEST(operand_stack, large_with_locals) constexpr auto max_height = 33; constexpr auto num_locals = 5; constexpr auto num_args = std::size(args); - OperandStack stack(args, num_locals, max_height); + OperandStack stack(args, num_args, num_locals, max_height); ASSERT_GT(address_diff(&stack, stack.rbegin()), 100) << "not allocated on the heap"; for (unsigned i = 0; i < max_height; ++i) @@ -279,7 +279,7 @@ TEST(operand_stack, large_with_locals) TEST(operand_stack, rbegin_rend) { - OperandStack stack({}, 0, 3); + OperandStack stack(nullptr, 0, 0, 3); EXPECT_EQ(stack.rbegin(), stack.rend()); stack.push(1); @@ -293,7 +293,7 @@ TEST(operand_stack, rbegin_rend) TEST(operand_stack, rbegin_rend_locals) { const fizzy::Value args[] = {0xa1}; - OperandStack stack(args, 4, 2); + OperandStack stack(args, std::size(args), 4, 2); EXPECT_EQ(stack.rbegin(), stack.rend()); stack.push(1); @@ -313,7 +313,7 @@ TEST(operand_stack, rbegin_rend_locals) TEST(operand_stack, to_vector) { - OperandStack stack({}, 0, 3); + OperandStack stack(nullptr, 0, 0, 3); EXPECT_THAT(std::vector(stack.rbegin(), stack.rend()), IsEmpty()); stack.push(1); diff --git a/test/utils/fizzy_engine.cpp b/test/utils/fizzy_engine.cpp index 5d3abdcf4..59f76b796 100644 --- a/test/utils/fizzy_engine.cpp +++ b/test/utils/fizzy_engine.cpp @@ -136,8 +136,9 @@ WasmEngine::Result FizzyEngine::execute( { static_assert(sizeof(uint64_t) == sizeof(Value)); const auto first_arg = reinterpret_cast(args.data()); - const auto status = fizzy::execute( - *m_instance, static_cast(func_ref), span(first_arg, args.size())); + assert(args.size() == + m_instance->module.get_function_type(static_cast(func_ref)).inputs.size()); + const auto status = fizzy::execute(*m_instance, static_cast(func_ref), first_arg); if (status.trapped) return {true, std::nullopt}; else if (status.has_value)