Skip to content

Commit

Permalink
Convert instructions to vector<uint8_t>
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Oct 22, 2020
1 parent a28a6b5 commit 64d006a
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 19 deletions.
6 changes: 3 additions & 3 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) inline constexpr float demot
return static_cast<float>(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<uint32_t>(immediates);
Expand Down Expand Up @@ -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<size_t>(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<Instr>(*pc++);
switch (instruction)
{
case Instr::unreachable:
Expand Down
2 changes: 1 addition & 1 deletion lib/fizzy/parser_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ parser_result<Code> 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};
Expand Down
2 changes: 1 addition & 1 deletion lib/fizzy/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ struct Code

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

// The decoded instructions' immediate values.
// These are instruction-type dependent fixed size value in the order of instructions.
Expand Down
4 changes: 2 additions & 2 deletions test/unittests/execute_death_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Instr>(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<uint8_t>(Instr::end));

auto module = std::make_unique<Module>();
module->typesec.emplace_back(FuncType{});
Expand Down
11 changes: 8 additions & 3 deletions test/unittests/execute_numeric_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t>(Instr::local_get), static_cast<uint8_t>(instr),
static_cast<uint8_t>(Instr::end)},
{0, 0, 0, 0}});

return execute(*instantiate(std::move(module)), 0, {arg});
}
Expand All @@ -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<uint8_t>(Instr::local_get), static_cast<uint8_t>(Instr::local_get),
static_cast<uint8_t>(instr), static_cast<uint8_t>(Instr::end)},
{0, 0, 0, 0, 1, 0, 0, 0}});

return execute(*instantiate(std::move(module)), 0, {lhs, rhs});
}
Expand Down
16 changes: 8 additions & 8 deletions test/unittests/execute_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ TEST(execute, i32_load_all_variants)
from_hex("0061736d0100000001060160017f017f030201000504010101010a0901070020002802000b");
const auto module = parse(wasm);

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

Expand All @@ -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<uint8_t>(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)));
Expand All @@ -418,7 +418,7 @@ TEST(execute, i64_load_all_variants)
from_hex("0061736d0100000001060160017f017e030201000504010101010a0901070020002903000b");
const auto module = parse(wasm);

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

Expand All @@ -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<uint8_t>(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)));
Expand Down Expand Up @@ -529,7 +529,7 @@ TEST(execute, i32_store_all_variants)
from_hex("0061736d0100000001060160027f7f00030201000504010101010a0b010900200120003602000b");
const auto module = parse(wasm);

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

Expand All @@ -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<uint8_t>(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());
Expand All @@ -565,7 +565,7 @@ TEST(execute, i64_store_all_variants)
from_hex("0061736d0100000001060160027e7f00030201000504010101010a0b010900200120003703000b");
const auto module = parse(wasm);

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

Expand All @@ -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<uint8_t>(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());
Expand Down
8 changes: 7 additions & 1 deletion test/utils/asserts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t>(b);
}

std::ostream& operator<<(std::ostream& os, ExecutionResult);
} // namespace fizzy

namespace fizzy::test
{
inline uint32_t as_uint32(fizzy::Value value)
Expand Down

0 comments on commit 64d006a

Please sign in to comment.