diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index ee77f94597..ff54229560 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -453,7 +453,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) inline constexpr float demot return static_cast(value); } -void branch(const Code& code, OperandStack& stack, const Instr*& pc, const uint8_t*& immediates, +void branch(const Code& code, OperandStack& stack, const uint8_t*& pc, const uint8_t*& immediates, uint32_t arity) noexcept { const auto code_offset = read(immediates); @@ -531,12 +531,12 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, 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* pc = code.instructions.data(); const uint8_t* immediates = code.immediates.data(); while (true) { - const auto instruction = *pc++; + const auto instruction = static_cast(*pc++); switch (instruction) { case Instr::unreachable: diff --git a/lib/fizzy/parser_expr.cpp b/lib/fizzy/parser_expr.cpp index 28bc47a00f..f0ced862dc 100644 --- a/lib/fizzy/parser_expr.cpp +++ b/lib/fizzy/parser_expr.cpp @@ -869,7 +869,7 @@ parser_result parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f break; } } - code.instructions.emplace_back(instr); + code.instructions.emplace_back(opcode); } assert(control_stack.empty()); return {code, pos}; diff --git a/lib/fizzy/types.hpp b/lib/fizzy/types.hpp index 6fccae4e29..06fbbd2391 100644 --- a/lib/fizzy/types.hpp +++ b/lib/fizzy/types.hpp @@ -362,7 +362,7 @@ struct Code // The instructions bytecode without immediate values. // https://webassembly.github.io/spec/core/binary/instructions.html - std::vector instructions; + std::vector instructions; // The decoded instructions' immediate values. // These are instruction-type dependent fixed size value in the order of instructions. diff --git a/test/unittests/execute_death_test.cpp b/test/unittests/execute_death_test.cpp index b94610a5cd..51539671bd 100644 --- a/test/unittests/execute_death_test.cpp +++ b/test/unittests/execute_death_test.cpp @@ -11,11 +11,11 @@ using namespace fizzy; #if !defined(NDEBUG) || __has_feature(undefined_behavior_sanitizer) TEST(execute_death, malformed_instruction_opcode) { - constexpr auto malformed_opcode = static_cast(6); + constexpr uint8_t malformed_opcode = 6; Code code; code.instructions.emplace_back(malformed_opcode); - code.instructions.emplace_back(Instr::end); + code.instructions.emplace_back(static_cast(Instr::end)); auto module = std::make_unique(); module->typesec.emplace_back(FuncType{}); diff --git a/test/unittests/execute_numeric_test.cpp b/test/unittests/execute_numeric_test.cpp index f56671686e..4662d2dc15 100644 --- a/test/unittests/execute_numeric_test.cpp +++ b/test/unittests/execute_numeric_test.cpp @@ -20,7 +20,10 @@ ExecutionResult execute_unary_operation(Instr instr, uint64_t arg) // type is currently needed only to get arity of function, so exact value types don't matter module->typesec.emplace_back(FuncType{{ValType::i32}, {ValType::i32}}); module->funcsec.emplace_back(TypeIdx{0}); - module->codesec.emplace_back(Code{1, 0, {Instr::local_get, instr, Instr::end}, {0, 0, 0, 0}}); + module->codesec.emplace_back(Code{1, 0, + {static_cast(Instr::local_get), static_cast(instr), + static_cast(Instr::end)}, + {0, 0, 0, 0}}); return execute(*instantiate(std::move(module)), 0, {arg}); } @@ -31,8 +34,10 @@ ExecutionResult execute_binary_operation(Instr instr, uint64_t lhs, uint64_t rhs // type is currently needed only to get arity of function, so exact value types don't matter module->typesec.emplace_back(FuncType{{ValType::i32, ValType::i32}, {ValType::i32}}); module->funcsec.emplace_back(TypeIdx{0}); - module->codesec.emplace_back(Code{ - 2, 0, {Instr::local_get, Instr::local_get, instr, Instr::end}, {0, 0, 0, 0, 1, 0, 0, 0}}); + module->codesec.emplace_back(Code{2, 0, + {static_cast(Instr::local_get), static_cast(Instr::local_get), + static_cast(instr), static_cast(Instr::end)}, + {0, 0, 0, 0, 1, 0, 0, 0}}); return execute(*instantiate(std::move(module)), 0, {lhs, rhs}); } diff --git a/test/unittests/execute_test.cpp b/test/unittests/execute_test.cpp index d7b4032ff4..8611afe4a9 100644 --- a/test/unittests/execute_test.cpp +++ b/test/unittests/execute_test.cpp @@ -380,7 +380,7 @@ TEST(execute, i32_load_all_variants) from_hex("0061736d0100000001060160017f017f030201000504010101010a0901070020002802000b"); const auto module = parse(wasm); - auto& load_instr = const_cast(module->codesec[0].instructions[1]); + auto& load_instr = const_cast(module->codesec[0].instructions[1]); ASSERT_EQ(load_instr, Instr::i32_load); ASSERT_EQ(module->codesec[0].immediates.substr(4), "00000000"_bytes); // load offset. @@ -396,7 +396,7 @@ TEST(execute, i32_load_all_variants) for (const auto& test_case : test_cases) { - load_instr = std::get<0>(test_case); + load_instr = static_cast(std::get<0>(test_case)); auto instance = instantiate(*module); std::copy(std::begin(memory_fill), std::end(memory_fill), std::begin(*instance->memory)); EXPECT_THAT(execute(*instance, 0, {1}), Result(std::get<1>(test_case))); @@ -418,7 +418,7 @@ TEST(execute, i64_load_all_variants) from_hex("0061736d0100000001060160017f017e030201000504010101010a0901070020002903000b"); const auto module = parse(wasm); - auto& load_instr = const_cast(module->codesec[0].instructions[1]); + auto& load_instr = const_cast(module->codesec[0].instructions[1]); ASSERT_EQ(load_instr, Instr::i64_load); ASSERT_EQ(module->codesec[0].immediates.substr(4), "00000000"_bytes); // load offset. @@ -436,7 +436,7 @@ TEST(execute, i64_load_all_variants) for (const auto& test_case : test_cases) { - load_instr = std::get<0>(test_case); + load_instr = static_cast(std::get<0>(test_case)); auto instance = instantiate(*module); std::copy(std::begin(memory_fill), std::end(memory_fill), std::begin(*instance->memory)); EXPECT_THAT(execute(*instance, 0, {1}), Result(std::get<1>(test_case))); @@ -529,7 +529,7 @@ TEST(execute, i32_store_all_variants) from_hex("0061736d0100000001060160027f7f00030201000504010101010a0b010900200120003602000b"); const auto module = parse(wasm); - auto& store_instr = const_cast(module->codesec[0].instructions[2]); + auto& store_instr = const_cast(module->codesec[0].instructions[2]); ASSERT_EQ(store_instr, Instr::i32_store); ASSERT_EQ(module->codesec[0].immediates.substr(8), "00000000"_bytes); // store offset @@ -541,7 +541,7 @@ TEST(execute, i32_store_all_variants) for (const auto& test_case : test_cases) { - store_instr = std::get<0>(test_case); + store_instr = static_cast(std::get<0>(test_case)); auto instance = instantiate(*module); std::fill_n(instance->memory->begin(), 6, uint8_t{0xcc}); EXPECT_THAT(execute(*instance, 0, {0xb3b2b1b0, 1}), Result()); @@ -565,7 +565,7 @@ TEST(execute, i64_store_all_variants) from_hex("0061736d0100000001060160027e7f00030201000504010101010a0b010900200120003703000b"); const auto module = parse(wasm); - auto& store_instr = const_cast(module->codesec[0].instructions[2]); + auto& store_instr = const_cast(module->codesec[0].instructions[2]); ASSERT_EQ(store_instr, Instr::i64_store); ASSERT_EQ(module->codesec[0].immediates.substr(8), "00000000"_bytes); // store offset @@ -578,7 +578,7 @@ TEST(execute, i64_store_all_variants) for (const auto& test_case : test_cases) { - store_instr = std::get<0>(test_case); + store_instr = static_cast(std::get<0>(test_case)); auto instance = instantiate(*module); std::fill_n(instance->memory->begin(), 10, uint8_t{0xcc}); EXPECT_THAT(execute(*instance, 0, {0xb7b6b5b4b3b2b1b0, 1}), Result()); diff --git a/test/utils/asserts.hpp b/test/utils/asserts.hpp index 058d986c31..3aa8e3f881 100644 --- a/test/utils/asserts.hpp +++ b/test/utils/asserts.hpp @@ -53,9 +53,15 @@ MATCHER_P(Result, value, "") // NOLINT(readability-redundant-string-init) namespace fizzy { -std::ostream& operator<<(std::ostream& os, ExecutionResult); +/// Equal operator for Instr and bytes. Convenient for unit tests. +inline constexpr bool operator==(uint8_t a, Instr b) noexcept +{ + return a == static_cast(b); } +std::ostream& operator<<(std::ostream& os, ExecutionResult); +} // namespace fizzy + namespace fizzy::test { inline uint32_t as_uint32(fizzy::Value value)