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