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/base/platform/elapsed-timer.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/signature.h"
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/flags.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/zone-containers.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/ast-decoder.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/decoder.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-module.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-opcodes.h"
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/wasm-compiler.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace wasm {
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...)                                    \
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  do {                                                \
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } while (false)
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...)
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The root of a decoded tree.
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct Tree {
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LocalType type;     // tree type.
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t count;     // number of children.
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* pc;     // start of the syntax tree.
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode* node;       // node in the TurboFan graph.
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Tree* children[1];  // pointers to children.
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); }
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A production represents an incomplete decoded tree in the LR decoder.
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct Production {
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Tree* tree;  // the root of the syntax tree.
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int index;   // the current index into the children of the tree.
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); }
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* pc() const { return tree->pc; }
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool done() const { return index >= static_cast<int>(tree->count); }
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; }
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// An SsaEnv environment carries the current local variable renaming
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// as well as the current effect and control dependency in the TF graph.
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// It maintains a control state that tracks whether the environment
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// is reachable, has reached a control end, or has been merged.
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct SsaEnv {
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum State { kControlEnd, kUnreachable, kReached, kMerged };
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  State state;
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode* control;
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode* effect;
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode** locals;
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool go() { return state >= kReached; }
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Kill(State new_state = kControlEnd) {
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    state = new_state;
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    locals = nullptr;
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    control = nullptr;
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    effect = nullptr;
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// An entry in the stack of blocks during decoding.
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct Block {
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* ssa_env;  // SSA renaming environment.
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int stack_depth;  // production stack depth.
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// An entry in the stack of ifs during decoding.
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct IfEnv {
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* false_env;
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* merge_env;
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv** case_envs;
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Macros that build nodes only if there is a graph and the current SSA
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// environment is reachable from start. This avoids problems with malformed
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TF graphs when decoding inputs that have unreachable code.
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define BUILD0(func) (build() ? builder_->func() : nullptr)
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// shift-reduce strategy with multiple internal stacks.
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass LR_WasmDecoder : public Decoder {
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LR_WasmDecoder(Zone* zone, TFBuilder* builder)
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : Decoder(nullptr, nullptr),
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        zone_(zone),
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        builder_(builder),
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        trees_(zone),
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        stack_(zone),
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        blocks_(zone),
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ifs_(zone) {}
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TreeResult Decode(FunctionEnv* function_env, const byte* base, const byte* pc,
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    const byte* end) {
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    base::ElapsedTimer decode_timer;
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (FLAG_trace_wasm_decode_time) {
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      decode_timer.Start();
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    trees_.clear();
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    stack_.clear();
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    blocks_.clear();
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ifs_.clear();
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (end < pc) {
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      error(pc, "function body end < start");
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return result_;
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    base_ = base;
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Reset(pc, end);
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    function_env_ = function_env;
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    InitSsaEnv();
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DecodeFunctionBody();
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Tree* tree = nullptr;
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (ok()) {
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (ssa_env_->go()) {
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (stack_.size() > 0) {
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error(stack_.back().pc(), end, "fell off end of code");
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AddImplicitReturnAtEnd();
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (trees_.size() == 0) {
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (function_env_->sig->return_count() > 0) {
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error(start_, "no trees created");
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        tree = trees_[0];
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (ok()) {
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (FLAG_trace_wasm_decode_time) {
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        double ms = decode_timer.Elapsed().InMillisecondsF();
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        PrintF(" - decoding took %0.3f ms\n", ms);
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TRACE("wasm-decode ok\n\n");
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            startrel(error_pc_), error_msg_.get());
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return toResult(tree);
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const size_t kErrorMsgSize = 128;
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Zone* zone_;
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFBuilder* builder_;
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* base_;
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TreeResult result_;
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* ssa_env_;
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FunctionEnv* function_env_;
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneVector<Tree*> trees_;
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneVector<Production> stack_;
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneVector<Block> blocks_;
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ZoneVector<IfEnv> ifs_;
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline bool build() { return builder_ && ssa_env_->go(); }
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InitSsaEnv() {
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FunctionSig* sig = function_env_->sig;
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int param_count = static_cast<int>(sig->parameter_count());
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TFNode* start = nullptr;
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t size = sizeof(TFNode*) * EnvironmentCount();
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->state = SsaEnv::kReached;
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->locals =
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int pos = 0;
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_) {
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      start = builder_->Start(param_count + 1);
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Initialize parameters.
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (int i = 0; i < param_count; i++) {
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ssa_env->locals[pos++] = builder_->Param(i, sig->GetParam(i));
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Initialize int32 locals.
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (function_env_->local_int32_count > 0) {
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* zero = builder_->Int32Constant(0);
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (uint32_t i = 0; i < function_env_->local_int32_count; i++) {
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env->locals[pos++] = zero;
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Initialize int64 locals.
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (function_env_->local_int64_count > 0) {
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* zero = builder_->Int64Constant(0);
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (uint32_t i = 0; i < function_env_->local_int64_count; i++) {
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env->locals[pos++] = zero;
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Initialize float32 locals.
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (function_env_->local_float32_count > 0) {
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* zero = builder_->Float32Constant(0);
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (uint32_t i = 0; i < function_env_->local_float32_count; i++) {
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env->locals[pos++] = zero;
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Initialize float64 locals.
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (function_env_->local_float64_count > 0) {
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* zero = builder_->Float64Constant(0);
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (uint32_t i = 0; i < function_env_->local_float64_count; i++) {
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env->locals[pos++] = zero;
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(function_env_->total_locals, pos);
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(EnvironmentCount(), pos);
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      builder_->set_module(function_env_->module);
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->control = start;
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env->effect = start;
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetEnv("initial", ssa_env);
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Leaf(LocalType type, TFNode* node = nullptr) {
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t size = sizeof(Tree);
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->type = type;
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->count = 0;
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->pc = pc_;
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->node = node;
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->children[0] = nullptr;
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Reduce(tree);
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Shift(LocalType type, uint32_t count) {
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t size =
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        sizeof(Tree) + (count == 0 ? 0 : ((count - 1) * sizeof(Tree*)));
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->type = type;
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->count = count;
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->pc = pc_;
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    tree->node = nullptr;
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (uint32_t i = 0; i < count; i++) tree->children[i] = nullptr;
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (count == 0) {
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Production p = {tree, 0};
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Reduce(&p);
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Reduce(tree);
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      stack_.push_back({tree, 0});
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Reduce(Tree* tree) {
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (true) {
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (stack_.size() == 0) {
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        trees_.push_back(tree);
271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Production* p = &stack_.back();
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      p->tree->children[p->index++] = tree;
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Reduce(p);
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (p->done()) {
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        tree = p->tree;
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        stack_.pop_back();
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* indentation() {
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static const int kMaxIndent = 64;
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static char bytes[kMaxIndent + 1];
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' ';
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bytes[kMaxIndent] = 0;
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (stack_.size() < kMaxIndent / 2) {
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      bytes[stack_.size() * 2] = 0;
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return bytes;
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Decodes the body of a function, producing reduced trees into {result}.
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DecodeFunctionBody() {
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("wasm-decode %p...%p (%d bytes) %s\n",
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          reinterpret_cast<const void*>(start_),
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          reinterpret_cast<const void*>(limit_),
301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (pc_ >= limit_) return;  // Nothing to do.
304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (true) {  // decoding loop.
306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int len = 1;
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TRACE("wasm-decode module+%-6d %s func+%d: 0x%02x %s\n", baserel(pc_),
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            indentation(), startrel(pc_), opcode,
310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            WasmOpcodes::OpcodeName(opcode));
311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FunctionSig* sig = WasmOpcodes::Signature(opcode);
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (sig) {
314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // A simple expression with a fixed signature.
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Shift(sig->GetReturn(), static_cast<uint32_t>(sig->parameter_count()));
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        pc_ += len;
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (pc_ >= limit_) {
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // End of code reached or exceeded.
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (pc_ > limit_ && ok()) {
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("Beyond end of code");
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return;
323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        continue;  // back to decoding loop.
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      switch (opcode) {
328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprNop:
329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstStmt);
330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprBlock: {
332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          int length = Operand<uint8_t>(pc_);
333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (length < 1) {
334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Leaf(kAstStmt);
335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Shift(kAstEnd, length);
337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // The break environment is the outer environment.
338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* break_env = ssa_env_;
339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            PushBlock(break_env);
340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("block:start", Steal(break_env));
341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 2;
343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprLoop: {
346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          int length = Operand<uint8_t>(pc_);
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (length < 1) {
348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Leaf(kAstStmt);
349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Shift(kAstEnd, length);
351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // The break environment is the outer environment.
352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* break_env = ssa_env_;
353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            PushBlock(break_env);
354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* cont_env = Steal(break_env);
355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // The continue environment is the inner environment.
356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            PrepareForLoop(cont_env);
357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("loop:start", Split(cont_env));
358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            if (ssa_env_->go()) ssa_env_->state = SsaEnv::kReached;
359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            PushBlock(cont_env);
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            blocks_.back().stack_depth = -1;  // no production for inner block.
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 2;
363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprIf:
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstStmt, 2);
367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprIfElse:
369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstEnd, 3);  // Result type is typeof(x) in {c ? x : y}.
370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprSelect:
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstStmt, 3);  // Result type is typeof(x) in {c ? x : y}.
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprBr: {
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t depth = Operand<uint8_t>(pc_);
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstEnd, 1);
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (depth >= blocks_.size()) {
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("improperly nested branch");
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 2;
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprBrIf: {
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t depth = Operand<uint8_t>(pc_);
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstStmt, 2);
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (depth >= blocks_.size()) {
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("improperly nested conditional branch");
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 2;
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprTableSwitch: {
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!checkAvailable(5)) {
394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("expected #tableswitch <cases> <table>, fell off end");
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint16_t case_count = *reinterpret_cast<const uint16_t*>(pc_ + 1);
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint16_t table_count = *reinterpret_cast<const uint16_t*>(pc_ + 3);
399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 5 + table_count * 2;
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (table_count == 0) {
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("tableswitch with 0 entries");
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (!checkAvailable(len)) {
407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("expected #tableswitch <cases> <table>, fell off end");
408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstEnd, 1 + case_count);
412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Verify table.
414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (int i = 0; i < table_count; i++) {
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            uint16_t target =
416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                *reinterpret_cast<const uint16_t*>(pc_ + 5 + i * 2);
417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            if (target >= 0x8000) {
418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              size_t depth = target - 0x8000;
419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              if (depth > blocks_.size()) {
420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                error(pc_ + 5 + i * 2, "improper branch in tableswitch");
421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              }
422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            } else {
423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              if (target >= case_count) {
424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                error(pc_ + 5 + i * 2, "invalid case target in tableswitch");
425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              }
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprReturn: {
431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          int count = static_cast<int>(function_env_->sig->return_count());
432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (count == 0) {
433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            BUILD(Return, 0, builder_->Buffer(0));
434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            ssa_env_->Kill();
435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Leaf(kAstEnd);
436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Shift(kAstEnd, count);
438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprUnreachable: {
442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BUILD0(Unreachable);
443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env_->Kill(SsaEnv::kControlEnd);
444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstEnd, nullptr);
445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI8Const: {
448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          int32_t value = Operand<int8_t>(pc_);
449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstI32, BUILD(Int32Constant, value));
450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 2;
451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32Const: {
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          int32_t value = Operand<int32_t>(pc_);
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstI32, BUILD(Int32Constant, value));
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 5;
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64Const: {
460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          int64_t value = Operand<int64_t>(pc_);
461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstI64, BUILD(Int64Constant, value));
462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 9;
463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprF32Const: {
466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          float value = Operand<float>(pc_);
467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstF32, BUILD(Float32Constant, value));
468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 5;
469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprF64Const: {
472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          double value = Operand<double>(pc_);
473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstF64, BUILD(Float64Constant, value));
474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = 9;
475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprGetLocal: {
478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t index;
479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          LocalType type = LocalOperand(pc_, &index, &len);
480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* val =
481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              build() && type != kAstStmt ? ssa_env_->locals[index] : nullptr;
482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(type, val);
483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprSetLocal: {
486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t index;
487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          LocalType type = LocalOperand(pc_, &index, &len);
488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(type, 1);
489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprLoadGlobal: {
492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t index;
493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          LocalType type = GlobalOperand(pc_, &index, &len);
494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(type, BUILD(LoadGlobal, index));
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprStoreGlobal: {
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t index;
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          LocalType type = GlobalOperand(pc_, &index, &len);
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(type, 1);
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32LoadMem8S:
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32LoadMem8U:
505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32LoadMem16S:
506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32LoadMem16U:
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32LoadMem:
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeLoadMem(pc_, kAstI32);
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem8S:
511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem8U:
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem16S:
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem16U:
514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem32S:
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem32U:
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64LoadMem:
517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeLoadMem(pc_, kAstI64);
518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprF32LoadMem:
520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeLoadMem(pc_, kAstF32);
521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprF64LoadMem:
523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeLoadMem(pc_, kAstF64);
524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32StoreMem8:
526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32StoreMem16:
527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI32StoreMem:
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeStoreMem(pc_, kAstI32);
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64StoreMem8:
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64StoreMem16:
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64StoreMem32:
533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprI64StoreMem:
534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeStoreMem(pc_, kAstI64);
535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprF32StoreMem:
537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeStoreMem(pc_, kAstF32);
538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprF64StoreMem:
540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          len = DecodeStoreMem(pc_, kAstF64);
541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprMemorySize:
543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Leaf(kAstI32, BUILD(MemSize, 0));
544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprGrowMemory:
546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Shift(kAstI32, 1);
547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprCallFunction: {
549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t unused;
550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          FunctionSig* sig = FunctionSigOperand(pc_, &unused, &len);
551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (sig) {
552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            LocalType type =
553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Shift(type, static_cast<int>(sig->parameter_count()));
555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Leaf(kAstI32);  // error
557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case kExprCallIndirect: {
561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t unused;
562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          FunctionSig* sig = SigOperand(pc_, &unused, &len);
563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (sig) {
564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            LocalType type =
565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Shift(type, static_cast<int>(1 + sig->parameter_count()));
567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Leaf(kAstI32);  // error
569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        default:
573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error("Invalid opcode");
574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return;
575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      pc_ += len;
577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (pc_ >= limit_) {
578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // End of code reached or exceeded.
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (pc_ > limit_ && ok()) {
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error("Beyond end of code");
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return;
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PushBlock(SsaEnv* ssa_env) {
588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    blocks_.push_back({ssa_env, static_cast<int>(stack_.size() - 1)});
589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int DecodeLoadMem(const byte* pc, LocalType type) {
592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int length = 2;
593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t offset;
594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemoryAccessOperand(pc, &length, &offset);
595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Shift(type, 1);
596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return length;
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int DecodeStoreMem(const byte* pc, LocalType type) {
600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int length = 2;
601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t offset;
602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemoryAccessOperand(pc, &length, &offset);
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Shift(type, 2);
604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return length;
605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AddImplicitReturnAtEnd() {
608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int retcount = static_cast<int>(function_env_->sig->return_count());
609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (retcount == 0) {
610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      BUILD0(ReturnVoid);
611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (static_cast<int>(trees_.size()) < retcount) {
615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      error(limit_, nullptr,
616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            "ImplicitReturn expects %d arguments, only %d remain", retcount,
617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            static_cast<int>(trees_.size()));
618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("wasm-decode implicit return of %d args\n", retcount);
622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TFNode** buffer = BUILD(Buffer, retcount);
624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int index = 0; index < retcount; index++) {
625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Tree* tree = trees_[trees_.size() - 1 - index];
626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (buffer) buffer[index] = tree->node;
627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      LocalType expected = function_env_->sig->GetReturn(index);
628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (tree->type != expected) {
629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        error(limit_, tree->pc,
630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              "ImplicitReturn[%d] expected type %s, found %s of type %s", index,
631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              WasmOpcodes::TypeName(expected),
632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              WasmOpcodes::OpcodeName(tree->opcode()),
633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              WasmOpcodes::TypeName(tree->type));
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return;
635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    BUILD(Return, retcount, buffer);
639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int baserel(const byte* ptr) {
642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return base_ ? static_cast<int>(ptr - base_) : 0;
643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Reduce(Production* p) {
648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    WasmOpcode opcode = p->opcode();
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("-----reduce module+%-6d %s func+%d: 0x%02x %s\n", baserel(p->pc()),
650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          indentation(), startrel(p->pc()), opcode,
651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          WasmOpcodes::OpcodeName(opcode));
652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FunctionSig* sig = WasmOpcodes::Signature(opcode);
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (sig) {
654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // A simple expression with a fixed signature.
655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TypeCheckLast(p, sig->GetParam(p->index - 1));
656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (p->done() && build()) {
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (sig->parameter_count() == 2) {
658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->node = builder_->Binop(opcode, p->tree->children[0]->node,
659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          p->tree->children[1]->node);
660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (sig->parameter_count() == 1) {
661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->node = builder_->Unop(opcode, p->tree->children[0]->node);
662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          UNREACHABLE();
664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprBlock: {
671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->done()) {
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Block* last = &blocks_.back();
673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK_EQ(stack_.size() - 1, last->stack_depth);
674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // fallthrough with the last expression.
675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ReduceBreakToExprBlock(p, last);
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("block:end", last->ssa_env);
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blocks_.pop_back();
678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprLoop: {
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->done()) {
683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Pop the continue environment.
684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blocks_.pop_back();
685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Get the break environment.
686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Block* last = &blocks_.back();
687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK_EQ(stack_.size() - 1, last->stack_depth);
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // fallthrough with the last expression.
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ReduceBreakToExprBlock(p, last);
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("loop:end", last->ssa_env);
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          blocks_.pop_back();
692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprIf: {
696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index == 1) {
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Condition done. Split environment for true branch.
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, kAstI32);
699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* false_env = ssa_env_;
700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* true_env = Split(ssa_env_);
701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ifs_.push_back({nullptr, false_env, nullptr});
702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BUILD(Branch, p->last()->node, &true_env->control,
703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                &false_env->control);
704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("if:true", true_env);
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (p->index == 2) {
706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // True block done. Merge true and false environments.
707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          IfEnv* env = &ifs_.back();
708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* merge = env->merge_env;
709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (merge->go()) {
710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            merge->state = SsaEnv::kReached;
711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Goto(ssa_env_, merge);
712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("if:merge", merge);
714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ifs_.pop_back();
715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprIfElse: {
719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index == 1) {
720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Condition done. Split environment for true and false branches.
721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, kAstI32);
722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* merge_env = ssa_env_;
723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* if_true = nullptr;
724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* if_false = nullptr;
725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BUILD(Branch, p->last()->node, &if_true, &if_false);
726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* false_env = Split(ssa_env_);
727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* true_env = Steal(ssa_env_);
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          false_env->control = if_false;
729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          true_env->control = if_true;
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ifs_.push_back({false_env, merge_env, nullptr});
731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("if_else:true", true_env);
732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (p->index == 2) {
733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // True expr done.
734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          IfEnv* env = &ifs_.back();
735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          MergeIntoProduction(p, env->merge_env, p->last());
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Switch to environment for false branch.
737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* false_env = ifs_.back().false_env;
738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("if_else:false", false_env);
739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (p->index == 3) {
740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // False expr done.
741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          IfEnv* env = &ifs_.back();
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          MergeIntoProduction(p, env->merge_env, p->last());
743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("if_else:merge", env->merge_env);
744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ifs_.pop_back();
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprSelect: {
749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index == 1) {
750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Condition done.
751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, kAstI32);
752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (p->index == 2) {
753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // True expression done.
754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->type = p->last()->type;
755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (p->tree->type == kAstStmt) {
756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error(p->pc(), p->tree->children[1]->pc,
757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  "select operand should be expression");
758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // False expression done.
761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DCHECK(p->done());
762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, p->tree->type);
763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (build()) {
764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode* controls[2];
765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            builder_->Branch(p->tree->children[0]->node, &controls[0],
766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             &controls[1]);
767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode* merge = builder_->Merge(2, controls);
768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode* vals[2] = {p->tree->children[1]->node,
769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               p->tree->children[2]->node};
770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode* phi = builder_->Phi(p->tree->type, 2, vals, merge);
771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            p->tree->node = phi;
772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            ssa_env_->control = merge;
773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprBr: {
778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint32_t depth = Operand<uint8_t>(p->pc());
779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (depth >= blocks_.size()) {
780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error("improperly nested branch");
781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Block* block = &blocks_[blocks_.size() - depth - 1];
784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ReduceBreakToExprBlock(p, block);
785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprBrIf: {
788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index == 1) {
789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, kAstI32);
790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (p->done()) {
791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t depth = Operand<uint8_t>(p->pc());
792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (depth >= blocks_.size()) {
793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            error("improperly nested branch");
794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Block* block = &blocks_[blocks_.size() - depth - 1];
797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* fenv = ssa_env_;
798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* tenv = Split(fenv);
799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BUILD(Branch, p->tree->children[0]->node, &tenv->control,
800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                &fenv->control);
801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env_ = tenv;
802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ReduceBreakToExprBlock(p, block);
803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env_ = fenv;
804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprTableSwitch: {
808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint16_t table_count = *reinterpret_cast<const uint16_t*>(p->pc() + 3);
809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (table_count == 1) {
810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Degenerate switch with only a default target.
811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (p->index == 1) {
812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* break_env = ssa_env_;
813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            PushBlock(break_env);
814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("switch:default", Steal(break_env));
815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (p->done()) {
817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Block* block = &blocks_.back();
818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // fall through to the end.
819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            ReduceBreakToExprBlock(p, block);
820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("switch:end", block->ssa_env);
821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            blocks_.pop_back();
822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index == 1) {
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Switch key finished.
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, kAstI32);
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* sw = BUILD(Switch, table_count, p->last()->node);
831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Allocate environments for each case.
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint16_t case_count = *reinterpret_cast<const uint16_t*>(p->pc() + 1);
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv** case_envs = zone_->NewArray<SsaEnv*>(case_count);
835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (int i = 0; i < case_count; i++) {
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            case_envs[i] = UnreachableEnv();
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ifs_.push_back({nullptr, nullptr, case_envs});
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* break_env = ssa_env_;
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          PushBlock(break_env);
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SsaEnv* copy = Steal(break_env);
843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env_ = copy;
844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Build the environments for each case based on the table.
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          const uint16_t* table =
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              reinterpret_cast<const uint16_t*>(p->pc() + 5);
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (int i = 0; i < table_count; i++) {
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            uint16_t target = table[i];
850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* env = Split(copy);
851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            env->control = (i == table_count - 1) ? BUILD(IfDefault, sw)
852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                  : BUILD(IfValue, i, sw);
853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            if (target >= 0x8000) {
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              // Targets an outer block.
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              int depth = target - 0x8000;
856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              SsaEnv* tenv = blocks_[blocks_.size() - depth - 1].ssa_env;
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              Goto(env, tenv);
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            } else {
859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              // Targets a case.
860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              Goto(env, case_envs[target]);
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Switch to the environment for the first case.
865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          SetEnv("switch:case", case_envs[0]);
866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Switch case finished.
868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (p->done()) {
869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // Last case. Fall through to the end.
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Block* block = &blocks_.back();
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            ReduceBreakToExprBlock(p, block);
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* next = block->ssa_env;
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            blocks_.pop_back();
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            ifs_.pop_back();
875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("switch:end", next);
876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            // Interior case. Maybe fall through to the next case.
878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SsaEnv* next = ifs_.back().case_envs[p->index - 1];
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            if (ssa_env_->go()) Goto(ssa_env_, next);
880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            SetEnv("switch:case", next);
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprReturn: {
886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TypeCheckLast(p, function_env_->sig->GetReturn(p->index - 1));
887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->done()) {
888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (build()) {
889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            int count = p->tree->count;
890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode** buffer = builder_->Buffer(count);
891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            for (int i = 0; i < count; i++) {
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              buffer[i] = p->tree->children[i]->node;
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            BUILD(Return, count, buffer);
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          ssa_env_->Kill(SsaEnv::kControlEnd);
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprSetLocal: {
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int unused = 0;
902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint32_t index;
903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        LocalType type = LocalOperand(p->pc(), &index, &unused);
904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Tree* val = p->last();
905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (type == val->type) {
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (build()) ssa_env_->locals[index] = val->node;
907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->node = val->node;
908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error(p->pc(), val->pc, "Typecheck failed in SetLocal");
910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprStoreGlobal: {
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int unused = 0;
915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint32_t index;
916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        LocalType type = GlobalOperand(p->pc(), &index, &unused);
917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Tree* val = p->last();
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (type == val->type) {
919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          BUILD(StoreGlobal, index, val->node);
920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->node = val->node;
921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          error(p->pc(), val->pc, "Typecheck failed in StoreGlobal");
923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32LoadMem8S:
928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI32, MachineType::Int8());
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32LoadMem8U:
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI32, MachineType::Uint8());
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32LoadMem16S:
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI32, MachineType::Int16());
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32LoadMem16U:
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI32, MachineType::Uint16());
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32LoadMem:
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI32, MachineType::Int32());
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem8S:
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Int8());
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem8U:
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Uint8());
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem16S:
943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Int16());
944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem16U:
945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Uint16());
946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem32S:
947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Int32());
948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem32U:
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Uint32());
950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64LoadMem:
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstI64, MachineType::Int64());
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprF32LoadMem:
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstF32, MachineType::Float32());
955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprF64LoadMem:
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceLoadMem(p, kAstF64, MachineType::Float64());
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32StoreMem8:
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI32, MachineType::Int8());
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32StoreMem16:
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI32, MachineType::Int16());
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI32StoreMem:
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI32, MachineType::Int32());
965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64StoreMem8:
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI64, MachineType::Int8());
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64StoreMem16:
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI64, MachineType::Int16());
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64StoreMem32:
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI64, MachineType::Int32());
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprI64StoreMem:
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstI64, MachineType::Int64());
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprF32StoreMem:
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstF32, MachineType::Float32());
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprF64StoreMem:
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ReduceStoreMem(p, kAstF64, MachineType::Float64());
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprGrowMemory:
982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TypeCheckLast(p, kAstI32);
983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // TODO(titzer): build node for GrowMemory
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        p->tree->node = BUILD(Int32Constant, 0);
985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return;
986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprCallFunction: {
988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int len;
989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint32_t index;
990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FunctionSig* sig = FunctionSigOperand(p->pc(), &index, &len);
991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!sig) break;
992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index > 0) {
993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, sig->GetParam(p->index - 1));
994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->done() && build()) {
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t count = p->tree->count + 1;
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode** buffer = builder_->Buffer(count);
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          FunctionSig* sig = FunctionSigOperand(p->pc(), &index, &len);
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          USE(sig);
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          buffer[0] = nullptr;  // reserved for code object.
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (uint32_t i = 1; i < count; i++) {
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            buffer[i] = p->tree->children[i - 1]->node;
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->node = builder_->CallDirect(index, buffer);
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExprCallIndirect: {
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int len;
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint32_t index;
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FunctionSig* sig = SigOperand(p->pc(), &index, &len);
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->index == 1) {
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, kAstI32);
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TypeCheckLast(p, sig->GetParam(p->index - 2));
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (p->done() && build()) {
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t count = p->tree->count;
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode** buffer = builder_->Buffer(count);
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (uint32_t i = 0; i < count; i++) {
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            buffer[i] = p->tree->children[i]->node;
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          p->tree->node = builder_->CallIndirect(index, buffer);
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ReduceBreakToExprBlock(Production* p, Block* block) {
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (block->stack_depth < 0) {
1034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // This is the inner loop block, which does not have a value.
1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Goto(ssa_env_, block->ssa_env);
1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Merge the value into the production for the block.
1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Production* bp = &stack_[block->stack_depth];
1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      MergeIntoProduction(bp, block->ssa_env, p->last());
1040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void MergeIntoProduction(Production* p, SsaEnv* target, Tree* expr) {
1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!ssa_env_->go()) return;
1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool first = target->state == SsaEnv::kUnreachable;
1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Goto(ssa_env_, target);
1048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expr->type == kAstEnd) return;
1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (first) {
1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // first merge to this environment; set the type and the node.
1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      p->tree->type = expr->type;
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      p->tree->node = expr->node;
1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // merge with the existing value for this block.
1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      LocalType type = p->tree->type;
1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (expr->type != type) {
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        type = kAstStmt;
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        p->tree->type = kAstStmt;
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        p->tree->node = nullptr;
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (type != kAstStmt) {
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        p->tree->node = CreateOrMergeIntoPhi(type, target->control,
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             p->tree->node, expr->node);
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ReduceLoadMem(Production* p, LocalType type, MachineType mem_type) {
1069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_EQ(1, p->index);
1070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TypeCheckLast(p, kAstI32);  // index
1071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (build()) {
1072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int length = 0;
1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t offset = 0;
1074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      MemoryAccessOperand(p->pc(), &length, &offset);
1075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      p->tree->node =
1076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          builder_->LoadMem(type, mem_type, p->last()->node, offset);
1077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ReduceStoreMem(Production* p, LocalType type, MachineType mem_type) {
1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (p->index == 1) {
1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TypeCheckLast(p, kAstI32);  // index
1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK_EQ(2, p->index);
1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TypeCheckLast(p, type);
1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (build()) {
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int length = 0;
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint32_t offset = 0;
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        MemoryAccessOperand(p->pc(), &length, &offset);
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* val = p->tree->children[1]->node;
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        builder_->StoreMem(mem_type, p->tree->children[0]->node, offset, val);
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        p->tree->node = val;
1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TypeCheckLast(Production* p, LocalType expected) {
1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LocalType result = p->last()->type;
1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (result == expected) return;
1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (result == kAstEnd) return;
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (expected != kAstStmt) {
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      error(p->pc(), p->last()->pc,
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            "%s[%d] expected type %s, found %s of type %s",
1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            WasmOpcodes::OpcodeName(p->opcode()), p->index - 1,
1105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            WasmOpcodes::TypeName(expected),
1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            WasmOpcodes::OpcodeName(p->last()->opcode()),
1107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            WasmOpcodes::TypeName(p->last()->type));
1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void SetEnv(const char* reason, SsaEnv* env) {
1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("  env = %p, block depth = %d, reason = %s", static_cast<void*>(env),
1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          static_cast<int>(blocks_.size()), reason);
1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (env->control != nullptr && FLAG_trace_wasm_decoder) {
1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TRACE(", control = ");
1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      compiler::WasmGraphBuilder::PrintDebugName(env->control);
1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("\n");
1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ssa_env_ = env;
1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_) {
1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      builder_->set_control_ptr(&env->control);
1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      builder_->set_effect_ptr(&env->effect);
1123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Goto(SsaEnv* from, SsaEnv* to) {
1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(to);
1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!from->go()) return;
1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (to->state) {
1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SsaEnv::kUnreachable: {  // Overwrite destination.
1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->state = SsaEnv::kReached;
1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->locals = from->locals;
1133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->control = from->control;
1134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->effect = from->effect;
1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SsaEnv::kReached: {  // Create a new merge.
1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->state = SsaEnv::kMerged;
1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!builder_) break;
1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge control.
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* controls[] = {to->control, from->control};
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* merge = builder_->Merge(2, controls);
1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        to->control = merge;
1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge effects.
1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (from->effect != to->effect) {
1146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* effects[] = {to->effect, from->effect, merge};
1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          to->effect = builder_->EffectPhi(2, effects, merge);
1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge SSA values.
1150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* a = to->locals[i];
1152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* b = from->locals[i];
1153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (a != b) {
1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode* vals[] = {a, b};
1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            to->locals[i] =
1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                builder_->Phi(function_env_->GetLocalType(i), 2, vals, merge);
1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SsaEnv::kMerged: {
1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!builder_) break;
1163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        TFNode* merge = to->control;
1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Extend the existing merge.
1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        builder_->AppendToMerge(merge, from->control);
1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge effects.
1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (builder_->IsPhiWithMerge(to->effect, merge)) {
1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          builder_->AppendToPhi(merge, to->effect, from->effect);
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (to->effect != from->effect) {
1170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint32_t count = builder_->InputCount(merge);
1171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode** effects = builder_->Buffer(count);
1172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          for (uint32_t j = 0; j < count - 1; j++) {
1173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            effects[j] = to->effect;
1174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          effects[count - 1] = from->effect;
1176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          to->effect = builder_->EffectPhi(count, effects, merge);
1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // Merge locals.
1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* tnode = to->locals[i];
1181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          TFNode* fnode = from->locals[i];
1182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          if (builder_->IsPhiWithMerge(tnode, merge)) {
1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            builder_->AppendToPhi(merge, tnode, fnode);
1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (tnode != fnode) {
1185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            uint32_t count = builder_->InputCount(merge);
1186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            TFNode** vals = builder_->Buffer(count);
1187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            for (uint32_t j = 0; j < count - 1; j++) {
1188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              vals[j] = tnode;
1189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
1190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            vals[count - 1] = fnode;
1191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            to->locals[i] = builder_->Phi(function_env_->GetLocalType(i), count,
1192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          vals, merge);
1193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          }
1194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
1198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
1199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return from->Kill();
1201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TFNode* CreateOrMergeIntoPhi(LocalType type, TFNode* merge, TFNode* tnode,
1204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               TFNode* fnode) {
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_->IsPhiWithMerge(tnode, merge)) {
1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      builder_->AppendToPhi(merge, tnode, fnode);
1207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (tnode != fnode) {
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t count = builder_->InputCount(merge);
1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TFNode** vals = builder_->Buffer(count);
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      vals[count - 1] = fnode;
1212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return builder_->Phi(type, count, vals, merge);
1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return tnode;
1215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BuildInfiniteLoop() {
1218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (ssa_env_->go()) {
1219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrepareForLoop(ssa_env_);
1220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SsaEnv* cont_env = ssa_env_;
1221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ssa_env_ = Split(ssa_env_);
1222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ssa_env_->state = SsaEnv::kReached;
1223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Goto(ssa_env_, cont_env);
1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PrepareForLoop(SsaEnv* env) {
1228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (env->go()) {
1229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      env->state = SsaEnv::kMerged;
1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (builder_) {
1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        env->control = builder_->Loop(env->control);
1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        env->effect = builder_->EffectPhi(1, &env->effect, env->control);
1233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        builder_->Terminate(env->effect, env->control);
1234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          env->locals[i] = builder_->Phi(function_env_->GetLocalType(i), 1,
1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         &env->locals[i], env->control);
1237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
1238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create a complete copy of the {from}.
1243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* Split(SsaEnv* from) {
1244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(from);
1245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t size = sizeof(TFNode*) * EnvironmentCount();
1247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->control = from->control;
1248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->effect = from->effect;
1249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->state = from->state == SsaEnv::kUnreachable ? SsaEnv::kUnreachable
1250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                        : SsaEnv::kReached;
1251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (from->go()) {
1253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->state = SsaEnv::kReached;
1254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->locals =
1255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
1256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      memcpy(result->locals, from->locals, size);
1257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->state = SsaEnv::kUnreachable;
1259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result->locals = nullptr;
1260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create a copy of {from} that steals its state and leaves {from}
1266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // unreachable.
1267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* Steal(SsaEnv* from) {
1268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(from);
1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!from->go()) return UnreachableEnv();
1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->state = SsaEnv::kReached;
1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->locals = from->locals;
1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->control = from->control;
1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->effect = from->effect;
1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    from->Kill(SsaEnv::kUnreachable);
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create an unreachable environment.
1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SsaEnv* UnreachableEnv() {
1281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->state = SsaEnv::kUnreachable;
1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->control = nullptr;
1284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->effect = nullptr;
1285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result->locals = nullptr;
1286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load an operand at [pc + 1].
1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename V>
1291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V Operand(const byte* pc) {
1292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((limit_ - pc) < static_cast<int>(1 + sizeof(V))) {
1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      const char* msg = "Expected operand following opcode";
1294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      switch (sizeof(V)) {
1295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case 1:
1296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          msg = "Expected 1-byte operand following opcode";
1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case 2:
1299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          msg = "Expected 2-byte operand following opcode";
1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        case 4:
1302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          msg = "Expected 4-byte operand following opcode";
1303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        default:
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          break;
1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      error(pc, msg);
1308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return -1;
1309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return *reinterpret_cast<const V*>(pc + 1);
1311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int EnvironmentCount() {
1314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (builder_) return static_cast<int>(function_env_->GetLocalCount());
1315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 0;  // if we aren't building a graph, don't bother with SSA renaming.
1316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LocalType LocalOperand(const byte* pc, uint32_t* index, int* length) {
1319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *index = UnsignedLEB128Operand(pc, length);
1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (function_env_->IsValidLocal(*index)) {
1321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return function_env_->GetLocalType(*index);
1322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    error(pc, "invalid local variable index");
1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kAstStmt;
1325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LocalType GlobalOperand(const byte* pc, uint32_t* index, int* length) {
1328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *index = UnsignedLEB128Operand(pc, length);
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (function_env_->module->IsValidGlobal(*index)) {
1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return WasmOpcodes::LocalTypeFor(
1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          function_env_->module->GetGlobalType(*index));
1332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    error(pc, "invalid global variable index");
1334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kAstStmt;
1335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FunctionSig* FunctionSigOperand(const byte* pc, uint32_t* index,
1338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                  int* length) {
1339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *index = UnsignedLEB128Operand(pc, length);
1340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (function_env_->module->IsValidFunction(*index)) {
1341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return function_env_->module->GetFunctionSignature(*index);
1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    error(pc, "invalid function index");
1344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return nullptr;
1345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FunctionSig* SigOperand(const byte* pc, uint32_t* index, int* length) {
1348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *index = UnsignedLEB128Operand(pc, length);
1349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (function_env_->module->IsValidSignature(*index)) {
1350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return function_env_->module->GetSignature(*index);
1351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    error(pc, "invalid signature index");
1353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return nullptr;
1354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t UnsignedLEB128Operand(const byte* pc, int* length) {
1357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint32_t result = 0;
1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReadUnsignedLEB128ErrorCode error_code =
1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ReadUnsignedLEB128Operand(pc + 1, limit_, length, &result);
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (error_code == kInvalidLEB128) error(pc, "invalid LEB128 varint");
1361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (error_code == kMissingLEB128) error(pc, "expected LEB128 varint");
1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    (*length)++;
1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return result;
1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void MemoryAccessOperand(const byte* pc, int* length, uint32_t* offset) {
1367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    byte bitfield = Operand<uint8_t>(pc);
1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (MemoryAccess::OffsetField::decode(bitfield)) {
1369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      *offset = UnsignedLEB128Operand(pc + 1, length);
1370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (*length)++;  // to account for the memory access byte
1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      *offset = 0;
1373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      *length = 2;
1374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual void onFirstError() {
1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    limit_ = start_;     // Terminate decoding loop.
1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    builder_ = nullptr;  // Don't build any more nodes.
1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG
1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PrintStackForDebugging();
1382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG
1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PrintStackForDebugging() { PrintProduction(0); }
1387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void PrintProduction(size_t depth) {
1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (depth >= stack_.size()) return;
1390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Production* p = &stack_[depth];
1391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (size_t d = 0; d < depth; d++) PrintF("  ");
1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PrintF("@%d %s [%d]\n", static_cast<int>(p->tree->pc - start_),
1394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           WasmOpcodes::OpcodeName(p->opcode()), p->tree->count);
1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = 0; i < p->index; i++) {
1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Tree* child = p->tree->children[i];
1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (size_t d = 0; d <= depth; d++) PrintF("  ");
1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrintF("@%d %s [%d]", static_cast<int>(child->pc - start_),
1399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             WasmOpcodes::OpcodeName(child->opcode()), child->count);
1400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (child->node) {
1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        PrintF(" => TF");
1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        compiler::WasmGraphBuilder::PrintDebugName(child->node);
1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PrintF("\n");
1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PrintProduction(depth + 1);
1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
1409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTreeResult VerifyWasmCode(FunctionEnv* env, const byte* base, const byte* start,
1413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          const byte* end) {
1414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Zone zone;
1415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LR_WasmDecoder decoder(&zone, nullptr);
1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TreeResult result = decoder.Decode(env, base, start, end);
1417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return result;
1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, const byte* base,
1422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        const byte* start, const byte* end) {
1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Zone zone;
1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LR_WasmDecoder decoder(&zone, builder);
1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TreeResult result = decoder.Decode(env, base, start, end);
1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return result;
1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstd::ostream& operator<<(std::ostream& os, const Tree& tree) {
1431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (tree.pc == nullptr) {
1432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    os << "null";
1433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return os;
1434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode()));
1436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (tree.count > 0) os << "(";
1437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (uint32_t i = 0; i < tree.count; i++) {
1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (i > 0) os << ", ";
1439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    os << *tree.children[i];
1440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (tree.count > 0) os << ")";
1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return os;
1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte* pc,
1447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                      const byte* limit,
1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                      int* length,
1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                      uint32_t* result) {
1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  *result = 0;
1451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* ptr = pc;
1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* end = pc + 5;  // maximum 5 bytes.
1453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (end > limit) end = limit;
1454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int shift = 0;
1455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  byte b = 0;
1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  while (ptr < end) {
1457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    b = *ptr++;
1458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *result = *result | ((b & 0x7F) << shift);
1459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if ((b & 0x80) == 0) break;
1460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    shift += 7;
1461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_LE(ptr - pc, 5);
1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  *length = static_cast<int>(ptr - pc);
1464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (ptr == end && (b & 0x80)) {
1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kInvalidLEB128;
1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (*length == 0) {
1467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kMissingLEB128;
1468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kNoError;
1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint OpcodeLength(const byte* pc) {
1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (static_cast<WasmOpcode>(*pc)) {
1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_OPCODE_CASE
1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprI8Const:
1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprBlock:
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprLoop:
1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprBr:
1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprBrIf:
1486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 2;
1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprI32Const:
1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprF32Const:
1489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 5;
1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprI64Const:
1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprF64Const:
1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 9;
1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprStoreGlobal:
1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprSetLocal:
1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprLoadGlobal:
1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprCallFunction:
1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprCallIndirect:
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprGetLocal: {
1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int length;
1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t result = 0;
1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ReadUnsignedLEB128Operand(pc + 1, pc + 6, &length, &result);
1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 1 + length;
1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprTableSwitch: {
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint16_t table_count = *reinterpret_cast<const uint16_t*>(pc + 3);
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 5 + table_count * 2;
1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    default:
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 1;
1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochint OpcodeArity(FunctionEnv* env, const byte* pc) {
1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_ARITY(name, ...)                          \
1517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const LocalType kTypes_##name[] = {__VA_ARGS__}; \
1518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kArity_##name =                        \
1519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      static_cast<int>(arraysize(kTypes_##name) - 1);
1520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FOREACH_SIGNATURE(DECLARE_ARITY);
1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_ARITY
1523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  switch (static_cast<WasmOpcode>(*pc)) {
1525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprI8Const:
1526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprI32Const:
1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprI64Const:
1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprF64Const:
1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprF32Const:
1530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprGetLocal:
1531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprLoadGlobal:
1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprNop:
1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprUnreachable:
1534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 0;
1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprBr:
1537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprStoreGlobal:
1538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprSetLocal:
1539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 1;
1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprIf:
1542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprBrIf:
1543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 2;
1544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprIfElse:
1545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprSelect:
1546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 3;
1547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprBlock:
1548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprLoop:
1549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return *(pc + 1);
1550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprCallFunction: {
1552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int index = *(pc + 1);
1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return static_cast<int>(
1554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          env->module->GetFunctionSignature(index)->parameter_count());
1555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprCallIndirect: {
1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int index = *(pc + 1);
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 1 + static_cast<int>(
1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     env->module->GetSignature(index)->parameter_count());
1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprReturn:
1562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return static_cast<int>(env->sig->return_count());
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case kExprTableSwitch: {
1564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint16_t case_count = *reinterpret_cast<const uint16_t*>(pc + 1);
1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 1 + case_count;
1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DECLARE_OPCODE_CASE(name, opcode, sig) \
1569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  case kExpr##name:                            \
1570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kArity_##sig;
1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
1575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
1576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef DECLARE_OPCODE_CASE
1577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  UNREACHABLE();
1579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return 0;
1580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace wasm
1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1584