| Index: src/wasm/function-body-decoder.cc
|
| diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc
|
| index d67a1e3cc9335f0eb73de149b79e48fc9b68b220..04a28062373adc52baebd65c23eec949f71aed2c 100644
|
| --- a/src/wasm/function-body-decoder.cc
|
| +++ b/src/wasm/function-body-decoder.cc
|
| @@ -85,9 +85,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];
|
| }
|
| };
|
|
|
| @@ -99,11 +99,12 @@ enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry };
|
| struct Control {
|
| const byte* pc;
|
| ControlKind kind;
|
| - int stack_depth; // stack height at the beginning of the construct.
|
| + size_t stack_depth; // stack height at the beginning of the construct.
|
| SsaEnv* end_env; // end environment for the construct.
|
| SsaEnv* false_env; // false environment (only for if).
|
| TryInfo* try_info; // Information used for compiling try statements.
|
| int32_t previous_catch; // The previous Control (on the stack) with a catch.
|
| + bool unreachable; // The current block has been ended.
|
|
|
| // Values merged into the end of this control construct.
|
| MergeValues merge;
|
| @@ -114,30 +115,30 @@ struct Control {
|
| inline bool is_try() const { return kind == kControlTry; }
|
|
|
| // Named constructors.
|
| - static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env,
|
| + static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env,
|
| int32_t previous_catch) {
|
| - return {pc, kControlBlock, stack_depth, end_env,
|
| - nullptr, nullptr, previous_catch, {0, {NO_VALUE}}};
|
| + return {pc, kControlBlock, stack_depth, end_env, nullptr,
|
| + nullptr, previous_catch, false, {0, {NO_VALUE}}};
|
| }
|
|
|
| - static Control If(const byte* pc, int stack_depth, SsaEnv* end_env,
|
| + static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env,
|
| SsaEnv* false_env, int32_t previous_catch) {
|
| - return {pc, kControlIf, stack_depth, end_env,
|
| - false_env, nullptr, previous_catch, {0, {NO_VALUE}}};
|
| + return {pc, kControlIf, stack_depth, end_env, false_env,
|
| + nullptr, previous_catch, false, {0, {NO_VALUE}}};
|
| }
|
|
|
| - static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env,
|
| + static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env,
|
| int32_t previous_catch) {
|
| - return {pc, kControlLoop, stack_depth, end_env,
|
| - nullptr, nullptr, previous_catch, {0, {NO_VALUE}}};
|
| + return {pc, kControlLoop, stack_depth, end_env, nullptr,
|
| + nullptr, previous_catch, false, {0, {NO_VALUE}}};
|
| }
|
|
|
| - static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env,
|
| + static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env,
|
| Zone* zone, SsaEnv* catch_env, int32_t previous_catch) {
|
| DCHECK_NOT_NULL(catch_env);
|
| TryInfo* try_info = new (zone) TryInfo(catch_env);
|
| - return {pc, kControlTry, stack_depth, end_env,
|
| - nullptr, try_info, previous_catch, {0, {NO_VALUE}}};
|
| + return {pc, kControlTry, stack_depth, end_env, nullptr,
|
| + try_info, previous_catch, false, {0, {NO_VALUE}}};
|
| }
|
| };
|
|
|
| @@ -654,9 +655,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
| }
|
|
|
| - if (pc_ >= end_) return; // Nothing to do.
|
| -
|
| - while (true) { // decoding loop.
|
| + while (pc_ < end_) { // decoding loop.
|
| unsigned len = 1;
|
| WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
|
| if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
|
| @@ -686,6 +685,10 @@ class WasmFullDecoder : public WasmDecoder {
|
| CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
|
| Value value = Pop(0, kWasmI32);
|
| BUILD(Throw, value.node);
|
| + // TODO(titzer): Throw should end control, but currently we build a
|
| + // (reachable) runtime call instead of connecting it directly to
|
| + // end.
|
| + // EndControl();
|
| break;
|
| }
|
| case kExprTry: {
|
| @@ -721,9 +724,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| break;
|
| }
|
|
|
| - if (ssa_env_->go()) {
|
| - MergeValuesInto(c);
|
| - }
|
| + FallThruTo(c);
|
| stack_.resize(c->stack_depth);
|
|
|
| DCHECK_NOT_NULL(c->try_info);
|
| @@ -787,8 +788,8 @@ class WasmFullDecoder : public WasmDecoder {
|
| break;
|
| }
|
| FallThruTo(c);
|
| - // Switch to environment for false branch.
|
| stack_.resize(c->stack_depth);
|
| + // Switch to environment for false branch.
|
| SetEnv("if_else:false", c->false_env);
|
| c->false_env = nullptr; // record that an else is already seen
|
| break;
|
| @@ -802,7 +803,8 @@ class WasmFullDecoder : public WasmDecoder {
|
| Control* c = &control_.back();
|
| if (c->is_loop()) {
|
| // A loop just leaves the values on the stack.
|
| - TypeCheckLoopFallThru(c);
|
| + TypeCheckFallThru(c);
|
| + if (c->unreachable) PushEndValues(c);
|
| PopControl();
|
| SetEnv("loop:end", ssa_env_);
|
| break;
|
| @@ -811,8 +813,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| if (c->false_env != nullptr) {
|
| // End the true branch of a one-armed if.
|
| Goto(c->false_env, c->end_env);
|
| - if (ssa_env_->go() &&
|
| - static_cast<int>(stack_.size()) != c->stack_depth) {
|
| + if (!c->unreachable && stack_.size() != c->stack_depth) {
|
| error("end of if expected empty stack");
|
| stack_.resize(c->stack_depth);
|
| }
|
| @@ -835,23 +836,13 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
| FallThruTo(c);
|
| SetEnv(name, c->end_env);
|
| + PushEndValues(c);
|
|
|
| - // Push the end values onto the stack.
|
| - stack_.resize(c->stack_depth);
|
| - if (c->merge.arity == 1) {
|
| - stack_.push_back(c->merge.vals.first);
|
| - } else {
|
| - for (unsigned i = 0; i < c->merge.arity; i++) {
|
| - stack_.push_back(c->merge.vals.array[i]);
|
| - }
|
| - }
|
| -
|
| - PopControl();
|
| -
|
| - if (control_.empty()) {
|
| - // If the last (implicit) control was popped, check we are at end.
|
| + if (control_.size() == 1) {
|
| + // If at the last (implicit) control, check we are at end.
|
| if (pc_ + 1 != end_) {
|
| error(pc_, pc_ + 1, "trailing code after function end");
|
| + break;
|
| }
|
| last_end_found_ = true;
|
| if (ssa_env_->go()) {
|
| @@ -859,25 +850,18 @@ class WasmFullDecoder : public WasmDecoder {
|
| TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn");
|
| DoReturn();
|
| TRACE("\n");
|
| + } else {
|
| + TypeCheckFallThru(c);
|
| }
|
| - return;
|
| }
|
| + PopControl();
|
| break;
|
| }
|
| case kExprSelect: {
|
| Value cond = Pop(2, kWasmI32);
|
| Value fval = Pop();
|
| - Value tval = Pop();
|
| - if (tval.type == kWasmStmt || tval.type != fval.type) {
|
| - if (tval.type != kWasmEnd && fval.type != kWasmEnd) {
|
| - error("type mismatch in select");
|
| - break;
|
| - }
|
| - }
|
| + Value tval = Pop(0, fval.type);
|
| if (build()) {
|
| - DCHECK(tval.type != kWasmEnd);
|
| - DCHECK(fval.type != kWasmEnd);
|
| - DCHECK(cond.type != kWasmEnd);
|
| TFNode* controls[2];
|
| builder_->BranchNoHint(cond.node, &controls[0], &controls[1]);
|
| TFNode* merge = builder_->Merge(2, controls);
|
| @@ -886,7 +870,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| Push(tval.type, phi);
|
| ssa_env_->control = merge;
|
| } else {
|
| - Push(tval.type, nullptr);
|
| + Push(tval.type == kWasmVar ? fval.type : tval.type, nullptr);
|
| }
|
| break;
|
| }
|
| @@ -928,6 +912,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();
|
| @@ -941,6 +926,27 @@ 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 {
|
| @@ -957,6 +963,7 @@ class WasmFullDecoder : public WasmDecoder {
|
| ssa_env_ = break_env;
|
| }
|
| len = 1 + iterator.length();
|
| + EndControl();
|
| break;
|
| }
|
| case kExprReturn: {
|
| @@ -1207,6 +1214,35 @@ class WasmFullDecoder : public WasmDecoder {
|
|
|
| #if DEBUG
|
| if (FLAG_trace_wasm_decoder) {
|
| + PrintF(" ");
|
| + for (size_t i = 0; i < control_.size(); ++i) {
|
| + Control* c = &control_[i];
|
| + enum ControlKind {
|
| + kControlIf,
|
| + kControlBlock,
|
| + kControlLoop,
|
| + kControlTry
|
| + };
|
| + switch (c->kind) {
|
| + case kControlIf:
|
| + PrintF("I");
|
| + break;
|
| + case kControlBlock:
|
| + PrintF("B");
|
| + break;
|
| + case kControlLoop:
|
| + PrintF("L");
|
| + break;
|
| + case kControlTry:
|
| + PrintF("T");
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + PrintF("%u", c->merge.arity);
|
| + if (c->unreachable) PrintF("*");
|
| + }
|
| + PrintF(" | ");
|
| for (size_t i = 0; i < stack_.size(); ++i) {
|
| Value& val = stack_[i];
|
| WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
|
| @@ -1236,20 +1272,23 @@ class WasmFullDecoder : public WasmDecoder {
|
| default:
|
| break;
|
| }
|
| + if (val.node == nullptr) PrintF("?");
|
| }
|
| PrintF("\n");
|
| }
|
| #endif
|
| pc_ += len;
|
| - if (pc_ >= end_) {
|
| - // End of code reached or exceeded.
|
| - if (pc_ > end_ && ok()) error("Beyond end of code");
|
| - return;
|
| - }
|
| } // end decode loop
|
| + if (pc_ > end_ && ok()) error("Beyond end of code");
|
| }
|
|
|
| - void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); }
|
| + void EndControl() {
|
| + ssa_env_->Kill(SsaEnv::kControlEnd);
|
| + if (!control_.empty()) {
|
| + stack_.resize(control_.back().stack_depth);
|
| + control_.back().unreachable = true;
|
| + }
|
| + }
|
|
|
| void SetBlockType(Control* c, BlockTypeOperand& operand) {
|
| c->merge.arity = operand.arity;
|
| @@ -1286,26 +1325,22 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| void PushBlock(SsaEnv* end_env) {
|
| - const int stack_depth = static_cast<int>(stack_.size());
|
| control_.emplace_back(
|
| - Control::Block(pc_, stack_depth, end_env, current_catch_));
|
| + Control::Block(pc_, stack_.size(), end_env, current_catch_));
|
| }
|
|
|
| void PushLoop(SsaEnv* end_env) {
|
| - const int stack_depth = static_cast<int>(stack_.size());
|
| control_.emplace_back(
|
| - Control::Loop(pc_, stack_depth, end_env, current_catch_));
|
| + Control::Loop(pc_, stack_.size(), end_env, current_catch_));
|
| }
|
|
|
| void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
|
| - const int stack_depth = static_cast<int>(stack_.size());
|
| control_.emplace_back(
|
| - Control::If(pc_, stack_depth, end_env, false_env, current_catch_));
|
| + Control::If(pc_, stack_.size(), end_env, false_env, current_catch_));
|
| }
|
|
|
| void PushTry(SsaEnv* end_env, SsaEnv* catch_env) {
|
| - const int stack_depth = static_cast<int>(stack_.size());
|
| - control_.emplace_back(Control::Try(pc_, stack_depth, end_env, zone_,
|
| + control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_,
|
| catch_env, current_catch_));
|
| current_catch_ = static_cast<int32_t>(control_.size() - 1);
|
| }
|
| @@ -1413,11 +1448,24 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| void Push(ValueType type, TFNode* node) {
|
| - if (type != kWasmStmt && type != kWasmEnd) {
|
| + if (type != kWasmStmt) {
|
| stack_.push_back({pc_, node, type});
|
| }
|
| }
|
|
|
| + 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);
|
| + } else {
|
| + for (unsigned i = 0; i < c->merge.arity; i++) {
|
| + stack_.push_back(c->merge.vals.array[i]);
|
| + }
|
| + }
|
| + DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
|
| + }
|
| +
|
| void PushReturns(FunctionSig* sig, TFNode** rets) {
|
| for (size_t i = 0; i < sig->return_count(); i++) {
|
| // When verifying only, then {rets} will be null, so push null.
|
| @@ -1431,30 +1479,23 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| Value Pop(int index, ValueType expected) {
|
| - if (!ssa_env_->go()) {
|
| - // Unreachable code is essentially not typechecked.
|
| - return {pc_, nullptr, expected};
|
| - }
|
| Value val = Pop();
|
| - if (val.type != expected) {
|
| - if (val.type != kWasmEnd) {
|
| - error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
|
| - SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
|
| - SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
|
| - }
|
| + if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) {
|
| + error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
|
| + SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
|
| + SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
|
| }
|
| return val;
|
| }
|
|
|
| Value Pop() {
|
| - if (!ssa_env_->go()) {
|
| - // Unreachable code is essentially not typechecked.
|
| - return {pc_, nullptr, kWasmEnd};
|
| - }
|
| size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
|
| if (stack_.size() <= limit) {
|
| - Value val = {pc_, nullptr, kWasmStmt};
|
| - error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
|
| + // Popping past the current control start in reachable code.
|
| + Value val = {pc_, nullptr, kWasmVar};
|
| + if (!control_.back().unreachable) {
|
| + error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
|
| + }
|
| return val;
|
| }
|
| Value val = stack_.back();
|
| @@ -1462,22 +1503,6 @@ class WasmFullDecoder : public WasmDecoder {
|
| return val;
|
| }
|
|
|
| - Value PopUpTo(int stack_depth) {
|
| - if (!ssa_env_->go()) {
|
| - // Unreachable code is essentially not typechecked.
|
| - return {pc_, nullptr, kWasmEnd};
|
| - }
|
| - if (stack_depth == static_cast<int>(stack_.size())) {
|
| - Value val = {pc_, nullptr, kWasmStmt};
|
| - return val;
|
| - } else {
|
| - DCHECK_LE(stack_depth, stack_.size());
|
| - Value val = Pop();
|
| - stack_.resize(stack_depth);
|
| - return val;
|
| - }
|
| - }
|
| -
|
| int baserel(const byte* ptr) {
|
| return base_ ? static_cast<int>(ptr - base_) : 0;
|
| }
|
| @@ -1485,17 +1510,17 @@ class WasmFullDecoder : public WasmDecoder {
|
| int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
|
|
|
| void BreakTo(unsigned depth) {
|
| - if (!ssa_env_->go()) return;
|
| Control* c = &control_[control_.size() - depth - 1];
|
| if (c->is_loop()) {
|
| // This is the inner loop block, which does not have a value.
|
| Goto(ssa_env_, c->end_env);
|
| } else {
|
| // Merge the value(s) into the end of the block.
|
| - if (c->stack_depth + c->merge.arity > stack_.size()) {
|
| + size_t expected = control_.back().stack_depth + c->merge.arity;
|
| + if (stack_.size() < expected && !control_.back().unreachable) {
|
| error(
|
| pc_, pc_,
|
| - "expected at least %d values on the stack for br to @%d, found %d",
|
| + "expected at least %u values on the stack for br to @%d, found %d",
|
| c->merge.arity, startrel(c->pc),
|
| static_cast<int>(stack_.size() - c->stack_depth));
|
| return;
|
| @@ -1505,37 +1530,41 @@ class WasmFullDecoder : public WasmDecoder {
|
| }
|
|
|
| void FallThruTo(Control* c) {
|
| - if (!ssa_env_->go()) return;
|
| + DCHECK_EQ(c, &control_.back());
|
| // Merge the value(s) into the end of the block.
|
| - int arity = static_cast<int>(c->merge.arity);
|
| - if (c->stack_depth + arity != static_cast<int>(stack_.size())) {
|
| - error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d",
|
| - arity, startrel(c->pc));
|
| + size_t expected = c->stack_depth + c->merge.arity;
|
| + if (stack_.size() == expected ||
|
| + (stack_.size() < expected && c->unreachable)) {
|
| + MergeValuesInto(c);
|
| + c->unreachable = false;
|
| return;
|
| }
|
| - MergeValuesInto(c);
|
| + error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d",
|
| + c->merge.arity, startrel(c->pc));
|
| }
|
|
|
| - inline Value& GetMergeValueFromStack(Control* c, int i) {
|
| + inline Value& GetMergeValueFromStack(Control* c, size_t i) {
|
| return stack_[stack_.size() - c->merge.arity + i];
|
| }
|
|
|
| - void TypeCheckLoopFallThru(Control* c) {
|
| - if (!ssa_env_->go()) return;
|
| + 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 != static_cast<int>(stack_.size())) {
|
| + if (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;
|
| }
|
| // Typecheck the values left on the stack.
|
| - for (unsigned i = 0; i < c->merge.arity; i++) {
|
| + size_t avail = stack_.size() - c->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) {
|
| - error(pc_, pc_, "type error in merge[%d] (expected %s, got %s)", i,
|
| + error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
|
| WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
|
| return;
|
| }
|
| @@ -1545,23 +1574,24 @@ class WasmFullDecoder : public WasmDecoder {
|
| void MergeValuesInto(Control* c) {
|
| SsaEnv* target = c->end_env;
|
| bool first = target->state == SsaEnv::kUnreachable;
|
| + bool reachable = ssa_env_->go();
|
| Goto(ssa_env_, target);
|
|
|
| - for (unsigned i = 0; i < c->merge.arity; i++) {
|
| + 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];
|
| - if (val.type != old.type) {
|
| - error(pc_, pc_, "type error in merge[%d] (expected %s, got %s)", 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));
|
| return;
|
| }
|
| - if (builder_) {
|
| + if (builder_ && reachable) {
|
| + DCHECK_NOT_NULL(val.node);
|
| old.node =
|
| first ? val.node : CreateOrMergeIntoPhi(old.type, target->control,
|
| old.node, val.node);
|
| - } else {
|
| - old.node = nullptr;
|
| }
|
| }
|
| }
|
| @@ -1586,13 +1616,13 @@ class WasmFullDecoder : public WasmDecoder {
|
| break;
|
| }
|
| }
|
| - PrintF(" env = %p, state = %c, reason = %s", static_cast<void*>(env),
|
| + PrintF("{set_env = %p, state = %c, reason = %s", static_cast<void*>(env),
|
| state, reason);
|
| if (env && env->control) {
|
| PrintF(", control = ");
|
| compiler::WasmGraphBuilder::PrintDebugName(env->control);
|
| }
|
| - PrintF("\n");
|
| + PrintF("}");
|
| }
|
| #endif
|
| ssa_env_ = env;
|
|
|