Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: wasmx/fizzy
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 38a45ebb1c89334b69977a2874cf0dbee9cb4368
Choose a base ref
..
head repository: wasmx/fizzy
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 05a3574d0eb51eb1926e6bbe6ae45289c1c8b784
Choose a head ref
Showing with 142 additions and 71 deletions.
  1. +30 −20 test/unittests/execute_control_test.cpp
  2. +55 −47 test/unittests/parser_expr_test.cpp
  3. +15 −4 test/unittests/parser_test.cpp
  4. +42 −0 test/unittests/validation_stack_test.cpp
50 changes: 30 additions & 20 deletions test/unittests/execute_control_test.cpp
Original file line number Diff line number Diff line change
@@ -32,8 +32,8 @@ TEST(execute_control, nop)

TEST(execute_control, block_br)
{
/* wat2wasm --no-check
(func
/* wat2wasm
(func (result i32)
(local i32 i32)
(block
i32.const 0xa
@@ -46,55 +46,65 @@ TEST(execute_control, block_br)
)
*/
const auto wasm = from_hex(
"0061736d01000000010401600000030201000a15011301027f0240410a21010c00410b21010b20010b");
"0061736d010000000105016000017f030201000a15011301027f0240410a21010c00410b21010b20010b");

EXPECT_THAT(execute(parse(wasm), 0, {}), Result(0xa));
}

TEST(execute_control, loop_void_empty)
TEST(execute_control, loop_void)
{
/* wat2wasm --no-check
(func
/* wat2wasm
(func (param i64 i64) (result i64)
(loop
get_local 0 ;; Leaves an item on the stack what makes the loop invalid.
local.get 0
local.set 1
)
local.get 1
)
*/
const auto wasm = from_hex("0061736d01000000010401600000030201000a09010700034020000b0b");
const auto result = execute(parse(wasm), 0, {1});
const auto wasm =
from_hex("0061736d0100000001070160027e7e017e030201000a0d010b000340200021010b20010b");
const auto result = execute(parse(wasm), 0, {1, 0});
EXPECT_THAT(result, Result(1));
}

TEST(execute_control, block_void_empty)
TEST(execute_control, block_void)
{
/* wat2wasm --no-check
(func
/* wat2wasm
(func (param i32 i32) (result i32)
(block
get_local 0 ;; Leaves an item on the stack what makes the block invalid.
local.get 0
local.set 1
)
local.get 1
)
*/
const auto wasm = from_hex("0061736d01000000010401600000030201000a09010700024020000b0b");
const auto result = execute(parse(wasm), 0, {100});
const auto wasm =
from_hex("0061736d0100000001070160027f7f017f030201000a0d010b000240200021010b20010b");
const auto result = execute(parse(wasm), 0, {100, 99});
EXPECT_THAT(result, Result(100));
}

TEST(execute_control, loop_void_br_if_16)
{
/* wat2wasm --no-check
(func (param i32)
/* wat2wasm
(func (param i32) (result i32)
(local i32)
(loop
local.get 0 ;; This is the input argument.
i32.const 1
i32.sub
local.tee 0
br_if 0
local.get 0 ;; Leaves an item on the stack what makes the loop invalid.
local.get 0
local.set 1
)
local.get 1
)
*/
const auto wasm =
from_hex("0061736d0100000001050160017f00030201000a120110000340200041016b22000d0020000b0b");
const auto wasm = from_hex(
"0061736d0100000001060160017f017f030201000a18011601017f0340200041016b22000d00200021010b2001"
"0b");
EXPECT_THAT(execute(parse(wasm), 0, {16}), Result(0));
}

102 changes: 55 additions & 47 deletions test/unittests/parser_expr_test.cpp
Original file line number Diff line number Diff line change
@@ -31,24 +31,24 @@ TEST(parser_expr, instr_loop)
EXPECT_EQ(code1.immediates.size(), 0);
EXPECT_EQ(code1.max_stack_height, 0);

const auto loop_i32 = "037f41000b0b"_bytes;
const auto loop_i32 = "037f41000b1a0b"_bytes;
const auto [code2, pos2] = parse_expr(loop_i32);
EXPECT_EQ(
code2.instructions, (std::vector{Instr::loop, Instr::i32_const, Instr::end, Instr::end}));
EXPECT_EQ(code2.instructions,
(std::vector{Instr::loop, Instr::i32_const, Instr::end, Instr::drop, Instr::end}));
EXPECT_EQ(code2.immediates.size(), 4);
EXPECT_EQ(code2.max_stack_height, 1);

const auto loop_f32 = "037d43000000000b0b"_bytes;
const auto loop_f32 = "037d43000000000b1a0b"_bytes;
const auto [code3, pos3] = parse_expr(loop_f32);
EXPECT_EQ(
code3.instructions, (std::vector{Instr::loop, Instr::f32_const, Instr::end, Instr::end}));
EXPECT_EQ(code3.instructions,
(std::vector{Instr::loop, Instr::f32_const, Instr::end, Instr::drop, Instr::end}));
EXPECT_EQ(code3.immediates.size(), 0);
EXPECT_EQ(code3.max_stack_height, 1);

const auto loop_f64 = "037d4400000000000000000b0b"_bytes;
const auto loop_f64 = "037d4400000000000000000b1a0b"_bytes;
const auto [code4, pos4] = parse_expr(loop_f64);
EXPECT_EQ(
code4.instructions, (std::vector{Instr::loop, Instr::f64_const, Instr::end, Instr::end}));
EXPECT_EQ(code4.instructions,
(std::vector{Instr::loop, Instr::f64_const, Instr::end, Instr::drop, Instr::end}));
EXPECT_EQ(code4.immediates.size(), 0);
EXPECT_EQ(code4.max_stack_height, 1);
}
@@ -74,20 +74,20 @@ TEST(parser_expr, instr_block)
"04000000"
"09000000"_bytes);

const auto block_i64 = "027e42000b0b"_bytes;
const auto block_i64 = "027e42000b1a0b"_bytes;
const auto [code2, pos2] = parse_expr(block_i64);
EXPECT_EQ(
code2.instructions, (std::vector{Instr::block, Instr::i64_const, Instr::end, Instr::end}));
EXPECT_EQ(code2.instructions,
(std::vector{Instr::block, Instr::i64_const, Instr::end, Instr::drop, Instr::end}));
EXPECT_EQ(code2.immediates,
"01"
"03000000"
"11000000"
"0000000000000000"_bytes);

const auto block_f64 = "027c4400000000000000000b0b"_bytes;
const auto block_f64 = "027c4400000000000000000b1a0b"_bytes;
const auto [code3, pos3] = parse_expr(block_f64);
EXPECT_EQ(
code3.instructions, (std::vector{Instr::block, Instr::f64_const, Instr::end, Instr::end}));
EXPECT_EQ(code3.instructions,
(std::vector{Instr::block, Instr::f64_const, Instr::end, Instr::drop, Instr::end}));
EXPECT_EQ(code3.immediates,
"01"
"03000000"
@@ -112,13 +112,15 @@ TEST(parser_expr, block_br)
// local.set 1
// end
// local.get 1
// drop
// end

const auto code_bin = "010240410a21010c00410b21010b20010b"_bytes;
const auto code_bin = "010240410a21010c00410b21010b20011a0b"_bytes;
const auto [code, pos] = parse_expr(code_bin);
EXPECT_EQ(code.instructions,
(std::vector{Instr::nop, Instr::block, Instr::i32_const, Instr::local_set, Instr::br,
Instr::i32_const, Instr::local_set, Instr::end, Instr::local_get, Instr::end}));
EXPECT_EQ(
code.instructions, (std::vector{Instr::nop, Instr::block, Instr::i32_const,
Instr::local_set, Instr::br, Instr::i32_const, Instr::local_set,
Instr::end, Instr::local_get, Instr::drop, Instr::end}));
EXPECT_EQ(code.immediates,
"00"
"08000000"
@@ -134,32 +136,34 @@ TEST(parser_expr, block_br)

TEST(parser_expr, instr_br_table)
{
/*
(block
(block
(block
(block
(block
(br_table 3 2 1 0 4 (get_local 0))
(return (i32.const 99))
)
(return (i32.const 100))
)
(return (i32.const 101))
)
(return (i32.const 102))
)
(return (i32.const 103))
)
(i32.const 104)
/* wat2wasm
(func (param i32) (result i32)
(block
(block
(block
(block
(block
(br_table 3 2 1 0 4 (get_local 0))
(return (i32.const 99))
)
(return (i32.const 100))
)
(return (i32.const 101))
)
(return (i32.const 102))
)
(return (i32.const 103))
)
(i32.const 104)
)
*/
const auto wasm = from_hex(
"0061736d0100000001060160017f017f030201000a330131000240024002400240024020000e04030201000441"
"e3000f0b41e4000f0b41e5000f0b41e6000f0b41e7000f0b41e8000b");

const auto code_bin =
"0240024002400240024020000e04030201000441e3"
"000f0b41e4000f0b41e5000f0b41e6000f0b41e7000f0b41e8000b000c04"
"6e616d6502050100010000"_bytes;

const auto [code, pos] = parse_expr(code_bin);
const auto module = parse(wasm);
ASSERT_EQ(module.codesec.size(), 1);
const auto& code = module.codesec[0];

EXPECT_EQ(code.instructions,
(std::vector{Instr::block, Instr::block, Instr::block, Instr::block, Instr::block,
@@ -183,17 +187,21 @@ TEST(parser_expr, instr_br_table)

TEST(parser_expr, instr_br_table_empty_vector)
{
/*
/* wat2wasm
(func (param i32) (result i32)
(block
(br_table 0 (get_local 0))
(return (i32.const 99))
)
(i32.const 100)
)
*/
const auto wasm = from_hex(
"0061736d0100000001060160017f017f030201000a13011100024020000e000041e3000f0b41e4000b");

const auto code_bin = "024020000e000041e3000f0b41e4000b000c046e616d6502050100010000"_bytes;

const auto [code, pos] = parse_expr(code_bin);
const auto module = parse(wasm);
ASSERT_EQ(module.codesec.size(), 1);
const auto& code = module.codesec[0];

EXPECT_EQ(code.instructions,
(std::vector{Instr::block, Instr::local_get, Instr::br_table, Instr::i32_const,
19 changes: 15 additions & 4 deletions test/unittests/parser_test.cpp
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
// Copyright 2019-2020 The Fizzy Authors.
// SPDX-License-Identifier: Apache-2.0

#include "instructions.hpp"
#include "parser.hpp"
#include <gtest/gtest.h>
#include <test/utils/asserts.hpp>
@@ -1063,7 +1064,7 @@ TEST(parser, code_section_with_memory_size)
"3f000b"_bytes;
const auto code_bin = add_size_prefix(func_bin);
const auto section_contents = make_vec({code_bin});
const auto bin = bytes{wasm_prefix} + make_section(1, make_vec({make_functype({}, {})})) +
const auto bin = bytes{wasm_prefix} + make_section(1, make_vec({make_functype({}, {0x7f})})) +
make_section(3, "0100"_bytes) + make_section(5, make_vec({"0000"_bytes})) +
make_section(10, section_contents);
const auto module = parse(bin);
@@ -1125,10 +1126,16 @@ TEST(parser, code_section_fp_instructions)
0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf};

const auto metrics_table = fizzy::get_instruction_metrics_table();

for (const auto instr : fp_instructions)
{
auto func_bin = "00"_bytes // vec(locals)
+ i32_const(0) + i32_const(0) + bytes{instr};
const auto metrics = metrics_table[instr];
auto func_bin = "00"_bytes; // vec(locals)
for (int i = 0; i < metrics.stack_height_required; ++i)
func_bin += i32_const(0);
func_bin += bytes{instr};

switch (instr)
{
case 0x2a: // f32.load
@@ -1144,7 +1151,11 @@ TEST(parser, code_section_fp_instructions)
func_bin += bytes(8, 0);
break;
}
func_bin += bytes{0xb}; // end

if (metrics.stack_height_required + metrics.stack_height_change == 1)
func_bin += bytes{0x1a}; // drop
func_bin += bytes{0xb}; // end

const auto code_bin = add_size_prefix(func_bin);
const auto code_section = make_vec({code_bin});
const auto function_section = make_vec({"00"_bytes});
42 changes: 42 additions & 0 deletions test/unittests/validation_stack_test.cpp
Original file line number Diff line number Diff line change
@@ -90,6 +90,19 @@ TEST(validation_stack, block_with_result_stack_underflow)
EXPECT_THROW_MESSAGE(parse(wasm), validation_error, "stack underflow");
}

TEST(validation_stack, DISABLED_block_too_many_results)
{
/* wat2wasm --no-check
(func
(block
get_local 0 ;; Leaves an item on the stack what makes the block invalid.
)
)
*/
const auto wasm = from_hex("0061736d01000000010401600000030201000a09010700024020000b0b");
EXPECT_THROW_MESSAGE(parse(wasm), validation_error, "too many results");
}

TEST(validation_stack, loop_stack_underflow)
{
/* wat2wasm --no-check
@@ -147,6 +160,35 @@ TEST(validation_stack, loop_with_result_stack_underflow)
EXPECT_THROW_MESSAGE(parse(wasm), validation_error, "stack underflow");
}

TEST(validation_stack, DISABLED_loop_too_many_results)
{
/* wat2wasm --no-check
(func
(loop
get_local 0 ;; Leaves an item on the stack what makes the loop invalid.
)
)
*/
const auto wasm = from_hex("0061736d01000000010401600000030201000a09010700034020000b0b");
EXPECT_THROW_MESSAGE(parse(wasm), validation_error, "too many results");

/* wat2wasm --no-check
(func (param i32)
(loop
local.get 0 ;; This is the input argument.
i32.const 1
i32.sub
local.tee 0
br_if 0
local.get 0 ;; Leaves an item on the stack what makes the loop invalid.
)
)
*/
const auto wasm2 =
from_hex("0061736d0100000001050160017f00030201000a120110000340200041016b22000d0020000b0b");
EXPECT_THROW_MESSAGE(parse(wasm2), validation_error, "too many results");
}

TEST(validation_stack, call_stack_underflow)
{
/* wat2wasm --no-check