Skip to content

Commit b380911

Browse files
committed
Convert instructions to vector<uint8_t>
1 parent d13addb commit b380911

File tree

7 files changed

+30
-19
lines changed

7 files changed

+30
-19
lines changed

lib/fizzy/execute.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) inline constexpr float demot
453453
return static_cast<float>(value);
454454
}
455455

456-
void branch(const Code& code, OperandStack& stack, const Instr*& pc, const uint8_t*& immediates,
456+
void branch(const Code& code, OperandStack& stack, const uint8_t*& pc, const uint8_t*& immediates,
457457
uint32_t arity) noexcept
458458
{
459459
const auto code_offset = read<uint32_t>(immediates);
@@ -531,12 +531,12 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args,
531531
OperandStack stack(args, func_type.inputs.size(), code.local_count,
532532
static_cast<size_t>(code.max_stack_height));
533533

534-
const Instr* pc = code.instructions.data();
534+
const uint8_t* pc = code.instructions.data();
535535
const uint8_t* immediates = code.immediates.data();
536536

537537
while (true)
538538
{
539-
const auto instruction = *pc++;
539+
const auto instruction = static_cast<Instr>(*pc++);
540540
switch (instruction)
541541
{
542542
case Instr::unreachable:

lib/fizzy/parser_expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
869869
break;
870870
}
871871
}
872-
code.instructions.emplace_back(instr);
872+
code.instructions.emplace_back(opcode);
873873
}
874874
assert(control_stack.empty());
875875
return {code, pos};

lib/fizzy/types.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ struct Code
362362

363363
// The instructions bytecode without immediate values.
364364
// https://webassembly.github.io/spec/core/binary/instructions.html
365-
std::vector<Instr> instructions;
365+
std::vector<uint8_t> instructions;
366366

367367
// The decoded instructions' immediate values.
368368
// These are instruction-type dependent fixed size value in the order of instructions.

test/unittests/execute_death_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ using namespace fizzy;
1111
#if !defined(NDEBUG) || __has_feature(undefined_behavior_sanitizer)
1212
TEST(execute_death, malformed_instruction_opcode)
1313
{
14-
constexpr auto malformed_opcode = static_cast<Instr>(6);
14+
constexpr uint8_t malformed_opcode = 6;
1515

1616
Code code;
1717
code.instructions.emplace_back(malformed_opcode);
18-
code.instructions.emplace_back(Instr::end);
18+
code.instructions.emplace_back(static_cast<uint8_t>(Instr::end));
1919

2020
auto module = std::make_unique<Module>();
2121
module->typesec.emplace_back(FuncType{});

test/unittests/execute_numeric_test.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ ExecutionResult execute_unary_operation(Instr instr, uint64_t arg)
2020
// type is currently needed only to get arity of function, so exact value types don't matter
2121
module->typesec.emplace_back(FuncType{{ValType::i32}, {ValType::i32}});
2222
module->funcsec.emplace_back(TypeIdx{0});
23-
module->codesec.emplace_back(Code{1, 0, {Instr::local_get, instr, Instr::end}, {0, 0, 0, 0}});
23+
module->codesec.emplace_back(Code{1, 0,
24+
{static_cast<uint8_t>(Instr::local_get), static_cast<uint8_t>(instr),
25+
static_cast<uint8_t>(Instr::end)},
26+
{0, 0, 0, 0}});
2427

2528
return execute(*instantiate(std::move(module)), 0, {arg});
2629
}
@@ -31,8 +34,10 @@ ExecutionResult execute_binary_operation(Instr instr, uint64_t lhs, uint64_t rhs
3134
// type is currently needed only to get arity of function, so exact value types don't matter
3235
module->typesec.emplace_back(FuncType{{ValType::i32, ValType::i32}, {ValType::i32}});
3336
module->funcsec.emplace_back(TypeIdx{0});
34-
module->codesec.emplace_back(Code{
35-
2, 0, {Instr::local_get, Instr::local_get, instr, Instr::end}, {0, 0, 0, 0, 1, 0, 0, 0}});
37+
module->codesec.emplace_back(Code{2, 0,
38+
{static_cast<uint8_t>(Instr::local_get), static_cast<uint8_t>(Instr::local_get),
39+
static_cast<uint8_t>(instr), static_cast<uint8_t>(Instr::end)},
40+
{0, 0, 0, 0, 1, 0, 0, 0}});
3641

3742
return execute(*instantiate(std::move(module)), 0, {lhs, rhs});
3843
}

test/unittests/execute_test.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ TEST(execute, i32_load_all_variants)
380380
from_hex("0061736d0100000001060160017f017f030201000504010101010a0901070020002802000b");
381381
const auto module = parse(wasm);
382382

383-
auto& load_instr = const_cast<Instr&>(module->codesec[0].instructions[1]);
383+
auto& load_instr = const_cast<uint8_t&>(module->codesec[0].instructions[1]);
384384
ASSERT_EQ(load_instr, Instr::i32_load);
385385
ASSERT_EQ(module->codesec[0].immediates.substr(4), "00000000"_bytes); // load offset.
386386

@@ -396,7 +396,7 @@ TEST(execute, i32_load_all_variants)
396396

397397
for (const auto& test_case : test_cases)
398398
{
399-
load_instr = std::get<0>(test_case);
399+
load_instr = static_cast<uint8_t>(std::get<0>(test_case));
400400
auto instance = instantiate(*module);
401401
std::copy(std::begin(memory_fill), std::end(memory_fill), std::begin(*instance->memory));
402402
EXPECT_THAT(execute(*instance, 0, {1}), Result(std::get<1>(test_case)));
@@ -418,7 +418,7 @@ TEST(execute, i64_load_all_variants)
418418
from_hex("0061736d0100000001060160017f017e030201000504010101010a0901070020002903000b");
419419
const auto module = parse(wasm);
420420

421-
auto& load_instr = const_cast<Instr&>(module->codesec[0].instructions[1]);
421+
auto& load_instr = const_cast<uint8_t&>(module->codesec[0].instructions[1]);
422422
ASSERT_EQ(load_instr, Instr::i64_load);
423423
ASSERT_EQ(module->codesec[0].immediates.substr(4), "00000000"_bytes); // load offset.
424424

@@ -436,7 +436,7 @@ TEST(execute, i64_load_all_variants)
436436

437437
for (const auto& test_case : test_cases)
438438
{
439-
load_instr = std::get<0>(test_case);
439+
load_instr = static_cast<uint8_t>(std::get<0>(test_case));
440440
auto instance = instantiate(*module);
441441
std::copy(std::begin(memory_fill), std::end(memory_fill), std::begin(*instance->memory));
442442
EXPECT_THAT(execute(*instance, 0, {1}), Result(std::get<1>(test_case)));
@@ -529,7 +529,7 @@ TEST(execute, i32_store_all_variants)
529529
from_hex("0061736d0100000001060160027f7f00030201000504010101010a0b010900200120003602000b");
530530
const auto module = parse(wasm);
531531

532-
auto& store_instr = const_cast<Instr&>(module->codesec[0].instructions[2]);
532+
auto& store_instr = const_cast<uint8_t&>(module->codesec[0].instructions[2]);
533533
ASSERT_EQ(store_instr, Instr::i32_store);
534534
ASSERT_EQ(module->codesec[0].immediates.substr(8), "00000000"_bytes); // store offset
535535

@@ -541,7 +541,7 @@ TEST(execute, i32_store_all_variants)
541541

542542
for (const auto& test_case : test_cases)
543543
{
544-
store_instr = std::get<0>(test_case);
544+
store_instr = static_cast<uint8_t>(std::get<0>(test_case));
545545
auto instance = instantiate(*module);
546546
std::fill_n(instance->memory->begin(), 6, uint8_t{0xcc});
547547
EXPECT_THAT(execute(*instance, 0, {0xb3b2b1b0, 1}), Result());
@@ -565,7 +565,7 @@ TEST(execute, i64_store_all_variants)
565565
from_hex("0061736d0100000001060160027e7f00030201000504010101010a0b010900200120003703000b");
566566
const auto module = parse(wasm);
567567

568-
auto& store_instr = const_cast<Instr&>(module->codesec[0].instructions[2]);
568+
auto& store_instr = const_cast<uint8_t&>(module->codesec[0].instructions[2]);
569569
ASSERT_EQ(store_instr, Instr::i64_store);
570570
ASSERT_EQ(module->codesec[0].immediates.substr(8), "00000000"_bytes); // store offset
571571

@@ -578,7 +578,7 @@ TEST(execute, i64_store_all_variants)
578578

579579
for (const auto& test_case : test_cases)
580580
{
581-
store_instr = std::get<0>(test_case);
581+
store_instr = static_cast<uint8_t>(std::get<0>(test_case));
582582
auto instance = instantiate(*module);
583583
std::fill_n(instance->memory->begin(), 10, uint8_t{0xcc});
584584
EXPECT_THAT(execute(*instance, 0, {0xb7b6b5b4b3b2b1b0, 1}), Result());

test/utils/asserts.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,15 @@ MATCHER_P(Result, value, "") // NOLINT(readability-redundant-string-init)
5353

5454
namespace fizzy
5555
{
56-
std::ostream& operator<<(std::ostream& os, ExecutionResult);
56+
/// Equal operator for Instr and bytes. Convenient for unit tests.
57+
inline constexpr bool operator==(uint8_t a, Instr b) noexcept
58+
{
59+
return a == static_cast<uint8_t>(b);
5760
}
5861

62+
std::ostream& operator<<(std::ostream& os, ExecutionResult);
63+
} // namespace fizzy
64+
5965
namespace fizzy::test
6066
{
6167
inline uint32_t as_uint32(fizzy::Value value)

0 commit comments

Comments
 (0)