1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/signature.h"
6
7#include "src/base/platform/elapsed-timer.h"
8#include "src/bit-vector.h"
9#include "src/flags.h"
10#include "src/handles.h"
11#include "src/objects-inl.h"
12#include "src/zone/zone-containers.h"
13
14#include "src/wasm/decoder.h"
15#include "src/wasm/function-body-decoder-impl.h"
16#include "src/wasm/function-body-decoder.h"
17#include "src/wasm/wasm-limits.h"
18#include "src/wasm/wasm-module.h"
19#include "src/wasm/wasm-opcodes.h"
20
21#include "src/ostreams.h"
22
23#include "src/compiler/wasm-compiler.h"
24
25namespace v8 {
26namespace internal {
27namespace wasm {
28
29#if DEBUG
30#define TRACE(...)                                    \
31  do {                                                \
32    if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
33  } while (false)
34#else
35#define TRACE(...)
36#endif
37
38#define CHECK_PROTOTYPE_OPCODE(flag)                           \
39  if (module_ != nullptr && module_->origin == kAsmJsOrigin) { \
40    error("Opcode not supported for asmjs modules");           \
41  }                                                            \
42  if (!FLAG_##flag) {                                          \
43    error("Invalid opcode (enable with --" #flag ")");         \
44    break;                                                     \
45  }
46
47// An SsaEnv environment carries the current local variable renaming
48// as well as the current effect and control dependency in the TF graph.
49// It maintains a control state that tracks whether the environment
50// is reachable, has reached a control end, or has been merged.
51struct SsaEnv {
52  enum State { kControlEnd, kUnreachable, kReached, kMerged };
53
54  State state;
55  TFNode* control;
56  TFNode* effect;
57  TFNode** locals;
58
59  bool go() { return state >= kReached; }
60  void Kill(State new_state = kControlEnd) {
61    state = new_state;
62    locals = nullptr;
63    control = nullptr;
64    effect = nullptr;
65  }
66  void SetNotMerged() {
67    if (state == kMerged) state = kReached;
68  }
69};
70
71// An entry on the value stack.
72struct Value {
73  const byte* pc;
74  TFNode* node;
75  ValueType type;
76};
77
78struct TryInfo : public ZoneObject {
79  SsaEnv* catch_env;
80  TFNode* exception;
81
82  explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
83};
84
85struct MergeValues {
86  uint32_t arity;
87  union {
88    Value* array;
89    Value first;
90  } vals;  // Either multiple values or a single value.
91
92  Value& operator[](size_t i) {
93    DCHECK_GT(arity, i);
94    return arity == 1 ? vals.first : vals.array[i];
95  }
96};
97
98static Value* NO_VALUE = nullptr;
99
100enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry };
101
102// An entry on the control stack (i.e. if, block, loop).
103struct Control {
104  const byte* pc;
105  ControlKind kind;
106  size_t stack_depth;      // stack height at the beginning of the construct.
107  SsaEnv* end_env;         // end environment for the construct.
108  SsaEnv* false_env;       // false environment (only for if).
109  TryInfo* try_info;       // Information used for compiling try statements.
110  int32_t previous_catch;  // The previous Control (on the stack) with a catch.
111  bool unreachable;        // The current block has been ended.
112
113  // Values merged into the end of this control construct.
114  MergeValues merge;
115
116  inline bool is_if() const { return kind == kControlIf; }
117  inline bool is_block() const { return kind == kControlBlock; }
118  inline bool is_loop() const { return kind == kControlLoop; }
119  inline bool is_try() const { return kind == kControlTry; }
120
121  // Named constructors.
122  static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env,
123                       int32_t previous_catch) {
124    return {pc,      kControlBlock,  stack_depth, end_env,        nullptr,
125            nullptr, previous_catch, false,       {0, {NO_VALUE}}};
126  }
127
128  static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env,
129                    SsaEnv* false_env, int32_t previous_catch) {
130    return {pc,      kControlIf,     stack_depth, end_env,        false_env,
131            nullptr, previous_catch, false,       {0, {NO_VALUE}}};
132  }
133
134  static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env,
135                      int32_t previous_catch) {
136    return {pc,      kControlLoop,   stack_depth, end_env,        nullptr,
137            nullptr, previous_catch, false,       {0, {NO_VALUE}}};
138  }
139
140  static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env,
141                     Zone* zone, SsaEnv* catch_env, int32_t previous_catch) {
142    DCHECK_NOT_NULL(catch_env);
143    TryInfo* try_info = new (zone) TryInfo(catch_env);
144    return {pc,       kControlTry,    stack_depth, end_env,        nullptr,
145            try_info, previous_catch, false,       {0, {NO_VALUE}}};
146  }
147};
148
149// Macros that build nodes only if there is a graph and the current SSA
150// environment is reachable from start. This avoids problems with malformed
151// TF graphs when decoding inputs that have unreachable code.
152#define BUILD(func, ...) \
153  (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr)
154#define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr)
155
156// Generic Wasm bytecode decoder with utilities for decoding operands,
157// lengths, etc.
158class WasmDecoder : public Decoder {
159 public:
160  WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
161              const byte* end)
162      : Decoder(start, end),
163        module_(module),
164        sig_(sig),
165        local_types_(nullptr) {}
166  const WasmModule* module_;
167  FunctionSig* sig_;
168
169  ZoneVector<ValueType>* local_types_;
170
171  size_t total_locals() const {
172    return local_types_ == nullptr ? 0 : local_types_->size();
173  }
174
175  static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
176                           ZoneVector<ValueType>* type_list) {
177    DCHECK_NOT_NULL(type_list);
178    // Initialize from signature.
179    if (sig != nullptr) {
180      type_list->reserve(sig->parameter_count());
181      for (size_t i = 0; i < sig->parameter_count(); ++i) {
182        type_list->push_back(sig->GetParam(i));
183      }
184    }
185    // Decode local declarations, if any.
186    uint32_t entries = decoder->consume_u32v("local decls count");
187    if (decoder->failed()) return false;
188
189    TRACE("local decls count: %u\n", entries);
190    while (entries-- > 0 && decoder->ok() && decoder->more()) {
191      uint32_t count = decoder->consume_u32v("local count");
192      if (decoder->failed()) return false;
193
194      if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
195        decoder->error(decoder->pc() - 1, "local count too large");
196        return false;
197      }
198      byte code = decoder->consume_u8("local type");
199      if (decoder->failed()) return false;
200
201      ValueType type;
202      switch (code) {
203        case kLocalI32:
204          type = kWasmI32;
205          break;
206        case kLocalI64:
207          type = kWasmI64;
208          break;
209        case kLocalF32:
210          type = kWasmF32;
211          break;
212        case kLocalF64:
213          type = kWasmF64;
214          break;
215        case kLocalS128:
216          type = kWasmS128;
217          break;
218        case kLocalS1x4:
219          type = kWasmS1x4;
220          break;
221        case kLocalS1x8:
222          type = kWasmS1x8;
223          break;
224        case kLocalS1x16:
225          type = kWasmS1x16;
226          break;
227        default:
228          decoder->error(decoder->pc() - 1, "invalid local type");
229          return false;
230      }
231      type_list->insert(type_list->end(), count, type);
232    }
233    DCHECK(decoder->ok());
234    return true;
235  }
236
237  static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
238                                          int locals_count, Zone* zone) {
239    if (pc >= decoder->end()) return nullptr;
240    if (*pc != kExprLoop) return nullptr;
241
242    BitVector* assigned = new (zone) BitVector(locals_count, zone);
243    int depth = 0;
244    // Iteratively process all AST nodes nested inside the loop.
245    while (pc < decoder->end() && decoder->ok()) {
246      WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
247      unsigned length = 1;
248      switch (opcode) {
249        case kExprLoop:
250        case kExprIf:
251        case kExprBlock:
252        case kExprTry:
253          length = OpcodeLength(decoder, pc);
254          depth++;
255          break;
256        case kExprSetLocal:  // fallthru
257        case kExprTeeLocal: {
258          LocalIndexOperand operand(decoder, pc);
259          if (assigned->length() > 0 &&
260              operand.index < static_cast<uint32_t>(assigned->length())) {
261            // Unverified code might have an out-of-bounds index.
262            assigned->Add(operand.index);
263          }
264          length = 1 + operand.length;
265          break;
266        }
267        case kExprEnd:
268          depth--;
269          break;
270        default:
271          length = OpcodeLength(decoder, pc);
272          break;
273      }
274      if (depth <= 0) break;
275      pc += length;
276    }
277    return decoder->ok() ? assigned : nullptr;
278  }
279
280  inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
281    if (operand.index < total_locals()) {
282      if (local_types_) {
283        operand.type = local_types_->at(operand.index);
284      } else {
285        operand.type = kWasmStmt;
286      }
287      return true;
288    }
289    error(pc, pc + 1, "invalid local index: %u", operand.index);
290    return false;
291  }
292
293  inline bool Validate(const byte* pc, GlobalIndexOperand& operand) {
294    if (module_ != nullptr && operand.index < module_->globals.size()) {
295      operand.global = &module_->globals[operand.index];
296      operand.type = operand.global->type;
297      return true;
298    }
299    error(pc, pc + 1, "invalid global index: %u", operand.index);
300    return false;
301  }
302
303  inline bool Complete(const byte* pc, CallFunctionOperand& operand) {
304    if (module_ != nullptr && operand.index < module_->functions.size()) {
305      operand.sig = module_->functions[operand.index].sig;
306      return true;
307    }
308    return false;
309  }
310
311  inline bool Validate(const byte* pc, CallFunctionOperand& operand) {
312    if (Complete(pc, operand)) {
313      return true;
314    }
315    error(pc, pc + 1, "invalid function index: %u", operand.index);
316    return false;
317  }
318
319  inline bool Complete(const byte* pc, CallIndirectOperand& operand) {
320    if (module_ != nullptr && operand.index < module_->signatures.size()) {
321      operand.sig = module_->signatures[operand.index];
322      return true;
323    }
324    return false;
325  }
326
327  inline bool Validate(const byte* pc, CallIndirectOperand& operand) {
328    if (module_ == nullptr || module_->function_tables.empty()) {
329      error("function table has to exist to execute call_indirect");
330      return false;
331    }
332    if (Complete(pc, operand)) {
333      return true;
334    }
335    error(pc, pc + 1, "invalid signature index: #%u", operand.index);
336    return false;
337  }
338
339  inline bool Validate(const byte* pc, BreakDepthOperand& operand,
340                       ZoneVector<Control>& control) {
341    if (operand.depth < control.size()) {
342      operand.target = &control[control.size() - operand.depth - 1];
343      return true;
344    }
345    error(pc, pc + 1, "invalid break depth: %u", operand.depth);
346    return false;
347  }
348
349  bool Validate(const byte* pc, BranchTableOperand& operand,
350                size_t block_depth) {
351    // TODO(titzer): add extra redundant validation for br_table here?
352    return true;
353  }
354
355  inline bool Validate(const byte* pc, WasmOpcode opcode,
356                       SimdLaneOperand& operand) {
357    uint8_t num_lanes = 0;
358    switch (opcode) {
359      case kExprF32x4ExtractLane:
360      case kExprF32x4ReplaceLane:
361      case kExprI32x4ExtractLane:
362      case kExprI32x4ReplaceLane:
363        num_lanes = 4;
364        break;
365      case kExprI16x8ExtractLane:
366      case kExprI16x8ReplaceLane:
367        num_lanes = 8;
368        break;
369      case kExprI8x16ExtractLane:
370      case kExprI8x16ReplaceLane:
371        num_lanes = 16;
372        break;
373      default:
374        UNREACHABLE();
375        break;
376    }
377    if (operand.lane < 0 || operand.lane >= num_lanes) {
378      error(pc_, pc_ + 2, "invalid lane index");
379      return false;
380    } else {
381      return true;
382    }
383  }
384
385  inline bool Validate(const byte* pc, WasmOpcode opcode,
386                       SimdShiftOperand& operand) {
387    uint8_t max_shift = 0;
388    switch (opcode) {
389      case kExprI32x4Shl:
390      case kExprI32x4ShrS:
391      case kExprI32x4ShrU:
392        max_shift = 32;
393        break;
394      case kExprI16x8Shl:
395      case kExprI16x8ShrS:
396      case kExprI16x8ShrU:
397        max_shift = 16;
398        break;
399      case kExprI8x16Shl:
400      case kExprI8x16ShrS:
401      case kExprI8x16ShrU:
402        max_shift = 8;
403        break;
404      default:
405        UNREACHABLE();
406        break;
407    }
408    if (operand.shift < 0 || operand.shift >= max_shift) {
409      error(pc_, pc_ + 2, "invalid shift amount");
410      return false;
411    } else {
412      return true;
413    }
414  }
415
416  static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
417    switch (static_cast<byte>(*pc)) {
418#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
419      FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
420      FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
421#undef DECLARE_OPCODE_CASE
422      {
423        MemoryAccessOperand operand(decoder, pc, UINT32_MAX);
424        return 1 + operand.length;
425      }
426      case kExprBr:
427      case kExprBrIf: {
428        BreakDepthOperand operand(decoder, pc);
429        return 1 + operand.length;
430      }
431      case kExprSetGlobal:
432      case kExprGetGlobal: {
433        GlobalIndexOperand operand(decoder, pc);
434        return 1 + operand.length;
435      }
436
437      case kExprCallFunction: {
438        CallFunctionOperand operand(decoder, pc);
439        return 1 + operand.length;
440      }
441      case kExprCallIndirect: {
442        CallIndirectOperand operand(decoder, pc);
443        return 1 + operand.length;
444      }
445
446      case kExprTry:
447      case kExprIf:  // fall thru
448      case kExprLoop:
449      case kExprBlock: {
450        BlockTypeOperand operand(decoder, pc);
451        return 1 + operand.length;
452      }
453
454      case kExprSetLocal:
455      case kExprTeeLocal:
456      case kExprGetLocal:
457      case kExprCatch: {
458        LocalIndexOperand operand(decoder, pc);
459        return 1 + operand.length;
460      }
461      case kExprBrTable: {
462        BranchTableOperand operand(decoder, pc);
463        BranchTableIterator iterator(decoder, operand);
464        return 1 + iterator.length();
465      }
466      case kExprI32Const: {
467        ImmI32Operand operand(decoder, pc);
468        return 1 + operand.length;
469      }
470      case kExprI64Const: {
471        ImmI64Operand operand(decoder, pc);
472        return 1 + operand.length;
473      }
474      case kExprGrowMemory:
475      case kExprMemorySize: {
476        MemoryIndexOperand operand(decoder, pc);
477        return 1 + operand.length;
478      }
479      case kExprF32Const:
480        return 5;
481      case kExprF64Const:
482        return 9;
483      case kSimdPrefix: {
484        byte simd_index = decoder->checked_read_u8(pc, 1, "simd_index");
485        WasmOpcode opcode =
486            static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
487        switch (opcode) {
488#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
489          FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
490#undef DECLARE_OPCODE_CASE
491          {
492            return 2;
493          }
494#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
495          FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
496#undef DECLARE_OPCODE_CASE
497          {
498            return 3;
499          }
500          default:
501            decoder->error(pc, "invalid SIMD opcode");
502            return 2;
503        }
504      }
505      default:
506        return 1;
507    }
508  }
509};
510
511static const int32_t kNullCatch = -1;
512
513// The full WASM decoder for bytecode. Verifies bytecode and, optionally,
514// generates a TurboFan IR graph.
515class WasmFullDecoder : public WasmDecoder {
516 public:
517  WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
518                  const FunctionBody& body)
519      : WasmFullDecoder(zone, module, nullptr, body) {}
520
521  WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
522      : WasmFullDecoder(zone, builder->module_env() == nullptr
523                                  ? nullptr
524                                  : builder->module_env()->module,
525                        builder, body) {}
526
527  bool Decode() {
528    if (FLAG_wasm_code_fuzzer_gen_test) {
529      PrintRawWasmCode(start_, end_);
530    }
531    base::ElapsedTimer decode_timer;
532    if (FLAG_trace_wasm_decode_time) {
533      decode_timer.Start();
534    }
535    stack_.clear();
536    control_.clear();
537
538    if (end_ < pc_) {
539      error("function body end < start");
540      return false;
541    }
542
543    DCHECK_EQ(0, local_types_->size());
544    WasmDecoder::DecodeLocals(this, sig_, local_types_);
545    InitSsaEnv();
546    DecodeFunctionBody();
547
548    if (failed()) return TraceFailed();
549
550    if (!control_.empty()) {
551      // Generate a better error message whether the unterminated control
552      // structure is the function body block or an innner structure.
553      if (control_.size() > 1) {
554        error(pc_, control_.back().pc, "unterminated control structure");
555      } else {
556        error("function body must end with \"end\" opcode.");
557      }
558      return TraceFailed();
559    }
560
561    if (!last_end_found_) {
562      error("function body must end with \"end\" opcode.");
563      return false;
564    }
565
566    if (FLAG_trace_wasm_decode_time) {
567      double ms = decode_timer.Elapsed().InMillisecondsF();
568      PrintF("wasm-decode %s (%0.3f ms)\n\n", ok() ? "ok" : "failed", ms);
569    } else {
570      TRACE("wasm-decode %s\n\n", ok() ? "ok" : "failed");
571    }
572
573    return true;
574  }
575
576  bool TraceFailed() {
577    TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
578          startrel(error_pc_), error_msg_.get());
579    return false;
580  }
581
582 private:
583  WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
584                  TFBuilder* builder, const FunctionBody& body)
585      : WasmDecoder(module, body.sig, body.start, body.end),
586        zone_(zone),
587        builder_(builder),
588        base_(body.base),
589        local_type_vec_(zone),
590        stack_(zone),
591        control_(zone),
592        last_end_found_(false),
593        current_catch_(kNullCatch) {
594    local_types_ = &local_type_vec_;
595  }
596
597  static const size_t kErrorMsgSize = 128;
598
599  Zone* zone_;
600  TFBuilder* builder_;
601  const byte* base_;
602
603  SsaEnv* ssa_env_;
604
605  ZoneVector<ValueType> local_type_vec_;  // types of local variables.
606  ZoneVector<Value> stack_;               // stack of values.
607  ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
608  bool last_end_found_;
609
610  int32_t current_catch_;
611
612  TryInfo* current_try_info() { return control_[current_catch_].try_info; }
613
614  inline bool build() { return builder_ && ssa_env_->go(); }
615
616  void InitSsaEnv() {
617    TFNode* start = nullptr;
618    SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
619    size_t size = sizeof(TFNode*) * EnvironmentCount();
620    ssa_env->state = SsaEnv::kReached;
621    ssa_env->locals =
622        size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
623
624    if (builder_) {
625      start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
626      // Initialize local variables.
627      uint32_t index = 0;
628      while (index < sig_->parameter_count()) {
629        ssa_env->locals[index] = builder_->Param(index);
630        index++;
631      }
632      while (index < local_type_vec_.size()) {
633        ValueType type = local_type_vec_[index];
634        TFNode* node = DefaultValue(type);
635        while (index < local_type_vec_.size() &&
636               local_type_vec_[index] == type) {
637          // Do a whole run of like-typed locals at a time.
638          ssa_env->locals[index++] = node;
639        }
640      }
641    }
642    ssa_env->control = start;
643    ssa_env->effect = start;
644    SetEnv("initial", ssa_env);
645    if (builder_) {
646      // The function-prologue stack check is associated with position 0, which
647      // is never a position of any instruction in the function.
648      builder_->StackCheck(0);
649    }
650  }
651
652  TFNode* DefaultValue(ValueType type) {
653    switch (type) {
654      case kWasmI32:
655        return builder_->Int32Constant(0);
656      case kWasmI64:
657        return builder_->Int64Constant(0);
658      case kWasmF32:
659        return builder_->Float32Constant(0);
660      case kWasmF64:
661        return builder_->Float64Constant(0);
662      case kWasmS128:
663        return builder_->CreateS128Value(0);
664      default:
665        UNREACHABLE();
666        return nullptr;
667    }
668  }
669
670  char* indentation() {
671    static const int kMaxIndent = 64;
672    static char bytes[kMaxIndent + 1];
673    for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' ';
674    bytes[kMaxIndent] = 0;
675    if (stack_.size() < kMaxIndent / 2) {
676      bytes[stack_.size() * 2] = 0;
677    }
678    return bytes;
679  }
680
681  bool CheckHasMemory() {
682    if (!module_->has_memory) {
683      error(pc_ - 1, "memory instruction with no memory");
684    }
685    return module_->has_memory;
686  }
687
688  // Decodes the body of a function.
689  void DecodeFunctionBody() {
690    TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
691          reinterpret_cast<const void*>(start_),
692          reinterpret_cast<const void*>(end_), baserel(pc_),
693          static_cast<int>(end_ - start_), builder_ ? "graph building" : "");
694
695    {
696      // Set up initial function block.
697      SsaEnv* break_env = ssa_env_;
698      SetEnv("initial env", Steal(break_env));
699      PushBlock(break_env);
700      Control* c = &control_.back();
701      c->merge.arity = static_cast<uint32_t>(sig_->return_count());
702
703      if (c->merge.arity == 1) {
704        c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)};
705      } else if (c->merge.arity > 1) {
706        c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
707        for (unsigned i = 0; i < c->merge.arity; i++) {
708          c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)};
709        }
710      }
711    }
712
713    while (pc_ < end_) {  // decoding loop.
714      unsigned len = 1;
715      WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
716#if DEBUG
717      if (FLAG_trace_wasm_decoder && !WasmOpcodes::IsPrefixOpcode(opcode)) {
718        TRACE("  @%-8d #%-20s|", startrel(pc_),
719              WasmOpcodes::OpcodeName(opcode));
720      }
721#endif
722
723      FunctionSig* sig = WasmOpcodes::Signature(opcode);
724      if (sig) {
725        BuildSimpleOperator(opcode, sig);
726      } else {
727        // Complex bytecode.
728        switch (opcode) {
729          case kExprNop:
730            break;
731          case kExprBlock: {
732            // The break environment is the outer environment.
733            BlockTypeOperand operand(this, pc_);
734            SsaEnv* break_env = ssa_env_;
735            PushBlock(break_env);
736            SetEnv("block:start", Steal(break_env));
737            SetBlockType(&control_.back(), operand);
738            len = 1 + operand.length;
739            break;
740          }
741          case kExprThrow: {
742            CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
743            Value value = Pop(0, kWasmI32);
744            BUILD(Throw, value.node);
745            // TODO(titzer): Throw should end control, but currently we build a
746            // (reachable) runtime call instead of connecting it directly to
747            // end.
748            //            EndControl();
749            break;
750          }
751          case kExprTry: {
752            CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
753            BlockTypeOperand operand(this, pc_);
754            SsaEnv* outer_env = ssa_env_;
755            SsaEnv* try_env = Steal(outer_env);
756            SsaEnv* catch_env = UnreachableEnv();
757            PushTry(outer_env, catch_env);
758            SetEnv("try_catch:start", try_env);
759            SetBlockType(&control_.back(), operand);
760            len = 1 + operand.length;
761            break;
762          }
763          case kExprCatch: {
764            CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
765            LocalIndexOperand operand(this, pc_);
766            len = 1 + operand.length;
767
768            if (control_.empty()) {
769              error("catch does not match any try");
770              break;
771            }
772
773            Control* c = &control_.back();
774            if (!c->is_try()) {
775              error("catch does not match any try");
776              break;
777            }
778
779            if (c->try_info->catch_env == nullptr) {
780              error(pc_, "catch already present for try with catch");
781              break;
782            }
783
784            FallThruTo(c);
785            stack_.resize(c->stack_depth);
786
787            DCHECK_NOT_NULL(c->try_info);
788            SsaEnv* catch_env = c->try_info->catch_env;
789            c->try_info->catch_env = nullptr;
790            SetEnv("catch:begin", catch_env);
791            current_catch_ = c->previous_catch;
792
793            if (Validate(pc_, operand)) {
794              if (ssa_env_->locals) {
795                TFNode* exception_as_i32 =
796                    BUILD(Catch, c->try_info->exception, position());
797                ssa_env_->locals[operand.index] = exception_as_i32;
798              }
799            }
800
801            break;
802          }
803          case kExprLoop: {
804            BlockTypeOperand operand(this, pc_);
805            SsaEnv* finish_try_env = Steal(ssa_env_);
806            // The continue environment is the inner environment.
807            SsaEnv* loop_body_env = PrepareForLoop(pc_, finish_try_env);
808            SetEnv("loop:start", loop_body_env);
809            ssa_env_->SetNotMerged();
810            PushLoop(finish_try_env);
811            SetBlockType(&control_.back(), operand);
812            len = 1 + operand.length;
813            break;
814          }
815          case kExprIf: {
816            // Condition on top of stack. Split environments for branches.
817            BlockTypeOperand operand(this, pc_);
818            Value cond = Pop(0, kWasmI32);
819            TFNode* if_true = nullptr;
820            TFNode* if_false = nullptr;
821            BUILD(BranchNoHint, cond.node, &if_true, &if_false);
822            SsaEnv* end_env = ssa_env_;
823            SsaEnv* false_env = Split(ssa_env_);
824            false_env->control = if_false;
825            SsaEnv* true_env = Steal(ssa_env_);
826            true_env->control = if_true;
827            PushIf(end_env, false_env);
828            SetEnv("if:true", true_env);
829            SetBlockType(&control_.back(), operand);
830            len = 1 + operand.length;
831            break;
832          }
833          case kExprElse: {
834            if (control_.empty()) {
835              error("else does not match any if");
836              break;
837            }
838            Control* c = &control_.back();
839            if (!c->is_if()) {
840              error(pc_, c->pc, "else does not match an if");
841              break;
842            }
843            if (c->false_env == nullptr) {
844              error(pc_, c->pc, "else already present for if");
845              break;
846            }
847            FallThruTo(c);
848            stack_.resize(c->stack_depth);
849            // Switch to environment for false branch.
850            SetEnv("if_else:false", c->false_env);
851            c->false_env = nullptr;  // record that an else is already seen
852            break;
853          }
854          case kExprEnd: {
855            if (control_.empty()) {
856              error("end does not match any if, try, or block");
857              return;
858            }
859            const char* name = "block:end";
860            Control* c = &control_.back();
861            if (c->is_loop()) {
862              // A loop just leaves the values on the stack.
863              TypeCheckFallThru(c);
864              if (c->unreachable) PushEndValues(c);
865              PopControl();
866              SetEnv("loop:end", ssa_env_);
867              break;
868            }
869            if (c->is_if()) {
870              if (c->false_env != nullptr) {
871                // End the true branch of a one-armed if.
872                Goto(c->false_env, c->end_env);
873                if (!c->unreachable && stack_.size() != c->stack_depth) {
874                  error("end of if expected empty stack");
875                  stack_.resize(c->stack_depth);
876                }
877                if (c->merge.arity > 0) {
878                  error("non-void one-armed if");
879                }
880                name = "if:merge";
881              } else {
882                // End the false branch of a two-armed if.
883                name = "if_else:merge";
884              }
885            } else if (c->is_try()) {
886              name = "try:end";
887
888              // validate that catch was seen.
889              if (c->try_info->catch_env != nullptr) {
890                error(pc_, "missing catch in try");
891                break;
892              }
893            }
894            FallThruTo(c);
895            SetEnv(name, c->end_env);
896            PushEndValues(c);
897
898            if (control_.size() == 1) {
899              // If at the last (implicit) control, check we are at end.
900              if (pc_ + 1 != end_) {
901                error(pc_, pc_ + 1, "trailing code after function end");
902                break;
903              }
904              last_end_found_ = true;
905              if (ssa_env_->go()) {
906                // The result of the block is the return value.
907                TRACE("  @%-8d #xx:%-20s|", startrel(pc_), "(implicit) return");
908                DoReturn();
909                TRACE("\n");
910              } else {
911                TypeCheckFallThru(c);
912              }
913            }
914            PopControl();
915            break;
916          }
917          case kExprSelect: {
918            Value cond = Pop(2, kWasmI32);
919            Value fval = Pop();
920            Value tval = Pop(0, fval.type);
921            if (build()) {
922              TFNode* controls[2];
923              builder_->BranchNoHint(cond.node, &controls[0], &controls[1]);
924              TFNode* merge = builder_->Merge(2, controls);
925              TFNode* vals[2] = {tval.node, fval.node};
926              TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
927              Push(tval.type, phi);
928              ssa_env_->control = merge;
929            } else {
930              Push(tval.type == kWasmVar ? fval.type : tval.type, nullptr);
931            }
932            break;
933          }
934          case kExprBr: {
935            BreakDepthOperand operand(this, pc_);
936            if (Validate(pc_, operand, control_)) {
937              BreakTo(operand.depth);
938            }
939            len = 1 + operand.length;
940            EndControl();
941            break;
942          }
943          case kExprBrIf: {
944            BreakDepthOperand operand(this, pc_);
945            Value cond = Pop(0, kWasmI32);
946            if (ok() && Validate(pc_, operand, control_)) {
947              SsaEnv* fenv = ssa_env_;
948              SsaEnv* tenv = Split(fenv);
949              fenv->SetNotMerged();
950              BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
951              ssa_env_ = tenv;
952              BreakTo(operand.depth);
953              ssa_env_ = fenv;
954            }
955            len = 1 + operand.length;
956            break;
957          }
958          case kExprBrTable: {
959            BranchTableOperand operand(this, pc_);
960            BranchTableIterator iterator(this, operand);
961            if (Validate(pc_, operand, control_.size())) {
962              Value key = Pop(0, kWasmI32);
963              if (failed()) break;
964
965              SsaEnv* break_env = ssa_env_;
966              if (operand.table_count > 0) {
967                // Build branches to the various blocks based on the table.
968                TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
969
970                SsaEnv* copy = Steal(break_env);
971                ssa_env_ = copy;
972                MergeValues* merge = nullptr;
973                while (ok() && iterator.has_next()) {
974                  uint32_t i = iterator.cur_index();
975                  const byte* pos = iterator.pc();
976                  uint32_t target = iterator.next();
977                  if (target >= control_.size()) {
978                    error(pos, "improper branch in br_table");
979                    break;
980                  }
981                  ssa_env_ = Split(copy);
982                  ssa_env_->control = (i == operand.table_count)
983                                          ? BUILD(IfDefault, sw)
984                                          : BUILD(IfValue, i, sw);
985                  BreakTo(target);
986
987                  // Check that label types match up.
988                  Control* c = &control_[control_.size() - target - 1];
989                  if (i == 0) {
990                    merge = &c->merge;
991                  } else if (merge->arity != c->merge.arity) {
992                    error(pos, pos, "inconsistent arity in br_table target %d"
993                          " (previous was %u, this one %u)",
994                          i, merge->arity, c->merge.arity);
995                  } else if (control_.back().unreachable) {
996                    for (uint32_t j = 0; ok() && j < merge->arity; ++j) {
997                      if ((*merge)[j].type != c->merge[j].type) {
998                        error(pos, pos,
999                              "type error in br_table target %d operand %d"
1000                              " (previous expected %s, this one %s)", i, j,
1001                              WasmOpcodes::TypeName((*merge)[j].type),
1002                              WasmOpcodes::TypeName(c->merge[j].type));
1003                      }
1004                    }
1005                  }
1006                }
1007                if (failed()) break;
1008              } else {
1009                // Only a default target. Do the equivalent of br.
1010                const byte* pos = iterator.pc();
1011                uint32_t target = iterator.next();
1012                if (target >= control_.size()) {
1013                  error(pos, "improper branch in br_table");
1014                  break;
1015                }
1016                BreakTo(target);
1017              }
1018              // br_table ends the control flow like br.
1019              ssa_env_ = break_env;
1020            }
1021            len = 1 + iterator.length();
1022            EndControl();
1023            break;
1024          }
1025          case kExprReturn: {
1026            DoReturn();
1027            break;
1028          }
1029          case kExprUnreachable: {
1030            BUILD(Unreachable, position());
1031            EndControl();
1032            break;
1033          }
1034          case kExprI32Const: {
1035            ImmI32Operand operand(this, pc_);
1036            Push(kWasmI32, BUILD(Int32Constant, operand.value));
1037            len = 1 + operand.length;
1038            break;
1039          }
1040          case kExprI64Const: {
1041            ImmI64Operand operand(this, pc_);
1042            Push(kWasmI64, BUILD(Int64Constant, operand.value));
1043            len = 1 + operand.length;
1044            break;
1045          }
1046          case kExprF32Const: {
1047            ImmF32Operand operand(this, pc_);
1048            Push(kWasmF32, BUILD(Float32Constant, operand.value));
1049            len = 1 + operand.length;
1050            break;
1051          }
1052          case kExprF64Const: {
1053            ImmF64Operand operand(this, pc_);
1054            Push(kWasmF64, BUILD(Float64Constant, operand.value));
1055            len = 1 + operand.length;
1056            break;
1057          }
1058          case kExprGetLocal: {
1059            LocalIndexOperand operand(this, pc_);
1060            if (Validate(pc_, operand)) {
1061              if (build()) {
1062                Push(operand.type, ssa_env_->locals[operand.index]);
1063              } else {
1064                Push(operand.type, nullptr);
1065              }
1066            }
1067            len = 1 + operand.length;
1068            break;
1069          }
1070          case kExprSetLocal: {
1071            LocalIndexOperand operand(this, pc_);
1072            if (Validate(pc_, operand)) {
1073              Value val = Pop(0, local_type_vec_[operand.index]);
1074              if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
1075            }
1076            len = 1 + operand.length;
1077            break;
1078          }
1079          case kExprTeeLocal: {
1080            LocalIndexOperand operand(this, pc_);
1081            if (Validate(pc_, operand)) {
1082              Value val = Pop(0, local_type_vec_[operand.index]);
1083              if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
1084              Push(val.type, val.node);
1085            }
1086            len = 1 + operand.length;
1087            break;
1088          }
1089          case kExprDrop: {
1090            Pop();
1091            break;
1092          }
1093          case kExprGetGlobal: {
1094            GlobalIndexOperand operand(this, pc_);
1095            if (Validate(pc_, operand)) {
1096              Push(operand.type, BUILD(GetGlobal, operand.index));
1097            }
1098            len = 1 + operand.length;
1099            break;
1100          }
1101          case kExprSetGlobal: {
1102            GlobalIndexOperand operand(this, pc_);
1103            if (Validate(pc_, operand)) {
1104              if (operand.global->mutability) {
1105                Value val = Pop(0, operand.type);
1106                BUILD(SetGlobal, operand.index, val.node);
1107              } else {
1108                error(pc_, pc_ + 1, "immutable global #%u cannot be assigned",
1109                      operand.index);
1110              }
1111            }
1112            len = 1 + operand.length;
1113            break;
1114          }
1115          case kExprI32LoadMem8S:
1116            len = DecodeLoadMem(kWasmI32, MachineType::Int8());
1117            break;
1118          case kExprI32LoadMem8U:
1119            len = DecodeLoadMem(kWasmI32, MachineType::Uint8());
1120            break;
1121          case kExprI32LoadMem16S:
1122            len = DecodeLoadMem(kWasmI32, MachineType::Int16());
1123            break;
1124          case kExprI32LoadMem16U:
1125            len = DecodeLoadMem(kWasmI32, MachineType::Uint16());
1126            break;
1127          case kExprI32LoadMem:
1128            len = DecodeLoadMem(kWasmI32, MachineType::Int32());
1129            break;
1130          case kExprI64LoadMem8S:
1131            len = DecodeLoadMem(kWasmI64, MachineType::Int8());
1132            break;
1133          case kExprI64LoadMem8U:
1134            len = DecodeLoadMem(kWasmI64, MachineType::Uint8());
1135            break;
1136          case kExprI64LoadMem16S:
1137            len = DecodeLoadMem(kWasmI64, MachineType::Int16());
1138            break;
1139          case kExprI64LoadMem16U:
1140            len = DecodeLoadMem(kWasmI64, MachineType::Uint16());
1141            break;
1142          case kExprI64LoadMem32S:
1143            len = DecodeLoadMem(kWasmI64, MachineType::Int32());
1144            break;
1145          case kExprI64LoadMem32U:
1146            len = DecodeLoadMem(kWasmI64, MachineType::Uint32());
1147            break;
1148          case kExprI64LoadMem:
1149            len = DecodeLoadMem(kWasmI64, MachineType::Int64());
1150            break;
1151          case kExprF32LoadMem:
1152            len = DecodeLoadMem(kWasmF32, MachineType::Float32());
1153            break;
1154          case kExprF64LoadMem:
1155            len = DecodeLoadMem(kWasmF64, MachineType::Float64());
1156            break;
1157          case kExprI32StoreMem8:
1158            len = DecodeStoreMem(kWasmI32, MachineType::Int8());
1159            break;
1160          case kExprI32StoreMem16:
1161            len = DecodeStoreMem(kWasmI32, MachineType::Int16());
1162            break;
1163          case kExprI32StoreMem:
1164            len = DecodeStoreMem(kWasmI32, MachineType::Int32());
1165            break;
1166          case kExprI64StoreMem8:
1167            len = DecodeStoreMem(kWasmI64, MachineType::Int8());
1168            break;
1169          case kExprI64StoreMem16:
1170            len = DecodeStoreMem(kWasmI64, MachineType::Int16());
1171            break;
1172          case kExprI64StoreMem32:
1173            len = DecodeStoreMem(kWasmI64, MachineType::Int32());
1174            break;
1175          case kExprI64StoreMem:
1176            len = DecodeStoreMem(kWasmI64, MachineType::Int64());
1177            break;
1178          case kExprF32StoreMem:
1179            len = DecodeStoreMem(kWasmF32, MachineType::Float32());
1180            break;
1181          case kExprF64StoreMem:
1182            len = DecodeStoreMem(kWasmF64, MachineType::Float64());
1183            break;
1184          case kExprGrowMemory: {
1185            if (!CheckHasMemory()) break;
1186            MemoryIndexOperand operand(this, pc_);
1187            DCHECK_NOT_NULL(module_);
1188            if (module_->origin != kAsmJsOrigin) {
1189              Value val = Pop(0, kWasmI32);
1190              Push(kWasmI32, BUILD(GrowMemory, val.node));
1191            } else {
1192              error("grow_memory is not supported for asmjs modules");
1193            }
1194            len = 1 + operand.length;
1195            break;
1196          }
1197          case kExprMemorySize: {
1198            if (!CheckHasMemory()) break;
1199            MemoryIndexOperand operand(this, pc_);
1200            Push(kWasmI32, BUILD(CurrentMemoryPages));
1201            len = 1 + operand.length;
1202            break;
1203          }
1204          case kExprCallFunction: {
1205            CallFunctionOperand operand(this, pc_);
1206            if (Validate(pc_, operand)) {
1207              TFNode** buffer = PopArgs(operand.sig);
1208              TFNode** rets = nullptr;
1209              BUILD(CallDirect, operand.index, buffer, &rets, position());
1210              PushReturns(operand.sig, rets);
1211            }
1212            len = 1 + operand.length;
1213            break;
1214          }
1215          case kExprCallIndirect: {
1216            CallIndirectOperand operand(this, pc_);
1217            if (Validate(pc_, operand)) {
1218              Value index = Pop(0, kWasmI32);
1219              TFNode** buffer = PopArgs(operand.sig);
1220              if (buffer) buffer[0] = index.node;
1221              TFNode** rets = nullptr;
1222              BUILD(CallIndirect, operand.index, buffer, &rets, position());
1223              PushReturns(operand.sig, rets);
1224            }
1225            len = 1 + operand.length;
1226            break;
1227          }
1228          case kSimdPrefix: {
1229            CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
1230            len++;
1231            byte simd_index = checked_read_u8(pc_, 1, "simd index");
1232            opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
1233            TRACE("  @%-4d #%-20s|", startrel(pc_),
1234                  WasmOpcodes::OpcodeName(opcode));
1235            len += DecodeSimdOpcode(opcode);
1236            break;
1237          }
1238          case kAtomicPrefix: {
1239            if (module_ == nullptr || module_->origin != kAsmJsOrigin) {
1240              error("Atomics are allowed only in AsmJs modules");
1241              break;
1242            }
1243            if (!FLAG_wasm_atomics_prototype) {
1244              error("Invalid opcode (enable with --wasm_atomics_prototype)");
1245              break;
1246            }
1247            len = 2;
1248            byte atomic_opcode = checked_read_u8(pc_, 1, "atomic index");
1249            opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_opcode);
1250            sig = WasmOpcodes::AtomicSignature(opcode);
1251            if (sig) {
1252              BuildAtomicOperator(opcode);
1253            }
1254            break;
1255          }
1256          default: {
1257            // Deal with special asmjs opcodes.
1258            if (module_ != nullptr && module_->origin == kAsmJsOrigin) {
1259              sig = WasmOpcodes::AsmjsSignature(opcode);
1260              if (sig) {
1261                BuildSimpleOperator(opcode, sig);
1262              }
1263            } else {
1264              error("Invalid opcode");
1265              return;
1266            }
1267          }
1268        }
1269      }
1270
1271#if DEBUG
1272      if (FLAG_trace_wasm_decoder) {
1273        PrintF(" ");
1274        for (size_t i = 0; i < control_.size(); ++i) {
1275          Control* c = &control_[i];
1276          enum ControlKind {
1277            kControlIf,
1278            kControlBlock,
1279            kControlLoop,
1280            kControlTry
1281          };
1282          switch (c->kind) {
1283            case kControlIf:
1284              PrintF("I");
1285              break;
1286            case kControlBlock:
1287              PrintF("B");
1288              break;
1289            case kControlLoop:
1290              PrintF("L");
1291              break;
1292            case kControlTry:
1293              PrintF("T");
1294              break;
1295            default:
1296              break;
1297          }
1298          PrintF("%u", c->merge.arity);
1299          if (c->unreachable) PrintF("*");
1300        }
1301        PrintF(" | ");
1302        for (size_t i = 0; i < stack_.size(); ++i) {
1303          Value& val = stack_[i];
1304          WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1305          if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1306            opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
1307          }
1308          PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
1309                 static_cast<int>(val.pc - start_),
1310                 WasmOpcodes::OpcodeName(opcode));
1311          switch (opcode) {
1312            case kExprI32Const: {
1313              ImmI32Operand operand(this, val.pc);
1314              PrintF("[%d]", operand.value);
1315              break;
1316            }
1317            case kExprGetLocal: {
1318              LocalIndexOperand operand(this, val.pc);
1319              PrintF("[%u]", operand.index);
1320              break;
1321            }
1322            case kExprSetLocal:  // fallthru
1323            case kExprTeeLocal: {
1324              LocalIndexOperand operand(this, val.pc);
1325              PrintF("[%u]", operand.index);
1326              break;
1327            }
1328            default:
1329              break;
1330          }
1331          if (val.node == nullptr) PrintF("?");
1332        }
1333        PrintF("\n");
1334      }
1335#endif
1336      pc_ += len;
1337    }  // end decode loop
1338    if (pc_ > end_ && ok()) error("Beyond end of code");
1339  }
1340
1341  void EndControl() {
1342    ssa_env_->Kill(SsaEnv::kControlEnd);
1343    if (!control_.empty()) {
1344      stack_.resize(control_.back().stack_depth);
1345      control_.back().unreachable = true;
1346    }
1347  }
1348
1349  void SetBlockType(Control* c, BlockTypeOperand& operand) {
1350    c->merge.arity = operand.arity;
1351    if (c->merge.arity == 1) {
1352      c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)};
1353    } else if (c->merge.arity > 1) {
1354      c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
1355      for (unsigned i = 0; i < c->merge.arity; i++) {
1356        c->merge.vals.array[i] = {pc_, nullptr, operand.read_entry(i)};
1357      }
1358    }
1359  }
1360
1361  TFNode** PopArgs(FunctionSig* sig) {
1362    if (build()) {
1363      int count = static_cast<int>(sig->parameter_count());
1364      TFNode** buffer = builder_->Buffer(count + 1);
1365      buffer[0] = nullptr;  // reserved for code object or function index.
1366      for (int i = count - 1; i >= 0; i--) {
1367        buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
1368      }
1369      return buffer;
1370    } else {
1371      int count = static_cast<int>(sig->parameter_count());
1372      for (int i = count - 1; i >= 0; i--) {
1373        Pop(i, sig->GetParam(i));
1374      }
1375      return nullptr;
1376    }
1377  }
1378
1379  ValueType GetReturnType(FunctionSig* sig) {
1380    return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
1381  }
1382
1383  void PushBlock(SsaEnv* end_env) {
1384    control_.emplace_back(
1385        Control::Block(pc_, stack_.size(), end_env, current_catch_));
1386  }
1387
1388  void PushLoop(SsaEnv* end_env) {
1389    control_.emplace_back(
1390        Control::Loop(pc_, stack_.size(), end_env, current_catch_));
1391  }
1392
1393  void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1394    control_.emplace_back(
1395        Control::If(pc_, stack_.size(), end_env, false_env, current_catch_));
1396  }
1397
1398  void PushTry(SsaEnv* end_env, SsaEnv* catch_env) {
1399    control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_,
1400                                       catch_env, current_catch_));
1401    current_catch_ = static_cast<int32_t>(control_.size() - 1);
1402  }
1403
1404  void PopControl() { control_.pop_back(); }
1405
1406  int DecodeLoadMem(ValueType type, MachineType mem_type) {
1407    if (!CheckHasMemory()) return 0;
1408    MemoryAccessOperand operand(this, pc_,
1409                                ElementSizeLog2Of(mem_type.representation()));
1410
1411    Value index = Pop(0, kWasmI32);
1412    TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
1413                         operand.alignment, position());
1414    Push(type, node);
1415    return 1 + operand.length;
1416  }
1417
1418  int DecodeStoreMem(ValueType type, MachineType mem_type) {
1419    if (!CheckHasMemory()) return 0;
1420    MemoryAccessOperand operand(this, pc_,
1421                                ElementSizeLog2Of(mem_type.representation()));
1422    Value val = Pop(1, type);
1423    Value index = Pop(0, kWasmI32);
1424    BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
1425          val.node, position());
1426    return 1 + operand.length;
1427  }
1428
1429  unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
1430    SimdLaneOperand operand(this, pc_);
1431    if (Validate(pc_, opcode, operand)) {
1432      compiler::NodeVector inputs(1, zone_);
1433      inputs[0] = Pop(0, ValueType::kSimd128).node;
1434      TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
1435      Push(type, node);
1436    }
1437    return operand.length;
1438  }
1439
1440  unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
1441    SimdLaneOperand operand(this, pc_);
1442    if (Validate(pc_, opcode, operand)) {
1443      compiler::NodeVector inputs(2, zone_);
1444      inputs[1] = Pop(1, type).node;
1445      inputs[0] = Pop(0, ValueType::kSimd128).node;
1446      TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
1447      Push(ValueType::kSimd128, node);
1448    }
1449    return operand.length;
1450  }
1451
1452  unsigned SimdShiftOp(WasmOpcode opcode) {
1453    SimdShiftOperand operand(this, pc_);
1454    if (Validate(pc_, opcode, operand)) {
1455      compiler::NodeVector inputs(1, zone_);
1456      inputs[0] = Pop(0, ValueType::kSimd128).node;
1457      TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
1458      Push(ValueType::kSimd128, node);
1459    }
1460    return operand.length;
1461  }
1462
1463  unsigned DecodeSimdOpcode(WasmOpcode opcode) {
1464    unsigned len = 0;
1465    switch (opcode) {
1466      case kExprF32x4ExtractLane: {
1467        len = SimdExtractLane(opcode, ValueType::kFloat32);
1468        break;
1469      }
1470      case kExprI32x4ExtractLane:
1471      case kExprI16x8ExtractLane:
1472      case kExprI8x16ExtractLane: {
1473        len = SimdExtractLane(opcode, ValueType::kWord32);
1474        break;
1475      }
1476      case kExprF32x4ReplaceLane: {
1477        len = SimdReplaceLane(opcode, ValueType::kFloat32);
1478        break;
1479      }
1480      case kExprI32x4ReplaceLane:
1481      case kExprI16x8ReplaceLane:
1482      case kExprI8x16ReplaceLane: {
1483        len = SimdReplaceLane(opcode, ValueType::kWord32);
1484        break;
1485      }
1486      case kExprI32x4Shl:
1487      case kExprI32x4ShrS:
1488      case kExprI32x4ShrU:
1489      case kExprI16x8Shl:
1490      case kExprI16x8ShrS:
1491      case kExprI16x8ShrU:
1492      case kExprI8x16Shl:
1493      case kExprI8x16ShrS:
1494      case kExprI8x16ShrU: {
1495        len = SimdShiftOp(opcode);
1496        break;
1497      }
1498      default: {
1499        FunctionSig* sig = WasmOpcodes::Signature(opcode);
1500        if (sig != nullptr) {
1501          compiler::NodeVector inputs(sig->parameter_count(), zone_);
1502          for (size_t i = sig->parameter_count(); i > 0; i--) {
1503            Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1));
1504            inputs[i - 1] = val.node;
1505          }
1506          TFNode* node = BUILD(SimdOp, opcode, inputs);
1507          Push(GetReturnType(sig), node);
1508        } else {
1509          error("invalid simd opcode");
1510        }
1511      }
1512    }
1513    return len;
1514  }
1515
1516  void BuildAtomicOperator(WasmOpcode opcode) { UNIMPLEMENTED(); }
1517
1518  void DoReturn() {
1519    int count = static_cast<int>(sig_->return_count());
1520    TFNode** buffer = nullptr;
1521    if (build()) buffer = builder_->Buffer(count);
1522
1523    // Pop return values off the stack in reverse order.
1524    for (int i = count - 1; i >= 0; i--) {
1525      Value val = Pop(i, sig_->GetReturn(i));
1526      if (buffer) buffer[i] = val.node;
1527    }
1528
1529    BUILD(Return, count, buffer);
1530    EndControl();
1531  }
1532
1533  void Push(ValueType type, TFNode* node) {
1534    if (type != kWasmStmt) {
1535      stack_.push_back({pc_, node, type});
1536    }
1537  }
1538
1539  void PushEndValues(Control* c) {
1540    DCHECK_EQ(c, &control_.back());
1541    stack_.resize(c->stack_depth);
1542    if (c->merge.arity == 1) {
1543      stack_.push_back(c->merge.vals.first);
1544    } else {
1545      for (unsigned i = 0; i < c->merge.arity; i++) {
1546        stack_.push_back(c->merge.vals.array[i]);
1547      }
1548    }
1549    DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
1550  }
1551
1552  void PushReturns(FunctionSig* sig, TFNode** rets) {
1553    for (size_t i = 0; i < sig->return_count(); i++) {
1554      // When verifying only, then {rets} will be null, so push null.
1555      Push(sig->GetReturn(i), rets ? rets[i] : nullptr);
1556    }
1557  }
1558
1559  const char* SafeOpcodeNameAt(const byte* pc) {
1560    if (pc >= end_) return "<end>";
1561    return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1562  }
1563
1564  Value Pop(int index, ValueType expected) {
1565    Value val = Pop();
1566    if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) {
1567      error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
1568            SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
1569            SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
1570    }
1571    return val;
1572  }
1573
1574  Value Pop() {
1575    size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
1576    if (stack_.size() <= limit) {
1577      // Popping past the current control start in reachable code.
1578      Value val = {pc_, nullptr, kWasmVar};
1579      if (!control_.back().unreachable) {
1580        error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
1581      }
1582      return val;
1583    }
1584    Value val = stack_.back();
1585    stack_.pop_back();
1586    return val;
1587  }
1588
1589  int baserel(const byte* ptr) {
1590    return base_ ? static_cast<int>(ptr - base_) : 0;
1591  }
1592
1593  int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1594
1595  void BreakTo(unsigned depth) {
1596    Control* c = &control_[control_.size() - depth - 1];
1597    if (c->is_loop()) {
1598      // This is the inner loop block, which does not have a value.
1599      Goto(ssa_env_, c->end_env);
1600    } else {
1601      // Merge the value(s) into the end of the block.
1602      size_t expected = control_.back().stack_depth + c->merge.arity;
1603      if (stack_.size() < expected && !control_.back().unreachable) {
1604        error(
1605            pc_, pc_,
1606            "expected at least %u values on the stack for br to @%d, found %d",
1607            c->merge.arity, startrel(c->pc),
1608            static_cast<int>(stack_.size() - c->stack_depth));
1609        return;
1610      }
1611      MergeValuesInto(c);
1612    }
1613  }
1614
1615  void FallThruTo(Control* c) {
1616    DCHECK_EQ(c, &control_.back());
1617    // Merge the value(s) into the end of the block.
1618    size_t expected = c->stack_depth + c->merge.arity;
1619    if (stack_.size() == expected ||
1620        (stack_.size() < expected && c->unreachable)) {
1621      MergeValuesInto(c);
1622      c->unreachable = false;
1623      return;
1624    }
1625    error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d",
1626          c->merge.arity, startrel(c->pc));
1627  }
1628
1629  inline Value& GetMergeValueFromStack(Control* c, size_t i) {
1630    return stack_[stack_.size() - c->merge.arity + i];
1631  }
1632
1633  void TypeCheckFallThru(Control* c) {
1634    DCHECK_EQ(c, &control_.back());
1635    // Fallthru must match arity exactly.
1636    int arity = static_cast<int>(c->merge.arity);
1637    if (c->stack_depth + arity < stack_.size() ||
1638        (c->stack_depth + arity != stack_.size() && !c->unreachable)) {
1639      error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d",
1640            arity, startrel(c->pc));
1641      return;
1642    }
1643    // Typecheck the values left on the stack.
1644    size_t avail = stack_.size() - c->stack_depth;
1645    for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
1646         i < c->merge.arity; i++) {
1647      Value& val = GetMergeValueFromStack(c, i);
1648      Value& old = c->merge[i];
1649      if (val.type != old.type) {
1650        error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
1651              WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
1652        return;
1653      }
1654    }
1655  }
1656
1657  void MergeValuesInto(Control* c) {
1658    SsaEnv* target = c->end_env;
1659    bool first = target->state == SsaEnv::kUnreachable;
1660    bool reachable = ssa_env_->go();
1661    Goto(ssa_env_, target);
1662
1663    size_t avail = stack_.size() - control_.back().stack_depth;
1664    for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
1665         i < c->merge.arity; i++) {
1666      Value& val = GetMergeValueFromStack(c, i);
1667      Value& old = c->merge[i];
1668      if (val.type != old.type && val.type != kWasmVar) {
1669        error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
1670              WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
1671        return;
1672      }
1673      if (builder_ && reachable) {
1674        DCHECK_NOT_NULL(val.node);
1675        old.node =
1676            first ? val.node : CreateOrMergeIntoPhi(old.type, target->control,
1677                                                    old.node, val.node);
1678      }
1679    }
1680  }
1681
1682  void SetEnv(const char* reason, SsaEnv* env) {
1683#if DEBUG
1684    if (FLAG_trace_wasm_decoder) {
1685      char state = 'X';
1686      if (env) {
1687        switch (env->state) {
1688          case SsaEnv::kReached:
1689            state = 'R';
1690            break;
1691          case SsaEnv::kUnreachable:
1692            state = 'U';
1693            break;
1694          case SsaEnv::kMerged:
1695            state = 'M';
1696            break;
1697          case SsaEnv::kControlEnd:
1698            state = 'E';
1699            break;
1700        }
1701      }
1702      PrintF("{set_env = %p, state = %c, reason = %s", static_cast<void*>(env),
1703             state, reason);
1704      if (env && env->control) {
1705        PrintF(", control = ");
1706        compiler::WasmGraphBuilder::PrintDebugName(env->control);
1707      }
1708      PrintF("}");
1709    }
1710#endif
1711    ssa_env_ = env;
1712    if (builder_) {
1713      builder_->set_control_ptr(&env->control);
1714      builder_->set_effect_ptr(&env->effect);
1715    }
1716  }
1717
1718  TFNode* CheckForException(TFNode* node) {
1719    if (node == nullptr) {
1720      return nullptr;
1721    }
1722
1723    const bool inside_try_scope = current_catch_ != kNullCatch;
1724
1725    if (!inside_try_scope) {
1726      return node;
1727    }
1728
1729    TFNode* if_success = nullptr;
1730    TFNode* if_exception = nullptr;
1731    if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
1732      return node;
1733    }
1734
1735    SsaEnv* success_env = Steal(ssa_env_);
1736    success_env->control = if_success;
1737
1738    SsaEnv* exception_env = Split(success_env);
1739    exception_env->control = if_exception;
1740    TryInfo* try_info = current_try_info();
1741    Goto(exception_env, try_info->catch_env);
1742    TFNode* exception = try_info->exception;
1743    if (exception == nullptr) {
1744      DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
1745      try_info->exception = if_exception;
1746    } else {
1747      DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
1748      try_info->exception =
1749          CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
1750                               try_info->exception, if_exception);
1751    }
1752
1753    SetEnv("if_success", success_env);
1754    return node;
1755  }
1756
1757  void Goto(SsaEnv* from, SsaEnv* to) {
1758    DCHECK_NOT_NULL(to);
1759    if (!from->go()) return;
1760    switch (to->state) {
1761      case SsaEnv::kUnreachable: {  // Overwrite destination.
1762        to->state = SsaEnv::kReached;
1763        to->locals = from->locals;
1764        to->control = from->control;
1765        to->effect = from->effect;
1766        break;
1767      }
1768      case SsaEnv::kReached: {  // Create a new merge.
1769        to->state = SsaEnv::kMerged;
1770        if (!builder_) break;
1771        // Merge control.
1772        TFNode* controls[] = {to->control, from->control};
1773        TFNode* merge = builder_->Merge(2, controls);
1774        to->control = merge;
1775        // Merge effects.
1776        if (from->effect != to->effect) {
1777          TFNode* effects[] = {to->effect, from->effect, merge};
1778          to->effect = builder_->EffectPhi(2, effects, merge);
1779        }
1780        // Merge SSA values.
1781        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1782          TFNode* a = to->locals[i];
1783          TFNode* b = from->locals[i];
1784          if (a != b) {
1785            TFNode* vals[] = {a, b};
1786            to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
1787          }
1788        }
1789        break;
1790      }
1791      case SsaEnv::kMerged: {
1792        if (!builder_) break;
1793        TFNode* merge = to->control;
1794        // Extend the existing merge.
1795        builder_->AppendToMerge(merge, from->control);
1796        // Merge effects.
1797        if (builder_->IsPhiWithMerge(to->effect, merge)) {
1798          builder_->AppendToPhi(to->effect, from->effect);
1799        } else if (to->effect != from->effect) {
1800          uint32_t count = builder_->InputCount(merge);
1801          TFNode** effects = builder_->Buffer(count);
1802          for (uint32_t j = 0; j < count - 1; j++) {
1803            effects[j] = to->effect;
1804          }
1805          effects[count - 1] = from->effect;
1806          to->effect = builder_->EffectPhi(count, effects, merge);
1807        }
1808        // Merge locals.
1809        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1810          TFNode* tnode = to->locals[i];
1811          TFNode* fnode = from->locals[i];
1812          if (builder_->IsPhiWithMerge(tnode, merge)) {
1813            builder_->AppendToPhi(tnode, fnode);
1814          } else if (tnode != fnode) {
1815            uint32_t count = builder_->InputCount(merge);
1816            TFNode** vals = builder_->Buffer(count);
1817            for (uint32_t j = 0; j < count - 1; j++) {
1818              vals[j] = tnode;
1819            }
1820            vals[count - 1] = fnode;
1821            to->locals[i] =
1822                builder_->Phi(local_type_vec_[i], count, vals, merge);
1823          }
1824        }
1825        break;
1826      }
1827      default:
1828        UNREACHABLE();
1829    }
1830    return from->Kill();
1831  }
1832
1833  TFNode* CreateOrMergeIntoPhi(ValueType type, TFNode* merge, TFNode* tnode,
1834                               TFNode* fnode) {
1835    DCHECK_NOT_NULL(builder_);
1836    if (builder_->IsPhiWithMerge(tnode, merge)) {
1837      builder_->AppendToPhi(tnode, fnode);
1838    } else if (tnode != fnode) {
1839      uint32_t count = builder_->InputCount(merge);
1840      TFNode** vals = builder_->Buffer(count);
1841      for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
1842      vals[count - 1] = fnode;
1843      return builder_->Phi(type, count, vals, merge);
1844    }
1845    return tnode;
1846  }
1847
1848  SsaEnv* PrepareForLoop(const byte* pc, SsaEnv* env) {
1849    if (!builder_) return Split(env);
1850    if (!env->go()) return Split(env);
1851    env->state = SsaEnv::kMerged;
1852
1853    env->control = builder_->Loop(env->control);
1854    env->effect = builder_->EffectPhi(1, &env->effect, env->control);
1855    builder_->Terminate(env->effect, env->control);
1856    if (FLAG_wasm_loop_assignment_analysis) {
1857      BitVector* assigned = AnalyzeLoopAssignment(
1858          this, pc, static_cast<int>(total_locals()), zone_);
1859      if (failed()) return env;
1860      if (assigned != nullptr) {
1861        // Only introduce phis for variables assigned in this loop.
1862        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1863          if (!assigned->Contains(i)) continue;
1864          env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i],
1865                                         env->control);
1866        }
1867        SsaEnv* loop_body_env = Split(env);
1868        builder_->StackCheck(position(), &(loop_body_env->effect),
1869                             &(loop_body_env->control));
1870        return loop_body_env;
1871      }
1872    }
1873
1874    // Conservatively introduce phis for all local variables.
1875    for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1876      env->locals[i] =
1877          builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
1878    }
1879
1880    SsaEnv* loop_body_env = Split(env);
1881    builder_->StackCheck(position(), &(loop_body_env->effect),
1882                         &(loop_body_env->control));
1883    return loop_body_env;
1884  }
1885
1886  // Create a complete copy of the {from}.
1887  SsaEnv* Split(SsaEnv* from) {
1888    DCHECK_NOT_NULL(from);
1889    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1890    size_t size = sizeof(TFNode*) * EnvironmentCount();
1891    result->control = from->control;
1892    result->effect = from->effect;
1893
1894    if (from->go()) {
1895      result->state = SsaEnv::kReached;
1896      result->locals =
1897          size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
1898      memcpy(result->locals, from->locals, size);
1899    } else {
1900      result->state = SsaEnv::kUnreachable;
1901      result->locals = nullptr;
1902    }
1903
1904    return result;
1905  }
1906
1907  // Create a copy of {from} that steals its state and leaves {from}
1908  // unreachable.
1909  SsaEnv* Steal(SsaEnv* from) {
1910    DCHECK_NOT_NULL(from);
1911    if (!from->go()) return UnreachableEnv();
1912    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1913    result->state = SsaEnv::kReached;
1914    result->locals = from->locals;
1915    result->control = from->control;
1916    result->effect = from->effect;
1917    from->Kill(SsaEnv::kUnreachable);
1918    return result;
1919  }
1920
1921  // Create an unreachable environment.
1922  SsaEnv* UnreachableEnv() {
1923    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1924    result->state = SsaEnv::kUnreachable;
1925    result->control = nullptr;
1926    result->effect = nullptr;
1927    result->locals = nullptr;
1928    return result;
1929  }
1930
1931  int EnvironmentCount() {
1932    if (builder_) return static_cast<int>(local_type_vec_.size());
1933    return 0;  // if we aren't building a graph, don't bother with SSA renaming.
1934  }
1935
1936  virtual void onFirstError() {
1937    end_ = start_;       // Terminate decoding loop.
1938    builder_ = nullptr;  // Don't build any more nodes.
1939    TRACE(" !%s\n", error_msg_.get());
1940  }
1941
1942  inline wasm::WasmCodePosition position() {
1943    int offset = static_cast<int>(pc_ - start_);
1944    DCHECK_EQ(pc_ - start_, offset);  // overflows cannot happen
1945    return offset;
1946  }
1947
1948  inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
1949    TFNode* node;
1950    switch (sig->parameter_count()) {
1951      case 1: {
1952        Value val = Pop(0, sig->GetParam(0));
1953        node = BUILD(Unop, opcode, val.node, position());
1954        break;
1955      }
1956      case 2: {
1957        Value rval = Pop(1, sig->GetParam(1));
1958        Value lval = Pop(0, sig->GetParam(0));
1959        node = BUILD(Binop, opcode, lval.node, rval.node, position());
1960        break;
1961      }
1962      default:
1963        UNREACHABLE();
1964        node = nullptr;
1965        break;
1966    }
1967    Push(GetReturnType(sig), node);
1968  }
1969};
1970
1971bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
1972                      const byte* end) {
1973  Decoder decoder(start, end);
1974  if (WasmDecoder::DecodeLocals(&decoder, nullptr, &decls->type_list)) {
1975    DCHECK(decoder.ok());
1976    decls->encoded_size = decoder.pc_offset();
1977    return true;
1978  }
1979  return false;
1980}
1981
1982BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
1983                                   BodyLocalDecls* decls)
1984    : Decoder(start, end) {
1985  if (decls != nullptr) {
1986    if (DecodeLocalDecls(decls, start, end)) {
1987      pc_ += decls->encoded_size;
1988      if (pc_ > end_) pc_ = end_;
1989    }
1990  }
1991}
1992
1993DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
1994                            const wasm::WasmModule* module,
1995                            FunctionBody& body) {
1996  Zone zone(allocator, ZONE_NAME);
1997  WasmFullDecoder decoder(&zone, module, body);
1998  decoder.Decode();
1999  return decoder.toResult<DecodeStruct*>(nullptr);
2000}
2001
2002DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
2003                          FunctionBody& body) {
2004  Zone zone(allocator, ZONE_NAME);
2005  WasmFullDecoder decoder(&zone, builder, body);
2006  decoder.Decode();
2007  return decoder.toResult<DecodeStruct*>(nullptr);
2008}
2009
2010unsigned OpcodeLength(const byte* pc, const byte* end) {
2011  Decoder decoder(pc, end);
2012  return WasmDecoder::OpcodeLength(&decoder, pc);
2013}
2014
2015void PrintRawWasmCode(const byte* start, const byte* end) {
2016  AccountingAllocator allocator;
2017  PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);
2018}
2019
2020namespace {
2021const char* RawOpcodeName(WasmOpcode opcode) {
2022  switch (opcode) {
2023#define DECLARE_NAME_CASE(name, opcode, sig) \
2024  case kExpr##name:                          \
2025    return "kExpr" #name;
2026    FOREACH_OPCODE(DECLARE_NAME_CASE)
2027#undef DECLARE_NAME_CASE
2028    default:
2029      break;
2030  }
2031  return "Unknown";
2032}
2033}  // namespace
2034
2035bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
2036                      const wasm::WasmModule* module) {
2037  OFStream os(stdout);
2038  Zone zone(allocator, ZONE_NAME);
2039  WasmFullDecoder decoder(&zone, module, body);
2040  int line_nr = 0;
2041
2042  // Print the function signature.
2043  if (body.sig) {
2044    os << "// signature: " << *body.sig << std::endl;
2045    ++line_nr;
2046  }
2047
2048  // Print the local declarations.
2049  BodyLocalDecls decls(&zone);
2050  BytecodeIterator i(body.start, body.end, &decls);
2051  if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
2052    os << "// locals: ";
2053    if (!decls.type_list.empty()) {
2054      ValueType type = decls.type_list[0];
2055      uint32_t count = 0;
2056      for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
2057        if (decls.type_list[pos] == type) {
2058          ++count;
2059        } else {
2060          os << " " << count << " " << WasmOpcodes::TypeName(type);
2061          type = decls.type_list[pos];
2062          count = 1;
2063        }
2064      }
2065    }
2066    os << std::endl;
2067    ++line_nr;
2068
2069    for (const byte* locals = body.start; locals < i.pc(); locals++) {
2070      os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
2071    }
2072    os << std::endl;
2073    ++line_nr;
2074  }
2075
2076  os << "// body: " << std::endl;
2077  ++line_nr;
2078  unsigned control_depth = 0;
2079  for (; i.has_next(); i.next()) {
2080    unsigned length = WasmDecoder::OpcodeLength(&decoder, i.pc());
2081
2082    WasmOpcode opcode = i.current();
2083    if (opcode == kExprElse) control_depth--;
2084
2085    int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
2086
2087    // 64 whitespaces
2088    const char* padding =
2089        "                                                                ";
2090    os.write(padding, num_whitespaces);
2091
2092    os << RawOpcodeName(opcode) << ",";
2093
2094    for (size_t j = 1; j < length; ++j) {
2095      os << " 0x" << AsHex(i.pc()[j], 2) << ",";
2096    }
2097
2098    switch (opcode) {
2099      case kExprElse:
2100        os << "   // @" << i.pc_offset();
2101        control_depth++;
2102        break;
2103      case kExprLoop:
2104      case kExprIf:
2105      case kExprBlock:
2106      case kExprTry: {
2107        BlockTypeOperand operand(&i, i.pc());
2108        os << "   // @" << i.pc_offset();
2109        for (unsigned i = 0; i < operand.arity; i++) {
2110          os << " " << WasmOpcodes::TypeName(operand.read_entry(i));
2111        }
2112        control_depth++;
2113        break;
2114      }
2115      case kExprEnd:
2116        os << "   // @" << i.pc_offset();
2117        control_depth--;
2118        break;
2119      case kExprBr: {
2120        BreakDepthOperand operand(&i, i.pc());
2121        os << "   // depth=" << operand.depth;
2122        break;
2123      }
2124      case kExprBrIf: {
2125        BreakDepthOperand operand(&i, i.pc());
2126        os << "   // depth=" << operand.depth;
2127        break;
2128      }
2129      case kExprBrTable: {
2130        BranchTableOperand operand(&i, i.pc());
2131        os << " // entries=" << operand.table_count;
2132        break;
2133      }
2134      case kExprCallIndirect: {
2135        CallIndirectOperand operand(&i, i.pc());
2136        os << "   // sig #" << operand.index;
2137        if (decoder.Complete(i.pc(), operand)) {
2138          os << ": " << *operand.sig;
2139        }
2140        break;
2141      }
2142      case kExprCallFunction: {
2143        CallFunctionOperand operand(&i, i.pc());
2144        os << " // function #" << operand.index;
2145        if (decoder.Complete(i.pc(), operand)) {
2146          os << ": " << *operand.sig;
2147        }
2148        break;
2149      }
2150      default:
2151        break;
2152    }
2153    os << std::endl;
2154    ++line_nr;
2155  }
2156
2157  return decoder.ok();
2158}
2159
2160BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
2161                                           const byte* start, const byte* end) {
2162  Decoder decoder(start, end);
2163  return WasmDecoder::AnalyzeLoopAssignment(&decoder, start,
2164                                            static_cast<int>(num_locals), zone);
2165}
2166
2167}  // namespace wasm
2168}  // namespace internal
2169}  // namespace v8
2170