From bcfa400306bf74e380c7bc38cd5cab498c7d224c Mon Sep 17 00:00:00 2001 From: titzer Date: Fri, 4 Mar 2016 15:48:00 -0800 Subject: [PATCH] [wasm] Remove TableSwitch and replace with br_table. R=rossberg@chromium.org,binji@chromium.org,bradnelson@chromium.org BUG= Review URL: https://codereview.chromium.org/1764723002 Cr-Commit-Position: refs/heads/master@{#34511} --- src/wasm/ast-decoder.cc | 100 ++--- src/wasm/ast-decoder.h | 17 +- src/wasm/wasm-macro-gen.h | 11 +- src/wasm/wasm-opcodes.h | 2 +- test/cctest/wasm/test-run-wasm.cc | 388 ++++++++---------- test/unittests/wasm/ast-decoder-unittest.cc | 131 +++--- .../unittests/wasm/wasm-macro-gen-unittest.cc | 13 +- 7 files changed, 258 insertions(+), 404 deletions(-) diff --git a/src/wasm/ast-decoder.cc b/src/wasm/ast-decoder.cc index b4af1b388f..e56991a482 100644 --- a/src/wasm/ast-decoder.cc +++ b/src/wasm/ast-decoder.cc @@ -195,26 +195,14 @@ class WasmDecoder : public Decoder { return false; } - bool Validate(const byte* pc, TableSwitchOperand& operand, + bool Validate(const byte* pc, BranchTableOperand& operand, size_t block_depth) { - if (operand.table_count == 0) { - error(pc, "tableswitch with 0 entries"); - return false; - } // Verify table. - for (uint32_t i = 0; i < operand.table_count; i++) { + for (uint32_t i = 0; i < operand.table_count + 1; i++) { uint16_t target = operand.read_entry(this, i); - if (target >= 0x8000) { - size_t depth = target - 0x8000; - if (depth > block_depth) { - error(operand.table + i * 2, "improper branch in tableswitch"); - return false; - } - } else { - if (target >= operand.case_count) { - error(operand.table + i * 2, "invalid case target in tableswitch"); - return false; - } + if (target >= block_depth) { + error(operand.table + i * 2, "improper branch in br_table"); + return false; } } return true; @@ -280,9 +268,8 @@ class WasmDecoder : public Decoder { case kExprReturn: { return static_cast(function_env_->sig->return_count()); } - case kExprTableSwitch: { - TableSwitchOperand operand(this, pc); - return 1 + operand.case_count; + case kExprBrTable: { + return 1; } #define DECLARE_OPCODE_CASE(name, opcode, sig) \ @@ -344,8 +331,8 @@ class WasmDecoder : public Decoder { LocalIndexOperand operand(this, pc); return 1 + operand.length; } - case kExprTableSwitch: { - TableSwitchOperand operand(this, pc); + case kExprBrTable: { + BranchTableOperand operand(this, pc); return 1 + operand.length; } case kExprI8Const: @@ -656,10 +643,10 @@ class LR_WasmDecoder : public WasmDecoder { len = 1 + operand.length; break; } - case kExprTableSwitch: { - TableSwitchOperand operand(this, pc_); + case kExprBrTable: { + BranchTableOperand operand(this, pc_); if (Validate(pc_, operand, blocks_.size())) { - Shift(kAstEnd, 1 + operand.case_count); + Shift(kAstEnd, 1); } len = 1 + operand.length; break; @@ -1044,68 +1031,37 @@ class LR_WasmDecoder : public WasmDecoder { } break; } - case kExprTableSwitch: { + case kExprBrTable: { if (p->index == 1) { // Switch key finished. TypeCheckLast(p, kAstI32); if (failed()) break; - TableSwitchOperand operand(this, p->pc()); + BranchTableOperand operand(this, p->pc()); DCHECK(Validate(p->pc(), operand, blocks_.size())); - // Build the switch only if it has more than just a default target. - bool build_switch = operand.table_count > 1; + // Build a switch only if it has more than just a default target. + bool build_switch = operand.table_count > 0; TFNode* sw = nullptr; - if (build_switch) - sw = BUILD(Switch, operand.table_count, p->last()->node); - - // Allocate environments for each case. - SsaEnv** case_envs = zone_->NewArray(operand.case_count); - for (uint32_t i = 0; i < operand.case_count; i++) { - case_envs[i] = UnreachableEnv(); + if (build_switch) { + sw = BUILD(Switch, operand.table_count + 1, p->last()->node); } - ifs_.push_back({nullptr, nullptr, case_envs}); - SsaEnv* break_env = ssa_env_; - PushBlock(break_env); - SsaEnv* copy = Steal(break_env); - ssa_env_ = copy; - - // Build the environments for each case based on the table. - for (uint32_t i = 0; i < operand.table_count; i++) { + // Process the targets of the break table. + SsaEnv* prev = ssa_env_; + SsaEnv* copy = Steal(prev); + for (uint32_t i = 0; i < operand.table_count + 1; i++) { uint16_t target = operand.read_entry(this, i); SsaEnv* env = copy; if (build_switch) { - env = Split(env); - env->control = (i == operand.table_count - 1) - ? BUILD(IfDefault, sw) - : BUILD(IfValue, i, sw); - } - if (target >= 0x8000) { - // Targets an outer block. - int depth = target - 0x8000; - SsaEnv* tenv = blocks_[blocks_.size() - depth - 1].ssa_env; - Goto(env, tenv); - } else { - // Targets a case. - Goto(env, case_envs[target]); + ssa_env_ = env = Split(env); + env->control = i == operand.table_count ? BUILD(IfDefault, sw) + : BUILD(IfValue, i, sw); } + SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env; + Goto(env, tenv); } - } - - if (p->done()) { - // Last case. Fall through to the end. - Block* block = &blocks_.back(); - if (p->index > 1) ReduceBreakToExprBlock(p, block); - SsaEnv* next = block->ssa_env; - blocks_.pop_back(); - ifs_.pop_back(); - SetEnv("switch:end", next); - } else { - // Interior case. Maybe fall through to the next case. - SsaEnv* next = ifs_.back().case_envs[p->index - 1]; - if (p->index > 1 && ssa_env_->go()) Goto(ssa_env_, next); - SetEnv("switch:case", next); + ssa_env_ = prev; } break; } diff --git a/src/wasm/ast-decoder.h b/src/wasm/ast-decoder.h index d173986e72..4693af1ca0 100644 --- a/src/wasm/ast-decoder.h +++ b/src/wasm/ast-decoder.h @@ -142,24 +142,23 @@ struct ImportIndexOperand { } }; -struct TableSwitchOperand { - uint32_t case_count; +struct BranchTableOperand { uint32_t table_count; const byte* table; int length; - inline TableSwitchOperand(Decoder* decoder, const byte* pc) { - case_count = decoder->checked_read_u16(pc, 1, "expected #cases"); - table_count = decoder->checked_read_u16(pc, 3, "expected #entries"); - length = 4 + table_count * 2; + inline BranchTableOperand(Decoder* decoder, const byte* pc) { + table_count = decoder->checked_read_u16(pc, 1, "expected #entries"); + length = 2 + table_count * 2 + 2; - if (decoder->check(pc, 5, table_count * 2, "expected ")) { - table = pc + 5; + if (decoder->check(pc, 3, table_count * 2 + 2, + "expected
")) { + table = pc + 3; } else { table = nullptr; } } inline uint16_t read_entry(Decoder* decoder, int i) { - DCHECK(i >= 0 && static_cast(i) < table_count); + DCHECK(i >= 0 && static_cast(i) <= table_count); return table ? decoder->read_u16(table + i * sizeof(uint16_t)) : 0; } }; diff --git a/src/wasm/wasm-macro-gen.h b/src/wasm/wasm-macro-gen.h index a83c34504d..dc7a9a1c96 100644 --- a/src/wasm/wasm-macro-gen.h +++ b/src/wasm/wasm-macro-gen.h @@ -33,14 +33,8 @@ #define WASM_RETURN(...) kExprReturn, __VA_ARGS__ #define WASM_UNREACHABLE kExprUnreachable -#define WASM_TABLESWITCH_OP(case_count, table_count, ...) \ - kExprTableSwitch, static_cast(case_count), \ - static_cast(case_count >> 8), static_cast(table_count), \ - static_cast(table_count >> 8), __VA_ARGS__ - -#define WASM_TABLESWITCH_BODY0(key) key - -#define WASM_TABLESWITCH_BODY(key, ...) key, __VA_ARGS__ +#define WASM_BR_TABLE(key, count, ...) \ + kExprBrTable, U16_LE(count), __VA_ARGS__, key #define WASM_CASE(x) static_cast(x), static_cast(x >> 8) #define WASM_CASE_BR(x) static_cast(x), static_cast(0x80 | (x) >> 8) @@ -407,6 +401,7 @@ inline void CheckI64v(int64_t value, int length) { #define SIG_INDEX(v) U16_LE(v) #define FUNC_INDEX(v) U16_LE(v) #define NAME_OFFSET(v) U32_LE(v) +#define BR_TARGET(v) U16_LE(v) #define MASK_7 ((1 << 7) - 1) #define MASK_14 ((1 << 14) - 1) diff --git a/src/wasm/wasm-opcodes.h b/src/wasm/wasm-opcodes.h index e4274e20ea..106572ce99 100644 --- a/src/wasm/wasm-opcodes.h +++ b/src/wasm/wasm-opcodes.h @@ -80,7 +80,7 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function); V(Select, 0x05, _) \ V(Br, 0x06, _) \ V(BrIf, 0x07, _) \ - V(TableSwitch, 0x08, _) \ + V(BrTable, 0x08, _) \ V(Return, 0x14, _) \ V(Unreachable, 0x15, _) diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc index 7df2e5739b..c29c52cdb6 100644 --- a/test/cctest/wasm/test-run-wasm.cc +++ b/test/cctest/wasm/test-run-wasm.cc @@ -18,6 +18,12 @@ using namespace v8::internal; using namespace v8::internal::compiler; using namespace v8::internal::wasm; +// for even shorter tests. +#define B2(a, b) kExprBlock, 2, a, b +#define B1(a) kExprBlock, 1, a +#define RET(x) kExprReturn, x +#define RET_I8(x) kExprReturn, kExprI8Const, x + TEST(Run_WasmInt8Const) { WasmRunner r; const byte kExpectedValue = 121; @@ -876,7 +882,7 @@ TEST(Run_Wasm_IfElse_Unreachable1) { TEST(Run_Wasm_Return12) { WasmRunner r; - BUILD(r, WASM_RETURN(WASM_I8(12))); + BUILD(r, RET_I8(12)); CHECK_EQ(12, r.Call()); } @@ -884,7 +890,7 @@ TEST(Run_Wasm_Return12) { TEST(Run_Wasm_Return17) { WasmRunner r; - BUILD(r, WASM_BLOCK(1, WASM_RETURN(WASM_I8(17)))); + BUILD(r, B1(RET_I8(17))); CHECK_EQ(17, r.Call()); } @@ -892,7 +898,7 @@ TEST(Run_Wasm_Return17) { TEST(Run_Wasm_Return_I32) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); + BUILD(r, RET(WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } @@ -902,7 +908,7 @@ TEST(Run_Wasm_Return_I32) { TEST(Run_Wasm_Return_I64) { WasmRunner r(MachineType::Int64()); - BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); + BUILD(r, RET(WASM_GET_LOCAL(0))); FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } @@ -912,7 +918,7 @@ TEST(Run_Wasm_Return_I64) { TEST(Run_Wasm_Return_F32) { WasmRunner r(MachineType::Float32()); - BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); + BUILD(r, RET(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { float expect = *i; @@ -929,7 +935,7 @@ TEST(Run_Wasm_Return_F32) { TEST(Run_Wasm_Return_F64) { WasmRunner r(MachineType::Float64()); - BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); + BUILD(r, RET(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { double expect = *i; @@ -957,10 +963,10 @@ TEST(Run_Wasm_Select) { TEST(Run_Wasm_Select_strict1) { WasmRunner r(MachineType::Int32()); // select(a=0, a=1, a=2); return a - BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)), - WASM_SET_LOCAL(0, WASM_I8(1)), - WASM_SET_LOCAL(0, WASM_I8(2))), - WASM_GET_LOCAL(0))); + BUILD(r, B2(WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)), + WASM_SET_LOCAL(0, WASM_I8(1)), + WASM_SET_LOCAL(0, WASM_I8(2))), + WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); } } @@ -993,55 +999,67 @@ TEST(Run_Wasm_Select_strict3) { TEST(Run_Wasm_BrIf_strict) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK( - 2, WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), - WASM_SET_LOCAL(0, WASM_I8(99)))), - WASM_GET_LOCAL(0))); + BUILD( + r, + B2(B1(WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(99)))), + WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); } } -TEST(Run_Wasm_TableSwitch0a) { +TEST(Run_Wasm_BrTable0a) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)), - WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(91))); + BUILD(r, + B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), WASM_I8(91))); FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); } } -TEST(Run_Wasm_TableSwitch0b) { +TEST(Run_Wasm_BrTable0b) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK( - 2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(0)), - WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(92))); + BUILD(r, + B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(0))), + WASM_I8(92))); FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); } } -TEST(Run_Wasm_TableSwitch0c) { +TEST(Run_Wasm_BrTable0c) { WasmRunner r(MachineType::Int32()); - BUILD(r, - WASM_BLOCK(2, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), - WASM_CASE_BR(1)), - WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), - WASM_RETURN(WASM_I8(76))), - WASM_I8(77))); + BUILD( + r, + B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(1))), + RET_I8(76)), + WASM_I8(77))); FOR_INT32_INPUTS(i) { int32_t expected = *i == 0 ? 76 : 77; CHECK_EQ(expected, r.Call(*i)); } } -TEST(Run_Wasm_TableSwitch1) { +TEST(Run_Wasm_BrTable1) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(93)))); + BUILD(r, B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), RET_I8(93)); FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); } } - -TEST(Run_Wasm_TableSwitch_br) { +TEST(Run_Wasm_BrTable_loop) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_TABLESWITCH_OP(1, 2, WASM_CASE_BR(0), WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91))), + BUILD(r, + B2(WASM_LOOP(1, WASM_BR_TABLE(WASM_INC_LOCAL_BY(0, 1), 2, BR_TARGET(2), + BR_TARGET(1), BR_TARGET(0))), + RET_I8(99)), + WASM_I8(98)); + CHECK_EQ(99, r.Call(0)); + CHECK_EQ(98, r.Call(-1)); + CHECK_EQ(98, r.Call(-2)); + CHECK_EQ(98, r.Call(-3)); + CHECK_EQ(98, r.Call(-100)); +} + +TEST(Run_Wasm_BrTable_br) { + WasmRunner r(MachineType::Int32()); + BUILD(r, + B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(1), BR_TARGET(0))), + RET_I8(91)), WASM_I8(99)); CHECK_EQ(99, r.Call(0)); CHECK_EQ(91, r.Call(1)); @@ -1049,17 +1067,14 @@ TEST(Run_Wasm_TableSwitch_br) { CHECK_EQ(91, r.Call(3)); } - -TEST(Run_Wasm_TableSwitch_br2) { +TEST(Run_Wasm_BrTable_br2) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK( - 2, WASM_BLOCK(2, WASM_TABLESWITCH_OP( - 1, 4, WASM_CASE_BR(0), WASM_CASE_BR(1), - WASM_CASE_BR(2), WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), - WASM_RETURN(WASM_I8(85))), - WASM_RETURN(WASM_I8(86))), - WASM_RETURN(WASM_I8(87))), + + BUILD(r, B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(1), + BR_TARGET(2), BR_TARGET(3), BR_TARGET(0))), + RET_I8(85)), + RET_I8(86)), + RET_I8(87)), WASM_I8(88)); CHECK_EQ(86, r.Call(0)); CHECK_EQ(87, r.Call(1)); @@ -1069,95 +1084,74 @@ TEST(Run_Wasm_TableSwitch_br2) { CHECK_EQ(85, r.Call(5)); } - -TEST(Run_Wasm_TableSwitch2) { - WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91)), - WASM_RETURN(WASM_I8(92)))); - FOR_INT32_INPUTS(i) { - int32_t expected = *i == 0 ? 91 : 92; - CHECK_EQ(expected, r.Call(*i)); - } -} - - -TEST(Run_Wasm_TableSwitch2b) { - WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(1), WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(81)), - WASM_RETURN(WASM_I8(82)))); - FOR_INT32_INPUTS(i) { - int32_t expected = *i == 0 ? 82 : 81; - CHECK_EQ(expected, r.Call(*i)); - } -} - - -TEST(Run_Wasm_TableSwitch4) { +TEST(Run_Wasm_BrTable4) { for (int i = 0; i < 4; i++) { - const uint16_t br = 0x8000u; - uint16_t c = 0; - uint16_t cases[] = {i == 0 ? br : c++, i == 1 ? br : c++, i == 2 ? br : c++, - i == 3 ? br : c++}; - byte code[] = { - WASM_BLOCK(1, WASM_TABLESWITCH_OP( - 3, 4, WASM_CASE(cases[0]), WASM_CASE(cases[1]), - WASM_CASE(cases[2]), WASM_CASE(cases[3])), - WASM_TABLESWITCH_BODY( - WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(71)), - WASM_RETURN(WASM_I8(72)), WASM_RETURN(WASM_I8(73)))), - WASM_RETURN(WASM_I8(74))}; + for (int t = 0; t < 4; t++) { + uint16_t cases[] = {0, 1, 2, 3}; + cases[i] = t; + byte code[] = {B2(B2(B2(B2(B1(WASM_BR_TABLE( + WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]), + BR_TARGET(cases[1]), BR_TARGET(cases[2]), + BR_TARGET(cases[3]))), + RET_I8(70)), + RET_I8(71)), + RET_I8(72)), + RET_I8(73)), + WASM_I8(75)}; - WasmRunner r(MachineType::Int32()); - r.Build(code, code + arraysize(code)); + WasmRunner r(MachineType::Int32()); + r.Build(code, code + arraysize(code)); - FOR_INT32_INPUTS(i) { - int index = (*i < 0 || *i > 3) ? 3 : *i; - int32_t expected = 71 + cases[index]; - if (expected >= 0x8000) expected = 74; - CHECK_EQ(expected, r.Call(*i)); + for (int x = -3; x < 50; x++) { + int index = (x > 3 || x < 0) ? 3 : x; + int32_t expected = 70 + cases[index]; + CHECK_EQ(expected, r.Call(x)); + } } } } +TEST(Run_Wasm_BrTable4x4) { + for (byte a = 0; a < 4; a++) { + for (byte b = 0; b < 4; b++) { + for (byte c = 0; c < 4; c++) { + for (byte d = 0; d < 4; d++) { + for (int i = 0; i < 4; i++) { + uint16_t cases[] = {a, b, c, d}; + byte code[] = { + B2(B2(B2(B2(B1(WASM_BR_TABLE( + WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]), + BR_TARGET(cases[1]), BR_TARGET(cases[2]), + BR_TARGET(cases[3]))), + RET_I8(50)), + RET_I8(51)), + RET_I8(52)), + RET_I8(53)), + WASM_I8(55)}; -TEST(Run_Wasm_TableSwitch4b) { - for (int a = 0; a < 2; a++) { - for (int b = 0; b < 2; b++) { - for (int c = 0; c < 2; c++) { - for (int d = 0; d < 2; d++) { - if (a + b + c + d == 0) continue; - if (a + b + c + d == 4) continue; + WasmRunner r(MachineType::Int32()); + r.Build(code, code + arraysize(code)); - byte code[] = { - WASM_TABLESWITCH_OP(2, 4, WASM_CASE(a), WASM_CASE(b), - WASM_CASE(c), WASM_CASE(d)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(61)), - WASM_RETURN(WASM_I8(62)))}; - - WasmRunner r(MachineType::Int32()); - r.Build(code, code + arraysize(code)); - - CHECK_EQ(61 + a, r.Call(0)); - CHECK_EQ(61 + b, r.Call(1)); - CHECK_EQ(61 + c, r.Call(2)); - CHECK_EQ(61 + d, r.Call(3)); - CHECK_EQ(61 + d, r.Call(4)); + for (int x = -6; x < 47; x++) { + int index = (x > 3 || x < 0) ? 3 : x; + int32_t expected = 50 + cases[index]; + CHECK_EQ(expected, r.Call(x)); + } + } } } } } } - -TEST(Run_Wasm_TableSwitch4_fallthru) { +TEST(Run_Wasm_BrTable4_fallthru) { byte code[] = { - WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2), - WASM_CASE(3)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1), - WASM_INC_LOCAL_BY(1, 2), WASM_INC_LOCAL_BY(1, 4), - WASM_INC_LOCAL_BY(1, 8)), + B2(B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(0), + BR_TARGET(1), BR_TARGET(2), BR_TARGET(3))), + WASM_INC_LOCAL_BY(1, 1)), + WASM_INC_LOCAL_BY(1, 2)), + WASM_INC_LOCAL_BY(1, 4)), + WASM_INC_LOCAL_BY(1, 8)), WASM_GET_LOCAL(1)}; WasmRunner r(MachineType::Int32(), MachineType::Int32()); @@ -1176,34 +1170,6 @@ TEST(Run_Wasm_TableSwitch4_fallthru) { CHECK_EQ(108, r.Call(4, 100)); } - -TEST(Run_Wasm_TableSwitch4_fallthru_br) { - byte code[] = { - WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2), - WASM_CASE(3)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1), - WASM_BRV(0, WASM_INC_LOCAL_BY(1, 2)), - WASM_INC_LOCAL_BY(1, 4), - WASM_BRV(0, WASM_INC_LOCAL_BY(1, 8))), - WASM_GET_LOCAL(1)}; - - WasmRunner r(MachineType::Int32(), MachineType::Int32()); - r.Build(code, code + arraysize(code)); - - CHECK_EQ(3, r.Call(0, 0)); - CHECK_EQ(2, r.Call(1, 0)); - CHECK_EQ(12, r.Call(2, 0)); - CHECK_EQ(8, r.Call(3, 0)); - CHECK_EQ(8, r.Call(4, 0)); - - CHECK_EQ(203, r.Call(0, 200)); - CHECK_EQ(202, r.Call(1, 200)); - CHECK_EQ(212, r.Call(2, 200)); - CHECK_EQ(208, r.Call(3, 200)); - CHECK_EQ(208, r.Call(4, 200)); -} - - TEST(Run_Wasm_F32ReinterpretI32) { TestingModule module; int32_t* memory = module.AddMemoryElems(8); @@ -1268,7 +1234,7 @@ TEST(Run_Wasm_VoidReturn1) { // Build the calling function. WasmRunner r; r.env()->module = &module; - BUILD(r, WASM_BLOCK(2, WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected))); + BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected))); int32_t result = r.Call(); CHECK_EQ(kExpected, result); @@ -1288,7 +1254,7 @@ TEST(Run_Wasm_VoidReturn2) { // Build the calling function. WasmRunner r; r.env()->module = &module; - BUILD(r, WASM_BLOCK(2, WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected))); + BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected))); int32_t result = r.Call(); CHECK_EQ(kExpected, result); @@ -1298,10 +1264,10 @@ TEST(Run_Wasm_VoidReturn2) { TEST(Run_Wasm_Block_If_P) { WasmRunner r(MachineType::Int32()); // { if (p0) return 51; return 52; } - BUILD(r, WASM_BLOCK(2, // -- - WASM_IF(WASM_GET_LOCAL(0), // -- - WASM_BRV(0, WASM_I8(51))), // -- - WASM_I8(52))); // -- + BUILD(r, B2( // -- + WASM_IF(WASM_GET_LOCAL(0), // -- + WASM_BRV(0, WASM_I8(51))), // -- + WASM_I8(52))); // -- FOR_INT32_INPUTS(i) { int32_t expected = *i ? 51 : 52; CHECK_EQ(expected, r.Call(*i)); @@ -1311,8 +1277,7 @@ TEST(Run_Wasm_Block_If_P) { TEST(Run_Wasm_Block_BrIf_P) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), - WASM_I8(52))); + BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), WASM_I8(52))); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 51 : 52; CHECK_EQ(expected, r.Call(*i)); @@ -1323,11 +1288,11 @@ TEST(Run_Wasm_Block_BrIf_P) { TEST(Run_Wasm_Block_IfElse_P_assign) { WasmRunner r(MachineType::Int32()); // { if (p0) p0 = 71; else p0 = 72; return p0; } - BUILD(r, WASM_BLOCK(2, // -- - WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- - WASM_SET_LOCAL(0, WASM_I8(71)), // -- - WASM_SET_LOCAL(0, WASM_I8(72))), // -- - WASM_GET_LOCAL(0))); + BUILD(r, B2( // -- + WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- + WASM_SET_LOCAL(0, WASM_I8(71)), // -- + WASM_SET_LOCAL(0, WASM_I8(72))), // -- + WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 71 : 72; CHECK_EQ(expected, r.Call(*i)); @@ -1338,10 +1303,10 @@ TEST(Run_Wasm_Block_IfElse_P_assign) { TEST(Run_Wasm_Block_IfElse_P_return) { WasmRunner r(MachineType::Int32()); // if (p0) return 81; else return 82; - BUILD(r, // -- - WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- - WASM_RETURN(WASM_I8(81)), // -- - WASM_RETURN(WASM_I8(82)))); // -- + BUILD(r, // -- + WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- + RET_I8(81), // -- + RET_I8(82))); // -- FOR_INT32_INPUTS(i) { int32_t expected = *i ? 81 : 82; CHECK_EQ(expected, r.Call(*i)); @@ -1365,8 +1330,7 @@ TEST(Run_Wasm_Block_If_P_assign) { TEST(Run_Wasm_DanglingAssign) { WasmRunner r(MachineType::Int32()); // { return 0; p0 = 0; } - BUILD(r, - WASM_BLOCK(2, WASM_RETURN(WASM_I8(99)), WASM_SET_LOCAL(0, WASM_ZERO))); + BUILD(r, B2(RET_I8(99), WASM_SET_LOCAL(0, WASM_ZERO))); CHECK_EQ(99, r.Call(1)); } @@ -1443,9 +1407,9 @@ TEST(Run_Wasm_WhileCountDown) { TEST(Run_Wasm_Loop_if_break1) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)), - WASM_SET_LOCAL(0, WASM_I8(99))), - WASM_GET_LOCAL(0))); + BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)), + WASM_SET_LOCAL(0, WASM_I8(99))), + WASM_GET_LOCAL(0))); CHECK_EQ(99, r.Call(0)); CHECK_EQ(3, r.Call(3)); CHECK_EQ(10000, r.Call(10000)); @@ -1455,9 +1419,9 @@ TEST(Run_Wasm_Loop_if_break1) { TEST(Run_Wasm_Loop_if_break2) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)), - WASM_SET_LOCAL(0, WASM_I8(99))), - WASM_GET_LOCAL(0))); + BUILD(r, B2(WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)), + WASM_SET_LOCAL(0, WASM_I8(99))), + WASM_GET_LOCAL(0))); CHECK_EQ(99, r.Call(0)); CHECK_EQ(3, r.Call(3)); CHECK_EQ(10000, r.Call(10000)); @@ -1467,8 +1431,8 @@ TEST(Run_Wasm_Loop_if_break2) { TEST(Run_Wasm_Loop_if_break_fallthru) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(1, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)), - WASM_SET_LOCAL(0, WASM_I8(93)))), + BUILD(r, B1(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)), + WASM_SET_LOCAL(0, WASM_I8(93)))), WASM_GET_LOCAL(0)); CHECK_EQ(93, r.Call(0)); CHECK_EQ(3, r.Call(3)); @@ -1950,8 +1914,7 @@ TEST(Build_Wasm_Infinite_Loop_effect) { TEST(Run_Wasm_Unreachable0a) { WasmRunner r(MachineType::Int32()); - BUILD(r, - WASM_BLOCK(2, WASM_BRV(0, WASM_I8(9)), WASM_RETURN(WASM_GET_LOCAL(0)))); + BUILD(r, B2(WASM_BRV(0, WASM_I8(9)), RET(WASM_GET_LOCAL(0)))); CHECK_EQ(9, r.Call(0)); CHECK_EQ(9, r.Call(1)); } @@ -1959,7 +1922,7 @@ TEST(Run_Wasm_Unreachable0a) { TEST(Run_Wasm_Unreachable0b) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE)); + BUILD(r, B2(WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE)); CHECK_EQ(7, r.Call(0)); CHECK_EQ(7, r.Call(1)); } @@ -1998,8 +1961,8 @@ TEST(Build_Wasm_UnreachableIf2) { TEST(Run_Wasm_Unreachable_Load) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_GET_LOCAL(0)), - WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)))); + BUILD(r, B2(WASM_BRV(0, WASM_GET_LOCAL(0)), + WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)))); CHECK_EQ(11, r.Call(11)); CHECK_EQ(21, r.Call(21)); } @@ -2007,8 +1970,7 @@ TEST(Run_Wasm_Unreachable_Load) { TEST(Run_Wasm_Infinite_Loop_not_taken1) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), - WASM_I8(45))); + BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I8(45))); // Run the code, but don't go into the infinite loop. CHECK_EQ(45, r.Call(0)); } @@ -2016,9 +1978,8 @@ TEST(Run_Wasm_Infinite_Loop_not_taken1) { TEST(Run_Wasm_Infinite_Loop_not_taken2) { WasmRunner r(MachineType::Int32()); - BUILD(r, - WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)), - WASM_INFINITE_LOOP))); + BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)), + WASM_INFINITE_LOOP))); // Run the code, but don't go into the infinite loop. CHECK_EQ(45, r.Call(1)); } @@ -2026,8 +1987,8 @@ TEST(Run_Wasm_Infinite_Loop_not_taken2) { TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), - WASM_INFINITE_LOOP)); + BUILD(r, + B2(WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), WASM_INFINITE_LOOP)); // Run the code, but don't go into the infinite loop. CHECK_EQ(45, r.Call(1)); } @@ -2186,11 +2147,10 @@ TEST(Run_WasmInt64Global) { int64_t* global = module.AddGlobal(MachineType::Int64()); WasmRunner r(&module, MachineType::Int32()); // global = global + p0 - BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( - 0, WASM_I64_ADD( - WASM_LOAD_GLOBAL(0), - WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))), - WASM_ZERO)); + BUILD(r, B2(WASM_STORE_GLOBAL( + 0, WASM_I64_ADD(WASM_LOAD_GLOBAL(0), + WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))), + WASM_ZERO)); *global = 0xFFFFFFFFFFFFFFFFLL; for (int i = 9; i < 444444; i += 111111) { @@ -2207,11 +2167,10 @@ TEST(Run_WasmFloat32Global) { float* global = module.AddGlobal(MachineType::Float32()); WasmRunner r(&module, MachineType::Int32()); // global = global + p0 - BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( - 0, WASM_F32_ADD( - WASM_LOAD_GLOBAL(0), - WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))), - WASM_ZERO)); + BUILD(r, B2(WASM_STORE_GLOBAL( + 0, WASM_F32_ADD(WASM_LOAD_GLOBAL(0), + WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))), + WASM_ZERO)); *global = 1.25; for (int i = 9; i < 4444; i += 1111) { @@ -2227,11 +2186,10 @@ TEST(Run_WasmFloat64Global) { double* global = module.AddGlobal(MachineType::Float64()); WasmRunner r(&module, MachineType::Int32()); // global = global + p0 - BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( - 0, WASM_F64_ADD( - WASM_LOAD_GLOBAL(0), - WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))), - WASM_ZERO)); + BUILD(r, B2(WASM_STORE_GLOBAL( + 0, WASM_F64_ADD(WASM_LOAD_GLOBAL(0), + WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))), + WASM_ZERO)); *global = 1.25; for (int i = 9; i < 4444; i += 1111) { @@ -2647,13 +2605,12 @@ TEST(Run_Wasm_AddCall) { WasmRunner r(&module, MachineType::Int32()); byte local = r.AllocateLocal(kAstI32); - BUILD(r, - WASM_BLOCK(2, WASM_SET_LOCAL(local, WASM_I8(99)), - WASM_I32_ADD( - WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0), - WASM_GET_LOCAL(0)), - WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(1), - WASM_GET_LOCAL(local))))); + BUILD(r, B2(WASM_SET_LOCAL(local, WASM_I8(99)), + WASM_I32_ADD( + WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0), + WASM_GET_LOCAL(0)), + WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(1), + WASM_GET_LOCAL(local))))); CHECK_EQ(198, r.Call(0)); CHECK_EQ(200, r.Call(1)); @@ -2675,8 +2632,7 @@ TEST(Run_Wasm_CountDown_expr) { TEST(Run_Wasm_ExprBlock2a) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), - WASM_I8(1))); + BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(1))); CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(1)); } @@ -2684,8 +2640,7 @@ TEST(Run_Wasm_ExprBlock2a) { TEST(Run_Wasm_ExprBlock2b) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), - WASM_I8(2))); + BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(2))); CHECK_EQ(2, r.Call(0)); CHECK_EQ(1, r.Call(1)); } @@ -2693,8 +2648,7 @@ TEST(Run_Wasm_ExprBlock2b) { TEST(Run_Wasm_ExprBlock2c) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), - WASM_I8(1))); + BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(1))); CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(1)); } @@ -2702,8 +2656,7 @@ TEST(Run_Wasm_ExprBlock2c) { TEST(Run_Wasm_ExprBlock2d) { WasmRunner r(MachineType::Int32()); - BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), - WASM_I8(2))); + BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(2))); CHECK_EQ(2, r.Call(0)); CHECK_EQ(1, r.Call(1)); } @@ -2775,9 +2728,8 @@ TEST(Run_Wasm_nested_ifs) { TEST(Run_Wasm_ExprBlock_if) { WasmRunner r(MachineType::Int32()); - BUILD(r, - WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)), - WASM_BRV(0, WASM_I8(14))))); + BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)), + WASM_BRV(0, WASM_I8(14))))); CHECK_EQ(11, r.Call(1)); CHECK_EQ(14, r.Call(0)); diff --git a/test/unittests/wasm/ast-decoder-unittest.cc b/test/unittests/wasm/ast-decoder-unittest.cc index c14af0dd27..e491179c8c 100644 --- a/test/unittests/wasm/ast-decoder-unittest.cc +++ b/test/unittests/wasm/ast-decoder-unittest.cc @@ -1671,120 +1671,81 @@ TEST_F(AstDecoderTest, ExprBrIf_Unify) { } } -TEST_F(AstDecoderTest, TableSwitch0) { - static byte code[] = {kExprTableSwitch, 0, 0, 0, 0}; +TEST_F(AstDecoderTest, BrTable0) { + static byte code[] = {kExprBrTable, 0, 0}; EXPECT_FAILURE(&env_v_v, code); } -TEST_F(AstDecoderTest, TableSwitch0b) { - static byte code[] = {kExprTableSwitch, 0, 0, 0, 0, kExprI8Const, 11}; +TEST_F(AstDecoderTest, BrTable0b) { + static byte code[] = {kExprBrTable, 0, 0, kExprI8Const, 11}; EXPECT_FAILURE(&env_v_v, code); EXPECT_FAILURE(&env_i_i, code); } -TEST_F(AstDecoderTest, TableSwitch0c) { +TEST_F(AstDecoderTest, BrTable0c) { + static byte code[] = {kExprBrTable, 0, 1, 0, 0, kExprI8Const, 11}; + EXPECT_FAILURE(&env_v_v, code); + EXPECT_FAILURE(&env_i_i, code); +} + +TEST_F(AstDecoderTest, BrTable1a) { static byte code[] = { - WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)), WASM_I8(67))}; + WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 0, BR_TARGET(0)))}; EXPECT_VERIFIES(&env_v_v, code); } -TEST_F(AstDecoderTest, TableSwitch0d) { +TEST_F(AstDecoderTest, BrTable1b) { static byte code[] = { - WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(1)), - WASM_I8(67))}; - EXPECT_VERIFIES(&env_v_v, code); -} - -TEST_F(AstDecoderTest, TableSwitch1) { - static byte code[] = {WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_I8(0), WASM_I8(9))}; - EXPECT_VERIFIES(&env_i_i, code); + WASM_BLOCK(1, WASM_BR_TABLE(WASM_ZERO, 0, BR_TARGET(0)))}; EXPECT_VERIFIES(&env_v_v, code); + EXPECT_FAILURE(&env_i_i, code); EXPECT_FAILURE(&env_f_ff, code); EXPECT_FAILURE(&env_d_dd, code); } -TEST_F(AstDecoderTest, TableSwitch_off_end) { - static byte code[] = {WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_I8(0), WASM_I8(9))}; - for (size_t len = arraysize(code) - 1; len > 0; len--) { - Verify(kError, &env_v_v, code, code + len); - } -} - -TEST_F(AstDecoderTest, TableSwitch2) { +TEST_F(AstDecoderTest, BrTable2a) { static byte code[] = { - WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)), - WASM_TABLESWITCH_BODY(WASM_I8(3), WASM_I8(10), WASM_I8(11))}; - EXPECT_VERIFIES(&env_i_i, code); + WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(0)))}; EXPECT_VERIFIES(&env_v_v, code); - EXPECT_FAILURE(&env_f_ff, code); - EXPECT_FAILURE(&env_d_dd, code); } -TEST_F(AstDecoderTest, TableSwitch1b) { - EXPECT_VERIFIES_INLINE(&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_ZERO)); - - EXPECT_VERIFIES_INLINE(&env_f_ff, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_ZERO, WASM_F32(0.0))); - - EXPECT_VERIFIES_INLINE(&env_d_dd, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_ZERO, WASM_F64(0.0))); +TEST_F(AstDecoderTest, BrTable2b) { + static byte code[] = {WASM_BLOCK( + 1, WASM_BLOCK( + 1, WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(1))))}; + EXPECT_VERIFIES(&env_v_v, code); } -TEST_F(AstDecoderTest, TableSwitch_br1) { - for (int depth = 0; depth < 2; depth++) { - byte code[] = {WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)), - WASM_GET_LOCAL(0))}; - EXPECT_VERIFIES(&env_v_i, code); - EXPECT_FAILURE(&env_i_i, code); +TEST_F(AstDecoderTest, BrTable_off_end) { + static byte code[] = { + WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))}; + for (size_t len = 1; len < sizeof(code); len++) { + Verify(kError, &env_i_i, code, code + len); } } -TEST_F(AstDecoderTest, TableSwitch_invalid_br) { - for (int depth = 1; depth < 4; depth++) { - EXPECT_FAILURE_INLINE(&env_v_i, - WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)), - WASM_GET_LOCAL(0)); - EXPECT_FAILURE_INLINE( - &env_v_i, - WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(depth), WASM_CASE_BR(depth)), - WASM_GET_LOCAL(0)); +TEST_F(AstDecoderTest, BrTable_invalid_br1) { + for (int depth = 0; depth < 4; depth++) { + byte code[] = { + WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))}; + if (depth == 0) { + EXPECT_VERIFIES(&env_v_i, code); + } else { + EXPECT_FAILURE(&env_v_i, code); + } } } -TEST_F(AstDecoderTest, TableSwitch_invalid_case_ref) { - EXPECT_FAILURE_INLINE(&env_i_i, WASM_TABLESWITCH_OP(0, 1, WASM_CASE(0)), - WASM_GET_LOCAL(0)); - EXPECT_FAILURE_INLINE(&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(1)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_ZERO)); -} - -TEST_F(AstDecoderTest, TableSwitch1_br) { - EXPECT_VERIFIES_INLINE( - &env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_ZERO))); -} - -TEST_F(AstDecoderTest, TableSwitch2_br) { - EXPECT_VERIFIES_INLINE( - &env_i_i, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(0)), - WASM_BRV(0, WASM_I8(1)))); - - EXPECT_FAILURE_INLINE( - &env_f_ff, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)), - WASM_TABLESWITCH_BODY(WASM_ZERO, WASM_BRV(0, WASM_I8(3)), - WASM_BRV(0, WASM_I8(4)))); -} - -TEST_F(AstDecoderTest, TableSwitch2x2) { - EXPECT_VERIFIES_INLINE( - &env_i_i, WASM_TABLESWITCH_OP(2, 4, WASM_CASE(0), WASM_CASE(1), - WASM_CASE(0), WASM_CASE(1)), - WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(3)), - WASM_BRV(0, WASM_I8(4)))); +TEST_F(AstDecoderTest, BrTable_invalid_br2) { + for (int depth = 0; depth < 4; depth++) { + byte code[] = { + WASM_LOOP(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))}; + if (depth <= 1) { + EXPECT_VERIFIES(&env_v_i, code); + } else { + EXPECT_FAILURE(&env_v_i, code); + } + } } TEST_F(AstDecoderTest, ExprBreakNesting1) { diff --git a/test/unittests/wasm/wasm-macro-gen-unittest.cc b/test/unittests/wasm/wasm-macro-gen-unittest.cc index d6661cce7b..cb60b6c03f 100644 --- a/test/unittests/wasm/wasm-macro-gen-unittest.cc +++ b/test/unittests/wasm/wasm-macro-gen-unittest.cc @@ -92,17 +92,8 @@ TEST_F(WasmMacroGenTest, MacroStatements) { EXPECT_SIZE(3, WASM_CONTINUE(0)); } - -TEST_F(WasmMacroGenTest, TableSwitch) { - EXPECT_SIZE(2, WASM_CASE(9)); - EXPECT_SIZE(2, WASM_CASE_BR(11)); - - EXPECT_SIZE(7, WASM_TABLESWITCH_OP(0, 1, WASM_CASE(7))); - EXPECT_SIZE(9, WASM_TABLESWITCH_OP(0, 2, WASM_CASE(7), WASM_CASE(8))); - - EXPECT_SIZE(4, WASM_TABLESWITCH_BODY(WASM_I8(88), WASM_I8(77))); - EXPECT_SIZE( - 6, WASM_TABLESWITCH_BODY(WASM_I8(33), WASM_I8(44), WASM_GET_LOCAL(0))); +TEST_F(WasmMacroGenTest, BrTable) { + EXPECT_SIZE(7, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1))); }