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