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#ifndef V8_WASM_DECODER_H_ 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_WASM_DECODER_H_ 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory> 9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 10bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/base/compiler-specific.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/flags.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/signature.h" 13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/utils.h" 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-result.h" 15f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/zone/zone-containers.h" 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 { 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal { 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace wasm { 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...) \ 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch do { \ 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } while (false) 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...) 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A helper utility to decode bytes, integers, fields, varints, etc, from 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// a buffer of bytes. 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Decoder { 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public: 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Decoder(const byte* start, const byte* end) 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : start_(start), 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pc_(start), 3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch end_(end), 3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch error_pc_(nullptr), 3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch error_pt_(nullptr) {} 4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Decoder(const byte* start, const byte* pc, const byte* end) 4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : start_(start), 4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch pc_(pc), 43109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch end_(end), 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error_pc_(nullptr), 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error_pt_(nullptr) {} 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch virtual ~Decoder() {} 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch inline bool check(const byte* base, unsigned offset, unsigned length, 5013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const char* msg) { 51109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK_GE(base, start_); 5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if ((base + offset + length) > end_) { 53bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch error(base, base + offset, "%s", msg); 54109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return false; 55109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 56109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return true; 57109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 58109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 59109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads a single 8-bit byte, reporting an error if out of bounds. 6013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch inline uint8_t checked_read_u8(const byte* base, unsigned offset, 61109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const char* msg = "expected 1 byte") { 62109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return check(base, offset, 1, msg) ? base[offset] : 0; 63109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 64109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 65109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads 16-bit word, reporting an error if out of bounds. 6613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch inline uint16_t checked_read_u16(const byte* base, unsigned offset, 67109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const char* msg = "expected 2 bytes") { 68109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return check(base, offset, 2, msg) ? read_u16(base + offset) : 0; 69109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 70109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 71109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads 32-bit word, reporting an error if out of bounds. 7213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch inline uint32_t checked_read_u32(const byte* base, unsigned offset, 73109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const char* msg = "expected 4 bytes") { 74109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return check(base, offset, 4, msg) ? read_u32(base + offset) : 0; 75109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 76109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 77109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads 64-bit word, reporting an error if out of bounds. 7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch inline uint64_t checked_read_u64(const byte* base, unsigned offset, 79109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const char* msg = "expected 8 bytes") { 80109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return check(base, offset, 8, msg) ? read_u64(base + offset) : 0; 81109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 82109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Reads a variable-length unsigned integer (little endian). 8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint32_t checked_read_u32v(const byte* base, unsigned offset, 8513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch unsigned* length, 863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const char* msg = "expected LEB32") { 873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return checked_read_leb<uint32_t, false>(base, offset, length, msg); 883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 89109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Reads a variable-length signed integer (little endian). 9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int32_t checked_read_i32v(const byte* base, unsigned offset, unsigned* length, 923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const char* msg = "expected SLEB32") { 933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch uint32_t result = 943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch checked_read_leb<uint32_t, true>(base, offset, length, msg); 953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (*length == 5) return bit_cast<int32_t>(result); 963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (*length > 0) { 973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int shift = 32 - 7 * *length; 983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Perform sign extension. 993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return bit_cast<int32_t>(result << shift) >> shift; 100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 0; 1023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Reads a variable-length unsigned integer (little endian). 10513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint64_t checked_read_u64v(const byte* base, unsigned offset, 10613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch unsigned* length, 1073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const char* msg = "expected LEB64") { 1083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return checked_read_leb<uint64_t, false>(base, offset, length, msg); 1093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 1103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 1113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Reads a variable-length signed integer (little endian). 11213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch int64_t checked_read_i64v(const byte* base, unsigned offset, unsigned* length, 1133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const char* msg = "expected SLEB64") { 1143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch uint64_t result = 1153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch checked_read_leb<uint64_t, true>(base, offset, length, msg); 1163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (*length == 10) return bit_cast<int64_t>(result); 1173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (*length > 0) { 1183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int shift = 64 - 7 * *length; 1193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Perform sign extension. 1203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return bit_cast<int64_t>(result << shift) >> shift; 121109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 0; 123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 125109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads a single 16-bit unsigned integer (little endian). 126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch inline uint16_t read_u16(const byte* ptr) { 127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(ptr >= start_ && (ptr + 2) <= end_); 128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ReadLittleEndianValue<uint16_t>(ptr); 129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads a single 32-bit unsigned integer (little endian). 132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch inline uint32_t read_u32(const byte* ptr) { 133109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(ptr >= start_ && (ptr + 4) <= end_); 134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ReadLittleEndianValue<uint32_t>(ptr); 135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reads a single 64-bit unsigned integer (little endian). 138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch inline uint64_t read_u64(const byte* ptr) { 139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(ptr >= start_ && (ptr + 8) <= end_); 140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ReadLittleEndianValue<uint64_t>(ptr); 141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reads a 8-bit unsigned integer (byte) and advances {pc_}. 144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uint8_t consume_u8(const char* name = nullptr) { 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), 146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch name ? name : "uint8_t"); 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (checkAvailable(1)) { 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch byte val = *(pc_++); 149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE("%02x = %d\n", val, val); 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return val; 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return traceOffEnd<uint8_t>(); 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reads a 16-bit unsigned integer (little endian) and advances {pc_}. 156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uint16_t consume_u16(const char* name = nullptr) { 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch name ? name : "uint16_t"); 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (checkAvailable(2)) { 160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uint16_t val = read_u16(pc_); 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val); 162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pc_ += 2; 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return val; 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return traceOffEnd<uint16_t>(); 166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}. 169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uint32_t consume_u32(const char* name = nullptr) { 170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), 171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch name ? name : "uint32_t"); 172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (checkAvailable(4)) { 173109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch uint32_t val = read_u32(pc_); 174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val); 175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pc_ += 4; 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return val; 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 178109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return traceOffEnd<uint32_t>(); 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}. 18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch uint32_t consume_u32v(const char* name = nullptr) { 183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return consume_leb<uint32_t, false>(name); 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}. 187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int32_t consume_i32v(const char* name = nullptr) { 188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return consume_leb<int32_t, true>(name); 189f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 190f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 191f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Consume {size} bytes and send them to the bit bucket, advancing {pc_}. 192f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void consume_bytes(uint32_t size, const char* name = "skip") { 19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#if DEBUG 19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (name) { 19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Only trace if the name is not null. 19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TRACE(" +%d %-20s: %d bytes\n", static_cast<int>(pc_ - start_), name, 19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch size); 19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif 2003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (checkAvailable(size)) { 2013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch pc_ += size; 2023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch pc_ = end_; 2043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 2053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 2063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check that at least {size} bytes exist between {pc_} and {end_}. 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool checkAvailable(int size) { 2093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch intptr_t pc_overflow_value = std::numeric_limits<intptr_t>::max() - size; 2103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (size < 0 || (intptr_t)pc_ > pc_overflow_value) { 2113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch error(pc_, nullptr, "reading %d bytes would underflow/overflow", size); 2123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return false; 21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (pc_ < start_ || end_ < (pc_ + size)) { 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error(pc_, nullptr, "expected %d bytes, fell off end", size); 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return false; 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return true; 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void error(const char* msg) { error(pc_, nullptr, "%s", msg); } 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 223bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void error(const byte* pc, const char* msg) { error(pc, nullptr, "%s", msg); } 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Sets internal error state. 226bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch void PRINTF_FORMAT(4, 5) 227bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch error(const byte* pc, const byte* pt, const char* format, ...) { 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (ok()) { 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if DEBUG 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_wasm_break_on_decoder_error) { 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::OS::DebugBreak(); 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kMaxErrorMsg = 256; 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch char* buffer = new char[kMaxErrorMsg]; 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch va_list arguments; 237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch va_start(arguments, format); 238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments); 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch va_end(arguments); 240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch error_msg_.reset(buffer); 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error_pc_ = pc; 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error_pt_ = pt; 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch onFirstError(); 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Behavior triggered on first error, overridden in subclasses. 248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch virtual void onFirstError() {} 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Debugging helper to print bytes up to the end. 251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch template <typename T> 252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch T traceOffEnd() { 253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch T t = 0; 25462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (const byte* ptr = pc_; ptr < end_; ptr++) { 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE("%02x ", *ptr); 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE("<end>\n"); 25862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch pc_ = end_; 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return t; 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Converts the given value to a {Result}, copying the error if necessary. 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch template <typename T> 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Result<T> toResult(T val) { 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Result<T> result; 266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (failed()) { 2673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch TRACE("Result error: %s\n", error_msg_.get()); 268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result.error_code = kError; 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result.start = start_; 270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result.error_pc = error_pc_; 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result.error_pt = error_pt_; 2723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // transfer ownership of the error to the result. 273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch result.error_msg.reset(error_msg_.release()); 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result.error_code = kSuccess; 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 27713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch result.val = std::move(val); 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return result; 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Resets the boundaries of this decoder. 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Reset(const byte* start, const byte* end) { 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch start_ = start; 284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch pc_ = start; 285109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch end_ = end; 286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error_pc_ = nullptr; 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch error_pt_ = nullptr; 288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch error_msg_.reset(); 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 291c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool ok() const { return error_msg_ == nullptr; } 292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool failed() const { return !ok(); } 29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool more() const { return pc_ < end_; } 2943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const byte* start() const { return start_; } 29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const byte* pc() const { return pc_; } 29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch uint32_t pc_offset() const { return static_cast<uint32_t>(pc_ - start_); } 29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const byte* end() const { return end_; } 299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch protected: 301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const byte* start_; 302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const byte* pc_; 303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const byte* end_; 304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const byte* error_pc_; 305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const byte* error_pt_; 306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch std::unique_ptr<char[]> error_msg_; 3073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch private: 3093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch template <typename IntType, bool is_signed> 31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length, 3113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const char* msg) { 3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!check(base, offset, 1, msg)) { 3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch *length = 0; 3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 0; 3153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; 3183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const byte* ptr = base + offset; 3193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const byte* end = ptr + kMaxLength; 32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (end > end_) end = end_; 3213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int shift = 0; 3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch byte b = 0; 3233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IntType result = 0; 3243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch while (ptr < end) { 3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch b = *ptr++; 3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch result = result | (static_cast<IntType>(b & 0x7F) << shift); 3273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((b & 0x80) == 0) break; 3283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shift += 7; 3293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_LE(ptr - (base + offset), kMaxLength); 33113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch *length = static_cast<unsigned>(ptr - (base + offset)); 3323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (ptr == end) { 3333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Check there are no bits set beyond the bitwidth of {IntType}. 3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8); 3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch const byte kExtraBitsMask = 3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF); 3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int extra_bits_value; 3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (is_signed) { 3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // A signed-LEB128 must sign-extend the final byte, excluding its 3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // most-signifcant bit. e.g. for a 32-bit LEB128: 3413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // kExtraBits = 4 3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // kExtraBitsMask = 0xf0 3433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If b is 0x0f, the value is negative, so extra_bits_value is 0x70. 3443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // If b is 0x03, the value is positive, so extra_bits_value is 0x00. 3453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch extra_bits_value = (static_cast<int8_t>(b << kExtraBits) >> 8) & 3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch kExtraBitsMask & ~0x80; 3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } else { 3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch extra_bits_value = 0; 3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (*length == kMaxLength && (b & kExtraBitsMask) != extra_bits_value) { 3513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch error(base, ptr, "extra bits in varint"); 3523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 0; 3533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if ((b & 0x80) != 0) { 355bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch error(base, ptr, "%s", msg); 3563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return 0; 3573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return result; 3603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 361c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 362c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch template <typename IntType, bool is_signed> 363c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntType consume_leb(const char* name = nullptr) { 364c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), 365c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch name ? name : "varint"); 366c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (checkAvailable(1)) { 367c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; 368c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const byte* pos = pc_; 369c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch const byte* end = pc_ + kMaxLength; 37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (end > end_) end = end_; 371c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 372c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch IntType result = 0; 373c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int shift = 0; 374c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch byte b = 0; 375c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch while (pc_ < end) { 376c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch b = *pc_++; 377c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE("%02x ", b); 378c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result = result | (static_cast<IntType>(b & 0x7F) << shift); 379c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch shift += 7; 380c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if ((b & 0x80) == 0) break; 381c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 382c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 383c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int length = static_cast<int>(pc_ - pos); 384c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (pc_ == end && (b & 0x80)) { 38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TRACE("\n"); 386c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch error(pc_ - 1, "varint too large"); 387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (length == 0) { 38862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TRACE("\n"); 389c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch error(pc_, "varint of length 0"); 390c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (is_signed) { 391c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (length < kMaxLength) { 392c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch int sign_ext_shift = 8 * sizeof(IntType) - shift; 393c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Perform sign extension. 394c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch result = (result << sign_ext_shift) >> sign_ext_shift; 395c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 396c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE("= %" PRIi64 "\n", static_cast<int64_t>(result)); 397c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 398c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE("= %" PRIu64 "\n", static_cast<uint64_t>(result)); 399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return result; 401c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 402c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return traceOffEnd<uint32_t>(); 403c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef TRACE 407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace wasm 408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif // V8_WASM_DECODER_H_ 412