| Index: src/wasm/function-body-decoder.cc
|
| diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc
|
| index 114926d36b1a9aefe177d36d94275c7b4f420113..3311caa3e233574499818fea8c6609815af3b937 100644
|
| --- a/src/wasm/function-body-decoder.cc
|
| +++ b/src/wasm/function-body-decoder.cc
|
| @@ -89,9 +89,9 @@ struct MergeValues {
|
| Value first;
|
| } vals; // Either multiple values or a single value.
|
|
|
| - Value& first() {
|
| - DCHECK_GT(arity, 0);
|
| - return arity == 1 ? vals.first : vals.array[0];
|
| + Value& operator[](size_t i) {
|
| + DCHECK_GT(arity, i);
|
| + return arity == 1 ? vals.first : vals.array[i];
|
| }
|
| };
|
|
|
| @@ -960,6 +960,7 @@ class WasmFullDecoder : public WasmDecoder {
|
|
|
| SsaEnv* copy = Steal(break_env);
|
| ssa_env_ = copy;
|
| + MergeValues* merge = nullptr;
|
| while (ok() && iterator.has_next()) {
|
| uint32_t i = iterator.cur_index();
|
| const byte* pos = iterator.pc();
|
| @@ -973,6 +974,26 @@ class WasmFullDecoder : public WasmDecoder {
|
| ? BUILD(IfDefault, sw)
|
| : BUILD(IfValue, i, sw);
|
| BreakTo(target);
|
| +
|
| + // Check that label types match up.
|
| + Control* c = &control_[control_.size() - target - 1];
|
| + if (i == 0) {
|
| + merge = &c->merge;
|
| + } else if (merge->arity != c->merge.arity) {
|
| + error(pos, pos, "inconsistent arity in br_table target %d"
|
| + " (previous was %u, this one %u)",
|
| + i, merge->arity, c->merge.arity);
|
| + } else if (control_.back().unreachable) {
|
| + for (uint32_t j = 0; ok() && j < merge->arity; ++j) {
|
| + if ((*merge)[j].type != c->merge[j].type) {
|
| + error(pos, pos,
|
| + "type error in br_table target %d operand %d"
|
| + " (previous expected %s, this one %s)", i, j,
|
| + WasmOpcodes::TypeName((*merge)[j].type),
|
| + WasmOpcodes::TypeName(c->merge[j].type));
|
| + }
|
| + }
|
| + }
|
| }
|
| if (failed()) break;
|
| } else {
|
| @@ -1507,6 +1528,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| void PushEndValues(Control* c) {
|
| + DCHECK_EQ(c, &control_.back());
|
| stack_.resize(c->stack_depth);
|
| if (c->merge.arity == 1) {
|
| stack_.push_back(c->merge.vals.first);
|
| @@ -1568,8 +1590,8 @@ class WasmFullDecoder : public WasmDecoder {
|
| Goto(ssa_env_, c->end_env);
|
| } else {
|
| // Merge the value(s) into the end of the block.
|
| - size_t expected = c->stack_depth + c->merge.arity;
|
| - if (!c->unreachable && stack_.size() < expected) {
|
| + size_t expected = control_.back().stack_depth + c->merge.arity;
|
| + if (stack_.size() < expected && !control_.back().unreachable) {
|
| error(
|
| pc_, pc_,
|
| "expected at least %u values on the stack for br to @%d, found %d",
|
| @@ -1582,10 +1604,11 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| void FallThruTo(Control* c) {
|
| + DCHECK_EQ(c, &control_.back());
|
| // Merge the value(s) into the end of the block.
|
| size_t expected = c->stack_depth + c->merge.arity;
|
| if (stack_.size() == expected ||
|
| - (c->unreachable && stack_.size() < expected)) {
|
| + (stack_.size() < expected && c->unreachable)) {
|
| MergeValuesInto(c);
|
| c->unreachable = false;
|
| return;
|
| @@ -1599,10 +1622,11 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| void TypeCheckFallThru(Control* c) {
|
| + DCHECK_EQ(c, &control_.back());
|
| // Fallthru must match arity exactly.
|
| int arity = static_cast<int>(c->merge.arity);
|
| if (c->stack_depth + arity < stack_.size() ||
|
| - (!c->unreachable && c->stack_depth + arity != stack_.size())) {
|
| + (c->stack_depth + arity != stack_.size() && !c->unreachable)) {
|
| error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d",
|
| arity, startrel(c->pc));
|
| return;
|
| @@ -1612,8 +1636,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
|
| i < c->merge.arity; i++) {
|
| Value& val = GetMergeValueFromStack(c, i);
|
| - Value& old =
|
| - c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i];
|
| + Value& old = c->merge[i];
|
| if (val.type != old.type) {
|
| error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
|
| WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
|
| @@ -1628,12 +1651,11 @@ class WasmFullDecoder : public WasmDecoder {
|
| bool reachable = ssa_env_->go();
|
| Goto(ssa_env_, target);
|
|
|
| - size_t avail = stack_.size() - c->stack_depth;
|
| + size_t avail = stack_.size() - control_.back().stack_depth;
|
| for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
|
| i < c->merge.arity; i++) {
|
| Value& val = GetMergeValueFromStack(c, i);
|
| - Value& old =
|
| - c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i];
|
| + Value& old = c->merge[i];
|
| if (val.type != old.type && val.type != kWasmVar) {
|
| error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
|
| WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
|
|
|