Commit bcfa4003 authored by titzer's avatar titzer Committed by Commit bot

[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}
parent 38e2699c
...@@ -195,28 +195,16 @@ class WasmDecoder : public Decoder { ...@@ -195,28 +195,16 @@ class WasmDecoder : public Decoder {
return false; return false;
} }
bool Validate(const byte* pc, TableSwitchOperand& operand, bool Validate(const byte* pc, BranchTableOperand& operand,
size_t block_depth) { size_t block_depth) {
if (operand.table_count == 0) {
error(pc, "tableswitch with 0 entries");
return false;
}
// Verify table. // 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); uint16_t target = operand.read_entry(this, i);
if (target >= 0x8000) { if (target >= block_depth) {
size_t depth = target - 0x8000; error(operand.table + i * 2, "improper branch in br_table");
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; return false;
} }
} }
}
return true; return true;
} }
...@@ -280,9 +268,8 @@ class WasmDecoder : public Decoder { ...@@ -280,9 +268,8 @@ class WasmDecoder : public Decoder {
case kExprReturn: { case kExprReturn: {
return static_cast<int>(function_env_->sig->return_count()); return static_cast<int>(function_env_->sig->return_count());
} }
case kExprTableSwitch: { case kExprBrTable: {
TableSwitchOperand operand(this, pc); return 1;
return 1 + operand.case_count;
} }
#define DECLARE_OPCODE_CASE(name, opcode, sig) \ #define DECLARE_OPCODE_CASE(name, opcode, sig) \
...@@ -344,8 +331,8 @@ class WasmDecoder : public Decoder { ...@@ -344,8 +331,8 @@ class WasmDecoder : public Decoder {
LocalIndexOperand operand(this, pc); LocalIndexOperand operand(this, pc);
return 1 + operand.length; return 1 + operand.length;
} }
case kExprTableSwitch: { case kExprBrTable: {
TableSwitchOperand operand(this, pc); BranchTableOperand operand(this, pc);
return 1 + operand.length; return 1 + operand.length;
} }
case kExprI8Const: case kExprI8Const:
...@@ -656,10 +643,10 @@ class LR_WasmDecoder : public WasmDecoder { ...@@ -656,10 +643,10 @@ class LR_WasmDecoder : public WasmDecoder {
len = 1 + operand.length; len = 1 + operand.length;
break; break;
} }
case kExprTableSwitch: { case kExprBrTable: {
TableSwitchOperand operand(this, pc_); BranchTableOperand operand(this, pc_);
if (Validate(pc_, operand, blocks_.size())) { if (Validate(pc_, operand, blocks_.size())) {
Shift(kAstEnd, 1 + operand.case_count); Shift(kAstEnd, 1);
} }
len = 1 + operand.length; len = 1 + operand.length;
break; break;
...@@ -1044,68 +1031,37 @@ class LR_WasmDecoder : public WasmDecoder { ...@@ -1044,68 +1031,37 @@ class LR_WasmDecoder : public WasmDecoder {
} }
break; break;
} }
case kExprTableSwitch: { case kExprBrTable: {
if (p->index == 1) { if (p->index == 1) {
// Switch key finished. // Switch key finished.
TypeCheckLast(p, kAstI32); TypeCheckLast(p, kAstI32);
if (failed()) break; if (failed()) break;
TableSwitchOperand operand(this, p->pc()); BranchTableOperand operand(this, p->pc());
DCHECK(Validate(p->pc(), operand, blocks_.size())); DCHECK(Validate(p->pc(), operand, blocks_.size()));
// Build the switch only if it has more than just a default target. // Build a switch only if it has more than just a default target.
bool build_switch = operand.table_count > 1; bool build_switch = operand.table_count > 0;
TFNode* sw = nullptr; TFNode* sw = nullptr;
if (build_switch) if (build_switch) {
sw = BUILD(Switch, operand.table_count, p->last()->node); sw = BUILD(Switch, operand.table_count + 1, p->last()->node);
// Allocate environments for each case.
SsaEnv** case_envs = zone_->NewArray<SsaEnv*>(operand.case_count);
for (uint32_t i = 0; i < operand.case_count; i++) {
case_envs[i] = UnreachableEnv();
} }
ifs_.push_back({nullptr, nullptr, case_envs}); // Process the targets of the break table.
SsaEnv* break_env = ssa_env_; SsaEnv* prev = ssa_env_;
PushBlock(break_env); SsaEnv* copy = Steal(prev);
SsaEnv* copy = Steal(break_env); for (uint32_t i = 0; i < operand.table_count + 1; i++) {
ssa_env_ = copy;
// Build the environments for each case based on the table.
for (uint32_t i = 0; i < operand.table_count; i++) {
uint16_t target = operand.read_entry(this, i); uint16_t target = operand.read_entry(this, i);
SsaEnv* env = copy; SsaEnv* env = copy;
if (build_switch) { if (build_switch) {
env = Split(env); ssa_env_ = env = Split(env);
env->control = (i == operand.table_count - 1) env->control = i == operand.table_count ? BUILD(IfDefault, sw)
? BUILD(IfDefault, sw)
: BUILD(IfValue, i, sw); : BUILD(IfValue, i, sw);
} }
if (target >= 0x8000) { SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env;
// Targets an outer block.
int depth = target - 0x8000;
SsaEnv* tenv = blocks_[blocks_.size() - depth - 1].ssa_env;
Goto(env, tenv); Goto(env, tenv);
} else {
// Targets a case.
Goto(env, case_envs[target]);
}
}
} }
ssa_env_ = prev;
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);
} }
break; break;
} }
......
...@@ -142,24 +142,23 @@ struct ImportIndexOperand { ...@@ -142,24 +142,23 @@ struct ImportIndexOperand {
} }
}; };
struct TableSwitchOperand { struct BranchTableOperand {
uint32_t case_count;
uint32_t table_count; uint32_t table_count;
const byte* table; const byte* table;
int length; int length;
inline TableSwitchOperand(Decoder* decoder, const byte* pc) { inline BranchTableOperand(Decoder* decoder, const byte* pc) {
case_count = decoder->checked_read_u16(pc, 1, "expected #cases"); table_count = decoder->checked_read_u16(pc, 1, "expected #entries");
table_count = decoder->checked_read_u16(pc, 3, "expected #entries"); length = 2 + table_count * 2 + 2;
length = 4 + table_count * 2;
if (decoder->check(pc, 5, table_count * 2, "expected <table entries>")) { if (decoder->check(pc, 3, table_count * 2 + 2,
table = pc + 5; "expected <table entries>")) {
table = pc + 3;
} else { } else {
table = nullptr; table = nullptr;
} }
} }
inline uint16_t read_entry(Decoder* decoder, int i) { inline uint16_t read_entry(Decoder* decoder, int i) {
DCHECK(i >= 0 && static_cast<uint32_t>(i) < table_count); DCHECK(i >= 0 && static_cast<uint32_t>(i) <= table_count);
return table ? decoder->read_u16(table + i * sizeof(uint16_t)) : 0; return table ? decoder->read_u16(table + i * sizeof(uint16_t)) : 0;
} }
}; };
......
...@@ -33,14 +33,8 @@ ...@@ -33,14 +33,8 @@
#define WASM_RETURN(...) kExprReturn, __VA_ARGS__ #define WASM_RETURN(...) kExprReturn, __VA_ARGS__
#define WASM_UNREACHABLE kExprUnreachable #define WASM_UNREACHABLE kExprUnreachable
#define WASM_TABLESWITCH_OP(case_count, table_count, ...) \ #define WASM_BR_TABLE(key, count, ...) \
kExprTableSwitch, static_cast<byte>(case_count), \ kExprBrTable, U16_LE(count), __VA_ARGS__, key
static_cast<byte>(case_count >> 8), static_cast<byte>(table_count), \
static_cast<byte>(table_count >> 8), __VA_ARGS__
#define WASM_TABLESWITCH_BODY0(key) key
#define WASM_TABLESWITCH_BODY(key, ...) key, __VA_ARGS__
#define WASM_CASE(x) static_cast<byte>(x), static_cast<byte>(x >> 8) #define WASM_CASE(x) static_cast<byte>(x), static_cast<byte>(x >> 8)
#define WASM_CASE_BR(x) static_cast<byte>(x), static_cast<byte>(0x80 | (x) >> 8) #define WASM_CASE_BR(x) static_cast<byte>(x), static_cast<byte>(0x80 | (x) >> 8)
...@@ -407,6 +401,7 @@ inline void CheckI64v(int64_t value, int length) { ...@@ -407,6 +401,7 @@ inline void CheckI64v(int64_t value, int length) {
#define SIG_INDEX(v) U16_LE(v) #define SIG_INDEX(v) U16_LE(v)
#define FUNC_INDEX(v) U16_LE(v) #define FUNC_INDEX(v) U16_LE(v)
#define NAME_OFFSET(v) U32_LE(v) #define NAME_OFFSET(v) U32_LE(v)
#define BR_TARGET(v) U16_LE(v)
#define MASK_7 ((1 << 7) - 1) #define MASK_7 ((1 << 7) - 1)
#define MASK_14 ((1 << 14) - 1) #define MASK_14 ((1 << 14) - 1)
......
...@@ -80,7 +80,7 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function); ...@@ -80,7 +80,7 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
V(Select, 0x05, _) \ V(Select, 0x05, _) \
V(Br, 0x06, _) \ V(Br, 0x06, _) \
V(BrIf, 0x07, _) \ V(BrIf, 0x07, _) \
V(TableSwitch, 0x08, _) \ V(BrTable, 0x08, _) \
V(Return, 0x14, _) \ V(Return, 0x14, _) \
V(Unreachable, 0x15, _) V(Unreachable, 0x15, _)
......
...@@ -18,6 +18,12 @@ using namespace v8::internal; ...@@ -18,6 +18,12 @@ using namespace v8::internal;
using namespace v8::internal::compiler; using namespace v8::internal::compiler;
using namespace v8::internal::wasm; 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) { TEST(Run_WasmInt8Const) {
WasmRunner<int32_t> r; WasmRunner<int32_t> r;
const byte kExpectedValue = 121; const byte kExpectedValue = 121;
...@@ -876,7 +882,7 @@ TEST(Run_Wasm_IfElse_Unreachable1) { ...@@ -876,7 +882,7 @@ TEST(Run_Wasm_IfElse_Unreachable1) {
TEST(Run_Wasm_Return12) { TEST(Run_Wasm_Return12) {
WasmRunner<int32_t> r; WasmRunner<int32_t> r;
BUILD(r, WASM_RETURN(WASM_I8(12))); BUILD(r, RET_I8(12));
CHECK_EQ(12, r.Call()); CHECK_EQ(12, r.Call());
} }
...@@ -884,7 +890,7 @@ TEST(Run_Wasm_Return12) { ...@@ -884,7 +890,7 @@ TEST(Run_Wasm_Return12) {
TEST(Run_Wasm_Return17) { TEST(Run_Wasm_Return17) {
WasmRunner<int32_t> r; WasmRunner<int32_t> r;
BUILD(r, WASM_BLOCK(1, WASM_RETURN(WASM_I8(17)))); BUILD(r, B1(RET_I8(17)));
CHECK_EQ(17, r.Call()); CHECK_EQ(17, r.Call());
} }
...@@ -892,7 +898,7 @@ TEST(Run_Wasm_Return17) { ...@@ -892,7 +898,7 @@ TEST(Run_Wasm_Return17) {
TEST(Run_Wasm_Return_I32) { TEST(Run_Wasm_Return_I32) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> 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)); } FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
} }
...@@ -902,7 +908,7 @@ TEST(Run_Wasm_Return_I32) { ...@@ -902,7 +908,7 @@ TEST(Run_Wasm_Return_I32) {
TEST(Run_Wasm_Return_I64) { TEST(Run_Wasm_Return_I64) {
WasmRunner<int64_t> r(MachineType::Int64()); WasmRunner<int64_t> 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)); } FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
} }
...@@ -912,7 +918,7 @@ TEST(Run_Wasm_Return_I64) { ...@@ -912,7 +918,7 @@ TEST(Run_Wasm_Return_I64) {
TEST(Run_Wasm_Return_F32) { TEST(Run_Wasm_Return_F32) {
WasmRunner<float> r(MachineType::Float32()); WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); BUILD(r, RET(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { FOR_FLOAT32_INPUTS(i) {
float expect = *i; float expect = *i;
...@@ -929,7 +935,7 @@ TEST(Run_Wasm_Return_F32) { ...@@ -929,7 +935,7 @@ TEST(Run_Wasm_Return_F32) {
TEST(Run_Wasm_Return_F64) { TEST(Run_Wasm_Return_F64) {
WasmRunner<double> r(MachineType::Float64()); WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); BUILD(r, RET(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { FOR_FLOAT64_INPUTS(i) {
double expect = *i; double expect = *i;
...@@ -957,7 +963,7 @@ TEST(Run_Wasm_Select) { ...@@ -957,7 +963,7 @@ TEST(Run_Wasm_Select) {
TEST(Run_Wasm_Select_strict1) { TEST(Run_Wasm_Select_strict1) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
// select(a=0, a=1, a=2); return a // select(a=0, a=1, a=2); return a
BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(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(1)),
WASM_SET_LOCAL(0, WASM_I8(2))), WASM_SET_LOCAL(0, WASM_I8(2))),
WASM_GET_LOCAL(0))); WASM_GET_LOCAL(0)));
...@@ -993,36 +999,35 @@ TEST(Run_Wasm_Select_strict3) { ...@@ -993,36 +999,35 @@ TEST(Run_Wasm_Select_strict3) {
TEST(Run_Wasm_BrIf_strict) { TEST(Run_Wasm_BrIf_strict) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK( BUILD(
2, WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), r,
WASM_SET_LOCAL(0, WASM_I8(99)))), B2(B1(WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(99)))),
WASM_GET_LOCAL(0))); WASM_GET_LOCAL(0)));
FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); } FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
} }
TEST(Run_Wasm_TableSwitch0a) { TEST(Run_Wasm_BrTable0a) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)), BUILD(r,
WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(91))); 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)); } FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); }
} }
TEST(Run_Wasm_TableSwitch0b) { TEST(Run_Wasm_BrTable0b) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK( BUILD(r,
2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(0)), B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(0))),
WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(92))); WASM_I8(92)));
FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); } FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); }
} }
TEST(Run_Wasm_TableSwitch0c) { TEST(Run_Wasm_BrTable0c) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, BUILD(
WASM_BLOCK(2, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), r,
WASM_CASE_BR(1)), B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(1))),
WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), RET_I8(76)),
WASM_RETURN(WASM_I8(76))),
WASM_I8(77))); WASM_I8(77)));
FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(i) {
int32_t expected = *i == 0 ? 76 : 77; int32_t expected = *i == 0 ? 76 : 77;
...@@ -1030,18 +1035,31 @@ TEST(Run_Wasm_TableSwitch0c) { ...@@ -1030,18 +1035,31 @@ TEST(Run_Wasm_TableSwitch0c) {
} }
} }
TEST(Run_Wasm_TableSwitch1) { TEST(Run_Wasm_BrTable1) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), BUILD(r, B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), RET_I8(93));
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(93))));
FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); } FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); }
} }
TEST(Run_Wasm_BrTable_loop) {
WasmRunner<int32_t> r(MachineType::Int32());
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_TableSwitch_br) { TEST(Run_Wasm_BrTable_br) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_TABLESWITCH_OP(1, 2, WASM_CASE_BR(0), WASM_CASE(0)), BUILD(r,
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91))), B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(1), BR_TARGET(0))),
RET_I8(91)),
WASM_I8(99)); WASM_I8(99));
CHECK_EQ(99, r.Call(0)); CHECK_EQ(99, r.Call(0));
CHECK_EQ(91, r.Call(1)); CHECK_EQ(91, r.Call(1));
...@@ -1049,17 +1067,14 @@ TEST(Run_Wasm_TableSwitch_br) { ...@@ -1049,17 +1067,14 @@ TEST(Run_Wasm_TableSwitch_br) {
CHECK_EQ(91, r.Call(3)); CHECK_EQ(91, r.Call(3));
} }
TEST(Run_Wasm_BrTable_br2) {
TEST(Run_Wasm_TableSwitch_br2) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(
2, WASM_BLOCK(2, WASM_TABLESWITCH_OP( BUILD(r, B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(1),
1, 4, WASM_CASE_BR(0), WASM_CASE_BR(1), BR_TARGET(2), BR_TARGET(3), BR_TARGET(0))),
WASM_CASE_BR(2), WASM_CASE(0)), RET_I8(85)),
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), RET_I8(86)),
WASM_RETURN(WASM_I8(85))), RET_I8(87)),
WASM_RETURN(WASM_I8(86))),
WASM_RETURN(WASM_I8(87))),
WASM_I8(88)); WASM_I8(88));
CHECK_EQ(86, r.Call(0)); CHECK_EQ(86, r.Call(0));
CHECK_EQ(87, r.Call(1)); CHECK_EQ(87, r.Call(1));
...@@ -1069,94 +1084,73 @@ TEST(Run_Wasm_TableSwitch_br2) { ...@@ -1069,94 +1084,73 @@ TEST(Run_Wasm_TableSwitch_br2) {
CHECK_EQ(85, r.Call(5)); CHECK_EQ(85, r.Call(5));
} }
TEST(Run_Wasm_BrTable4) {
TEST(Run_Wasm_TableSwitch2) {
WasmRunner<int32_t> 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<int32_t> 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) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
const uint16_t br = 0x8000u; for (int t = 0; t < 4; t++) {
uint16_t c = 0; uint16_t cases[] = {0, 1, 2, 3};
uint16_t cases[] = {i == 0 ? br : c++, i == 1 ? br : c++, i == 2 ? br : c++, cases[i] = t;
i == 3 ? br : c++}; byte code[] = {B2(B2(B2(B2(B1(WASM_BR_TABLE(
byte code[] = { WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]),
WASM_BLOCK(1, WASM_TABLESWITCH_OP( BR_TARGET(cases[1]), BR_TARGET(cases[2]),
3, 4, WASM_CASE(cases[0]), WASM_CASE(cases[1]), BR_TARGET(cases[3]))),
WASM_CASE(cases[2]), WASM_CASE(cases[3])), RET_I8(70)),
WASM_TABLESWITCH_BODY( RET_I8(71)),
WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(71)), RET_I8(72)),
WASM_RETURN(WASM_I8(72)), WASM_RETURN(WASM_I8(73)))), RET_I8(73)),
WASM_RETURN(WASM_I8(74))}; WASM_I8(75)};
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
r.Build(code, code + arraysize(code)); r.Build(code, code + arraysize(code));
FOR_INT32_INPUTS(i) { for (int x = -3; x < 50; x++) {
int index = (*i < 0 || *i > 3) ? 3 : *i; int index = (x > 3 || x < 0) ? 3 : x;
int32_t expected = 71 + cases[index]; int32_t expected = 70 + cases[index];
if (expected >= 0x8000) expected = 74; CHECK_EQ(expected, r.Call(x));
CHECK_EQ(expected, r.Call(*i)); }
} }
} }
} }
TEST(Run_Wasm_BrTable4x4) {
TEST(Run_Wasm_TableSwitch4b) { for (byte a = 0; a < 4; a++) {
for (int a = 0; a < 2; a++) { for (byte b = 0; b < 4; b++) {
for (int b = 0; b < 2; b++) { for (byte c = 0; c < 4; c++) {
for (int c = 0; c < 2; c++) { for (byte d = 0; d < 4; d++) {
for (int d = 0; d < 2; d++) { for (int i = 0; i < 4; i++) {
if (a + b + c + d == 0) continue; uint16_t cases[] = {a, b, c, d};
if (a + b + c + d == 4) continue;
byte code[] = { byte code[] = {
WASM_TABLESWITCH_OP(2, 4, WASM_CASE(a), WASM_CASE(b), B2(B2(B2(B2(B1(WASM_BR_TABLE(
WASM_CASE(c), WASM_CASE(d)), WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]),
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(61)), BR_TARGET(cases[1]), BR_TARGET(cases[2]),
WASM_RETURN(WASM_I8(62)))}; BR_TARGET(cases[3]))),
RET_I8(50)),
RET_I8(51)),
RET_I8(52)),
RET_I8(53)),
WASM_I8(55)};
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
r.Build(code, code + arraysize(code)); r.Build(code, code + arraysize(code));
CHECK_EQ(61 + a, r.Call(0)); for (int x = -6; x < 47; x++) {
CHECK_EQ(61 + b, r.Call(1)); int index = (x > 3 || x < 0) ? 3 : x;
CHECK_EQ(61 + c, r.Call(2)); int32_t expected = 50 + cases[index];
CHECK_EQ(61 + d, r.Call(3)); CHECK_EQ(expected, r.Call(x));
CHECK_EQ(61 + d, r.Call(4)); }
}
} }
} }
} }
} }
} }
TEST(Run_Wasm_BrTable4_fallthru) {
TEST(Run_Wasm_TableSwitch4_fallthru) {
byte code[] = { byte code[] = {
WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2), B2(B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(0),
WASM_CASE(3)), BR_TARGET(1), BR_TARGET(2), BR_TARGET(3))),
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1), WASM_INC_LOCAL_BY(1, 1)),
WASM_INC_LOCAL_BY(1, 2), WASM_INC_LOCAL_BY(1, 4), WASM_INC_LOCAL_BY(1, 2)),
WASM_INC_LOCAL_BY(1, 4)),
WASM_INC_LOCAL_BY(1, 8)), WASM_INC_LOCAL_BY(1, 8)),
WASM_GET_LOCAL(1)}; WASM_GET_LOCAL(1)};
...@@ -1176,34 +1170,6 @@ TEST(Run_Wasm_TableSwitch4_fallthru) { ...@@ -1176,34 +1170,6 @@ TEST(Run_Wasm_TableSwitch4_fallthru) {
CHECK_EQ(108, r.Call(4, 100)); 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<int32_t> 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) { TEST(Run_Wasm_F32ReinterpretI32) {
TestingModule module; TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(8); int32_t* memory = module.AddMemoryElems<int32_t>(8);
...@@ -1268,7 +1234,7 @@ TEST(Run_Wasm_VoidReturn1) { ...@@ -1268,7 +1234,7 @@ TEST(Run_Wasm_VoidReturn1) {
// Build the calling function. // Build the calling function.
WasmRunner<int32_t> r; WasmRunner<int32_t> r;
r.env()->module = &module; 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(); int32_t result = r.Call();
CHECK_EQ(kExpected, result); CHECK_EQ(kExpected, result);
...@@ -1288,7 +1254,7 @@ TEST(Run_Wasm_VoidReturn2) { ...@@ -1288,7 +1254,7 @@ TEST(Run_Wasm_VoidReturn2) {
// Build the calling function. // Build the calling function.
WasmRunner<int32_t> r; WasmRunner<int32_t> r;
r.env()->module = &module; 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(); int32_t result = r.Call();
CHECK_EQ(kExpected, result); CHECK_EQ(kExpected, result);
...@@ -1298,7 +1264,7 @@ TEST(Run_Wasm_VoidReturn2) { ...@@ -1298,7 +1264,7 @@ TEST(Run_Wasm_VoidReturn2) {
TEST(Run_Wasm_Block_If_P) { TEST(Run_Wasm_Block_If_P) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
// { if (p0) return 51; return 52; } // { if (p0) return 51; return 52; }
BUILD(r, WASM_BLOCK(2, // -- BUILD(r, B2( // --
WASM_IF(WASM_GET_LOCAL(0), // -- WASM_IF(WASM_GET_LOCAL(0), // --
WASM_BRV(0, WASM_I8(51))), // -- WASM_BRV(0, WASM_I8(51))), // --
WASM_I8(52))); // -- WASM_I8(52))); // --
...@@ -1311,8 +1277,7 @@ TEST(Run_Wasm_Block_If_P) { ...@@ -1311,8 +1277,7 @@ TEST(Run_Wasm_Block_If_P) {
TEST(Run_Wasm_Block_BrIf_P) { TEST(Run_Wasm_Block_BrIf_P) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), WASM_I8(52)));
WASM_I8(52)));
FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(i) {
int32_t expected = *i ? 51 : 52; int32_t expected = *i ? 51 : 52;
CHECK_EQ(expected, r.Call(*i)); CHECK_EQ(expected, r.Call(*i));
...@@ -1323,7 +1288,7 @@ TEST(Run_Wasm_Block_BrIf_P) { ...@@ -1323,7 +1288,7 @@ TEST(Run_Wasm_Block_BrIf_P) {
TEST(Run_Wasm_Block_IfElse_P_assign) { TEST(Run_Wasm_Block_IfElse_P_assign) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
// { if (p0) p0 = 71; else p0 = 72; return p0; } // { if (p0) p0 = 71; else p0 = 72; return p0; }
BUILD(r, WASM_BLOCK(2, // -- BUILD(r, B2( // --
WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
WASM_SET_LOCAL(0, WASM_I8(71)), // -- WASM_SET_LOCAL(0, WASM_I8(71)), // --
WASM_SET_LOCAL(0, WASM_I8(72))), // -- WASM_SET_LOCAL(0, WASM_I8(72))), // --
...@@ -1340,8 +1305,8 @@ TEST(Run_Wasm_Block_IfElse_P_return) { ...@@ -1340,8 +1305,8 @@ TEST(Run_Wasm_Block_IfElse_P_return) {
// if (p0) return 81; else return 82; // if (p0) return 81; else return 82;
BUILD(r, // -- BUILD(r, // --
WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
WASM_RETURN(WASM_I8(81)), // -- RET_I8(81), // --
WASM_RETURN(WASM_I8(82)))); // -- RET_I8(82))); // --
FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(i) {
int32_t expected = *i ? 81 : 82; int32_t expected = *i ? 81 : 82;
CHECK_EQ(expected, r.Call(*i)); CHECK_EQ(expected, r.Call(*i));
...@@ -1365,8 +1330,7 @@ TEST(Run_Wasm_Block_If_P_assign) { ...@@ -1365,8 +1330,7 @@ TEST(Run_Wasm_Block_If_P_assign) {
TEST(Run_Wasm_DanglingAssign) { TEST(Run_Wasm_DanglingAssign) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
// { return 0; p0 = 0; } // { return 0; p0 = 0; }
BUILD(r, BUILD(r, B2(RET_I8(99), WASM_SET_LOCAL(0, WASM_ZERO)));
WASM_BLOCK(2, WASM_RETURN(WASM_I8(99)), WASM_SET_LOCAL(0, WASM_ZERO)));
CHECK_EQ(99, r.Call(1)); CHECK_EQ(99, r.Call(1));
} }
...@@ -1443,7 +1407,7 @@ TEST(Run_Wasm_WhileCountDown) { ...@@ -1443,7 +1407,7 @@ TEST(Run_Wasm_WhileCountDown) {
TEST(Run_Wasm_Loop_if_break1) { TEST(Run_Wasm_Loop_if_break1) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)), BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)),
WASM_SET_LOCAL(0, WASM_I8(99))), WASM_SET_LOCAL(0, WASM_I8(99))),
WASM_GET_LOCAL(0))); WASM_GET_LOCAL(0)));
CHECK_EQ(99, r.Call(0)); CHECK_EQ(99, r.Call(0));
...@@ -1455,7 +1419,7 @@ TEST(Run_Wasm_Loop_if_break1) { ...@@ -1455,7 +1419,7 @@ TEST(Run_Wasm_Loop_if_break1) {
TEST(Run_Wasm_Loop_if_break2) { TEST(Run_Wasm_Loop_if_break2) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_BR_IF(1, 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_SET_LOCAL(0, WASM_I8(99))),
WASM_GET_LOCAL(0))); WASM_GET_LOCAL(0)));
CHECK_EQ(99, r.Call(0)); CHECK_EQ(99, r.Call(0));
...@@ -1467,7 +1431,7 @@ TEST(Run_Wasm_Loop_if_break2) { ...@@ -1467,7 +1431,7 @@ TEST(Run_Wasm_Loop_if_break2) {
TEST(Run_Wasm_Loop_if_break_fallthru) { TEST(Run_Wasm_Loop_if_break_fallthru) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(1, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)), BUILD(r, B1(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
WASM_SET_LOCAL(0, WASM_I8(93)))), WASM_SET_LOCAL(0, WASM_I8(93)))),
WASM_GET_LOCAL(0)); WASM_GET_LOCAL(0));
CHECK_EQ(93, r.Call(0)); CHECK_EQ(93, r.Call(0));
...@@ -1950,8 +1914,7 @@ TEST(Build_Wasm_Infinite_Loop_effect) { ...@@ -1950,8 +1914,7 @@ TEST(Build_Wasm_Infinite_Loop_effect) {
TEST(Run_Wasm_Unreachable0a) { TEST(Run_Wasm_Unreachable0a) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, BUILD(r, B2(WASM_BRV(0, WASM_I8(9)), RET(WASM_GET_LOCAL(0))));
WASM_BLOCK(2, WASM_BRV(0, WASM_I8(9)), WASM_RETURN(WASM_GET_LOCAL(0))));
CHECK_EQ(9, r.Call(0)); CHECK_EQ(9, r.Call(0));
CHECK_EQ(9, r.Call(1)); CHECK_EQ(9, r.Call(1));
} }
...@@ -1959,7 +1922,7 @@ TEST(Run_Wasm_Unreachable0a) { ...@@ -1959,7 +1922,7 @@ TEST(Run_Wasm_Unreachable0a) {
TEST(Run_Wasm_Unreachable0b) { TEST(Run_Wasm_Unreachable0b) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> 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(0));
CHECK_EQ(7, r.Call(1)); CHECK_EQ(7, r.Call(1));
} }
...@@ -1998,7 +1961,7 @@ TEST(Build_Wasm_UnreachableIf2) { ...@@ -1998,7 +1961,7 @@ TEST(Build_Wasm_UnreachableIf2) {
TEST(Run_Wasm_Unreachable_Load) { TEST(Run_Wasm_Unreachable_Load) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_GET_LOCAL(0)), BUILD(r, B2(WASM_BRV(0, WASM_GET_LOCAL(0)),
WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)))); WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))));
CHECK_EQ(11, r.Call(11)); CHECK_EQ(11, r.Call(11));
CHECK_EQ(21, r.Call(21)); CHECK_EQ(21, r.Call(21));
...@@ -2007,8 +1970,7 @@ TEST(Run_Wasm_Unreachable_Load) { ...@@ -2007,8 +1970,7 @@ TEST(Run_Wasm_Unreachable_Load) {
TEST(Run_Wasm_Infinite_Loop_not_taken1) { TEST(Run_Wasm_Infinite_Loop_not_taken1) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I8(45)));
WASM_I8(45)));
// Run the code, but don't go into the infinite loop. // Run the code, but don't go into the infinite loop.
CHECK_EQ(45, r.Call(0)); CHECK_EQ(45, r.Call(0));
} }
...@@ -2016,8 +1978,7 @@ TEST(Run_Wasm_Infinite_Loop_not_taken1) { ...@@ -2016,8 +1978,7 @@ TEST(Run_Wasm_Infinite_Loop_not_taken1) {
TEST(Run_Wasm_Infinite_Loop_not_taken2) { TEST(Run_Wasm_Infinite_Loop_not_taken2) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)),
WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)),
WASM_INFINITE_LOOP))); WASM_INFINITE_LOOP)));
// Run the code, but don't go into the infinite loop. // Run the code, but don't go into the infinite loop.
CHECK_EQ(45, r.Call(1)); CHECK_EQ(45, r.Call(1));
...@@ -2026,8 +1987,8 @@ TEST(Run_Wasm_Infinite_Loop_not_taken2) { ...@@ -2026,8 +1987,8 @@ TEST(Run_Wasm_Infinite_Loop_not_taken2) {
TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) { TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), BUILD(r,
WASM_INFINITE_LOOP)); 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. // Run the code, but don't go into the infinite loop.
CHECK_EQ(45, r.Call(1)); CHECK_EQ(45, r.Call(1));
} }
...@@ -2186,9 +2147,8 @@ TEST(Run_WasmInt64Global) { ...@@ -2186,9 +2147,8 @@ TEST(Run_WasmInt64Global) {
int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64()); int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64());
WasmRunner<int32_t> r(&module, MachineType::Int32()); WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0 // global = global + p0
BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( BUILD(r, B2(WASM_STORE_GLOBAL(
0, WASM_I64_ADD( 0, WASM_I64_ADD(WASM_LOAD_GLOBAL(0),
WASM_LOAD_GLOBAL(0),
WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))), WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
WASM_ZERO)); WASM_ZERO));
...@@ -2207,9 +2167,8 @@ TEST(Run_WasmFloat32Global) { ...@@ -2207,9 +2167,8 @@ TEST(Run_WasmFloat32Global) {
float* global = module.AddGlobal<float>(MachineType::Float32()); float* global = module.AddGlobal<float>(MachineType::Float32());
WasmRunner<int32_t> r(&module, MachineType::Int32()); WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0 // global = global + p0
BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( BUILD(r, B2(WASM_STORE_GLOBAL(
0, WASM_F32_ADD( 0, WASM_F32_ADD(WASM_LOAD_GLOBAL(0),
WASM_LOAD_GLOBAL(0),
WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))), WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))),
WASM_ZERO)); WASM_ZERO));
...@@ -2227,9 +2186,8 @@ TEST(Run_WasmFloat64Global) { ...@@ -2227,9 +2186,8 @@ TEST(Run_WasmFloat64Global) {
double* global = module.AddGlobal<double>(MachineType::Float64()); double* global = module.AddGlobal<double>(MachineType::Float64());
WasmRunner<int32_t> r(&module, MachineType::Int32()); WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0 // global = global + p0
BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( BUILD(r, B2(WASM_STORE_GLOBAL(
0, WASM_F64_ADD( 0, WASM_F64_ADD(WASM_LOAD_GLOBAL(0),
WASM_LOAD_GLOBAL(0),
WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))), WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
WASM_ZERO)); WASM_ZERO));
...@@ -2647,8 +2605,7 @@ TEST(Run_Wasm_AddCall) { ...@@ -2647,8 +2605,7 @@ TEST(Run_Wasm_AddCall) {
WasmRunner<int32_t> r(&module, MachineType::Int32()); WasmRunner<int32_t> r(&module, MachineType::Int32());
byte local = r.AllocateLocal(kAstI32); byte local = r.AllocateLocal(kAstI32);
BUILD(r, BUILD(r, B2(WASM_SET_LOCAL(local, WASM_I8(99)),
WASM_BLOCK(2, WASM_SET_LOCAL(local, WASM_I8(99)),
WASM_I32_ADD( WASM_I32_ADD(
WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0), WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0),
WASM_GET_LOCAL(0)), WASM_GET_LOCAL(0)),
...@@ -2675,8 +2632,7 @@ TEST(Run_Wasm_CountDown_expr) { ...@@ -2675,8 +2632,7 @@ TEST(Run_Wasm_CountDown_expr) {
TEST(Run_Wasm_ExprBlock2a) { TEST(Run_Wasm_ExprBlock2a) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(1)));
WASM_I8(1)));
CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(0));
CHECK_EQ(1, r.Call(1)); CHECK_EQ(1, r.Call(1));
} }
...@@ -2684,8 +2640,7 @@ TEST(Run_Wasm_ExprBlock2a) { ...@@ -2684,8 +2640,7 @@ TEST(Run_Wasm_ExprBlock2a) {
TEST(Run_Wasm_ExprBlock2b) { TEST(Run_Wasm_ExprBlock2b) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(2)));
WASM_I8(2)));
CHECK_EQ(2, r.Call(0)); CHECK_EQ(2, r.Call(0));
CHECK_EQ(1, r.Call(1)); CHECK_EQ(1, r.Call(1));
} }
...@@ -2693,8 +2648,7 @@ TEST(Run_Wasm_ExprBlock2b) { ...@@ -2693,8 +2648,7 @@ TEST(Run_Wasm_ExprBlock2b) {
TEST(Run_Wasm_ExprBlock2c) { TEST(Run_Wasm_ExprBlock2c) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(1)));
WASM_I8(1)));
CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(0));
CHECK_EQ(1, r.Call(1)); CHECK_EQ(1, r.Call(1));
} }
...@@ -2702,8 +2656,7 @@ TEST(Run_Wasm_ExprBlock2c) { ...@@ -2702,8 +2656,7 @@ TEST(Run_Wasm_ExprBlock2c) {
TEST(Run_Wasm_ExprBlock2d) { TEST(Run_Wasm_ExprBlock2d) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(2)));
WASM_I8(2)));
CHECK_EQ(2, r.Call(0)); CHECK_EQ(2, r.Call(0));
CHECK_EQ(1, r.Call(1)); CHECK_EQ(1, r.Call(1));
} }
...@@ -2775,8 +2728,7 @@ TEST(Run_Wasm_nested_ifs) { ...@@ -2775,8 +2728,7 @@ TEST(Run_Wasm_nested_ifs) {
TEST(Run_Wasm_ExprBlock_if) { TEST(Run_Wasm_ExprBlock_if) {
WasmRunner<int32_t> r(MachineType::Int32()); WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r, BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)),
WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)),
WASM_BRV(0, WASM_I8(14))))); WASM_BRV(0, WASM_I8(14)))));
CHECK_EQ(11, r.Call(1)); CHECK_EQ(11, r.Call(1));
......
...@@ -1671,120 +1671,81 @@ TEST_F(AstDecoderTest, ExprBrIf_Unify) { ...@@ -1671,120 +1671,81 @@ TEST_F(AstDecoderTest, ExprBrIf_Unify) {
} }
} }
TEST_F(AstDecoderTest, TableSwitch0) { TEST_F(AstDecoderTest, BrTable0) {
static byte code[] = {kExprTableSwitch, 0, 0, 0, 0}; static byte code[] = {kExprBrTable, 0, 0};
EXPECT_FAILURE(&env_v_v, code); EXPECT_FAILURE(&env_v_v, code);
} }
TEST_F(AstDecoderTest, TableSwitch0b) { TEST_F(AstDecoderTest, BrTable0b) {
static byte code[] = {kExprTableSwitch, 0, 0, 0, 0, kExprI8Const, 11}; static byte code[] = {kExprBrTable, 0, 0, kExprI8Const, 11};
EXPECT_FAILURE(&env_v_v, code); EXPECT_FAILURE(&env_v_v, code);
EXPECT_FAILURE(&env_i_i, code); EXPECT_FAILURE(&env_i_i, code);
} }
TEST_F(AstDecoderTest, TableSwitch0c) { TEST_F(AstDecoderTest, BrTable0c) {
static byte code[] = { static byte code[] = {kExprBrTable, 0, 1, 0, 0, kExprI8Const, 11};
WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)), WASM_I8(67))}; EXPECT_FAILURE(&env_v_v, code);
EXPECT_VERIFIES(&env_v_v, code); EXPECT_FAILURE(&env_i_i, code);
} }
TEST_F(AstDecoderTest, TableSwitch0d) { TEST_F(AstDecoderTest, BrTable1a) {
static byte code[] = { static byte code[] = {
WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(1)), WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 0, BR_TARGET(0)))};
WASM_I8(67))};
EXPECT_VERIFIES(&env_v_v, code); EXPECT_VERIFIES(&env_v_v, code);
} }
TEST_F(AstDecoderTest, TableSwitch1) { TEST_F(AstDecoderTest, BrTable1b) {
static byte code[] = {WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), static byte code[] = {
WASM_TABLESWITCH_BODY(WASM_I8(0), WASM_I8(9))}; WASM_BLOCK(1, WASM_BR_TABLE(WASM_ZERO, 0, BR_TARGET(0)))};
EXPECT_VERIFIES(&env_i_i, code);
EXPECT_VERIFIES(&env_v_v, code); EXPECT_VERIFIES(&env_v_v, code);
EXPECT_FAILURE(&env_i_i, code);
EXPECT_FAILURE(&env_f_ff, code); EXPECT_FAILURE(&env_f_ff, code);
EXPECT_FAILURE(&env_d_dd, code); EXPECT_FAILURE(&env_d_dd, code);
} }
TEST_F(AstDecoderTest, TableSwitch_off_end) { TEST_F(AstDecoderTest, BrTable2a) {
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) {
static byte code[] = { static byte code[] = {
WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)), WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(0)))};
WASM_TABLESWITCH_BODY(WASM_I8(3), WASM_I8(10), WASM_I8(11))};
EXPECT_VERIFIES(&env_i_i, code);
EXPECT_VERIFIES(&env_v_v, code); EXPECT_VERIFIES(&env_v_v, code);
EXPECT_FAILURE(&env_f_ff, code);
EXPECT_FAILURE(&env_d_dd, code);
} }
TEST_F(AstDecoderTest, TableSwitch1b) { TEST_F(AstDecoderTest, BrTable2b) {
EXPECT_VERIFIES_INLINE(&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), static byte code[] = {WASM_BLOCK(
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_ZERO)); 1, WASM_BLOCK(
1, WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(1))))};
EXPECT_VERIFIES_INLINE(&env_f_ff, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), EXPECT_VERIFIES(&env_v_v, code);
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, TableSwitch_br1) { TEST_F(AstDecoderTest, BrTable_off_end) {
for (int depth = 0; depth < 2; depth++) { static byte code[] = {
byte code[] = {WASM_BLOCK(1, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)), WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))};
WASM_GET_LOCAL(0))}; for (size_t len = 1; len < sizeof(code); len++) {
EXPECT_VERIFIES(&env_v_i, code); Verify(kError, &env_i_i, code, code + len);
EXPECT_FAILURE(&env_i_i, code);
} }
} }
TEST_F(AstDecoderTest, TableSwitch_invalid_br) { TEST_F(AstDecoderTest, BrTable_invalid_br1) {
for (int depth = 1; depth < 4; depth++) { for (int depth = 0; depth < 4; depth++) {
EXPECT_FAILURE_INLINE(&env_v_i, byte code[] = {
WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(depth)), WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))};
WASM_GET_LOCAL(0)); if (depth == 0) {
EXPECT_FAILURE_INLINE( EXPECT_VERIFIES(&env_v_i, code);
&env_v_i, } else {
WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(depth), WASM_CASE_BR(depth)), EXPECT_FAILURE(&env_v_i, code);
WASM_GET_LOCAL(0)); }
} }
} }
TEST_F(AstDecoderTest, TableSwitch_invalid_case_ref) { TEST_F(AstDecoderTest, BrTable_invalid_br2) {
EXPECT_FAILURE_INLINE(&env_i_i, WASM_TABLESWITCH_OP(0, 1, WASM_CASE(0)), for (int depth = 0; depth < 4; depth++) {
WASM_GET_LOCAL(0)); byte code[] = {
EXPECT_FAILURE_INLINE(&env_i_i, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(1)), WASM_LOOP(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))};
WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_ZERO)); if (depth <= 1) {
} EXPECT_VERIFIES(&env_v_i, code);
} else {
TEST_F(AstDecoderTest, TableSwitch1_br) { EXPECT_FAILURE(&env_v_i, code);
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, ExprBreakNesting1) { TEST_F(AstDecoderTest, ExprBreakNesting1) {
......
...@@ -92,17 +92,8 @@ TEST_F(WasmMacroGenTest, MacroStatements) { ...@@ -92,17 +92,8 @@ TEST_F(WasmMacroGenTest, MacroStatements) {
EXPECT_SIZE(3, WASM_CONTINUE(0)); EXPECT_SIZE(3, WASM_CONTINUE(0));
} }
TEST_F(WasmMacroGenTest, BrTable) {
TEST_F(WasmMacroGenTest, TableSwitch) { EXPECT_SIZE(7, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
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)));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment