1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/signature.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/base/platform/elapsed-timer.h"
8109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/bit-vector.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/flags.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles.h"
1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
12f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/zone/zone-containers.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/decoder.h"
1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/wasm/function-body-decoder-impl.h"
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/wasm/function-body-decoder.h"
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/wasm/wasm-limits.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-module.h"
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-opcodes.h"
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/ostreams.h"
223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/wasm-compiler.h"
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace wasm {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...)                                    \
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  do {                                                \
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } while (false)
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...)
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define CHECK_PROTOTYPE_OPCODE(flag)                           \
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (module_ != nullptr && module_->origin == kAsmJsOrigin) { \
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    error("Opcode not supported for asmjs modules");           \
4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }                                                            \
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!FLAG_##flag) {                                          \
4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    error("Invalid opcode (enable with --" #flag ")");         \
4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    break;                                                     \
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// An SsaEnv environment carries the current local variable renaming
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// as well as the current effect and control dependency in the TF graph.
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// It maintains a control state that tracks whether the environment
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// is reachable, has reached a control end, or has been merged.
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct SsaEnv {
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum State { kControlEnd, kUnreachable, kReached, kMerged };
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  State state;
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode* control;
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode* effect;
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode** locals;
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool go() { return state >= kReached; }
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Kill(State new_state = kControlEnd) {
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    state = new_state;
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    locals = nullptr;
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    control = nullptr;
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    effect = nullptr;
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
66bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void SetNotMerged() {
67bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (state == kMerged) state = kReached;
68bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
71bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// An entry on the value stack.
72bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochstruct Value {
73bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  const byte* pc;
74bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  TFNode* node;
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ValueType type;
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstruct TryInfo : public ZoneObject {
79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  SsaEnv* catch_env;
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  TFNode* exception;
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch};
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
85f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstruct MergeValues {
86f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  uint32_t arity;
87f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  union {
88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Value* array;
89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Value first;
90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  } vals;  // Either multiple values or a single value.
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Value& operator[](size_t i) {
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_GT(arity, i);
9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return arity == 1 ? vals.first : vals.array[i];
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
96f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch};
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
98f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic Value* NO_VALUE = nullptr;
99f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochenum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry };
101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// An entry on the control stack (i.e. if, block, loop).
103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstruct Control {
104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const byte* pc;
105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  ControlKind kind;
10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t stack_depth;      // stack height at the beginning of the construct.
10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  SsaEnv* end_env;         // end environment for the construct.
10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  SsaEnv* false_env;       // false environment (only for if).
10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  TryInfo* try_info;       // Information used for compiling try statements.
110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int32_t previous_catch;  // The previous Control (on the stack) with a catch.
11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool unreachable;        // The current block has been ended.
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Values merged into the end of this control construct.
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  MergeValues merge;
115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  inline bool is_if() const { return kind == kControlIf; }
117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  inline bool is_block() const { return kind == kControlBlock; }
118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  inline bool is_loop() const { return kind == kControlLoop; }
119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  inline bool is_try() const { return kind == kControlTry; }
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Named constructors.
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env,
123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       int32_t previous_catch) {
12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {pc,      kControlBlock,  stack_depth, end_env,        nullptr,
12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            nullptr, previous_catch, false,       {0, {NO_VALUE}}};
126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env,
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    SsaEnv* false_env, int32_t previous_catch) {
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {pc,      kControlIf,     stack_depth, end_env,        false_env,
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            nullptr, previous_catch, false,       {0, {NO_VALUE}}};
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env,
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                      int32_t previous_catch) {
13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {pc,      kControlLoop,   stack_depth, end_env,        nullptr,
13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            nullptr, previous_catch, false,       {0, {NO_VALUE}}};
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env,
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                     Zone* zone, SsaEnv* catch_env, int32_t previous_catch) {
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_NOT_NULL(catch_env);
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TryInfo* try_info = new (zone) TryInfo(catch_env);
14462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return {pc,       kControlTry,    stack_depth, end_env,        nullptr,
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            try_info, previous_catch, false,       {0, {NO_VALUE}}};
146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Macros that build nodes only if there is a graph and the current SSA
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// environment is reachable from start. This avoids problems with malformed
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TF graphs when decoding inputs that have unreachable code.
152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#define BUILD(func, ...) \
153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr)
154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr)
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Generic Wasm bytecode decoder with utilities for decoding operands,
157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// lengths, etc.
158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass WasmDecoder : public Decoder {
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch public:
16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
1613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              const byte* end)
1623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      : Decoder(start, end),
1633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        module_(module),
1643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        sig_(sig),
1653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        local_types_(nullptr) {}
16662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const WasmModule* module_;
1673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FunctionSig* sig_;
16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
16962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ZoneVector<ValueType>* local_types_;
17062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
17162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t total_locals() const {
17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return local_types_ == nullptr ? 0 : local_types_->size();
17362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
17462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
17562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
17662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                           ZoneVector<ValueType>* type_list) {
17762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_NOT_NULL(type_list);
17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Initialize from signature.
17962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (sig != nullptr) {
18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      type_list->reserve(sig->parameter_count());
18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      for (size_t i = 0; i < sig->parameter_count(); ++i) {
18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        type_list->push_back(sig->GetParam(i));
18362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Decode local declarations, if any.
18662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    uint32_t entries = decoder->consume_u32v("local decls count");
18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (decoder->failed()) return false;
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    TRACE("local decls count: %u\n", entries);
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    while (entries-- > 0 && decoder->ok() && decoder->more()) {
19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      uint32_t count = decoder->consume_u32v("local count");
19262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (decoder->failed()) return false;
19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        decoder->error(decoder->pc() - 1, "local count too large");
19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return false;
19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      byte code = decoder->consume_u8("local type");
19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (decoder->failed()) return false;
20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ValueType type;
20262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      switch (code) {
20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalI32:
20462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmI32;
20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalI64:
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmI64;
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalF32:
21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmF32;
21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
21262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalF64:
21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmF64;
21462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalS128:
21662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmS128;
21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
21862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalS1x4:
21962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmS1x4;
22062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
22162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalS1x8:
22262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmS1x8;
22362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
22462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kLocalS1x16:
22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = kWasmS1x16;
22662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
22762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        default:
22862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          decoder->error(decoder->pc() - 1, "invalid local type");
22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          return false;
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      type_list->insert(type_list->end(), count, type);
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(decoder->ok());
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return true;
23562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          int locals_count, Zone* zone) {
23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (pc >= decoder->end()) return nullptr;
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (*pc != kExprLoop) return nullptr;
24162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
24262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BitVector* assigned = new (zone) BitVector(locals_count, zone);
24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    int depth = 0;
24462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Iteratively process all AST nodes nested inside the loop.
24562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    while (pc < decoder->end() && decoder->ok()) {
24662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
24762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      unsigned length = 1;
24862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      switch (opcode) {
24962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprLoop:
25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprIf:
25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprBlock:
25262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprTry:
25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          length = OpcodeLength(decoder, pc);
25462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          depth++;
25562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
25662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprSetLocal:  // fallthru
25762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprTeeLocal: {
25862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          LocalIndexOperand operand(decoder, pc);
25962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          if (assigned->length() > 0 &&
26062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              operand.index < static_cast<uint32_t>(assigned->length())) {
26162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            // Unverified code might have an out-of-bounds index.
26262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            assigned->Add(operand.index);
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          }
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          length = 1 + operand.length;
26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        }
26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        case kExprEnd:
26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          depth--;
26962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
27062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        default:
27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          length = OpcodeLength(decoder, pc);
27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          break;
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (depth <= 0) break;
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      pc += length;
27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return decoder->ok() ? assigned : nullptr;
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
28162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (operand.index < total_locals()) {
2823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (local_types_) {
2833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        operand.type = local_types_->at(operand.index);
2843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        operand.type = kWasmStmt;
2863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return true;
288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    error(pc, pc + 1, "invalid local index: %u", operand.index);
290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return false;
291109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
292109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Validate(const byte* pc, GlobalIndexOperand& operand) {
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (module_ != nullptr && operand.index < module_->globals.size()) {
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      operand.global = &module_->globals[operand.index];
296f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      operand.type = operand.global->type;
297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return true;
298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
299f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    error(pc, pc + 1, "invalid global index: %u", operand.index);
300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return false;
301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
30313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline bool Complete(const byte* pc, CallFunctionOperand& operand) {
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (module_ != nullptr && operand.index < module_->functions.size()) {
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      operand.sig = module_->functions[operand.index].sig;
30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return true;
30713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return false;
30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline bool Validate(const byte* pc, CallFunctionOperand& operand) {
31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (Complete(pc, operand)) {
313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return true;
314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
315f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    error(pc, pc + 1, "invalid function index: %u", operand.index);
316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return false;
317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
31913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline bool Complete(const byte* pc, CallIndirectOperand& operand) {
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (module_ != nullptr && operand.index < module_->signatures.size()) {
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      operand.sig = module_->signatures[operand.index];
32213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return true;
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
32413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return false;
32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline bool Validate(const byte* pc, CallIndirectOperand& operand) {
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (module_ == nullptr || module_->function_tables.empty()) {
329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      error("function table has to exist to execute call_indirect");
330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return false;
331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
33213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (Complete(pc, operand)) {
333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return true;
334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
335f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    error(pc, pc + 1, "invalid signature index: #%u", operand.index);
336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return false;
337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Validate(const byte* pc, BreakDepthOperand& operand,
340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                       ZoneVector<Control>& control) {
341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (operand.depth < control.size()) {
342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      operand.target = &control[control.size() - operand.depth - 1];
343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return true;
344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
345f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    error(pc, pc + 1, "invalid break depth: %u", operand.depth);
346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return false;
347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool Validate(const byte* pc, BranchTableOperand& operand,
350109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                size_t block_depth) {
351f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // TODO(titzer): add extra redundant validation for br_table here?
352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return true;
353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  inline bool Validate(const byte* pc, WasmOpcode opcode,
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       SimdLaneOperand& operand) {
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    uint8_t num_lanes = 0;
35862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    switch (opcode) {
35962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprF32x4ExtractLane:
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprF32x4ReplaceLane:
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ExtractLane:
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ReplaceLane:
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        num_lanes = 4;
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ExtractLane:
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ReplaceLane:
36762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        num_lanes = 8;
36862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ExtractLane:
37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ReplaceLane:
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        num_lanes = 16;
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      default:
37462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        UNREACHABLE();
37562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
37662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
37762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (operand.lane < 0 || operand.lane >= num_lanes) {
37862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      error(pc_, pc_ + 2, "invalid lane index");
37962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return false;
38062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } else {
38162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return true;
38262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
38362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
38462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  inline bool Validate(const byte* pc, WasmOpcode opcode,
38662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       SimdShiftOperand& operand) {
38762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    uint8_t max_shift = 0;
38862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    switch (opcode) {
38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4Shl:
39062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ShrS:
39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ShrU:
39262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        max_shift = 32;
39362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
39462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8Shl:
39562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ShrS:
39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ShrU:
39762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        max_shift = 16;
39862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
39962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16Shl:
40062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ShrS:
40162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ShrU:
40262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        max_shift = 8;
40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
40462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      default:
40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        UNREACHABLE();
40662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
40762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (operand.shift < 0 || operand.shift >= max_shift) {
40962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      error(pc_, pc_ + 2, "invalid shift amount");
410c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return false;
411c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    } else {
412c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return true;
413c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
414c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
415c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
41662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    switch (static_cast<byte>(*pc)) {
418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef DECLARE_OPCODE_CASE
422109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      {
42362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        MemoryAccessOperand operand(decoder, pc, UINT32_MAX);
424109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprBr:
427109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprBrIf: {
42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        BreakDepthOperand operand(decoder, pc);
429109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
430109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
431f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case kExprSetGlobal:
432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case kExprGetGlobal: {
43362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        GlobalIndexOperand operand(decoder, pc);
434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprCallFunction: {
43862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CallFunctionOperand operand(decoder, pc);
439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprCallIndirect: {
44262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CallIndirectOperand operand(decoder, pc);
443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
444109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
445f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
446f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprTry:
447f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprIf:  // fall thru
448f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprLoop:
449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprBlock: {
45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        BlockTypeOperand operand(decoder, pc);
451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
452109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprSetLocal:
455f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprTeeLocal:
456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case kExprGetLocal:
457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case kExprCatch: {
45862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        LocalIndexOperand operand(decoder, pc);
459109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
460109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
4613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      case kExprBrTable: {
46262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        BranchTableOperand operand(decoder, pc);
46362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        BranchTableIterator iterator(decoder, operand);
464f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        return 1 + iterator.length();
4653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
4663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      case kExprI32Const: {
46762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        ImmI32Operand operand(decoder, pc);
4683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        return 1 + operand.length;
4693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
4703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      case kExprI64Const: {
47162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        ImmI64Operand operand(decoder, pc);
472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1 + operand.length;
473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      }
474c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      case kExprGrowMemory:
475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      case kExprMemorySize: {
47662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        MemoryIndexOperand operand(decoder, pc);
477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        return 1 + operand.length;
478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
479109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprF32Const:
480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 5;
481109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case kExprF64Const:
482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 9;
483c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      case kSimdPrefix: {
48462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        byte simd_index = decoder->checked_read_u8(pc, 1, "simd_index");
485c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        WasmOpcode opcode =
486c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
487c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        switch (opcode) {
488c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
489c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
490c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#undef DECLARE_OPCODE_CASE
491c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
492c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            return 2;
493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
494c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
495c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
496c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#undef DECLARE_OPCODE_CASE
497c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
498c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            return 3;
499c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
500c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          default:
50162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            decoder->error(pc, "invalid SIMD opcode");
502c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            return 2;
503c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
504c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
505109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      default:
506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        return 1;
507109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch};
510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
511f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const int32_t kNullCatch = -1;
512f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
51362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// The full WASM decoder for bytecode. Verifies bytecode and, optionally,
51462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// generates a TurboFan IR graph.
515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass WasmFullDecoder : public WasmDecoder {
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
51762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
51862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  const FunctionBody& body)
51962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      : WasmFullDecoder(zone, module, nullptr, body) {}
52062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
52262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      : WasmFullDecoder(zone, builder->module_env() == nullptr
52362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  ? nullptr
52462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  : builder->module_env()->module,
52562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        builder, body) {}
526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
527bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool Decode() {
52862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (FLAG_wasm_code_fuzzer_gen_test) {
52962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      PrintRawWasmCode(start_, end_);
53062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
531bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    base::ElapsedTimer decode_timer;
532bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (FLAG_trace_wasm_decode_time) {
533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      decode_timer.Start();
534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
535bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    stack_.clear();
536bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    control_.clear();
537bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (end_ < pc_) {
539f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      error("function body end < start");
540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return false;
541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
54362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(0, local_types_->size());
54462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    WasmDecoder::DecodeLocals(this, sig_, local_types_);
545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InitSsaEnv();
546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DecodeFunctionBody();
547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
548bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (failed()) return TraceFailed();
549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (!control_.empty()) {
55162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Generate a better error message whether the unterminated control
55262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // structure is the function body block or an innner structure.
55362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (control_.size() > 1) {
55462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        error(pc_, control_.back().pc, "unterminated control structure");
55562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      } else {
55662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        error("function body must end with \"end\" opcode.");
55762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
558bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return TraceFailed();
559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
561f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!last_end_found_) {
562f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      error("function body must end with \"end\" opcode.");
563f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return false;
564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
566bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (FLAG_trace_wasm_decode_time) {
567bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      double ms = decode_timer.Elapsed().InMillisecondsF();
568f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      PrintF("wasm-decode %s (%0.3f ms)\n\n", ok() ? "ok" : "failed", ms);
569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
570f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      TRACE("wasm-decode %s\n\n", ok() ? "ok" : "failed");
571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
572109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return true;
574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool TraceFailed() {
577bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
578bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          startrel(error_pc_), error_msg_.get());
579bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return false;
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
58262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private:
58362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
58462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  TFBuilder* builder, const FunctionBody& body)
58562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      : WasmDecoder(module, body.sig, body.start, body.end),
58662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        zone_(zone),
58762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        builder_(builder),
58862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        base_(body.base),
58962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        local_type_vec_(zone),
59062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        stack_(zone),
59162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        control_(zone),
59262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        last_end_found_(false),
59362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        current_catch_(kNullCatch) {
59462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    local_types_ = &local_type_vec_;
5953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
5963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const size_t kErrorMsgSize = 128;
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Zone* zone_;
600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFBuilder* builder_;
601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* base_;
602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* ssa_env_;
604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
60562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ZoneVector<ValueType> local_type_vec_;  // types of local variables.
606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ZoneVector<Value> stack_;               // stack of values.
607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
608f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bool last_end_found_;
609f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
610f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int32_t current_catch_;
611f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
612f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  TryInfo* current_try_info() { return control_[current_catch_].try_info; }
613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline bool build() { return builder_ && ssa_env_->go(); }
615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InitSsaEnv() {
617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TFNode* start = nullptr;
618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t size = sizeof(TFNode*) * EnvironmentCount();
620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->state = SsaEnv::kReached;
621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->locals =
622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_) {
6253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
6263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Initialize local variables.
6273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      uint32_t index = 0;
6283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      while (index < sig_->parameter_count()) {
62962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        ssa_env->locals[index] = builder_->Param(index);
6303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        index++;
631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
6323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      while (index < local_type_vec_.size()) {
63362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        ValueType type = local_type_vec_[index];
6343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        TFNode* node = DefaultValue(type);
6353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        while (index < local_type_vec_.size() &&
6363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch               local_type_vec_[index] == type) {
6373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          // Do a whole run of like-typed locals at a time.
6383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          ssa_env->locals[index++] = node;
639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->control = start;
643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->effect = start;
644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetEnv("initial", ssa_env);
645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (builder_) {
64662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // The function-prologue stack check is associated with position 0, which
64762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // is never a position of any instruction in the function.
64862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      builder_->StackCheck(0);
649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
65262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  TFNode* DefaultValue(ValueType type) {
6533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    switch (type) {
65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kWasmI32:
6553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        return builder_->Int32Constant(0);
65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kWasmI64:
6573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        return builder_->Int64Constant(0);
65862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kWasmF32:
6593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        return builder_->Float32Constant(0);
66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kWasmF64:
6613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        return builder_->Float64Constant(0);
66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kWasmS128:
663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        return builder_->CreateS128Value(0);
6643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      default:
6653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        UNREACHABLE();
6663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        return nullptr;
6673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
6683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* indentation() {
671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static const int kMaxIndent = 64;
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static char bytes[kMaxIndent + 1];
67313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' ';
674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bytes[kMaxIndent] = 0;
675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (stack_.size() < kMaxIndent / 2) {
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bytes[stack_.size() * 2] = 0;
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return bytes;
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
68162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool CheckHasMemory() {
68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!module_->has_memory) {
68362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      error(pc_ - 1, "memory instruction with no memory");
6843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
68562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return module_->has_memory;
6863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
6873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
688bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Decodes the body of a function.
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DecodeFunctionBody() {
690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          reinterpret_cast<const void*>(start_),
69262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          reinterpret_cast<const void*>(end_), baserel(pc_),
69362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          static_cast<int>(end_ - start_), builder_ ? "graph building" : "");
694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    {
696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Set up initial function block.
697f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      SsaEnv* break_env = ssa_env_;
698f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      SetEnv("initial env", Steal(break_env));
699f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      PushBlock(break_env);
700f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Control* c = &control_.back();
701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      c->merge.arity = static_cast<uint32_t>(sig_->return_count());
702f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
703f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (c->merge.arity == 1) {
704f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)};
705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      } else if (c->merge.arity > 1) {
706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
707f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        for (unsigned i = 0; i < c->merge.arity; i++) {
708f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)};
709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
712f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
71362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    while (pc_ < end_) {  // decoding loop.
71413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      unsigned len = 1;
715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
71662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#if DEBUG
71762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (FLAG_trace_wasm_decoder && !WasmOpcodes::IsPrefixOpcode(opcode)) {
71862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        TRACE("  @%-8d #%-20s|", startrel(pc_),
71962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              WasmOpcodes::OpcodeName(opcode));
720f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
72162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FunctionSig* sig = WasmOpcodes::Signature(opcode);
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (sig) {
725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        BuildSimpleOperator(opcode, sig);
726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // Complex bytecode.
728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        switch (opcode) {
729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprNop:
730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
731bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprBlock: {
732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // The break environment is the outer environment.
733f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BlockTypeOperand operand(this, pc_);
734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* break_env = ssa_env_;
735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            PushBlock(break_env);
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("block:start", Steal(break_env));
737f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SetBlockType(&control_.back(), operand);
738f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len = 1 + operand.length;
739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          case kExprThrow: {
742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
74362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Value value = Pop(0, kWasmI32);
744f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BUILD(Throw, value.node);
74562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            // TODO(titzer): Throw should end control, but currently we build a
74662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            // (reachable) runtime call instead of connecting it directly to
74762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            // end.
74862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            //            EndControl();
749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            break;
750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          case kExprTry: {
752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
753f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BlockTypeOperand operand(this, pc_);
754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            SsaEnv* outer_env = ssa_env_;
755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            SsaEnv* try_env = Steal(outer_env);
756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SsaEnv* catch_env = UnreachableEnv();
757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            PushTry(outer_env, catch_env);
758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            SetEnv("try_catch:start", try_env);
759f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SetBlockType(&control_.back(), operand);
760f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len = 1 + operand.length;
761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            break;
762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          case kExprCatch: {
764f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            LocalIndexOperand operand(this, pc_);
766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            len = 1 + operand.length;
767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            if (control_.empty()) {
769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              error("catch does not match any try");
770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              break;
771f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            }
772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            Control* c = &control_.back();
774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (!c->is_try()) {
775f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              error("catch does not match any try");
776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              break;
777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            }
778f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
779f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (c->try_info->catch_env == nullptr) {
780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              error(pc_, "catch already present for try with catch");
781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              break;
782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            }
783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
78462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            FallThruTo(c);
785f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            stack_.resize(c->stack_depth);
786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
787f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            DCHECK_NOT_NULL(c->try_info);
788f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SsaEnv* catch_env = c->try_info->catch_env;
789f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            c->try_info->catch_env = nullptr;
790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            SetEnv("catch:begin", catch_env);
791f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            current_catch_ = c->previous_catch;
792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            if (Validate(pc_, operand)) {
794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              if (ssa_env_->locals) {
795f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                TFNode* exception_as_i32 =
796f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    BUILD(Catch, c->try_info->exception, position());
797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                ssa_env_->locals[operand.index] = exception_as_i32;
798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              }
799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            }
800f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            break;
802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
803bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprLoop: {
804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BlockTypeOperand operand(this, pc_);
805f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SsaEnv* finish_try_env = Steal(ssa_env_);
806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // The continue environment is the inner environment.
807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            SsaEnv* loop_body_env = PrepareForLoop(pc_, finish_try_env);
808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            SetEnv("loop:start", loop_body_env);
809bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            ssa_env_->SetNotMerged();
810f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            PushLoop(finish_try_env);
811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SetBlockType(&control_.back(), operand);
812f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len = 1 + operand.length;
813bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
815bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprIf: {
816bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            // Condition on top of stack. Split environments for branches.
817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BlockTypeOperand operand(this, pc_);
81862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Value cond = Pop(0, kWasmI32);
819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            TFNode* if_true = nullptr;
820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            TFNode* if_false = nullptr;
821c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            BUILD(BranchNoHint, cond.node, &if_true, &if_false);
822bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            SsaEnv* end_env = ssa_env_;
823bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            SsaEnv* false_env = Split(ssa_env_);
824bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            false_env->control = if_false;
825bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            SsaEnv* true_env = Steal(ssa_env_);
826bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            true_env->control = if_true;
827bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            PushIf(end_env, false_env);
828bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            SetEnv("if:true", true_env);
829f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SetBlockType(&control_.back(), operand);
830f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len = 1 + operand.length;
831bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
833bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprElse: {
834bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (control_.empty()) {
835f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              error("else does not match any if");
836bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
837bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
838bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            Control* c = &control_.back();
839bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (!c->is_if()) {
840bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              error(pc_, c->pc, "else does not match an if");
841bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
842bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
843bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (c->false_env == nullptr) {
844bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              error(pc_, c->pc, "else already present for if");
845bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
846bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
847f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            FallThruTo(c);
848f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            stack_.resize(c->stack_depth);
84962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            // Switch to environment for false branch.
850bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            SetEnv("if_else:false", c->false_env);
851bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            c->false_env = nullptr;  // record that an else is already seen
852bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
854bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprEnd: {
855bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (control_.empty()) {
856f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              error("end does not match any if, try, or block");
857f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              return;
858bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
859bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            const char* name = "block:end";
860bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            Control* c = &control_.back();
861f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (c->is_loop()) {
862f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              // A loop just leaves the values on the stack.
86362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              TypeCheckFallThru(c);
86462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              if (c->unreachable) PushEndValues(c);
865f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              PopControl();
866f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              SetEnv("loop:end", ssa_env_);
867f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              break;
868f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            }
869f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (c->is_if()) {
870bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              if (c->false_env != nullptr) {
871bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                // End the true branch of a one-armed if.
872bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                Goto(c->false_env, c->end_env);
87362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                if (!c->unreachable && stack_.size() != c->stack_depth) {
874f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  error("end of if expected empty stack");
875f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  stack_.resize(c->stack_depth);
876f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                }
877f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                if (c->merge.arity > 0) {
878f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  error("non-void one-armed if");
879f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                }
880bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                name = "if:merge";
881bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              } else {
882bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                // End the false branch of a two-armed if.
883bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                name = "if_else:merge";
884bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              }
885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            } else if (c->is_try()) {
886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              name = "try:end";
887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
888f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              // validate that catch was seen.
889f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (c->try_info->catch_env != nullptr) {
890f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                error(pc_, "missing catch in try");
891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                break;
892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              }
893f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            }
894f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            FallThruTo(c);
895f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            SetEnv(name, c->end_env);
89662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            PushEndValues(c);
897f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
89862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (control_.size() == 1) {
89962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              // If at the last (implicit) control, check we are at end.
900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (pc_ + 1 != end_) {
901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                error(pc_, pc_ + 1, "trailing code after function end");
90262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                break;
903f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              }
904f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              last_end_found_ = true;
905f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (ssa_env_->go()) {
906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                // The result of the block is the return value.
90762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                TRACE("  @%-8d #xx:%-20s|", startrel(pc_), "(implicit) return");
908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                DoReturn();
909f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                TRACE("\n");
91062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              } else {
91162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                TypeCheckFallThru(c);
912f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              }
913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
91462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            PopControl();
915bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
917bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprSelect: {
91862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Value cond = Pop(2, kWasmI32);
919bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            Value fval = Pop();
92062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Value tval = Pop(0, fval.type);
921bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (build()) {
922bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              TFNode* controls[2];
923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              builder_->BranchNoHint(cond.node, &controls[0], &controls[1]);
924bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              TFNode* merge = builder_->Merge(2, controls);
925bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              TFNode* vals[2] = {tval.node, fval.node};
926bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
927bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              Push(tval.type, phi);
928bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              ssa_env_->control = merge;
929bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            } else {
93062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Push(tval.type == kWasmVar ? fval.type : tval.type, nullptr);
931bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
932bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
934bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprBr: {
935bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            BreakDepthOperand operand(this, pc_);
936bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand, control_)) {
937f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              BreakTo(operand.depth);
938bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
939bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
940f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            EndControl();
941bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
942109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          }
943bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprBrIf: {
944bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            BreakDepthOperand operand(this, pc_);
94562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Value cond = Pop(0, kWasmI32);
946f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (ok() && Validate(pc_, operand, control_)) {
947bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              SsaEnv* fenv = ssa_env_;
948bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              SsaEnv* tenv = Split(fenv);
949bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              fenv->SetNotMerged();
950c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
951bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              ssa_env_ = tenv;
952f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              BreakTo(operand.depth);
953bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              ssa_env_ = fenv;
954bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
955bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
956bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
957109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          }
958bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprBrTable: {
959bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            BranchTableOperand operand(this, pc_);
960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BranchTableIterator iterator(this, operand);
961bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand, control_.size())) {
96262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Value key = Pop(0, kWasmI32);
963bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              if (failed()) break;
964bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
965bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              SsaEnv* break_env = ssa_env_;
966bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              if (operand.table_count > 0) {
967bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                // Build branches to the various blocks based on the table.
968bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
969bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
970bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                SsaEnv* copy = Steal(break_env);
971bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                ssa_env_ = copy;
97262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                MergeValues* merge = nullptr;
973c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                while (ok() && iterator.has_next()) {
974f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  uint32_t i = iterator.cur_index();
975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  const byte* pos = iterator.pc();
976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  uint32_t target = iterator.next();
977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  if (target >= control_.size()) {
978f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    error(pos, "improper branch in br_table");
979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    break;
980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  }
981bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                  ssa_env_ = Split(copy);
982bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                  ssa_env_->control = (i == operand.table_count)
983bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                          ? BUILD(IfDefault, sw)
984bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                          : BUILD(IfValue, i, sw);
985f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  BreakTo(target);
98662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
98762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  // Check that label types match up.
98862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Control* c = &control_[control_.size() - target - 1];
98962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  if (i == 0) {
99062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    merge = &c->merge;
99162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  } else if (merge->arity != c->merge.arity) {
99262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    error(pos, pos, "inconsistent arity in br_table target %d"
99362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          " (previous was %u, this one %u)",
99462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          i, merge->arity, c->merge.arity);
99562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  } else if (control_.back().unreachable) {
99662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    for (uint32_t j = 0; ok() && j < merge->arity; ++j) {
99762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      if ((*merge)[j].type != c->merge[j].type) {
99862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        error(pos, pos,
99962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              "type error in br_table target %d operand %d"
100062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              " (previous expected %s, this one %s)", i, j,
100162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              WasmOpcodes::TypeName((*merge)[j].type),
100262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              WasmOpcodes::TypeName(c->merge[j].type));
100362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      }
100462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    }
100562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  }
1006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                }
1007c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                if (failed()) break;
1008bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              } else {
1009bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                // Only a default target. Do the equivalent of br.
1010f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                const byte* pos = iterator.pc();
1011f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                uint32_t target = iterator.next();
1012f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                if (target >= control_.size()) {
1013f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  error(pos, "improper branch in br_table");
1014f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                  break;
1015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                }
1016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                BreakTo(target);
1017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              }
1018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              // br_table ends the control flow like br.
1019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              ssa_env_ = break_env;
1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1021f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len = 1 + iterator.length();
102262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            EndControl();
1023bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          }
1025bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprReturn: {
1026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            DoReturn();
1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1028109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          }
1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprUnreachable: {
1030f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            BUILD(Unreachable, position());
1031f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            EndControl();
1032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32Const: {
1035bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            ImmI32Operand operand(this, pc_);
103662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Push(kWasmI32, BUILD(Int32Constant, operand.value));
1037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1040bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64Const: {
1041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            ImmI64Operand operand(this, pc_);
104262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Push(kWasmI64, BUILD(Int64Constant, operand.value));
1043bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1045bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1046bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprF32Const: {
1047bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            ImmF32Operand operand(this, pc_);
104862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Push(kWasmF32, BUILD(Float32Constant, operand.value));
1049bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1050bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprF64Const: {
1053bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            ImmF64Operand operand(this, pc_);
105462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Push(kWasmF64, BUILD(Float64Constant, operand.value));
1055bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1056bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1057bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1058bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprGetLocal: {
1059bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            LocalIndexOperand operand(this, pc_);
1060bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand)) {
1061bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              if (build()) {
1062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                Push(operand.type, ssa_env_->locals[operand.index]);
1063bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              } else {
1064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                Push(operand.type, nullptr);
1065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              }
1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1067bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1068bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1069bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1070bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprSetLocal: {
1071bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            LocalIndexOperand operand(this, pc_);
1072bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand)) {
1073bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              Value val = Pop(0, local_type_vec_[operand.index]);
1074bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
1075f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            }
1076f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len = 1 + operand.length;
1077f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            break;
1078f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          }
1079f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          case kExprTeeLocal: {
1080f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            LocalIndexOperand operand(this, pc_);
1081f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (Validate(pc_, operand)) {
1082f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              Value val = Pop(0, local_type_vec_[operand.index]);
1083f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
1084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              Push(val.type, val.node);
1085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1089f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          case kExprDrop: {
1090f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            Pop();
1091f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            break;
1092f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          }
1093f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          case kExprGetGlobal: {
1094bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            GlobalIndexOperand operand(this, pc_);
1095bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand)) {
1096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              Push(operand.type, BUILD(GetGlobal, operand.index));
1097bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          case kExprSetGlobal: {
1102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            GlobalIndexOperand operand(this, pc_);
1103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand)) {
1104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (operand.global->mutability) {
1105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                Value val = Pop(0, operand.type);
1106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                BUILD(SetGlobal, operand.index, val.node);
1107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              } else {
1108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                error(pc_, pc_ + 1, "immutable global #%u cannot be assigned",
1109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                      operand.index);
1110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              }
1111bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32LoadMem8S:
111662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI32, MachineType::Int8());
1117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32LoadMem8U:
111962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI32, MachineType::Uint8());
1120bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32LoadMem16S:
112262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI32, MachineType::Int16());
1123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32LoadMem16U:
112562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI32, MachineType::Uint16());
1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32LoadMem:
112862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI32, MachineType::Int32());
1129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem8S:
113162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Int8());
1132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem8U:
113462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Uint8());
1135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem16S:
113762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Int16());
1138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem16U:
114062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Uint16());
1141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem32S:
114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Int32());
1144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem32U:
114662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Uint32());
1147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64LoadMem:
114962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmI64, MachineType::Int64());
1150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1151bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprF32LoadMem:
115262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmF32, MachineType::Float32());
1153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1154bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprF64LoadMem:
115562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeLoadMem(kWasmF64, MachineType::Float64());
1156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1157bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32StoreMem8:
115862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI32, MachineType::Int8());
1159bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1160bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32StoreMem16:
116162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI32, MachineType::Int16());
1162bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI32StoreMem:
116462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI32, MachineType::Int32());
1165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64StoreMem8:
116762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI64, MachineType::Int8());
1168bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1169bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64StoreMem16:
117062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI64, MachineType::Int16());
1171bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64StoreMem32:
117362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI64, MachineType::Int32());
1174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprI64StoreMem:
117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmI64, MachineType::Int64());
1177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1178bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprF32StoreMem:
117962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmF32, MachineType::Float32());
1180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprF64StoreMem:
118262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            len = DecodeStoreMem(kWasmF64, MachineType::Float64());
1183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          case kExprGrowMemory: {
118562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (!CheckHasMemory()) break;
1186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            MemoryIndexOperand operand(this, pc_);
118762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            DCHECK_NOT_NULL(module_);
1188f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            if (module_->origin != kAsmJsOrigin) {
118962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Value val = Pop(0, kWasmI32);
119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Push(kWasmI32, BUILD(GrowMemory, val.node));
1191f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            } else {
1192f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              error("grow_memory is not supported for asmjs modules");
1193f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            }
1194c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            len = 1 + operand.length;
1195f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            break;
1196c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1197c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          case kExprMemorySize: {
119862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (!CheckHasMemory()) break;
1199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            MemoryIndexOperand operand(this, pc_);
120062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Push(kWasmI32, BUILD(CurrentMemoryPages));
1201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            len = 1 + operand.length;
1202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprCallFunction: {
1205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            CallFunctionOperand operand(this, pc_);
1206bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand)) {
1207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              TFNode** buffer = PopArgs(operand.sig);
1208f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              TFNode** rets = nullptr;
1209f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              BUILD(CallDirect, operand.index, buffer, &rets, position());
1210f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              PushReturns(operand.sig, rets);
1211bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1215bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case kExprCallIndirect: {
1216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            CallIndirectOperand operand(this, pc_);
1217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            if (Validate(pc_, operand)) {
121862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Value index = Pop(0, kWasmI32);
1219bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              TFNode** buffer = PopArgs(operand.sig);
1220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (buffer) buffer[0] = index.node;
1221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              TFNode** rets = nullptr;
1222f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              BUILD(CallIndirect, operand.index, buffer, &rets, position());
1223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              PushReturns(operand.sig, rets);
1224bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1225bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            len = 1 + operand.length;
1226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
1228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          case kSimdPrefix: {
1229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
1230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            len++;
1231c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            byte simd_index = checked_read_u8(pc_, 1, "simd index");
1232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
123362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            TRACE("  @%-4d #%-20s|", startrel(pc_),
123462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  WasmOpcodes::OpcodeName(opcode));
1235f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            len += DecodeSimdOpcode(opcode);
1236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            break;
1237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
1238c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          case kAtomicPrefix: {
123962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (module_ == nullptr || module_->origin != kAsmJsOrigin) {
1240c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              error("Atomics are allowed only in AsmJs modules");
1241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              break;
1242c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
1243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            if (!FLAG_wasm_atomics_prototype) {
1244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              error("Invalid opcode (enable with --wasm_atomics_prototype)");
1245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              break;
1246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
1247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            len = 2;
1248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            byte atomic_opcode = checked_read_u8(pc_, 1, "atomic index");
1249c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_opcode);
1250c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            sig = WasmOpcodes::AtomicSignature(opcode);
1251c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            if (sig) {
1252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              BuildAtomicOperator(opcode);
1253c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
1254c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            break;
1255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          default: {
1257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            // Deal with special asmjs opcodes.
125862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (module_ != nullptr && module_->origin == kAsmJsOrigin) {
1259f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              sig = WasmOpcodes::AsmjsSignature(opcode);
1260f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              if (sig) {
1261f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                BuildSimpleOperator(opcode, sig);
1262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              }
1263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            } else {
1264f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              error("Invalid opcode");
1265f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              return;
1266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            }
1267f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          }
1268109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        }
1269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1271bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#if DEBUG
1272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (FLAG_trace_wasm_decoder) {
127362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        PrintF(" ");
127462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        for (size_t i = 0; i < control_.size(); ++i) {
127562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Control* c = &control_[i];
127662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          enum ControlKind {
127762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            kControlIf,
127862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            kControlBlock,
127962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            kControlLoop,
128062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            kControlTry
128162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          };
128262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          switch (c->kind) {
128362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            case kControlIf:
128462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              PrintF("I");
128562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              break;
128662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            case kControlBlock:
128762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              PrintF("B");
128862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              break;
128962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            case kControlLoop:
129062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              PrintF("L");
129162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              break;
129262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            case kControlTry:
129362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              PrintF("T");
129462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              break;
129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            default:
129662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              break;
129762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          }
129862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          PrintF("%u", c->merge.arity);
129962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          if (c->unreachable) PrintF("*");
130062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        }
130162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        PrintF(" | ");
130213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        for (size_t i = 0; i < stack_.size(); ++i) {
1303bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          Value& val = stack_[i];
1304bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1305f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1306f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
1307f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          }
1308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
1309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                 static_cast<int>(val.pc - start_),
131062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 WasmOpcodes::OpcodeName(opcode));
1311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          switch (opcode) {
1312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            case kExprI32Const: {
1313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              ImmI32Operand operand(this, val.pc);
1314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              PrintF("[%d]", operand.value);
1315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
1316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            case kExprGetLocal: {
1318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              LocalIndexOperand operand(this, val.pc);
1319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              PrintF("[%u]", operand.index);
1320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
1321bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1322f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            case kExprSetLocal:  // fallthru
1323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            case kExprTeeLocal: {
1324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              LocalIndexOperand operand(this, val.pc);
1325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              PrintF("[%u]", operand.index);
1326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
1327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            }
1328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            default:
1329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              break;
1330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          }
133162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          if (val.node == nullptr) PrintF("?");
1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1333bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrintF("\n");
1334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
1336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      pc_ += len;
1337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }  // end decode loop
133862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (pc_ > end_ && ok()) error("Beyond end of code");
1339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1340f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
134162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void EndControl() {
134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ssa_env_->Kill(SsaEnv::kControlEnd);
134362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!control_.empty()) {
134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      stack_.resize(control_.back().stack_depth);
134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      control_.back().unreachable = true;
134662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
134762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
1348f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1349f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void SetBlockType(Control* c, BlockTypeOperand& operand) {
1350f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    c->merge.arity = operand.arity;
1351f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (c->merge.arity == 1) {
1352f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)};
1353f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else if (c->merge.arity > 1) {
1354f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
1355f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      for (unsigned i = 0; i < c->merge.arity; i++) {
1356f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        c->merge.vals.array[i] = {pc_, nullptr, operand.read_entry(i)};
1357f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1358f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1360bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1361bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  TFNode** PopArgs(FunctionSig* sig) {
1362bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (build()) {
1363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      int count = static_cast<int>(sig->parameter_count());
1364bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      TFNode** buffer = builder_->Buffer(count + 1);
1365bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      buffer[0] = nullptr;  // reserved for code object or function index.
1366bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      for (int i = count - 1; i >= 0; i--) {
1367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
1368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
1369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return buffer;
1370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
1371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      int count = static_cast<int>(sig->parameter_count());
1372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      for (int i = count - 1; i >= 0; i--) {
1373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        Pop(i, sig->GetParam(i));
1374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
1375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return nullptr;
1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
137962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ValueType GetReturnType(FunctionSig* sig) {
138062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void PushBlock(SsaEnv* end_env) {
1384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    control_.emplace_back(
138562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Control::Block(pc_, stack_.size(), end_env, current_catch_));
1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void PushLoop(SsaEnv* end_env) {
1389f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    control_.emplace_back(
139062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Control::Loop(pc_, stack_.size(), end_env, current_catch_));
1391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1394f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    control_.emplace_back(
139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Control::If(pc_, stack_.size(), end_env, false_env, current_catch_));
1396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1398f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void PushTry(SsaEnv* end_env, SsaEnv* catch_env) {
139962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_,
1400f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                       catch_env, current_catch_));
1401f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    current_catch_ = static_cast<int32_t>(control_.size() - 1);
1402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1404f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void PopControl() { control_.pop_back(); }
1405f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
140662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int DecodeLoadMem(ValueType type, MachineType mem_type) {
140762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!CheckHasMemory()) return 0;
1408f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    MemoryAccessOperand operand(this, pc_,
1409f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                ElementSizeLog2Of(mem_type.representation()));
1410f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
141162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Value index = Pop(0, kWasmI32);
141213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
141313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                         operand.alignment, position());
1414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Push(type, node);
1415109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return 1 + operand.length;
1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int DecodeStoreMem(ValueType type, MachineType mem_type) {
141962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!CheckHasMemory()) return 0;
1420f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    MemoryAccessOperand operand(this, pc_,
1421f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                ElementSizeLog2Of(mem_type.representation()));
1422bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Value val = Pop(1, type);
142362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Value index = Pop(0, kWasmI32);
142413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
142513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          val.node, position());
1426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return 1 + operand.length;
1427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
142962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
143062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    SimdLaneOperand operand(this, pc_);
143162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (Validate(pc_, opcode, operand)) {
143262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      compiler::NodeVector inputs(1, zone_);
143362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      inputs[0] = Pop(0, ValueType::kSimd128).node;
143462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
1435c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Push(type, node);
1436c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1437c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return operand.length;
1438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1439c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
144062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
144162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    SimdLaneOperand operand(this, pc_);
144262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (Validate(pc_, opcode, operand)) {
144362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      compiler::NodeVector inputs(2, zone_);
144462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      inputs[1] = Pop(1, type).node;
144562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      inputs[0] = Pop(0, ValueType::kSimd128).node;
144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Push(ValueType::kSimd128, node);
144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
144962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return operand.length;
145062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
145162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
145262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  unsigned SimdShiftOp(WasmOpcode opcode) {
145362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    SimdShiftOperand operand(this, pc_);
145462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (Validate(pc_, opcode, operand)) {
145562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      compiler::NodeVector inputs(1, zone_);
145662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      inputs[0] = Pop(0, ValueType::kSimd128).node;
145762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
145862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Push(ValueType::kSimd128, node);
145962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
146062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return operand.length;
146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1463f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  unsigned DecodeSimdOpcode(WasmOpcode opcode) {
1464f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    unsigned len = 0;
1465f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    switch (opcode) {
146662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprF32x4ExtractLane: {
146762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        len = SimdExtractLane(opcode, ValueType::kFloat32);
1468c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        break;
1469c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
147062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ExtractLane:
147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ExtractLane:
147262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ExtractLane: {
147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        len = SimdExtractLane(opcode, ValueType::kWord32);
147462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
147562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
147662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprF32x4ReplaceLane: {
147762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        len = SimdReplaceLane(opcode, ValueType::kFloat32);
147862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
147962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
148062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ReplaceLane:
148162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ReplaceLane:
148262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ReplaceLane: {
148362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        len = SimdReplaceLane(opcode, ValueType::kWord32);
148462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        break;
148562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
148662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4Shl:
148762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ShrS:
148862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI32x4ShrU:
148962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8Shl:
149062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ShrS:
149162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI16x8ShrU:
149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16Shl:
149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ShrS:
149462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      case kExprI8x16ShrU: {
149562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        len = SimdShiftOp(opcode);
1496f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
1497f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1498f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      default: {
1499f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        FunctionSig* sig = WasmOpcodes::Signature(opcode);
1500f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (sig != nullptr) {
1501f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          compiler::NodeVector inputs(sig->parameter_count(), zone_);
1502f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          for (size_t i = sig->parameter_count(); i > 0; i--) {
1503f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1));
1504f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            inputs[i - 1] = val.node;
1505f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          }
1506f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          TFNode* node = BUILD(SimdOp, opcode, inputs);
1507f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          Push(GetReturnType(sig), node);
1508f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        } else {
1509f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          error("invalid simd opcode");
1510f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
1511f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1513f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return len;
1514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void BuildAtomicOperator(WasmOpcode opcode) { UNIMPLEMENTED(); }
1517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void DoReturn() {
1519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    int count = static_cast<int>(sig_->return_count());
1520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    TFNode** buffer = nullptr;
1521bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (build()) buffer = builder_->Buffer(count);
1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Pop return values off the stack in reverse order.
1524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    for (int i = count - 1; i >= 0; i--) {
1525bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Value val = Pop(i, sig_->GetReturn(i));
1526bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (buffer) buffer[i] = val.node;
1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1529f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    BUILD(Return, count, buffer);
1530f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    EndControl();
1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
153362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Push(ValueType type, TFNode* node) {
153462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (type != kWasmStmt) {
1535f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      stack_.push_back({pc_, node, type});
1536f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1538f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
153962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void PushEndValues(Control* c) {
154062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(c, &control_.back());
154162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    stack_.resize(c->stack_depth);
154262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (c->merge.arity == 1) {
154362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      stack_.push_back(c->merge.vals.first);
154462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } else {
154562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      for (unsigned i = 0; i < c->merge.arity; i++) {
154662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        stack_.push_back(c->merge.vals.array[i]);
154762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
154862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
154962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
155062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
155162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1552f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void PushReturns(FunctionSig* sig, TFNode** rets) {
1553f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    for (size_t i = 0; i < sig->return_count(); i++) {
1554f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // When verifying only, then {rets} will be null, so push null.
1555f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Push(sig->GetReturn(i), rets ? rets[i] : nullptr);
1556f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1559bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  const char* SafeOpcodeNameAt(const byte* pc) {
1560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (pc >= end_) return "<end>";
156162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1562bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
156462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Value Pop(int index, ValueType expected) {
1565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Value val = Pop();
156662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) {
156762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
156862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
156962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
1570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return val;
1572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Value Pop() {
1575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
1576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (stack_.size() <= limit) {
157762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Popping past the current control start in reachable code.
157862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Value val = {pc_, nullptr, kWasmVar};
157962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!control_.back().unreachable) {
158062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
158162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
1582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return val;
1583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Value val = stack_.back();
1585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    stack_.pop_back();
1586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return val;
1587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int baserel(const byte* ptr) {
1590bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return base_ ? static_cast<int>(ptr - base_) : 0;
1591109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1592109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1595f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void BreakTo(unsigned depth) {
1596f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Control* c = &control_[control_.size() - depth - 1];
1597f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (c->is_loop()) {
1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // This is the inner loop block, which does not have a value.
1599f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Goto(ssa_env_, c->end_env);
1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1601f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Merge the value(s) into the end of the block.
160262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      size_t expected = control_.back().stack_depth + c->merge.arity;
160362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (stack_.size() < expected && !control_.back().unreachable) {
1604f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        error(
1605f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            pc_, pc_,
160662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            "expected at least %u values on the stack for br to @%d, found %d",
1607f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            c->merge.arity, startrel(c->pc),
1608f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            static_cast<int>(stack_.size() - c->stack_depth));
1609f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        return;
1610f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1611f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      MergeValuesInto(c);
1612f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1613f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1615f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void FallThruTo(Control* c) {
161662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(c, &control_.back());
1617f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Merge the value(s) into the end of the block.
161862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t expected = c->stack_depth + c->merge.arity;
161962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (stack_.size() == expected ||
162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        (stack_.size() < expected && c->unreachable)) {
162162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      MergeValuesInto(c);
162262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      c->unreachable = false;
1623f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return;
1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
162562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d",
162662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          c->merge.arity, startrel(c->pc));
1627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
162962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  inline Value& GetMergeValueFromStack(Control* c, size_t i) {
1630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return stack_[stack_.size() - c->merge.arity + i];
1631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
163362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void TypeCheckFallThru(Control* c) {
163462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(c, &control_.back());
1635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Fallthru must match arity exactly.
1636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    int arity = static_cast<int>(c->merge.arity);
163762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (c->stack_depth + arity < stack_.size() ||
163862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        (c->stack_depth + arity != stack_.size() && !c->unreachable)) {
1639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d",
1640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            arity, startrel(c->pc));
1641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return;
1642f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1643f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Typecheck the values left on the stack.
164462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t avail = stack_.size() - c->stack_depth;
164562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
164662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         i < c->merge.arity; i++) {
1647f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Value& val = GetMergeValueFromStack(c, i);
164862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Value& old = c->merge[i];
1649f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (val.type != old.type) {
165062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
1651f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
1652f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        return;
1653f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1654f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1655f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void MergeValuesInto(Control* c) {
1658f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    SsaEnv* target = c->end_env;
1659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool first = target->state == SsaEnv::kUnreachable;
166062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bool reachable = ssa_env_->go();
1661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Goto(ssa_env_, target);
1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
166362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t avail = stack_.size() - control_.back().stack_depth;
166462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
166562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         i < c->merge.arity; i++) {
1666f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Value& val = GetMergeValueFromStack(c, i);
166762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Value& old = c->merge[i];
166862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (val.type != old.type && val.type != kWasmVar) {
166962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i,
1670f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
1671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        return;
1672f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
167362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (builder_ && reachable) {
167462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        DCHECK_NOT_NULL(val.node);
1675c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        old.node =
1676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            first ? val.node : CreateOrMergeIntoPhi(old.type, target->control,
1677c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                                    old.node, val.node);
1678c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void SetEnv(const char* reason, SsaEnv* env) {
16833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
1684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (FLAG_trace_wasm_decoder) {
1685bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      char state = 'X';
1686bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (env) {
1687bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        switch (env->state) {
1688bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case SsaEnv::kReached:
1689bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            state = 'R';
1690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1691bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case SsaEnv::kUnreachable:
1692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            state = 'U';
1693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case SsaEnv::kMerged:
1695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            state = 'M';
1696bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1697bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          case SsaEnv::kControlEnd:
1698bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            state = 'E';
1699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
1700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        }
1701bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
170262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      PrintF("{set_env = %p, state = %c, reason = %s", static_cast<void*>(env),
1703bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch             state, reason);
1704bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (env && env->control) {
1705bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        PrintF(", control = ");
1706bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        compiler::WasmGraphBuilder::PrintDebugName(env->control);
1707bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
170862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      PrintF("}");
1709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
17103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
1711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env_ = env;
1712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_) {
1713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      builder_->set_control_ptr(&env->control);
1714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      builder_->set_effect_ptr(&env->effect);
1715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1718f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  TFNode* CheckForException(TFNode* node) {
1719f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (node == nullptr) {
1720f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return nullptr;
1721f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1722f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1723f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const bool inside_try_scope = current_catch_ != kNullCatch;
1724f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!inside_try_scope) {
1726f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return node;
1727f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1728f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1729f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TFNode* if_success = nullptr;
1730f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TFNode* if_exception = nullptr;
1731f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
1732f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return node;
1733f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1734f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1735f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    SsaEnv* success_env = Steal(ssa_env_);
1736f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    success_env->control = if_success;
1737f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1738f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    SsaEnv* exception_env = Split(success_env);
1739f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    exception_env->control = if_exception;
1740f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TryInfo* try_info = current_try_info();
1741f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Goto(exception_env, try_info->catch_env);
1742f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TFNode* exception = try_info->exception;
1743f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (exception == nullptr) {
1744f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
1745f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      try_info->exception = if_exception;
1746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else {
1747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
1748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      try_info->exception =
174962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
1750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                               try_info->exception, if_exception);
1751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1753f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    SetEnv("if_success", success_env);
1754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return node;
1755f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Goto(SsaEnv* from, SsaEnv* to) {
1758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(to);
1759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!from->go()) return;
1760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (to->state) {
1761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SsaEnv::kUnreachable: {  // Overwrite destination.
1762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->state = SsaEnv::kReached;
1763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->locals = from->locals;
1764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->control = from->control;
1765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->effect = from->effect;
1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SsaEnv::kReached: {  // Create a new merge.
1769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->state = SsaEnv::kMerged;
1770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!builder_) break;
1771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge control.
1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* controls[] = {to->control, from->control};
1773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* merge = builder_->Merge(2, controls);
1774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->control = merge;
1775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge effects.
1776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (from->effect != to->effect) {
1777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* effects[] = {to->effect, from->effect, merge};
1778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          to->effect = builder_->EffectPhi(2, effects, merge);
1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge SSA values.
1781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* a = to->locals[i];
1783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* b = from->locals[i];
1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (a != b) {
1785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode* vals[] = {a, b};
17863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SsaEnv::kMerged: {
1792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!builder_) break;
1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* merge = to->control;
1794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Extend the existing merge.
1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        builder_->AppendToMerge(merge, from->control);
1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge effects.
1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (builder_->IsPhiWithMerge(to->effect, merge)) {
1798bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          builder_->AppendToPhi(to->effect, from->effect);
1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (to->effect != from->effect) {
1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t count = builder_->InputCount(merge);
1801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode** effects = builder_->Buffer(count);
1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (uint32_t j = 0; j < count - 1; j++) {
1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            effects[j] = to->effect;
1804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          effects[count - 1] = from->effect;
1806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          to->effect = builder_->EffectPhi(count, effects, merge);
1807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge locals.
1809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* tnode = to->locals[i];
1811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* fnode = from->locals[i];
1812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (builder_->IsPhiWithMerge(tnode, merge)) {
1813bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            builder_->AppendToPhi(tnode, fnode);
1814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (tnode != fnode) {
1815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            uint32_t count = builder_->InputCount(merge);
1816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode** vals = builder_->Buffer(count);
1817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            for (uint32_t j = 0; j < count - 1; j++) {
1818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              vals[j] = tnode;
1819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
1820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            vals[count - 1] = fnode;
18213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            to->locals[i] =
18223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                builder_->Phi(local_type_vec_[i], count, vals, merge);
1823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
1828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
1829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return from->Kill();
1831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
183362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  TFNode* CreateOrMergeIntoPhi(ValueType type, TFNode* merge, TFNode* tnode,
1834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               TFNode* fnode) {
1835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_NOT_NULL(builder_);
1836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_->IsPhiWithMerge(tnode, merge)) {
1837bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      builder_->AppendToPhi(tnode, fnode);
1838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (tnode != fnode) {
1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t count = builder_->InputCount(merge);
1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TFNode** vals = builder_->Buffer(count);
1841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
1842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      vals[count - 1] = fnode;
1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return builder_->Phi(type, count, vals, merge);
1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return tnode;
1846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  SsaEnv* PrepareForLoop(const byte* pc, SsaEnv* env) {
1849c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (!builder_) return Split(env);
1850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (!env->go()) return Split(env);
18513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    env->state = SsaEnv::kMerged;
18523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    env->control = builder_->Loop(env->control);
18543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    env->effect = builder_->EffectPhi(1, &env->effect, env->control);
18553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    builder_->Terminate(env->effect, env->control);
18563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (FLAG_wasm_loop_assignment_analysis) {
185762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      BitVector* assigned = AnalyzeLoopAssignment(
185862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          this, pc, static_cast<int>(total_locals()), zone_);
1859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (failed()) return env;
18603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (assigned != nullptr) {
18613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // Only introduce phis for variables assigned in this loop.
1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
18633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          if (!assigned->Contains(i)) continue;
18643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i],
18653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                         env->control);
1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        SsaEnv* loop_body_env = Split(env);
1868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        builder_->StackCheck(position(), &(loop_body_env->effect),
1869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             &(loop_body_env->control));
1870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        return loop_body_env;
1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
18733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Conservatively introduce phis for all local variables.
18753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    for (int i = EnvironmentCount() - 1; i >= 0; i--) {
18763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      env->locals[i] =
18773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
18783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
1879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    SsaEnv* loop_body_env = Split(env);
1881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    builder_->StackCheck(position(), &(loop_body_env->effect),
1882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                         &(loop_body_env->control));
1883c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return loop_body_env;
1884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create a complete copy of the {from}.
1887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* Split(SsaEnv* from) {
1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(from);
1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t size = sizeof(TFNode*) * EnvironmentCount();
1891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->control = from->control;
1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->effect = from->effect;
1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (from->go()) {
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->state = SsaEnv::kReached;
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->locals =
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      memcpy(result->locals, from->locals, size);
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->state = SsaEnv::kUnreachable;
1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->locals = nullptr;
1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create a copy of {from} that steals its state and leaves {from}
1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // unreachable.
1909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* Steal(SsaEnv* from) {
1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(from);
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!from->go()) return UnreachableEnv();
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->state = SsaEnv::kReached;
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->locals = from->locals;
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->control = from->control;
1916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->effect = from->effect;
1917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    from->Kill(SsaEnv::kUnreachable);
1918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create an unreachable environment.
1922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* UnreachableEnv() {
1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->state = SsaEnv::kUnreachable;
1925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->control = nullptr;
1926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->effect = nullptr;
1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->locals = nullptr;
1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int EnvironmentCount() {
19323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (builder_) return static_cast<int>(local_type_vec_.size());
1933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 0;  // if we aren't building a graph, don't bother with SSA renaming.
1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual void onFirstError() {
193762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    end_ = start_;       // Terminate decoding loop.
1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    builder_ = nullptr;  // Don't build any more nodes.
1939bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    TRACE(" !%s\n", error_msg_.get());
1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1941bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1942bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline wasm::WasmCodePosition position() {
1943bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    int offset = static_cast<int>(pc_ - start_);
1944bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK_EQ(pc_ - start_, offset);  // overflows cannot happen
1945bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return offset;
1946bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
1947f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1948f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
1949f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TFNode* node;
1950f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    switch (sig->parameter_count()) {
1951f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case 1: {
1952f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Value val = Pop(0, sig->GetParam(0));
1953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        node = BUILD(Unop, opcode, val.node, position());
1954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
1955f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1956f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case 2: {
1957f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Value rval = Pop(1, sig->GetParam(1));
1958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Value lval = Pop(0, sig->GetParam(0));
1959f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        node = BUILD(Binop, opcode, lval.node, rval.node, position());
1960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
1961f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
1962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      default:
1963f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        UNREACHABLE();
1964f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        node = nullptr;
1965f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
1966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
1967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Push(GetReturnType(sig), node);
1968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
197162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
19723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                      const byte* end) {
197362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Decoder decoder(start, end);
197462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (WasmDecoder::DecodeLocals(&decoder, nullptr, &decls->type_list)) {
197562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(decoder.ok());
197662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    decls->encoded_size = decoder.pc_offset();
197762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return true;
197862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
197962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return false;
19803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
198362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   BodyLocalDecls* decls)
1984f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    : Decoder(start, end) {
1985f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (decls != nullptr) {
198662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (DecodeLocalDecls(decls, start, end)) {
198762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      pc_ += decls->encoded_size;
1988f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (pc_ > end_) pc_ = end_;
1989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1993f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochDecodeResult VerifyWasmCode(AccountingAllocator* allocator,
199462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                            const wasm::WasmModule* module,
1995f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            FunctionBody& body) {
1996c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(allocator, ZONE_NAME);
199762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  WasmFullDecoder decoder(&zone, module, body);
1998bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  decoder.Decode();
1999f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return decoder.toResult<DecodeStruct*>(nullptr);
2000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2002f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochDecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
2003f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                          FunctionBody& body) {
2004c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(allocator, ZONE_NAME);
2005f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  WasmFullDecoder decoder(&zone, builder, body);
2006f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  decoder.Decode();
2007f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return decoder.toResult<DecodeStruct*>(nullptr);
2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
201013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochunsigned OpcodeLength(const byte* pc, const byte* end) {
201162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Decoder decoder(pc, end);
201262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return WasmDecoder::OpcodeLength(&decoder, pc);
2013109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
201562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid PrintRawWasmCode(const byte* start, const byte* end) {
2016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  AccountingAllocator allocator;
201762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);
201862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
201962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
202062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace {
202162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochconst char* RawOpcodeName(WasmOpcode opcode) {
202262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (opcode) {
202362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define DECLARE_NAME_CASE(name, opcode, sig) \
202462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  case kExpr##name:                          \
202562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return "kExpr" #name;
202662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FOREACH_OPCODE(DECLARE_NAME_CASE)
202762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#undef DECLARE_NAME_CASE
202862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default:
202962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
203062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
203162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return "Unknown";
2032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
203362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace
2034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
203562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
203662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      const wasm::WasmModule* module) {
203762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  OFStream os(stdout);
2038c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(allocator, ZONE_NAME);
203962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  WasmFullDecoder decoder(&zone, module, body);
204013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int line_nr = 0;
20413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Print the function signature.
20433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (body.sig) {
20443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    os << "// signature: " << *body.sig << std::endl;
204513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ++line_nr;
20463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
20483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Print the local declarations.
204962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BodyLocalDecls decls(&zone);
2050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BytecodeIterator i(body.start, body.end, &decls);
205162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
2052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    os << "// locals: ";
205362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!decls.type_list.empty()) {
205462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ValueType type = decls.type_list[0];
205562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      uint32_t count = 0;
205662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
205762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        if (decls.type_list[pos] == type) {
205862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          ++count;
205962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        } else {
206062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          os << " " << count << " " << WasmOpcodes::TypeName(type);
206162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          type = decls.type_list[pos];
206262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          count = 1;
206362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        }
206462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
20653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
20663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    os << std::endl;
2067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ++line_nr;
20683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (const byte* locals = body.start; locals < i.pc(); locals++) {
207013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
20713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
2072bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    os << std::endl;
207313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ++line_nr;
20743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
207613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  os << "// body: " << std::endl;
207713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ++line_nr;
207813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  unsigned control_depth = 0;
2079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (; i.has_next(); i.next()) {
208062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    unsigned length = WasmDecoder::OpcodeLength(&decoder, i.pc());
2081109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    WasmOpcode opcode = i.current();
2083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (opcode == kExprElse) control_depth--;
2084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
208513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
208613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
208713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // 64 whitespaces
208813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    const char* padding =
208913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        "                                                                ";
209013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    os.write(padding, num_whitespaces);
209162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
209262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    os << RawOpcodeName(opcode) << ",";
2093109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2094f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (size_t j = 1; j < length; ++j) {
209562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      os << " 0x" << AsHex(i.pc()[j], 2) << ",";
2096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
20973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    switch (opcode) {
2099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprElse:
2100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        os << "   // @" << i.pc_offset();
2101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        control_depth++;
2102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
2103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprLoop:
2104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprIf:
2105bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprBlock:
2106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case kExprTry: {
2107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        BlockTypeOperand operand(&i, i.pc());
2108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        os << "   // @" << i.pc_offset();
2109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        for (unsigned i = 0; i < operand.arity; i++) {
2110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          os << " " << WasmOpcodes::TypeName(operand.read_entry(i));
2111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
2112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        control_depth++;
2113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
2115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprEnd:
2116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        os << "   // @" << i.pc_offset();
2117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        control_depth--;
2118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2119bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprBr: {
2120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        BreakDepthOperand operand(&i, i.pc());
2121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        os << "   // depth=" << operand.depth;
2122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
2124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprBrIf: {
2125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        BreakDepthOperand operand(&i, i.pc());
2126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        os << "   // depth=" << operand.depth;
2127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
2129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprBrTable: {
2130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        BranchTableOperand operand(&i, i.pc());
2131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        os << " // entries=" << operand.table_count;
2132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
2134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprCallIndirect: {
2135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        CallIndirectOperand operand(&i, i.pc());
2136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        os << "   // sig #" << operand.index;
2137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (decoder.Complete(i.pc(), operand)) {
2138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          os << ": " << *operand.sig;
21393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        }
2140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
2142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case kExprCallFunction: {
2143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        CallFunctionOperand operand(&i, i.pc());
2144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        os << " // function #" << operand.index;
2145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (decoder.Complete(i.pc(), operand)) {
2146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          os << ": " << *operand.sig;
21473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        }
2148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
2149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
2150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      default:
2151bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
215262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
2153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    os << std::endl;
215413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ++line_nr;
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
215613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
215713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return decoder.ok();
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
21603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochBitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
2161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                           const byte* start, const byte* end) {
216262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Decoder decoder(start, end);
216362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return WasmDecoder::AnalyzeLoopAssignment(&decoder, start,
216462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                            static_cast<int>(num_locals), zone);
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace wasm
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2170