11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#if !V8_ENABLE_WEBASSEMBLY
61cb0ef41Sopenharmony_ci#error This header should only be included if WebAssembly is enabled.
71cb0ef41Sopenharmony_ci#endif  // !V8_ENABLE_WEBASSEMBLY
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
101cb0ef41Sopenharmony_ci#define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci// Do only include this header for implementing new Interface of the
131cb0ef41Sopenharmony_ci// WasmFullDecoder.
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci#include <inttypes.h>
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci#include "src/base/platform/elapsed-timer.h"
181cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h"
191cb0ef41Sopenharmony_ci#include "src/base/small-vector.h"
201cb0ef41Sopenharmony_ci#include "src/base/strings.h"
211cb0ef41Sopenharmony_ci#include "src/utils/bit-vector.h"
221cb0ef41Sopenharmony_ci#include "src/wasm/decoder.h"
231cb0ef41Sopenharmony_ci#include "src/wasm/function-body-decoder.h"
241cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h"
251cb0ef41Sopenharmony_ci#include "src/wasm/wasm-features.h"
261cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h"
271cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h"
281cb0ef41Sopenharmony_ci#include "src/wasm/wasm-opcodes.h"
291cb0ef41Sopenharmony_ci#include "src/wasm/wasm-subtyping.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cinamespace v8 {
321cb0ef41Sopenharmony_cinamespace internal {
331cb0ef41Sopenharmony_cinamespace wasm {
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cistruct WasmGlobal;
361cb0ef41Sopenharmony_cistruct WasmTag;
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci#define TRACE(...)                                    \
391cb0ef41Sopenharmony_ci  do {                                                \
401cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
411cb0ef41Sopenharmony_ci  } while (false)
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci#define TRACE_INST_FORMAT "  @%-8d #%-30s|"
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci// Return the evaluation of `condition` if validate==true, DCHECK that it's
461cb0ef41Sopenharmony_ci// true and always return true otherwise.
471cb0ef41Sopenharmony_ci#define VALIDATE(condition)                \
481cb0ef41Sopenharmony_ci  (validate ? V8_LIKELY(condition) : [&] { \
491cb0ef41Sopenharmony_ci    DCHECK(condition);                     \
501cb0ef41Sopenharmony_ci    return true;                           \
511cb0ef41Sopenharmony_ci  }())
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci#define CHECK_PROTOTYPE_OPCODE(feat)                                         \
541cb0ef41Sopenharmony_ci  DCHECK(this->module_->origin == kWasmOrigin);                              \
551cb0ef41Sopenharmony_ci  if (!VALIDATE(this->enabled_.has_##feat())) {                              \
561cb0ef41Sopenharmony_ci    this->DecodeError(                                                       \
571cb0ef41Sopenharmony_ci        "Invalid opcode 0x%02x (enable with --experimental-wasm-" #feat ")", \
581cb0ef41Sopenharmony_ci        opcode);                                                             \
591cb0ef41Sopenharmony_ci    return 0;                                                                \
601cb0ef41Sopenharmony_ci  }                                                                          \
611cb0ef41Sopenharmony_ci  this->detected_->Add(kFeature_##feat);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci#define ATOMIC_OP_LIST(V)                \
641cb0ef41Sopenharmony_ci  V(AtomicNotify, Uint32)                \
651cb0ef41Sopenharmony_ci  V(I32AtomicWait, Uint32)               \
661cb0ef41Sopenharmony_ci  V(I64AtomicWait, Uint64)               \
671cb0ef41Sopenharmony_ci  V(I32AtomicLoad, Uint32)               \
681cb0ef41Sopenharmony_ci  V(I64AtomicLoad, Uint64)               \
691cb0ef41Sopenharmony_ci  V(I32AtomicLoad8U, Uint8)              \
701cb0ef41Sopenharmony_ci  V(I32AtomicLoad16U, Uint16)            \
711cb0ef41Sopenharmony_ci  V(I64AtomicLoad8U, Uint8)              \
721cb0ef41Sopenharmony_ci  V(I64AtomicLoad16U, Uint16)            \
731cb0ef41Sopenharmony_ci  V(I64AtomicLoad32U, Uint32)            \
741cb0ef41Sopenharmony_ci  V(I32AtomicAdd, Uint32)                \
751cb0ef41Sopenharmony_ci  V(I32AtomicAdd8U, Uint8)               \
761cb0ef41Sopenharmony_ci  V(I32AtomicAdd16U, Uint16)             \
771cb0ef41Sopenharmony_ci  V(I64AtomicAdd, Uint64)                \
781cb0ef41Sopenharmony_ci  V(I64AtomicAdd8U, Uint8)               \
791cb0ef41Sopenharmony_ci  V(I64AtomicAdd16U, Uint16)             \
801cb0ef41Sopenharmony_ci  V(I64AtomicAdd32U, Uint32)             \
811cb0ef41Sopenharmony_ci  V(I32AtomicSub, Uint32)                \
821cb0ef41Sopenharmony_ci  V(I64AtomicSub, Uint64)                \
831cb0ef41Sopenharmony_ci  V(I32AtomicSub8U, Uint8)               \
841cb0ef41Sopenharmony_ci  V(I32AtomicSub16U, Uint16)             \
851cb0ef41Sopenharmony_ci  V(I64AtomicSub8U, Uint8)               \
861cb0ef41Sopenharmony_ci  V(I64AtomicSub16U, Uint16)             \
871cb0ef41Sopenharmony_ci  V(I64AtomicSub32U, Uint32)             \
881cb0ef41Sopenharmony_ci  V(I32AtomicAnd, Uint32)                \
891cb0ef41Sopenharmony_ci  V(I64AtomicAnd, Uint64)                \
901cb0ef41Sopenharmony_ci  V(I32AtomicAnd8U, Uint8)               \
911cb0ef41Sopenharmony_ci  V(I32AtomicAnd16U, Uint16)             \
921cb0ef41Sopenharmony_ci  V(I64AtomicAnd8U, Uint8)               \
931cb0ef41Sopenharmony_ci  V(I64AtomicAnd16U, Uint16)             \
941cb0ef41Sopenharmony_ci  V(I64AtomicAnd32U, Uint32)             \
951cb0ef41Sopenharmony_ci  V(I32AtomicOr, Uint32)                 \
961cb0ef41Sopenharmony_ci  V(I64AtomicOr, Uint64)                 \
971cb0ef41Sopenharmony_ci  V(I32AtomicOr8U, Uint8)                \
981cb0ef41Sopenharmony_ci  V(I32AtomicOr16U, Uint16)              \
991cb0ef41Sopenharmony_ci  V(I64AtomicOr8U, Uint8)                \
1001cb0ef41Sopenharmony_ci  V(I64AtomicOr16U, Uint16)              \
1011cb0ef41Sopenharmony_ci  V(I64AtomicOr32U, Uint32)              \
1021cb0ef41Sopenharmony_ci  V(I32AtomicXor, Uint32)                \
1031cb0ef41Sopenharmony_ci  V(I64AtomicXor, Uint64)                \
1041cb0ef41Sopenharmony_ci  V(I32AtomicXor8U, Uint8)               \
1051cb0ef41Sopenharmony_ci  V(I32AtomicXor16U, Uint16)             \
1061cb0ef41Sopenharmony_ci  V(I64AtomicXor8U, Uint8)               \
1071cb0ef41Sopenharmony_ci  V(I64AtomicXor16U, Uint16)             \
1081cb0ef41Sopenharmony_ci  V(I64AtomicXor32U, Uint32)             \
1091cb0ef41Sopenharmony_ci  V(I32AtomicExchange, Uint32)           \
1101cb0ef41Sopenharmony_ci  V(I64AtomicExchange, Uint64)           \
1111cb0ef41Sopenharmony_ci  V(I32AtomicExchange8U, Uint8)          \
1121cb0ef41Sopenharmony_ci  V(I32AtomicExchange16U, Uint16)        \
1131cb0ef41Sopenharmony_ci  V(I64AtomicExchange8U, Uint8)          \
1141cb0ef41Sopenharmony_ci  V(I64AtomicExchange16U, Uint16)        \
1151cb0ef41Sopenharmony_ci  V(I64AtomicExchange32U, Uint32)        \
1161cb0ef41Sopenharmony_ci  V(I32AtomicCompareExchange, Uint32)    \
1171cb0ef41Sopenharmony_ci  V(I64AtomicCompareExchange, Uint64)    \
1181cb0ef41Sopenharmony_ci  V(I32AtomicCompareExchange8U, Uint8)   \
1191cb0ef41Sopenharmony_ci  V(I32AtomicCompareExchange16U, Uint16) \
1201cb0ef41Sopenharmony_ci  V(I64AtomicCompareExchange8U, Uint8)   \
1211cb0ef41Sopenharmony_ci  V(I64AtomicCompareExchange16U, Uint16) \
1221cb0ef41Sopenharmony_ci  V(I64AtomicCompareExchange32U, Uint32)
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci#define ATOMIC_STORE_OP_LIST(V) \
1251cb0ef41Sopenharmony_ci  V(I32AtomicStore, Uint32)     \
1261cb0ef41Sopenharmony_ci  V(I64AtomicStore, Uint64)     \
1271cb0ef41Sopenharmony_ci  V(I32AtomicStore8U, Uint8)    \
1281cb0ef41Sopenharmony_ci  V(I32AtomicStore16U, Uint16)  \
1291cb0ef41Sopenharmony_ci  V(I64AtomicStore8U, Uint8)    \
1301cb0ef41Sopenharmony_ci  V(I64AtomicStore16U, Uint16)  \
1311cb0ef41Sopenharmony_ci  V(I64AtomicStore32U, Uint32)
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci// Decoder error with explicit PC and format arguments.
1341cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate, typename... Args>
1351cb0ef41Sopenharmony_civoid DecodeError(Decoder* decoder, const byte* pc, const char* str,
1361cb0ef41Sopenharmony_ci                 Args&&... args) {
1371cb0ef41Sopenharmony_ci  CHECK(validate == Decoder::kFullValidation ||
1381cb0ef41Sopenharmony_ci        validate == Decoder::kBooleanValidation);
1391cb0ef41Sopenharmony_ci  STATIC_ASSERT(sizeof...(Args) > 0);
1401cb0ef41Sopenharmony_ci  if (validate == Decoder::kBooleanValidation) {
1411cb0ef41Sopenharmony_ci    decoder->MarkError();
1421cb0ef41Sopenharmony_ci  } else {
1431cb0ef41Sopenharmony_ci    decoder->errorf(pc, str, std::forward<Args>(args)...);
1441cb0ef41Sopenharmony_ci  }
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci// Decoder error with explicit PC and no format arguments.
1481cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
1491cb0ef41Sopenharmony_civoid DecodeError(Decoder* decoder, const byte* pc, const char* str) {
1501cb0ef41Sopenharmony_ci  CHECK(validate == Decoder::kFullValidation ||
1511cb0ef41Sopenharmony_ci        validate == Decoder::kBooleanValidation);
1521cb0ef41Sopenharmony_ci  if (validate == Decoder::kBooleanValidation) {
1531cb0ef41Sopenharmony_ci    decoder->MarkError();
1541cb0ef41Sopenharmony_ci  } else {
1551cb0ef41Sopenharmony_ci    decoder->error(pc, str);
1561cb0ef41Sopenharmony_ci  }
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci// Decoder error without explicit PC, but with format arguments.
1601cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate, typename... Args>
1611cb0ef41Sopenharmony_civoid DecodeError(Decoder* decoder, const char* str, Args&&... args) {
1621cb0ef41Sopenharmony_ci  CHECK(validate == Decoder::kFullValidation ||
1631cb0ef41Sopenharmony_ci        validate == Decoder::kBooleanValidation);
1641cb0ef41Sopenharmony_ci  STATIC_ASSERT(sizeof...(Args) > 0);
1651cb0ef41Sopenharmony_ci  if (validate == Decoder::kBooleanValidation) {
1661cb0ef41Sopenharmony_ci    decoder->MarkError();
1671cb0ef41Sopenharmony_ci  } else {
1681cb0ef41Sopenharmony_ci    decoder->errorf(str, std::forward<Args>(args)...);
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci// Decoder error without explicit PC and without format arguments.
1731cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
1741cb0ef41Sopenharmony_civoid DecodeError(Decoder* decoder, const char* str) {
1751cb0ef41Sopenharmony_ci  CHECK(validate == Decoder::kFullValidation ||
1761cb0ef41Sopenharmony_ci        validate == Decoder::kBooleanValidation);
1771cb0ef41Sopenharmony_ci  if (validate == Decoder::kBooleanValidation) {
1781cb0ef41Sopenharmony_ci    decoder->MarkError();
1791cb0ef41Sopenharmony_ci  } else {
1801cb0ef41Sopenharmony_ci    decoder->error(str);
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_cinamespace value_type_reader {
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci// If {module} is not null, the read index will be checked against the module's
1871cb0ef41Sopenharmony_ci// type capacity.
1881cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
1891cb0ef41Sopenharmony_ciHeapType read_heap_type(Decoder* decoder, const byte* pc,
1901cb0ef41Sopenharmony_ci                        uint32_t* const length, const WasmModule* module,
1911cb0ef41Sopenharmony_ci                        const WasmFeatures& enabled) {
1921cb0ef41Sopenharmony_ci  int64_t heap_index = decoder->read_i33v<validate>(pc, length, "heap type");
1931cb0ef41Sopenharmony_ci  if (heap_index < 0) {
1941cb0ef41Sopenharmony_ci    int64_t min_1_byte_leb128 = -64;
1951cb0ef41Sopenharmony_ci    if (!VALIDATE(heap_index >= min_1_byte_leb128)) {
1961cb0ef41Sopenharmony_ci      DecodeError<validate>(decoder, pc, "Unknown heap type %" PRId64,
1971cb0ef41Sopenharmony_ci                            heap_index);
1981cb0ef41Sopenharmony_ci      return HeapType(HeapType::kBottom);
1991cb0ef41Sopenharmony_ci    }
2001cb0ef41Sopenharmony_ci    uint8_t uint_7_mask = 0x7F;
2011cb0ef41Sopenharmony_ci    uint8_t code = static_cast<ValueTypeCode>(heap_index) & uint_7_mask;
2021cb0ef41Sopenharmony_ci    switch (code) {
2031cb0ef41Sopenharmony_ci      case kEqRefCode:
2041cb0ef41Sopenharmony_ci      case kI31RefCode:
2051cb0ef41Sopenharmony_ci      case kDataRefCode:
2061cb0ef41Sopenharmony_ci      case kArrayRefCode:
2071cb0ef41Sopenharmony_ci      case kAnyRefCodeAlias:
2081cb0ef41Sopenharmony_ci        if (!VALIDATE(enabled.has_gc())) {
2091cb0ef41Sopenharmony_ci          DecodeError<validate>(
2101cb0ef41Sopenharmony_ci              decoder, pc,
2111cb0ef41Sopenharmony_ci              "invalid heap type '%s', enable with --experimental-wasm-gc",
2121cb0ef41Sopenharmony_ci              HeapType::from_code(code).name().c_str());
2131cb0ef41Sopenharmony_ci          return HeapType(HeapType::kBottom);
2141cb0ef41Sopenharmony_ci        }
2151cb0ef41Sopenharmony_ci        V8_FALLTHROUGH;
2161cb0ef41Sopenharmony_ci      case kAnyRefCode:
2171cb0ef41Sopenharmony_ci      case kFuncRefCode:
2181cb0ef41Sopenharmony_ci        return HeapType::from_code(code);
2191cb0ef41Sopenharmony_ci      default:
2201cb0ef41Sopenharmony_ci        DecodeError<validate>(decoder, pc, "Unknown heap type %" PRId64,
2211cb0ef41Sopenharmony_ci                              heap_index);
2221cb0ef41Sopenharmony_ci        return HeapType(HeapType::kBottom);
2231cb0ef41Sopenharmony_ci    }
2241cb0ef41Sopenharmony_ci  } else {
2251cb0ef41Sopenharmony_ci    if (!VALIDATE(enabled.has_typed_funcref())) {
2261cb0ef41Sopenharmony_ci      DecodeError<validate>(decoder, pc,
2271cb0ef41Sopenharmony_ci                            "Invalid indexed heap type, enable with "
2281cb0ef41Sopenharmony_ci                            "--experimental-wasm-typed-funcref");
2291cb0ef41Sopenharmony_ci      return HeapType(HeapType::kBottom);
2301cb0ef41Sopenharmony_ci    }
2311cb0ef41Sopenharmony_ci    uint32_t type_index = static_cast<uint32_t>(heap_index);
2321cb0ef41Sopenharmony_ci    if (!VALIDATE(type_index < kV8MaxWasmTypes)) {
2331cb0ef41Sopenharmony_ci      DecodeError<validate>(
2341cb0ef41Sopenharmony_ci          decoder, pc,
2351cb0ef41Sopenharmony_ci          "Type index %u is greater than the maximum number %zu "
2361cb0ef41Sopenharmony_ci          "of type definitions supported by V8",
2371cb0ef41Sopenharmony_ci          type_index, kV8MaxWasmTypes);
2381cb0ef41Sopenharmony_ci      return HeapType(HeapType::kBottom);
2391cb0ef41Sopenharmony_ci    }
2401cb0ef41Sopenharmony_ci    // We use capacity over size so this works mid-DecodeTypeSection.
2411cb0ef41Sopenharmony_ci    if (!VALIDATE(module == nullptr || type_index < module->types.capacity())) {
2421cb0ef41Sopenharmony_ci      DecodeError<validate>(decoder, pc, "Type index %u is out of bounds",
2431cb0ef41Sopenharmony_ci                            type_index);
2441cb0ef41Sopenharmony_ci      return HeapType(HeapType::kBottom);
2451cb0ef41Sopenharmony_ci    }
2461cb0ef41Sopenharmony_ci    return HeapType(type_index);
2471cb0ef41Sopenharmony_ci  }
2481cb0ef41Sopenharmony_ci}
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ciHeapType consume_heap_type(Decoder* decoder, const WasmModule* module,
2511cb0ef41Sopenharmony_ci                           const WasmFeatures& enabled);
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci// Read a value type starting at address {pc} using {decoder}.
2541cb0ef41Sopenharmony_ci// No bytes are consumed.
2551cb0ef41Sopenharmony_ci// The length of the read value type is written in {length}.
2561cb0ef41Sopenharmony_ci// Registers an error for an invalid type only if {validate} is not
2571cb0ef41Sopenharmony_ci// kNoValidate.
2581cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
2591cb0ef41Sopenharmony_ciValueType read_value_type(Decoder* decoder, const byte* pc,
2601cb0ef41Sopenharmony_ci                          uint32_t* const length, const WasmModule* module,
2611cb0ef41Sopenharmony_ci                          const WasmFeatures& enabled) {
2621cb0ef41Sopenharmony_ci  *length = 1;
2631cb0ef41Sopenharmony_ci  byte val = decoder->read_u8<validate>(pc, "value type opcode");
2641cb0ef41Sopenharmony_ci  if (decoder->failed()) {
2651cb0ef41Sopenharmony_ci    *length = 0;
2661cb0ef41Sopenharmony_ci    return kWasmBottom;
2671cb0ef41Sopenharmony_ci  }
2681cb0ef41Sopenharmony_ci  ValueTypeCode code = static_cast<ValueTypeCode>(val);
2691cb0ef41Sopenharmony_ci  switch (code) {
2701cb0ef41Sopenharmony_ci    case kEqRefCode:
2711cb0ef41Sopenharmony_ci    case kI31RefCode:
2721cb0ef41Sopenharmony_ci    case kDataRefCode:
2731cb0ef41Sopenharmony_ci    case kArrayRefCode:
2741cb0ef41Sopenharmony_ci    case kAnyRefCodeAlias:
2751cb0ef41Sopenharmony_ci      if (!VALIDATE(enabled.has_gc())) {
2761cb0ef41Sopenharmony_ci        DecodeError<validate>(
2771cb0ef41Sopenharmony_ci            decoder, pc,
2781cb0ef41Sopenharmony_ci            "invalid value type '%sref', enable with --experimental-wasm-gc",
2791cb0ef41Sopenharmony_ci            HeapType::from_code(code).name().c_str());
2801cb0ef41Sopenharmony_ci        return kWasmBottom;
2811cb0ef41Sopenharmony_ci      }
2821cb0ef41Sopenharmony_ci      V8_FALLTHROUGH;
2831cb0ef41Sopenharmony_ci    case kAnyRefCode:
2841cb0ef41Sopenharmony_ci    case kFuncRefCode: {
2851cb0ef41Sopenharmony_ci      HeapType heap_type = HeapType::from_code(code);
2861cb0ef41Sopenharmony_ci      Nullability nullability =
2871cb0ef41Sopenharmony_ci          code == kI31RefCode || code == kDataRefCode || code == kArrayRefCode
2881cb0ef41Sopenharmony_ci              ? kNonNullable
2891cb0ef41Sopenharmony_ci              : kNullable;
2901cb0ef41Sopenharmony_ci      return ValueType::Ref(heap_type, nullability);
2911cb0ef41Sopenharmony_ci    }
2921cb0ef41Sopenharmony_ci    case kI32Code:
2931cb0ef41Sopenharmony_ci      return kWasmI32;
2941cb0ef41Sopenharmony_ci    case kI64Code:
2951cb0ef41Sopenharmony_ci      return kWasmI64;
2961cb0ef41Sopenharmony_ci    case kF32Code:
2971cb0ef41Sopenharmony_ci      return kWasmF32;
2981cb0ef41Sopenharmony_ci    case kF64Code:
2991cb0ef41Sopenharmony_ci      return kWasmF64;
3001cb0ef41Sopenharmony_ci    case kRefCode:
3011cb0ef41Sopenharmony_ci    case kOptRefCode: {
3021cb0ef41Sopenharmony_ci      Nullability nullability = code == kOptRefCode ? kNullable : kNonNullable;
3031cb0ef41Sopenharmony_ci      if (!VALIDATE(enabled.has_typed_funcref())) {
3041cb0ef41Sopenharmony_ci        DecodeError<validate>(decoder, pc,
3051cb0ef41Sopenharmony_ci                              "Invalid type '(ref%s <heaptype>)', enable with "
3061cb0ef41Sopenharmony_ci                              "--experimental-wasm-typed-funcref",
3071cb0ef41Sopenharmony_ci                              nullability == kNullable ? " null" : "");
3081cb0ef41Sopenharmony_ci        return kWasmBottom;
3091cb0ef41Sopenharmony_ci      }
3101cb0ef41Sopenharmony_ci      HeapType heap_type =
3111cb0ef41Sopenharmony_ci          read_heap_type<validate>(decoder, pc + 1, length, module, enabled);
3121cb0ef41Sopenharmony_ci      *length += 1;
3131cb0ef41Sopenharmony_ci      return heap_type.is_bottom() ? kWasmBottom
3141cb0ef41Sopenharmony_ci                                   : ValueType::Ref(heap_type, nullability);
3151cb0ef41Sopenharmony_ci    }
3161cb0ef41Sopenharmony_ci    // TODO(7748): This is here only for backwards compatibility, and the parsed
3171cb0ef41Sopenharmony_ci    // depth is ignored.
3181cb0ef41Sopenharmony_ci    case kRttWithDepthCode:
3191cb0ef41Sopenharmony_ci    case kRttCode: {
3201cb0ef41Sopenharmony_ci      if (!VALIDATE(enabled.has_gc())) {
3211cb0ef41Sopenharmony_ci        DecodeError<validate>(
3221cb0ef41Sopenharmony_ci            decoder, pc,
3231cb0ef41Sopenharmony_ci            "invalid value type 'rtt', enable with --experimental-wasm-gc");
3241cb0ef41Sopenharmony_ci        return kWasmBottom;
3251cb0ef41Sopenharmony_ci      }
3261cb0ef41Sopenharmony_ci      if (code == kRttWithDepthCode) {
3271cb0ef41Sopenharmony_ci        uint32_t depth = decoder->read_u32v<validate>(pc + 1, length, "depth");
3281cb0ef41Sopenharmony_ci        *length += 1;
3291cb0ef41Sopenharmony_ci        if (!VALIDATE(depth <= kV8MaxRttSubtypingDepth)) {
3301cb0ef41Sopenharmony_ci          DecodeError<validate>(
3311cb0ef41Sopenharmony_ci              decoder, pc,
3321cb0ef41Sopenharmony_ci              "subtyping depth %u is greater than the maximum depth "
3331cb0ef41Sopenharmony_ci              "%u supported by V8",
3341cb0ef41Sopenharmony_ci              depth, kV8MaxRttSubtypingDepth);
3351cb0ef41Sopenharmony_ci          return kWasmBottom;
3361cb0ef41Sopenharmony_ci        }
3371cb0ef41Sopenharmony_ci      }
3381cb0ef41Sopenharmony_ci      uint32_t type_index_length;
3391cb0ef41Sopenharmony_ci      uint32_t type_index =
3401cb0ef41Sopenharmony_ci          decoder->read_u32v<validate>(pc + *length, &type_index_length);
3411cb0ef41Sopenharmony_ci      *length += type_index_length;
3421cb0ef41Sopenharmony_ci      if (!VALIDATE(type_index < kV8MaxWasmTypes)) {
3431cb0ef41Sopenharmony_ci        DecodeError<validate>(
3441cb0ef41Sopenharmony_ci            decoder, pc,
3451cb0ef41Sopenharmony_ci            "Type index %u is greater than the maximum number %zu "
3461cb0ef41Sopenharmony_ci            "of type definitions supported by V8",
3471cb0ef41Sopenharmony_ci            type_index, kV8MaxWasmTypes);
3481cb0ef41Sopenharmony_ci        return kWasmBottom;
3491cb0ef41Sopenharmony_ci      }
3501cb0ef41Sopenharmony_ci      // We use capacity over size so this works mid-DecodeTypeSection.
3511cb0ef41Sopenharmony_ci      if (!VALIDATE(module == nullptr ||
3521cb0ef41Sopenharmony_ci                    type_index < module->types.capacity())) {
3531cb0ef41Sopenharmony_ci        DecodeError<validate>(decoder, pc, "Type index %u is out of bounds",
3541cb0ef41Sopenharmony_ci                              type_index);
3551cb0ef41Sopenharmony_ci        return kWasmBottom;
3561cb0ef41Sopenharmony_ci      }
3571cb0ef41Sopenharmony_ci      return ValueType::Rtt(type_index);
3581cb0ef41Sopenharmony_ci    }
3591cb0ef41Sopenharmony_ci    case kS128Code: {
3601cb0ef41Sopenharmony_ci      if (!VALIDATE(enabled.has_simd())) {
3611cb0ef41Sopenharmony_ci        DecodeError<validate>(
3621cb0ef41Sopenharmony_ci            decoder, pc,
3631cb0ef41Sopenharmony_ci            "invalid value type 's128', enable with --experimental-wasm-simd");
3641cb0ef41Sopenharmony_ci        return kWasmBottom;
3651cb0ef41Sopenharmony_ci      }
3661cb0ef41Sopenharmony_ci      if (!VALIDATE(CheckHardwareSupportsSimd())) {
3671cb0ef41Sopenharmony_ci        DecodeError<validate>(decoder, pc, "Wasm SIMD unsupported");
3681cb0ef41Sopenharmony_ci        return kWasmBottom;
3691cb0ef41Sopenharmony_ci      }
3701cb0ef41Sopenharmony_ci      return kWasmS128;
3711cb0ef41Sopenharmony_ci    }
3721cb0ef41Sopenharmony_ci    // Although these codes are included in ValueTypeCode, they technically
3731cb0ef41Sopenharmony_ci    // do not correspond to value types and are only used in specific
3741cb0ef41Sopenharmony_ci    // contexts. The caller of this function is responsible for handling them.
3751cb0ef41Sopenharmony_ci    case kVoidCode:
3761cb0ef41Sopenharmony_ci    case kI8Code:
3771cb0ef41Sopenharmony_ci    case kI16Code:
3781cb0ef41Sopenharmony_ci      if (validate) {
3791cb0ef41Sopenharmony_ci        DecodeError<validate>(decoder, pc, "invalid value type 0x%x", code);
3801cb0ef41Sopenharmony_ci      }
3811cb0ef41Sopenharmony_ci      return kWasmBottom;
3821cb0ef41Sopenharmony_ci  }
3831cb0ef41Sopenharmony_ci  // Anything that doesn't match an enumeration value is an invalid type code.
3841cb0ef41Sopenharmony_ci  if (validate) {
3851cb0ef41Sopenharmony_ci    DecodeError<validate>(decoder, pc, "invalid value type 0x%x", code);
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci  return kWasmBottom;
3881cb0ef41Sopenharmony_ci}
3891cb0ef41Sopenharmony_ci}  // namespace value_type_reader
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_cienum DecodingMode { kFunctionBody, kInitExpression };
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci// Helpers for decoding different kinds of immediates which follow bytecodes.
3941cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
3951cb0ef41Sopenharmony_cistruct ImmI32Immediate {
3961cb0ef41Sopenharmony_ci  int32_t value;
3971cb0ef41Sopenharmony_ci  uint32_t length;
3981cb0ef41Sopenharmony_ci  ImmI32Immediate(Decoder* decoder, const byte* pc) {
3991cb0ef41Sopenharmony_ci    value = decoder->read_i32v<validate>(pc, &length, "immi32");
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci};
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4041cb0ef41Sopenharmony_cistruct ImmI64Immediate {
4051cb0ef41Sopenharmony_ci  int64_t value;
4061cb0ef41Sopenharmony_ci  uint32_t length;
4071cb0ef41Sopenharmony_ci  ImmI64Immediate(Decoder* decoder, const byte* pc) {
4081cb0ef41Sopenharmony_ci    value = decoder->read_i64v<validate>(pc, &length, "immi64");
4091cb0ef41Sopenharmony_ci  }
4101cb0ef41Sopenharmony_ci};
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4131cb0ef41Sopenharmony_cistruct ImmF32Immediate {
4141cb0ef41Sopenharmony_ci  float value;
4151cb0ef41Sopenharmony_ci  uint32_t length = 4;
4161cb0ef41Sopenharmony_ci  ImmF32Immediate(Decoder* decoder, const byte* pc) {
4171cb0ef41Sopenharmony_ci    // We can't use bit_cast here because calling any helper function that
4181cb0ef41Sopenharmony_ci    // returns a float would potentially flip NaN bits per C++ semantics, so we
4191cb0ef41Sopenharmony_ci    // have to inline the memcpy call directly.
4201cb0ef41Sopenharmony_ci    uint32_t tmp = decoder->read_u32<validate>(pc, "immf32");
4211cb0ef41Sopenharmony_ci    memcpy(&value, &tmp, sizeof(value));
4221cb0ef41Sopenharmony_ci  }
4231cb0ef41Sopenharmony_ci};
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4261cb0ef41Sopenharmony_cistruct ImmF64Immediate {
4271cb0ef41Sopenharmony_ci  double value;
4281cb0ef41Sopenharmony_ci  uint32_t length = 8;
4291cb0ef41Sopenharmony_ci  ImmF64Immediate(Decoder* decoder, const byte* pc) {
4301cb0ef41Sopenharmony_ci    // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
4311cb0ef41Sopenharmony_ci    uint64_t tmp = decoder->read_u64<validate>(pc, "immf64");
4321cb0ef41Sopenharmony_ci    memcpy(&value, &tmp, sizeof(value));
4331cb0ef41Sopenharmony_ci  }
4341cb0ef41Sopenharmony_ci};
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci// This is different than IndexImmediate because {index} is a byte.
4371cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4381cb0ef41Sopenharmony_cistruct MemoryIndexImmediate {
4391cb0ef41Sopenharmony_ci  uint8_t index = 0;
4401cb0ef41Sopenharmony_ci  uint32_t length = 1;
4411cb0ef41Sopenharmony_ci  MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
4421cb0ef41Sopenharmony_ci    index = decoder->read_u8<validate>(pc, "memory index");
4431cb0ef41Sopenharmony_ci  }
4441cb0ef41Sopenharmony_ci};
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ci// Parent class for all Immediates which read a u32v index value in their
4471cb0ef41Sopenharmony_ci// constructor.
4481cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4491cb0ef41Sopenharmony_cistruct IndexImmediate {
4501cb0ef41Sopenharmony_ci  uint32_t index;
4511cb0ef41Sopenharmony_ci  uint32_t length;
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci  IndexImmediate(Decoder* decoder, const byte* pc, const char* name) {
4541cb0ef41Sopenharmony_ci    index = decoder->read_u32v<validate>(pc, &length, name);
4551cb0ef41Sopenharmony_ci  }
4561cb0ef41Sopenharmony_ci};
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4591cb0ef41Sopenharmony_cistruct TagIndexImmediate : public IndexImmediate<validate> {
4601cb0ef41Sopenharmony_ci  const WasmTag* tag = nullptr;
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci  TagIndexImmediate(Decoder* decoder, const byte* pc)
4631cb0ef41Sopenharmony_ci      : IndexImmediate<validate>(decoder, pc, "tag index") {}
4641cb0ef41Sopenharmony_ci};
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4671cb0ef41Sopenharmony_cistruct GlobalIndexImmediate : public IndexImmediate<validate> {
4681cb0ef41Sopenharmony_ci  const WasmGlobal* global = nullptr;
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci  GlobalIndexImmediate(Decoder* decoder, const byte* pc)
4711cb0ef41Sopenharmony_ci      : IndexImmediate<validate>(decoder, pc, "global index") {}
4721cb0ef41Sopenharmony_ci};
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4751cb0ef41Sopenharmony_cistruct StructIndexImmediate : public IndexImmediate<validate> {
4761cb0ef41Sopenharmony_ci  const StructType* struct_type = nullptr;
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  StructIndexImmediate(Decoder* decoder, const byte* pc)
4791cb0ef41Sopenharmony_ci      : IndexImmediate<validate>(decoder, pc, "struct index") {}
4801cb0ef41Sopenharmony_ci};
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4831cb0ef41Sopenharmony_cistruct ArrayIndexImmediate : public IndexImmediate<validate> {
4841cb0ef41Sopenharmony_ci  const ArrayType* array_type = nullptr;
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci  ArrayIndexImmediate(Decoder* decoder, const byte* pc)
4871cb0ef41Sopenharmony_ci      : IndexImmediate<validate>(decoder, pc, "array index") {}
4881cb0ef41Sopenharmony_ci};
4891cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4901cb0ef41Sopenharmony_cistruct CallFunctionImmediate : public IndexImmediate<validate> {
4911cb0ef41Sopenharmony_ci  const FunctionSig* sig = nullptr;
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  CallFunctionImmediate(Decoder* decoder, const byte* pc)
4941cb0ef41Sopenharmony_ci      : IndexImmediate<validate>(decoder, pc, "function index") {}
4951cb0ef41Sopenharmony_ci};
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
4981cb0ef41Sopenharmony_cistruct SelectTypeImmediate {
4991cb0ef41Sopenharmony_ci  uint32_t length;
5001cb0ef41Sopenharmony_ci  ValueType type;
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  SelectTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
5031cb0ef41Sopenharmony_ci                      const byte* pc, const WasmModule* module) {
5041cb0ef41Sopenharmony_ci    uint8_t num_types =
5051cb0ef41Sopenharmony_ci        decoder->read_u32v<validate>(pc, &length, "number of select types");
5061cb0ef41Sopenharmony_ci    if (!VALIDATE(num_types == 1)) {
5071cb0ef41Sopenharmony_ci      DecodeError<validate>(
5081cb0ef41Sopenharmony_ci          decoder, pc + 1,
5091cb0ef41Sopenharmony_ci          "Invalid number of types. Select accepts exactly one type");
5101cb0ef41Sopenharmony_ci      return;
5111cb0ef41Sopenharmony_ci    }
5121cb0ef41Sopenharmony_ci    uint32_t type_length;
5131cb0ef41Sopenharmony_ci    type = value_type_reader::read_value_type<validate>(
5141cb0ef41Sopenharmony_ci        decoder, pc + length, &type_length, module, enabled);
5151cb0ef41Sopenharmony_ci    length += type_length;
5161cb0ef41Sopenharmony_ci  }
5171cb0ef41Sopenharmony_ci};
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
5201cb0ef41Sopenharmony_cistruct BlockTypeImmediate {
5211cb0ef41Sopenharmony_ci  uint32_t length = 1;
5221cb0ef41Sopenharmony_ci  ValueType type = kWasmVoid;
5231cb0ef41Sopenharmony_ci  uint32_t sig_index = 0;
5241cb0ef41Sopenharmony_ci  const FunctionSig* sig = nullptr;
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci  BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
5271cb0ef41Sopenharmony_ci                     const byte* pc, const WasmModule* module) {
5281cb0ef41Sopenharmony_ci    int64_t block_type =
5291cb0ef41Sopenharmony_ci        decoder->read_i33v<validate>(pc, &length, "block type");
5301cb0ef41Sopenharmony_ci    if (block_type < 0) {
5311cb0ef41Sopenharmony_ci      // All valid negative types are 1 byte in length, so we check against the
5321cb0ef41Sopenharmony_ci      // minimum 1-byte LEB128 value.
5331cb0ef41Sopenharmony_ci      constexpr int64_t min_1_byte_leb128 = -64;
5341cb0ef41Sopenharmony_ci      if (!VALIDATE(block_type >= min_1_byte_leb128)) {
5351cb0ef41Sopenharmony_ci        DecodeError<validate>(decoder, pc, "invalid block type %" PRId64,
5361cb0ef41Sopenharmony_ci                              block_type);
5371cb0ef41Sopenharmony_ci        return;
5381cb0ef41Sopenharmony_ci      }
5391cb0ef41Sopenharmony_ci      if (static_cast<ValueTypeCode>(block_type & 0x7F) == kVoidCode) return;
5401cb0ef41Sopenharmony_ci      type = value_type_reader::read_value_type<validate>(decoder, pc, &length,
5411cb0ef41Sopenharmony_ci                                                          module, enabled);
5421cb0ef41Sopenharmony_ci    } else {
5431cb0ef41Sopenharmony_ci      type = kWasmBottom;
5441cb0ef41Sopenharmony_ci      sig_index = static_cast<uint32_t>(block_type);
5451cb0ef41Sopenharmony_ci    }
5461cb0ef41Sopenharmony_ci  }
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci  uint32_t in_arity() const {
5491cb0ef41Sopenharmony_ci    if (type != kWasmBottom) return 0;
5501cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(sig->parameter_count());
5511cb0ef41Sopenharmony_ci  }
5521cb0ef41Sopenharmony_ci  uint32_t out_arity() const {
5531cb0ef41Sopenharmony_ci    if (type == kWasmVoid) return 0;
5541cb0ef41Sopenharmony_ci    if (type != kWasmBottom) return 1;
5551cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(sig->return_count());
5561cb0ef41Sopenharmony_ci  }
5571cb0ef41Sopenharmony_ci  ValueType in_type(uint32_t index) {
5581cb0ef41Sopenharmony_ci    DCHECK_EQ(kWasmBottom, type);
5591cb0ef41Sopenharmony_ci    return sig->GetParam(index);
5601cb0ef41Sopenharmony_ci  }
5611cb0ef41Sopenharmony_ci  ValueType out_type(uint32_t index) {
5621cb0ef41Sopenharmony_ci    if (type == kWasmBottom) return sig->GetReturn(index);
5631cb0ef41Sopenharmony_ci    DCHECK_NE(kWasmVoid, type);
5641cb0ef41Sopenharmony_ci    DCHECK_EQ(0, index);
5651cb0ef41Sopenharmony_ci    return type;
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci};
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
5701cb0ef41Sopenharmony_cistruct BranchDepthImmediate {
5711cb0ef41Sopenharmony_ci  uint32_t depth;
5721cb0ef41Sopenharmony_ci  uint32_t length;
5731cb0ef41Sopenharmony_ci  BranchDepthImmediate(Decoder* decoder, const byte* pc) {
5741cb0ef41Sopenharmony_ci    depth = decoder->read_u32v<validate>(pc, &length, "branch depth");
5751cb0ef41Sopenharmony_ci  }
5761cb0ef41Sopenharmony_ci};
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
5791cb0ef41Sopenharmony_cistruct FieldImmediate {
5801cb0ef41Sopenharmony_ci  StructIndexImmediate<validate> struct_imm;
5811cb0ef41Sopenharmony_ci  IndexImmediate<validate> field_imm;
5821cb0ef41Sopenharmony_ci  uint32_t length;
5831cb0ef41Sopenharmony_ci  FieldImmediate(Decoder* decoder, const byte* pc)
5841cb0ef41Sopenharmony_ci      : struct_imm(decoder, pc),
5851cb0ef41Sopenharmony_ci        field_imm(decoder, pc + struct_imm.length, "field index"),
5861cb0ef41Sopenharmony_ci        length(struct_imm.length + field_imm.length) {}
5871cb0ef41Sopenharmony_ci};
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
5901cb0ef41Sopenharmony_cistruct CallIndirectImmediate {
5911cb0ef41Sopenharmony_ci  IndexImmediate<validate> sig_imm;
5921cb0ef41Sopenharmony_ci  IndexImmediate<validate> table_imm;
5931cb0ef41Sopenharmony_ci  uint32_t length;
5941cb0ef41Sopenharmony_ci  const FunctionSig* sig = nullptr;
5951cb0ef41Sopenharmony_ci  CallIndirectImmediate(Decoder* decoder, const byte* pc)
5961cb0ef41Sopenharmony_ci      : sig_imm(decoder, pc, "singature index"),
5971cb0ef41Sopenharmony_ci        table_imm(decoder, pc + sig_imm.length, "table index"),
5981cb0ef41Sopenharmony_ci        length(sig_imm.length + table_imm.length) {}
5991cb0ef41Sopenharmony_ci};
6001cb0ef41Sopenharmony_ci
6011cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
6021cb0ef41Sopenharmony_cistruct BranchTableImmediate {
6031cb0ef41Sopenharmony_ci  uint32_t table_count;
6041cb0ef41Sopenharmony_ci  const byte* start;
6051cb0ef41Sopenharmony_ci  const byte* table;
6061cb0ef41Sopenharmony_ci  BranchTableImmediate(Decoder* decoder, const byte* pc) {
6071cb0ef41Sopenharmony_ci    start = pc;
6081cb0ef41Sopenharmony_ci    uint32_t len = 0;
6091cb0ef41Sopenharmony_ci    table_count = decoder->read_u32v<validate>(pc, &len, "table count");
6101cb0ef41Sopenharmony_ci    table = pc + len;
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci};
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci// A helper to iterate over a branch table.
6151cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
6161cb0ef41Sopenharmony_ciclass BranchTableIterator {
6171cb0ef41Sopenharmony_ci public:
6181cb0ef41Sopenharmony_ci  uint32_t cur_index() { return index_; }
6191cb0ef41Sopenharmony_ci  bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
6201cb0ef41Sopenharmony_ci  uint32_t next() {
6211cb0ef41Sopenharmony_ci    DCHECK(has_next());
6221cb0ef41Sopenharmony_ci    index_++;
6231cb0ef41Sopenharmony_ci    uint32_t length;
6241cb0ef41Sopenharmony_ci    uint32_t result =
6251cb0ef41Sopenharmony_ci        decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
6261cb0ef41Sopenharmony_ci    pc_ += length;
6271cb0ef41Sopenharmony_ci    return result;
6281cb0ef41Sopenharmony_ci  }
6291cb0ef41Sopenharmony_ci  // length, including the length of the {BranchTableImmediate}, but not the
6301cb0ef41Sopenharmony_ci  // opcode.
6311cb0ef41Sopenharmony_ci  uint32_t length() {
6321cb0ef41Sopenharmony_ci    while (has_next()) next();
6331cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(pc_ - start_);
6341cb0ef41Sopenharmony_ci  }
6351cb0ef41Sopenharmony_ci  const byte* pc() { return pc_; }
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  BranchTableIterator(Decoder* decoder,
6381cb0ef41Sopenharmony_ci                      const BranchTableImmediate<validate>& imm)
6391cb0ef41Sopenharmony_ci      : decoder_(decoder),
6401cb0ef41Sopenharmony_ci        start_(imm.start),
6411cb0ef41Sopenharmony_ci        pc_(imm.table),
6421cb0ef41Sopenharmony_ci        table_count_(imm.table_count) {}
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci private:
6451cb0ef41Sopenharmony_ci  Decoder* const decoder_;
6461cb0ef41Sopenharmony_ci  const byte* start_;
6471cb0ef41Sopenharmony_ci  const byte* pc_;
6481cb0ef41Sopenharmony_ci  uint32_t index_ = 0;          // the current index.
6491cb0ef41Sopenharmony_ci  const uint32_t table_count_;  // the count of entries, not including default.
6501cb0ef41Sopenharmony_ci};
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate,
6531cb0ef41Sopenharmony_ci          DecodingMode decoding_mode = kFunctionBody>
6541cb0ef41Sopenharmony_ciclass WasmDecoder;
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
6571cb0ef41Sopenharmony_cistruct MemoryAccessImmediate {
6581cb0ef41Sopenharmony_ci  uint32_t alignment;
6591cb0ef41Sopenharmony_ci  uint64_t offset;
6601cb0ef41Sopenharmony_ci  uint32_t length = 0;
6611cb0ef41Sopenharmony_ci  MemoryAccessImmediate(Decoder* decoder, const byte* pc,
6621cb0ef41Sopenharmony_ci                        uint32_t max_alignment, bool is_memory64) {
6631cb0ef41Sopenharmony_ci    uint32_t alignment_length;
6641cb0ef41Sopenharmony_ci    alignment =
6651cb0ef41Sopenharmony_ci        decoder->read_u32v<validate>(pc, &alignment_length, "alignment");
6661cb0ef41Sopenharmony_ci    if (!VALIDATE(alignment <= max_alignment)) {
6671cb0ef41Sopenharmony_ci      DecodeError<validate>(
6681cb0ef41Sopenharmony_ci          decoder, pc,
6691cb0ef41Sopenharmony_ci          "invalid alignment; expected maximum alignment is %u, "
6701cb0ef41Sopenharmony_ci          "actual alignment is %u",
6711cb0ef41Sopenharmony_ci          max_alignment, alignment);
6721cb0ef41Sopenharmony_ci    }
6731cb0ef41Sopenharmony_ci    uint32_t offset_length;
6741cb0ef41Sopenharmony_ci    offset = is_memory64 ? decoder->read_u64v<validate>(
6751cb0ef41Sopenharmony_ci                               pc + alignment_length, &offset_length, "offset")
6761cb0ef41Sopenharmony_ci                         : decoder->read_u32v<validate>(
6771cb0ef41Sopenharmony_ci                               pc + alignment_length, &offset_length, "offset");
6781cb0ef41Sopenharmony_ci    length = alignment_length + offset_length;
6791cb0ef41Sopenharmony_ci  }
6801cb0ef41Sopenharmony_ci};
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_ci// Immediate for SIMD lane operations.
6831cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
6841cb0ef41Sopenharmony_cistruct SimdLaneImmediate {
6851cb0ef41Sopenharmony_ci  uint8_t lane;
6861cb0ef41Sopenharmony_ci  uint32_t length = 1;
6871cb0ef41Sopenharmony_ci
6881cb0ef41Sopenharmony_ci  SimdLaneImmediate(Decoder* decoder, const byte* pc) {
6891cb0ef41Sopenharmony_ci    lane = decoder->read_u8<validate>(pc, "lane");
6901cb0ef41Sopenharmony_ci  }
6911cb0ef41Sopenharmony_ci};
6921cb0ef41Sopenharmony_ci
6931cb0ef41Sopenharmony_ci// Immediate for SIMD S8x16 shuffle operations.
6941cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
6951cb0ef41Sopenharmony_cistruct Simd128Immediate {
6961cb0ef41Sopenharmony_ci  uint8_t value[kSimd128Size] = {0};
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_ci  Simd128Immediate(Decoder* decoder, const byte* pc) {
6991cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < kSimd128Size; ++i) {
7001cb0ef41Sopenharmony_ci      value[i] = decoder->read_u8<validate>(pc + i, "value");
7011cb0ef41Sopenharmony_ci    }
7021cb0ef41Sopenharmony_ci  }
7031cb0ef41Sopenharmony_ci};
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7061cb0ef41Sopenharmony_cistruct MemoryInitImmediate {
7071cb0ef41Sopenharmony_ci  IndexImmediate<validate> data_segment;
7081cb0ef41Sopenharmony_ci  MemoryIndexImmediate<validate> memory;
7091cb0ef41Sopenharmony_ci  uint32_t length;
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ci  MemoryInitImmediate(Decoder* decoder, const byte* pc)
7121cb0ef41Sopenharmony_ci      : data_segment(decoder, pc, "data segment index"),
7131cb0ef41Sopenharmony_ci        memory(decoder, pc + data_segment.length),
7141cb0ef41Sopenharmony_ci        length(data_segment.length + memory.length) {}
7151cb0ef41Sopenharmony_ci};
7161cb0ef41Sopenharmony_ci
7171cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7181cb0ef41Sopenharmony_cistruct MemoryCopyImmediate {
7191cb0ef41Sopenharmony_ci  MemoryIndexImmediate<validate> memory_src;
7201cb0ef41Sopenharmony_ci  MemoryIndexImmediate<validate> memory_dst;
7211cb0ef41Sopenharmony_ci  uint32_t length;
7221cb0ef41Sopenharmony_ci
7231cb0ef41Sopenharmony_ci  MemoryCopyImmediate(Decoder* decoder, const byte* pc)
7241cb0ef41Sopenharmony_ci      : memory_src(decoder, pc),
7251cb0ef41Sopenharmony_ci        memory_dst(decoder, pc + memory_src.length),
7261cb0ef41Sopenharmony_ci        length(memory_src.length + memory_dst.length) {}
7271cb0ef41Sopenharmony_ci};
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7301cb0ef41Sopenharmony_cistruct TableInitImmediate {
7311cb0ef41Sopenharmony_ci  IndexImmediate<validate> element_segment;
7321cb0ef41Sopenharmony_ci  IndexImmediate<validate> table;
7331cb0ef41Sopenharmony_ci  uint32_t length;
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  TableInitImmediate(Decoder* decoder, const byte* pc)
7361cb0ef41Sopenharmony_ci      : element_segment(decoder, pc, "element segment index"),
7371cb0ef41Sopenharmony_ci        table(decoder, pc + element_segment.length, "table index"),
7381cb0ef41Sopenharmony_ci        length(element_segment.length + table.length) {}
7391cb0ef41Sopenharmony_ci};
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7421cb0ef41Sopenharmony_cistruct TableCopyImmediate {
7431cb0ef41Sopenharmony_ci  IndexImmediate<validate> table_dst;
7441cb0ef41Sopenharmony_ci  IndexImmediate<validate> table_src;
7451cb0ef41Sopenharmony_ci  uint32_t length;
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci  TableCopyImmediate(Decoder* decoder, const byte* pc)
7481cb0ef41Sopenharmony_ci      : table_dst(decoder, pc, "table index"),
7491cb0ef41Sopenharmony_ci        table_src(decoder, pc + table_dst.length, "table index"),
7501cb0ef41Sopenharmony_ci        length(table_src.length + table_dst.length) {}
7511cb0ef41Sopenharmony_ci};
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7541cb0ef41Sopenharmony_cistruct HeapTypeImmediate {
7551cb0ef41Sopenharmony_ci  uint32_t length = 1;
7561cb0ef41Sopenharmony_ci  HeapType type;
7571cb0ef41Sopenharmony_ci  HeapTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
7581cb0ef41Sopenharmony_ci                    const byte* pc, const WasmModule* module)
7591cb0ef41Sopenharmony_ci      : type(value_type_reader::read_heap_type<validate>(decoder, pc, &length,
7601cb0ef41Sopenharmony_ci                                                         module, enabled)) {}
7611cb0ef41Sopenharmony_ci};
7621cb0ef41Sopenharmony_ci
7631cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7641cb0ef41Sopenharmony_cistruct PcForErrors {
7651cb0ef41Sopenharmony_ci  PcForErrors(const byte* /* pc */) {}
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_ci  const byte* pc() const { return nullptr; }
7681cb0ef41Sopenharmony_ci};
7691cb0ef41Sopenharmony_ci
7701cb0ef41Sopenharmony_citemplate <>
7711cb0ef41Sopenharmony_cistruct PcForErrors<Decoder::kFullValidation> {
7721cb0ef41Sopenharmony_ci  const byte* pc_for_errors = nullptr;
7731cb0ef41Sopenharmony_ci
7741cb0ef41Sopenharmony_ci  PcForErrors(const byte* pc) : pc_for_errors(pc) {}
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci  const byte* pc() const { return pc_for_errors; }
7771cb0ef41Sopenharmony_ci};
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci// An entry on the value stack.
7801cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate>
7811cb0ef41Sopenharmony_cistruct ValueBase : public PcForErrors<validate> {
7821cb0ef41Sopenharmony_ci  ValueType type = kWasmVoid;
7831cb0ef41Sopenharmony_ci
7841cb0ef41Sopenharmony_ci  ValueBase(const byte* pc, ValueType type)
7851cb0ef41Sopenharmony_ci      : PcForErrors<validate>(pc), type(type) {}
7861cb0ef41Sopenharmony_ci};
7871cb0ef41Sopenharmony_ci
7881cb0ef41Sopenharmony_citemplate <typename Value>
7891cb0ef41Sopenharmony_cistruct Merge {
7901cb0ef41Sopenharmony_ci  uint32_t arity = 0;
7911cb0ef41Sopenharmony_ci  union {  // Either multiple values or a single value.
7921cb0ef41Sopenharmony_ci    Value* array;
7931cb0ef41Sopenharmony_ci    Value first;
7941cb0ef41Sopenharmony_ci  } vals = {nullptr};  // Initialize {array} with {nullptr}.
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci  // Tracks whether this merge was ever reached. Uses precise reachability, like
7971cb0ef41Sopenharmony_ci  // Reachability::kReachable.
7981cb0ef41Sopenharmony_ci  bool reached;
7991cb0ef41Sopenharmony_ci
8001cb0ef41Sopenharmony_ci  explicit Merge(bool reached = false) : reached(reached) {}
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_ci  Value& operator[](uint32_t i) {
8031cb0ef41Sopenharmony_ci    DCHECK_GT(arity, i);
8041cb0ef41Sopenharmony_ci    return arity == 1 ? vals.first : vals.array[i];
8051cb0ef41Sopenharmony_ci  }
8061cb0ef41Sopenharmony_ci};
8071cb0ef41Sopenharmony_ci
8081cb0ef41Sopenharmony_cienum ControlKind : uint8_t {
8091cb0ef41Sopenharmony_ci  kControlIf,
8101cb0ef41Sopenharmony_ci  kControlIfElse,
8111cb0ef41Sopenharmony_ci  kControlBlock,
8121cb0ef41Sopenharmony_ci  kControlLoop,
8131cb0ef41Sopenharmony_ci  kControlLet,
8141cb0ef41Sopenharmony_ci  kControlTry,
8151cb0ef41Sopenharmony_ci  kControlTryCatch,
8161cb0ef41Sopenharmony_ci  kControlTryCatchAll,
8171cb0ef41Sopenharmony_ci};
8181cb0ef41Sopenharmony_ci
8191cb0ef41Sopenharmony_cienum Reachability : uint8_t {
8201cb0ef41Sopenharmony_ci  // reachable code.
8211cb0ef41Sopenharmony_ci  kReachable,
8221cb0ef41Sopenharmony_ci  // reachable code in unreachable block (implies normal validation).
8231cb0ef41Sopenharmony_ci  kSpecOnlyReachable,
8241cb0ef41Sopenharmony_ci  // code unreachable in its own block (implies polymorphic validation).
8251cb0ef41Sopenharmony_ci  kUnreachable
8261cb0ef41Sopenharmony_ci};
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_ci// An entry on the control stack (i.e. if, block, loop, or try).
8291cb0ef41Sopenharmony_citemplate <typename Value, Decoder::ValidateFlag validate>
8301cb0ef41Sopenharmony_cistruct ControlBase : public PcForErrors<validate> {
8311cb0ef41Sopenharmony_ci  ControlKind kind = kControlBlock;
8321cb0ef41Sopenharmony_ci  uint32_t locals_count = 0;  // Additional locals introduced in this 'let'.
8331cb0ef41Sopenharmony_ci  uint32_t stack_depth = 0;   // Stack height at the beginning of the construct.
8341cb0ef41Sopenharmony_ci  uint32_t init_stack_depth = 0;  // Height of "locals initialization" stack
8351cb0ef41Sopenharmony_ci                                  // at the beginning of the construct.
8361cb0ef41Sopenharmony_ci  int32_t previous_catch = -1;  // Depth of the innermost catch containing this
8371cb0ef41Sopenharmony_ci                                // 'try'.
8381cb0ef41Sopenharmony_ci  Reachability reachability = kReachable;
8391cb0ef41Sopenharmony_ci
8401cb0ef41Sopenharmony_ci  // Values merged into the start or end of this control construct.
8411cb0ef41Sopenharmony_ci  Merge<Value> start_merge;
8421cb0ef41Sopenharmony_ci  Merge<Value> end_merge;
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ci  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ControlBase);
8451cb0ef41Sopenharmony_ci
8461cb0ef41Sopenharmony_ci  ControlBase(ControlKind kind, uint32_t locals_count, uint32_t stack_depth,
8471cb0ef41Sopenharmony_ci              uint32_t init_stack_depth, const uint8_t* pc,
8481cb0ef41Sopenharmony_ci              Reachability reachability)
8491cb0ef41Sopenharmony_ci      : PcForErrors<validate>(pc),
8501cb0ef41Sopenharmony_ci        kind(kind),
8511cb0ef41Sopenharmony_ci        locals_count(locals_count),
8521cb0ef41Sopenharmony_ci        stack_depth(stack_depth),
8531cb0ef41Sopenharmony_ci        init_stack_depth(init_stack_depth),
8541cb0ef41Sopenharmony_ci        reachability(reachability),
8551cb0ef41Sopenharmony_ci        start_merge(reachability == kReachable) {
8561cb0ef41Sopenharmony_ci    DCHECK(kind == kControlLet || locals_count == 0);
8571cb0ef41Sopenharmony_ci  }
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci  // Check whether the current block is reachable.
8601cb0ef41Sopenharmony_ci  bool reachable() const { return reachability == kReachable; }
8611cb0ef41Sopenharmony_ci
8621cb0ef41Sopenharmony_ci  // Check whether the rest of the block is unreachable.
8631cb0ef41Sopenharmony_ci  // Note that this is different from {!reachable()}, as there is also the
8641cb0ef41Sopenharmony_ci  // "indirect unreachable state", for which both {reachable()} and
8651cb0ef41Sopenharmony_ci  // {unreachable()} return false.
8661cb0ef41Sopenharmony_ci  bool unreachable() const { return reachability == kUnreachable; }
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci  // Return the reachability of new control structs started in this block.
8691cb0ef41Sopenharmony_ci  Reachability innerReachability() const {
8701cb0ef41Sopenharmony_ci    return reachability == kReachable ? kReachable : kSpecOnlyReachable;
8711cb0ef41Sopenharmony_ci  }
8721cb0ef41Sopenharmony_ci
8731cb0ef41Sopenharmony_ci  bool is_if() const { return is_onearmed_if() || is_if_else(); }
8741cb0ef41Sopenharmony_ci  bool is_onearmed_if() const { return kind == kControlIf; }
8751cb0ef41Sopenharmony_ci  bool is_if_else() const { return kind == kControlIfElse; }
8761cb0ef41Sopenharmony_ci  bool is_block() const { return kind == kControlBlock; }
8771cb0ef41Sopenharmony_ci  bool is_let() const { return kind == kControlLet; }
8781cb0ef41Sopenharmony_ci  bool is_loop() const { return kind == kControlLoop; }
8791cb0ef41Sopenharmony_ci  bool is_incomplete_try() const { return kind == kControlTry; }
8801cb0ef41Sopenharmony_ci  bool is_try_catch() const { return kind == kControlTryCatch; }
8811cb0ef41Sopenharmony_ci  bool is_try_catchall() const { return kind == kControlTryCatchAll; }
8821cb0ef41Sopenharmony_ci  bool is_try() const {
8831cb0ef41Sopenharmony_ci    return is_incomplete_try() || is_try_catch() || is_try_catchall();
8841cb0ef41Sopenharmony_ci  }
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci  Merge<Value>* br_merge() {
8871cb0ef41Sopenharmony_ci    return is_loop() ? &this->start_merge : &this->end_merge;
8881cb0ef41Sopenharmony_ci  }
8891cb0ef41Sopenharmony_ci};
8901cb0ef41Sopenharmony_ci
8911cb0ef41Sopenharmony_ci// This is the list of callback functions that an interface for the
8921cb0ef41Sopenharmony_ci// WasmFullDecoder should implement.
8931cb0ef41Sopenharmony_ci// F(Name, args...)
8941cb0ef41Sopenharmony_ci#define INTERFACE_FUNCTIONS(F)    \
8951cb0ef41Sopenharmony_ci  INTERFACE_META_FUNCTIONS(F)     \
8961cb0ef41Sopenharmony_ci  INTERFACE_CONSTANT_FUNCTIONS(F) \
8971cb0ef41Sopenharmony_ci  INTERFACE_NON_CONSTANT_FUNCTIONS(F)
8981cb0ef41Sopenharmony_ci
8991cb0ef41Sopenharmony_ci#define INTERFACE_META_FUNCTIONS(F)    \
9001cb0ef41Sopenharmony_ci  F(StartFunction)                     \
9011cb0ef41Sopenharmony_ci  F(StartFunctionBody, Control* block) \
9021cb0ef41Sopenharmony_ci  F(FinishFunction)                    \
9031cb0ef41Sopenharmony_ci  F(OnFirstError)                      \
9041cb0ef41Sopenharmony_ci  F(NextInstruction, WasmOpcode)       \
9051cb0ef41Sopenharmony_ci  F(Forward, const Value& from, Value* to)
9061cb0ef41Sopenharmony_ci
9071cb0ef41Sopenharmony_ci#define INTERFACE_CONSTANT_FUNCTIONS(F)                                   \
9081cb0ef41Sopenharmony_ci  F(I32Const, Value* result, int32_t value)                               \
9091cb0ef41Sopenharmony_ci  F(I64Const, Value* result, int64_t value)                               \
9101cb0ef41Sopenharmony_ci  F(F32Const, Value* result, float value)                                 \
9111cb0ef41Sopenharmony_ci  F(F64Const, Value* result, double value)                                \
9121cb0ef41Sopenharmony_ci  F(S128Const, Simd128Immediate<validate>& imm, Value* result)            \
9131cb0ef41Sopenharmony_ci  F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs,         \
9141cb0ef41Sopenharmony_ci    Value* result)                                                        \
9151cb0ef41Sopenharmony_ci  F(RefNull, ValueType type, Value* result)                               \
9161cb0ef41Sopenharmony_ci  F(RefFunc, uint32_t function_index, Value* result)                      \
9171cb0ef41Sopenharmony_ci  F(GlobalGet, Value* result, const GlobalIndexImmediate<validate>& imm)  \
9181cb0ef41Sopenharmony_ci  F(StructNewWithRtt, const StructIndexImmediate<validate>& imm,          \
9191cb0ef41Sopenharmony_ci    const Value& rtt, const Value args[], Value* result)                  \
9201cb0ef41Sopenharmony_ci  F(StructNewDefault, const StructIndexImmediate<validate>& imm,          \
9211cb0ef41Sopenharmony_ci    const Value& rtt, Value* result)                                      \
9221cb0ef41Sopenharmony_ci  F(ArrayInit, const ArrayIndexImmediate<validate>& imm,                  \
9231cb0ef41Sopenharmony_ci    const base::Vector<Value>& elements, const Value& rtt, Value* result) \
9241cb0ef41Sopenharmony_ci  F(ArrayInitFromData, const ArrayIndexImmediate<validate>& array_imm,    \
9251cb0ef41Sopenharmony_ci    const IndexImmediate<validate>& data_segment, const Value& offset,    \
9261cb0ef41Sopenharmony_ci    const Value& length, const Value& rtt, Value* result)                 \
9271cb0ef41Sopenharmony_ci  F(RttCanon, uint32_t type_index, Value* result)                         \
9281cb0ef41Sopenharmony_ci  F(DoReturn, uint32_t drop_values)
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci#define INTERFACE_NON_CONSTANT_FUNCTIONS(F) /*       force 80 columns       */ \
9311cb0ef41Sopenharmony_ci  /* Control: */                                                               \
9321cb0ef41Sopenharmony_ci  F(Block, Control* block)                                                     \
9331cb0ef41Sopenharmony_ci  F(Loop, Control* block)                                                      \
9341cb0ef41Sopenharmony_ci  F(Try, Control* block)                                                       \
9351cb0ef41Sopenharmony_ci  F(If, const Value& cond, Control* if_block)                                  \
9361cb0ef41Sopenharmony_ci  F(FallThruTo, Control* c)                                                    \
9371cb0ef41Sopenharmony_ci  F(PopControl, Control* block)                                                \
9381cb0ef41Sopenharmony_ci  /* Instructions: */                                                          \
9391cb0ef41Sopenharmony_ci  F(UnOp, WasmOpcode opcode, const Value& value, Value* result)                \
9401cb0ef41Sopenharmony_ci  F(RefAsNonNull, const Value& arg, Value* result)                             \
9411cb0ef41Sopenharmony_ci  F(Drop)                                                                      \
9421cb0ef41Sopenharmony_ci  F(LocalGet, Value* result, const IndexImmediate<validate>& imm)              \
9431cb0ef41Sopenharmony_ci  F(LocalSet, const Value& value, const IndexImmediate<validate>& imm)         \
9441cb0ef41Sopenharmony_ci  F(LocalTee, const Value& value, Value* result,                               \
9451cb0ef41Sopenharmony_ci    const IndexImmediate<validate>& imm)                                       \
9461cb0ef41Sopenharmony_ci  F(AllocateLocals, base::Vector<Value> local_values)                          \
9471cb0ef41Sopenharmony_ci  F(DeallocateLocals, uint32_t count)                                          \
9481cb0ef41Sopenharmony_ci  F(GlobalSet, const Value& value, const GlobalIndexImmediate<validate>& imm)  \
9491cb0ef41Sopenharmony_ci  F(TableGet, const Value& index, Value* result,                               \
9501cb0ef41Sopenharmony_ci    const IndexImmediate<validate>& imm)                                       \
9511cb0ef41Sopenharmony_ci  F(TableSet, const Value& index, const Value& value,                          \
9521cb0ef41Sopenharmony_ci    const IndexImmediate<validate>& imm)                                       \
9531cb0ef41Sopenharmony_ci  F(Trap, TrapReason reason)                                                   \
9541cb0ef41Sopenharmony_ci  F(NopForTestingUnsupportedInLiftoff)                                         \
9551cb0ef41Sopenharmony_ci  F(Select, const Value& cond, const Value& fval, const Value& tval,           \
9561cb0ef41Sopenharmony_ci    Value* result)                                                             \
9571cb0ef41Sopenharmony_ci  F(BrOrRet, uint32_t depth, uint32_t drop_values)                             \
9581cb0ef41Sopenharmony_ci  F(BrIf, const Value& cond, uint32_t depth)                                   \
9591cb0ef41Sopenharmony_ci  F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key)      \
9601cb0ef41Sopenharmony_ci  F(Else, Control* if_block)                                                   \
9611cb0ef41Sopenharmony_ci  F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm,        \
9621cb0ef41Sopenharmony_ci    const Value& index, Value* result)                                         \
9631cb0ef41Sopenharmony_ci  F(LoadTransform, LoadType type, LoadTransformationKind transform,            \
9641cb0ef41Sopenharmony_ci    const MemoryAccessImmediate<validate>& imm, const Value& index,            \
9651cb0ef41Sopenharmony_ci    Value* result)                                                             \
9661cb0ef41Sopenharmony_ci  F(LoadLane, LoadType type, const Value& value, const Value& index,           \
9671cb0ef41Sopenharmony_ci    const MemoryAccessImmediate<validate>& imm, const uint8_t laneidx,         \
9681cb0ef41Sopenharmony_ci    Value* result)                                                             \
9691cb0ef41Sopenharmony_ci  F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm,      \
9701cb0ef41Sopenharmony_ci    const Value& index, const Value& value)                                    \
9711cb0ef41Sopenharmony_ci  F(StoreLane, StoreType type, const MemoryAccessImmediate<validate>& imm,     \
9721cb0ef41Sopenharmony_ci    const Value& index, const Value& value, const uint8_t laneidx)             \
9731cb0ef41Sopenharmony_ci  F(CurrentMemoryPages, Value* result)                                         \
9741cb0ef41Sopenharmony_ci  F(MemoryGrow, const Value& value, Value* result)                             \
9751cb0ef41Sopenharmony_ci  F(CallDirect, const CallFunctionImmediate<validate>& imm,                    \
9761cb0ef41Sopenharmony_ci    const Value args[], Value returns[])                                       \
9771cb0ef41Sopenharmony_ci  F(CallIndirect, const Value& index,                                          \
9781cb0ef41Sopenharmony_ci    const CallIndirectImmediate<validate>& imm, const Value args[],            \
9791cb0ef41Sopenharmony_ci    Value returns[])                                                           \
9801cb0ef41Sopenharmony_ci  F(CallRef, const Value& func_ref, const FunctionSig* sig,                    \
9811cb0ef41Sopenharmony_ci    uint32_t sig_index, const Value args[], const Value returns[])             \
9821cb0ef41Sopenharmony_ci  F(ReturnCallRef, const Value& func_ref, const FunctionSig* sig,              \
9831cb0ef41Sopenharmony_ci    uint32_t sig_index, const Value args[])                                    \
9841cb0ef41Sopenharmony_ci  F(ReturnCall, const CallFunctionImmediate<validate>& imm,                    \
9851cb0ef41Sopenharmony_ci    const Value args[])                                                        \
9861cb0ef41Sopenharmony_ci  F(ReturnCallIndirect, const Value& index,                                    \
9871cb0ef41Sopenharmony_ci    const CallIndirectImmediate<validate>& imm, const Value args[])            \
9881cb0ef41Sopenharmony_ci  F(BrOnNull, const Value& ref_object, uint32_t depth,                         \
9891cb0ef41Sopenharmony_ci    bool pass_null_along_branch, Value* result_on_fallthrough)                 \
9901cb0ef41Sopenharmony_ci  F(BrOnNonNull, const Value& ref_object, uint32_t depth)                      \
9911cb0ef41Sopenharmony_ci  F(SimdOp, WasmOpcode opcode, base::Vector<Value> args, Value* result)        \
9921cb0ef41Sopenharmony_ci  F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm,     \
9931cb0ef41Sopenharmony_ci    const base::Vector<Value> inputs, Value* result)                           \
9941cb0ef41Sopenharmony_ci  F(S128Const, const Simd128Immediate<validate>& imm, Value* result)           \
9951cb0ef41Sopenharmony_ci  F(Simd8x16ShuffleOp, const Simd128Immediate<validate>& imm,                  \
9961cb0ef41Sopenharmony_ci    const Value& input0, const Value& input1, Value* result)                   \
9971cb0ef41Sopenharmony_ci  F(Throw, const TagIndexImmediate<validate>& imm,                             \
9981cb0ef41Sopenharmony_ci    const base::Vector<Value>& args)                                           \
9991cb0ef41Sopenharmony_ci  F(Rethrow, Control* block)                                                   \
10001cb0ef41Sopenharmony_ci  F(CatchException, const TagIndexImmediate<validate>& imm, Control* block,    \
10011cb0ef41Sopenharmony_ci    base::Vector<Value> caught_values)                                         \
10021cb0ef41Sopenharmony_ci  F(Delegate, uint32_t depth, Control* block)                                  \
10031cb0ef41Sopenharmony_ci  F(CatchAll, Control* block)                                                  \
10041cb0ef41Sopenharmony_ci  F(AtomicOp, WasmOpcode opcode, base::Vector<Value> args,                     \
10051cb0ef41Sopenharmony_ci    const MemoryAccessImmediate<validate>& imm, Value* result)                 \
10061cb0ef41Sopenharmony_ci  F(AtomicFence)                                                               \
10071cb0ef41Sopenharmony_ci  F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst,    \
10081cb0ef41Sopenharmony_ci    const Value& src, const Value& size)                                       \
10091cb0ef41Sopenharmony_ci  F(DataDrop, const IndexImmediate<validate>& imm)                             \
10101cb0ef41Sopenharmony_ci  F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst,    \
10111cb0ef41Sopenharmony_ci    const Value& src, const Value& size)                                       \
10121cb0ef41Sopenharmony_ci  F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst,   \
10131cb0ef41Sopenharmony_ci    const Value& value, const Value& size)                                     \
10141cb0ef41Sopenharmony_ci  F(TableInit, const TableInitImmediate<validate>& imm,                        \
10151cb0ef41Sopenharmony_ci    base::Vector<Value> args)                                                  \
10161cb0ef41Sopenharmony_ci  F(ElemDrop, const IndexImmediate<validate>& imm)                             \
10171cb0ef41Sopenharmony_ci  F(TableCopy, const TableCopyImmediate<validate>& imm,                        \
10181cb0ef41Sopenharmony_ci    base::Vector<Value> args)                                                  \
10191cb0ef41Sopenharmony_ci  F(TableGrow, const IndexImmediate<validate>& imm, const Value& value,        \
10201cb0ef41Sopenharmony_ci    const Value& delta, Value* result)                                         \
10211cb0ef41Sopenharmony_ci  F(TableSize, const IndexImmediate<validate>& imm, Value* result)             \
10221cb0ef41Sopenharmony_ci  F(TableFill, const IndexImmediate<validate>& imm, const Value& start,        \
10231cb0ef41Sopenharmony_ci    const Value& value, const Value& count)                                    \
10241cb0ef41Sopenharmony_ci  F(StructGet, const Value& struct_object,                                     \
10251cb0ef41Sopenharmony_ci    const FieldImmediate<validate>& field, bool is_signed, Value* result)      \
10261cb0ef41Sopenharmony_ci  F(StructSet, const Value& struct_object,                                     \
10271cb0ef41Sopenharmony_ci    const FieldImmediate<validate>& field, const Value& field_value)           \
10281cb0ef41Sopenharmony_ci  F(ArrayNewWithRtt, const ArrayIndexImmediate<validate>& imm,                 \
10291cb0ef41Sopenharmony_ci    const Value& length, const Value& initial_value, const Value& rtt,         \
10301cb0ef41Sopenharmony_ci    Value* result)                                                             \
10311cb0ef41Sopenharmony_ci  F(ArrayNewDefault, const ArrayIndexImmediate<validate>& imm,                 \
10321cb0ef41Sopenharmony_ci    const Value& length, const Value& rtt, Value* result)                      \
10331cb0ef41Sopenharmony_ci  F(ArrayGet, const Value& array_obj,                                          \
10341cb0ef41Sopenharmony_ci    const ArrayIndexImmediate<validate>& imm, const Value& index,              \
10351cb0ef41Sopenharmony_ci    bool is_signed, Value* result)                                             \
10361cb0ef41Sopenharmony_ci  F(ArraySet, const Value& array_obj,                                          \
10371cb0ef41Sopenharmony_ci    const ArrayIndexImmediate<validate>& imm, const Value& index,              \
10381cb0ef41Sopenharmony_ci    const Value& value)                                                        \
10391cb0ef41Sopenharmony_ci  F(ArrayLen, const Value& array_obj, Value* result)                           \
10401cb0ef41Sopenharmony_ci  F(ArrayCopy, const Value& src, const Value& src_index, const Value& dst,     \
10411cb0ef41Sopenharmony_ci    const Value& dst_index, const Value& length)                               \
10421cb0ef41Sopenharmony_ci  F(I31New, const Value& input, Value* result)                                 \
10431cb0ef41Sopenharmony_ci  F(I31GetS, const Value& input, Value* result)                                \
10441cb0ef41Sopenharmony_ci  F(I31GetU, const Value& input, Value* result)                                \
10451cb0ef41Sopenharmony_ci  F(RefTest, const Value& obj, const Value& rtt, Value* result)                \
10461cb0ef41Sopenharmony_ci  F(RefCast, const Value& obj, const Value& rtt, Value* result)                \
10471cb0ef41Sopenharmony_ci  F(AssertNull, const Value& obj, Value* result)                               \
10481cb0ef41Sopenharmony_ci  F(BrOnCast, const Value& obj, const Value& rtt, Value* result_on_branch,     \
10491cb0ef41Sopenharmony_ci    uint32_t depth)                                                            \
10501cb0ef41Sopenharmony_ci  F(BrOnCastFail, const Value& obj, const Value& rtt,                          \
10511cb0ef41Sopenharmony_ci    Value* result_on_fallthrough, uint32_t depth)                              \
10521cb0ef41Sopenharmony_ci  F(RefIsFunc, const Value& object, Value* result)                             \
10531cb0ef41Sopenharmony_ci  F(RefIsData, const Value& object, Value* result)                             \
10541cb0ef41Sopenharmony_ci  F(RefIsI31, const Value& object, Value* result)                              \
10551cb0ef41Sopenharmony_ci  F(RefIsArray, const Value& object, Value* result)                            \
10561cb0ef41Sopenharmony_ci  F(RefAsFunc, const Value& object, Value* result)                             \
10571cb0ef41Sopenharmony_ci  F(RefAsData, const Value& object, Value* result)                             \
10581cb0ef41Sopenharmony_ci  F(RefAsI31, const Value& object, Value* result)                              \
10591cb0ef41Sopenharmony_ci  F(RefAsArray, const Value& object, Value* result)                            \
10601cb0ef41Sopenharmony_ci  F(BrOnFunc, const Value& object, Value* value_on_branch, uint32_t br_depth)  \
10611cb0ef41Sopenharmony_ci  F(BrOnData, const Value& object, Value* value_on_branch, uint32_t br_depth)  \
10621cb0ef41Sopenharmony_ci  F(BrOnI31, const Value& object, Value* value_on_branch, uint32_t br_depth)   \
10631cb0ef41Sopenharmony_ci  F(BrOnArray, const Value& object, Value* value_on_branch, uint32_t br_depth) \
10641cb0ef41Sopenharmony_ci  F(BrOnNonFunc, const Value& object, Value* value_on_fallthrough,             \
10651cb0ef41Sopenharmony_ci    uint32_t br_depth)                                                         \
10661cb0ef41Sopenharmony_ci  F(BrOnNonData, const Value& object, Value* value_on_fallthrough,             \
10671cb0ef41Sopenharmony_ci    uint32_t br_depth)                                                         \
10681cb0ef41Sopenharmony_ci  F(BrOnNonI31, const Value& object, Value* value_on_fallthrough,              \
10691cb0ef41Sopenharmony_ci    uint32_t br_depth)                                                         \
10701cb0ef41Sopenharmony_ci  F(BrOnNonArray, const Value& object, Value* value_on_fallthrough,            \
10711cb0ef41Sopenharmony_ci    uint32_t br_depth)
10721cb0ef41Sopenharmony_ci
10731cb0ef41Sopenharmony_ci// Generic Wasm bytecode decoder with utilities for decoding immediates,
10741cb0ef41Sopenharmony_ci// lengths, etc.
10751cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate, DecodingMode decoding_mode>
10761cb0ef41Sopenharmony_ciclass WasmDecoder : public Decoder {
10771cb0ef41Sopenharmony_ci public:
10781cb0ef41Sopenharmony_ci  WasmDecoder(Zone* zone, const WasmModule* module, const WasmFeatures& enabled,
10791cb0ef41Sopenharmony_ci              WasmFeatures* detected, const FunctionSig* sig, const byte* start,
10801cb0ef41Sopenharmony_ci              const byte* end, uint32_t buffer_offset = 0)
10811cb0ef41Sopenharmony_ci      : Decoder(start, end, buffer_offset),
10821cb0ef41Sopenharmony_ci        local_types_(zone),
10831cb0ef41Sopenharmony_ci        initialized_locals_(zone),
10841cb0ef41Sopenharmony_ci        locals_initializers_stack_(zone),
10851cb0ef41Sopenharmony_ci        module_(module),
10861cb0ef41Sopenharmony_ci        enabled_(enabled),
10871cb0ef41Sopenharmony_ci        detected_(detected),
10881cb0ef41Sopenharmony_ci        sig_(sig) {}
10891cb0ef41Sopenharmony_ci
10901cb0ef41Sopenharmony_ci  Zone* zone() const { return local_types_.get_allocator().zone(); }
10911cb0ef41Sopenharmony_ci
10921cb0ef41Sopenharmony_ci  uint32_t num_locals() const {
10931cb0ef41Sopenharmony_ci    DCHECK_EQ(num_locals_, local_types_.size());
10941cb0ef41Sopenharmony_ci    return num_locals_;
10951cb0ef41Sopenharmony_ci  }
10961cb0ef41Sopenharmony_ci
10971cb0ef41Sopenharmony_ci  ValueType local_type(uint32_t index) const { return local_types_[index]; }
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci  void InitializeLocalsFromSig() {
11001cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(sig_);
11011cb0ef41Sopenharmony_ci    DCHECK_EQ(0, this->local_types_.size());
11021cb0ef41Sopenharmony_ci    local_types_.assign(sig_->parameters().begin(), sig_->parameters().end());
11031cb0ef41Sopenharmony_ci    num_locals_ = static_cast<uint32_t>(sig_->parameters().size());
11041cb0ef41Sopenharmony_ci  }
11051cb0ef41Sopenharmony_ci
11061cb0ef41Sopenharmony_ci  // Decodes local definitions in the current decoder.
11071cb0ef41Sopenharmony_ci  // Returns the number of newly defined locals, or -1 if decoding failed.
11081cb0ef41Sopenharmony_ci  // Writes the total length of decoded locals in {total_length}.
11091cb0ef41Sopenharmony_ci  // If {insert_position} is defined, the decoded locals will be inserted into
11101cb0ef41Sopenharmony_ci  // the {this->local_types_}. The decoder's pc is not advanced.
11111cb0ef41Sopenharmony_ci  int DecodeLocals(const byte* pc, uint32_t* total_length,
11121cb0ef41Sopenharmony_ci                   const base::Optional<uint32_t> insert_position) {
11131cb0ef41Sopenharmony_ci    uint32_t length;
11141cb0ef41Sopenharmony_ci    *total_length = 0;
11151cb0ef41Sopenharmony_ci    int total_count = 0;
11161cb0ef41Sopenharmony_ci
11171cb0ef41Sopenharmony_ci    // The 'else' value is useless, we pass it for convenience.
11181cb0ef41Sopenharmony_ci    auto insert_iterator = insert_position.has_value()
11191cb0ef41Sopenharmony_ci                               ? local_types_.begin() + insert_position.value()
11201cb0ef41Sopenharmony_ci                               : local_types_.begin();
11211cb0ef41Sopenharmony_ci
11221cb0ef41Sopenharmony_ci    // Decode local declarations, if any.
11231cb0ef41Sopenharmony_ci    uint32_t entries = read_u32v<validate>(pc, &length, "local decls count");
11241cb0ef41Sopenharmony_ci    if (!VALIDATE(ok())) {
11251cb0ef41Sopenharmony_ci      DecodeError(pc + *total_length, "invalid local decls count");
11261cb0ef41Sopenharmony_ci      return -1;
11271cb0ef41Sopenharmony_ci    }
11281cb0ef41Sopenharmony_ci    *total_length += length;
11291cb0ef41Sopenharmony_ci    TRACE("local decls count: %u\n", entries);
11301cb0ef41Sopenharmony_ci
11311cb0ef41Sopenharmony_ci    while (entries-- > 0) {
11321cb0ef41Sopenharmony_ci      if (!VALIDATE(more())) {
11331cb0ef41Sopenharmony_ci        DecodeError(end(),
11341cb0ef41Sopenharmony_ci                    "expected more local decls but reached end of input");
11351cb0ef41Sopenharmony_ci        return -1;
11361cb0ef41Sopenharmony_ci      }
11371cb0ef41Sopenharmony_ci
11381cb0ef41Sopenharmony_ci      uint32_t count =
11391cb0ef41Sopenharmony_ci          read_u32v<validate>(pc + *total_length, &length, "local count");
11401cb0ef41Sopenharmony_ci      if (!VALIDATE(ok())) {
11411cb0ef41Sopenharmony_ci        DecodeError(pc + *total_length, "invalid local count");
11421cb0ef41Sopenharmony_ci        return -1;
11431cb0ef41Sopenharmony_ci      }
11441cb0ef41Sopenharmony_ci      DCHECK_LE(local_types_.size(), kV8MaxWasmFunctionLocals);
11451cb0ef41Sopenharmony_ci      if (!VALIDATE(count <= kV8MaxWasmFunctionLocals - local_types_.size())) {
11461cb0ef41Sopenharmony_ci        DecodeError(pc + *total_length, "local count too large");
11471cb0ef41Sopenharmony_ci        return -1;
11481cb0ef41Sopenharmony_ci      }
11491cb0ef41Sopenharmony_ci      *total_length += length;
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci      ValueType type = value_type_reader::read_value_type<validate>(
11521cb0ef41Sopenharmony_ci          this, pc + *total_length, &length, this->module_, enabled_);
11531cb0ef41Sopenharmony_ci      if (!VALIDATE(type != kWasmBottom)) return -1;
11541cb0ef41Sopenharmony_ci      *total_length += length;
11551cb0ef41Sopenharmony_ci      total_count += count;
11561cb0ef41Sopenharmony_ci
11571cb0ef41Sopenharmony_ci      if (insert_position.has_value()) {
11581cb0ef41Sopenharmony_ci        // Move the insertion iterator to the end of the newly inserted locals.
11591cb0ef41Sopenharmony_ci        insert_iterator =
11601cb0ef41Sopenharmony_ci            local_types_.insert(insert_iterator, count, type) + count;
11611cb0ef41Sopenharmony_ci        num_locals_ += count;
11621cb0ef41Sopenharmony_ci      }
11631cb0ef41Sopenharmony_ci    }
11641cb0ef41Sopenharmony_ci
11651cb0ef41Sopenharmony_ci    DCHECK(ok());
11661cb0ef41Sopenharmony_ci    return total_count;
11671cb0ef41Sopenharmony_ci  }
11681cb0ef41Sopenharmony_ci
11691cb0ef41Sopenharmony_ci  // Shorthand that forwards to the {DecodeError} functions above, passing our
11701cb0ef41Sopenharmony_ci  // {validate} flag.
11711cb0ef41Sopenharmony_ci  template <typename... Args>
11721cb0ef41Sopenharmony_ci  void DecodeError(Args... args) {
11731cb0ef41Sopenharmony_ci    wasm::DecodeError<validate>(this, std::forward<Args>(args)...);
11741cb0ef41Sopenharmony_ci  }
11751cb0ef41Sopenharmony_ci
11761cb0ef41Sopenharmony_ci  // Returns a BitVector of length {locals_count + 1} representing the set of
11771cb0ef41Sopenharmony_ci  // variables that are assigned in the loop starting at {pc}. The additional
11781cb0ef41Sopenharmony_ci  // position at the end of the vector represents possible assignments to
11791cb0ef41Sopenharmony_ci  // the instance cache.
11801cb0ef41Sopenharmony_ci  static BitVector* AnalyzeLoopAssignment(WasmDecoder* decoder, const byte* pc,
11811cb0ef41Sopenharmony_ci                                          uint32_t locals_count, Zone* zone) {
11821cb0ef41Sopenharmony_ci    if (pc >= decoder->end()) return nullptr;
11831cb0ef41Sopenharmony_ci    if (*pc != kExprLoop) return nullptr;
11841cb0ef41Sopenharmony_ci    // The number of locals_count is augmented by 1 so that the 'locals_count'
11851cb0ef41Sopenharmony_ci    // index can be used to track the instance cache.
11861cb0ef41Sopenharmony_ci    BitVector* assigned = zone->New<BitVector>(locals_count + 1, zone);
11871cb0ef41Sopenharmony_ci    int depth = -1;  // We will increment the depth to 0 when we decode the
11881cb0ef41Sopenharmony_ci                     // starting 'loop' opcode.
11891cb0ef41Sopenharmony_ci    // Since 'let' can add additional locals at the beginning of the locals
11901cb0ef41Sopenharmony_ci    // index space, we need to track this offset for every depth up to the
11911cb0ef41Sopenharmony_ci    // current depth.
11921cb0ef41Sopenharmony_ci    base::SmallVector<uint32_t, 8> local_offsets(8);
11931cb0ef41Sopenharmony_ci    // Iteratively process all AST nodes nested inside the loop.
11941cb0ef41Sopenharmony_ci    while (pc < decoder->end() && VALIDATE(decoder->ok())) {
11951cb0ef41Sopenharmony_ci      WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
11961cb0ef41Sopenharmony_ci      switch (opcode) {
11971cb0ef41Sopenharmony_ci        case kExprLoop:
11981cb0ef41Sopenharmony_ci        case kExprIf:
11991cb0ef41Sopenharmony_ci        case kExprBlock:
12001cb0ef41Sopenharmony_ci        case kExprTry:
12011cb0ef41Sopenharmony_ci          depth++;
12021cb0ef41Sopenharmony_ci          local_offsets.resize_no_init(depth + 1);
12031cb0ef41Sopenharmony_ci          // No additional locals.
12041cb0ef41Sopenharmony_ci          local_offsets[depth] = depth > 0 ? local_offsets[depth - 1] : 0;
12051cb0ef41Sopenharmony_ci          break;
12061cb0ef41Sopenharmony_ci        case kExprLet: {
12071cb0ef41Sopenharmony_ci          depth++;
12081cb0ef41Sopenharmony_ci          local_offsets.resize_no_init(depth + 1);
12091cb0ef41Sopenharmony_ci          BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
12101cb0ef41Sopenharmony_ci                                           nullptr);
12111cb0ef41Sopenharmony_ci          uint32_t locals_length;
12121cb0ef41Sopenharmony_ci          int new_locals_count = decoder->DecodeLocals(
12131cb0ef41Sopenharmony_ci              pc + 1 + imm.length, &locals_length, base::Optional<uint32_t>());
12141cb0ef41Sopenharmony_ci          local_offsets[depth] = local_offsets[depth - 1] + new_locals_count;
12151cb0ef41Sopenharmony_ci          break;
12161cb0ef41Sopenharmony_ci        }
12171cb0ef41Sopenharmony_ci        case kExprLocalSet:
12181cb0ef41Sopenharmony_ci        case kExprLocalTee: {
12191cb0ef41Sopenharmony_ci          IndexImmediate<validate> imm(decoder, pc + 1, "local index");
12201cb0ef41Sopenharmony_ci          // Unverified code might have an out-of-bounds index.
12211cb0ef41Sopenharmony_ci          if (imm.index >= local_offsets[depth] &&
12221cb0ef41Sopenharmony_ci              imm.index - local_offsets[depth] < locals_count) {
12231cb0ef41Sopenharmony_ci            assigned->Add(imm.index - local_offsets[depth]);
12241cb0ef41Sopenharmony_ci          }
12251cb0ef41Sopenharmony_ci          break;
12261cb0ef41Sopenharmony_ci        }
12271cb0ef41Sopenharmony_ci        case kExprMemoryGrow:
12281cb0ef41Sopenharmony_ci        case kExprCallFunction:
12291cb0ef41Sopenharmony_ci        case kExprCallIndirect:
12301cb0ef41Sopenharmony_ci        case kExprCallRef:
12311cb0ef41Sopenharmony_ci          // Add instance cache to the assigned set.
12321cb0ef41Sopenharmony_ci          assigned->Add(locals_count);
12331cb0ef41Sopenharmony_ci          break;
12341cb0ef41Sopenharmony_ci        case kExprEnd:
12351cb0ef41Sopenharmony_ci          depth--;
12361cb0ef41Sopenharmony_ci          break;
12371cb0ef41Sopenharmony_ci        default:
12381cb0ef41Sopenharmony_ci          break;
12391cb0ef41Sopenharmony_ci      }
12401cb0ef41Sopenharmony_ci      if (depth < 0) break;
12411cb0ef41Sopenharmony_ci      pc += OpcodeLength(decoder, pc);
12421cb0ef41Sopenharmony_ci    }
12431cb0ef41Sopenharmony_ci    return VALIDATE(decoder->ok()) ? assigned : nullptr;
12441cb0ef41Sopenharmony_ci  }
12451cb0ef41Sopenharmony_ci
12461cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, TagIndexImmediate<validate>& imm) {
12471cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->tags.size())) {
12481cb0ef41Sopenharmony_ci      DecodeError(pc, "Invalid tag index: %u", imm.index);
12491cb0ef41Sopenharmony_ci      return false;
12501cb0ef41Sopenharmony_ci    }
12511cb0ef41Sopenharmony_ci    imm.tag = &module_->tags[imm.index];
12521cb0ef41Sopenharmony_ci    return true;
12531cb0ef41Sopenharmony_ci  }
12541cb0ef41Sopenharmony_ci
12551cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
12561cb0ef41Sopenharmony_ci    // We compare with the current size of the globals vector. This is important
12571cb0ef41Sopenharmony_ci    // if we are decoding a constant expression in the global section.
12581cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->globals.size())) {
12591cb0ef41Sopenharmony_ci      DecodeError(pc, "Invalid global index: %u", imm.index);
12601cb0ef41Sopenharmony_ci      return false;
12611cb0ef41Sopenharmony_ci    }
12621cb0ef41Sopenharmony_ci    imm.global = &module_->globals[imm.index];
12631cb0ef41Sopenharmony_ci
12641cb0ef41Sopenharmony_ci    if (decoding_mode == kInitExpression) {
12651cb0ef41Sopenharmony_ci      if (!VALIDATE(!imm.global->mutability)) {
12661cb0ef41Sopenharmony_ci        this->DecodeError(pc,
12671cb0ef41Sopenharmony_ci                          "mutable globals cannot be used in initializer "
12681cb0ef41Sopenharmony_ci                          "expressions");
12691cb0ef41Sopenharmony_ci        return false;
12701cb0ef41Sopenharmony_ci      }
12711cb0ef41Sopenharmony_ci      if (!VALIDATE(imm.global->imported || this->enabled_.has_gc())) {
12721cb0ef41Sopenharmony_ci        this->DecodeError(
12731cb0ef41Sopenharmony_ci            pc,
12741cb0ef41Sopenharmony_ci            "non-imported globals cannot be used in initializer expressions");
12751cb0ef41Sopenharmony_ci        return false;
12761cb0ef41Sopenharmony_ci      }
12771cb0ef41Sopenharmony_ci    }
12781cb0ef41Sopenharmony_ci
12791cb0ef41Sopenharmony_ci    return true;
12801cb0ef41Sopenharmony_ci  }
12811cb0ef41Sopenharmony_ci
12821cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, StructIndexImmediate<validate>& imm) {
12831cb0ef41Sopenharmony_ci    if (!VALIDATE(module_->has_struct(imm.index))) {
12841cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid struct index: %u", imm.index);
12851cb0ef41Sopenharmony_ci      return false;
12861cb0ef41Sopenharmony_ci    }
12871cb0ef41Sopenharmony_ci    imm.struct_type = module_->struct_type(imm.index);
12881cb0ef41Sopenharmony_ci    return true;
12891cb0ef41Sopenharmony_ci  }
12901cb0ef41Sopenharmony_ci
12911cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, FieldImmediate<validate>& imm) {
12921cb0ef41Sopenharmony_ci    if (!Validate(pc, imm.struct_imm)) return false;
12931cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.field_imm.index <
12941cb0ef41Sopenharmony_ci                  imm.struct_imm.struct_type->field_count())) {
12951cb0ef41Sopenharmony_ci      DecodeError(pc + imm.struct_imm.length, "invalid field index: %u",
12961cb0ef41Sopenharmony_ci                  imm.field_imm.index);
12971cb0ef41Sopenharmony_ci      return false;
12981cb0ef41Sopenharmony_ci    }
12991cb0ef41Sopenharmony_ci    return true;
13001cb0ef41Sopenharmony_ci  }
13011cb0ef41Sopenharmony_ci
13021cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, ArrayIndexImmediate<validate>& imm) {
13031cb0ef41Sopenharmony_ci    if (!VALIDATE(module_->has_array(imm.index))) {
13041cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid array index: %u", imm.index);
13051cb0ef41Sopenharmony_ci      return false;
13061cb0ef41Sopenharmony_ci    }
13071cb0ef41Sopenharmony_ci    imm.array_type = module_->array_type(imm.index);
13081cb0ef41Sopenharmony_ci    return true;
13091cb0ef41Sopenharmony_ci  }
13101cb0ef41Sopenharmony_ci
13111cb0ef41Sopenharmony_ci  bool CanReturnCall(const FunctionSig* target_sig) {
13121cb0ef41Sopenharmony_ci    if (sig_->return_count() != target_sig->return_count()) return false;
13131cb0ef41Sopenharmony_ci    auto target_sig_it = target_sig->returns().begin();
13141cb0ef41Sopenharmony_ci    for (ValueType ret_type : sig_->returns()) {
13151cb0ef41Sopenharmony_ci      if (!IsSubtypeOf(*target_sig_it++, ret_type, this->module_)) return false;
13161cb0ef41Sopenharmony_ci    }
13171cb0ef41Sopenharmony_ci    return true;
13181cb0ef41Sopenharmony_ci  }
13191cb0ef41Sopenharmony_ci
13201cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
13211cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->functions.size())) {
13221cb0ef41Sopenharmony_ci      DecodeError(pc, "function index #%u is out of bounds", imm.index);
13231cb0ef41Sopenharmony_ci      return false;
13241cb0ef41Sopenharmony_ci    }
13251cb0ef41Sopenharmony_ci    imm.sig = module_->functions[imm.index].sig;
13261cb0ef41Sopenharmony_ci    return true;
13271cb0ef41Sopenharmony_ci  }
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
13301cb0ef41Sopenharmony_ci    if (!ValidateSignature(pc, imm.sig_imm)) return false;
13311cb0ef41Sopenharmony_ci    if (!ValidateTable(pc + imm.sig_imm.length, imm.table_imm)) {
13321cb0ef41Sopenharmony_ci      return false;
13331cb0ef41Sopenharmony_ci    }
13341cb0ef41Sopenharmony_ci    ValueType table_type = module_->tables[imm.table_imm.index].type;
13351cb0ef41Sopenharmony_ci    if (!VALIDATE(IsSubtypeOf(table_type, kWasmFuncRef, module_))) {
13361cb0ef41Sopenharmony_ci      DecodeError(
13371cb0ef41Sopenharmony_ci          pc, "call_indirect: immediate table #%u is not of a function type",
13381cb0ef41Sopenharmony_ci          imm.table_imm.index);
13391cb0ef41Sopenharmony_ci      return false;
13401cb0ef41Sopenharmony_ci    }
13411cb0ef41Sopenharmony_ci
13421cb0ef41Sopenharmony_ci    // Check that the dynamic signature for this call is a subtype of the static
13431cb0ef41Sopenharmony_ci    // type of the table the function is defined in.
13441cb0ef41Sopenharmony_ci    ValueType immediate_type = ValueType::Ref(imm.sig_imm.index, kNonNullable);
13451cb0ef41Sopenharmony_ci    if (!VALIDATE(IsSubtypeOf(immediate_type, table_type, module_))) {
13461cb0ef41Sopenharmony_ci      DecodeError(pc,
13471cb0ef41Sopenharmony_ci                  "call_indirect: Immediate signature #%u is not a subtype of "
13481cb0ef41Sopenharmony_ci                  "immediate table #%u",
13491cb0ef41Sopenharmony_ci                  imm.sig_imm.index, imm.table_imm.index);
13501cb0ef41Sopenharmony_ci      return false;
13511cb0ef41Sopenharmony_ci    }
13521cb0ef41Sopenharmony_ci
13531cb0ef41Sopenharmony_ci    imm.sig = module_->signature(imm.sig_imm.index);
13541cb0ef41Sopenharmony_ci    return true;
13551cb0ef41Sopenharmony_ci  }
13561cb0ef41Sopenharmony_ci
13571cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, BranchDepthImmediate<validate>& imm,
13581cb0ef41Sopenharmony_ci                size_t control_depth) {
13591cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.depth < control_depth)) {
13601cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid branch depth: %u", imm.depth);
13611cb0ef41Sopenharmony_ci      return false;
13621cb0ef41Sopenharmony_ci    }
13631cb0ef41Sopenharmony_ci    return true;
13641cb0ef41Sopenharmony_ci  }
13651cb0ef41Sopenharmony_ci
13661cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
13671cb0ef41Sopenharmony_ci                size_t block_depth) {
13681cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.table_count <= kV8MaxWasmFunctionBrTableSize)) {
13691cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid table count (> max br_table size): %u",
13701cb0ef41Sopenharmony_ci                  imm.table_count);
13711cb0ef41Sopenharmony_ci      return false;
13721cb0ef41Sopenharmony_ci    }
13731cb0ef41Sopenharmony_ci    return checkAvailable(imm.table_count);
13741cb0ef41Sopenharmony_ci  }
13751cb0ef41Sopenharmony_ci
13761cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, WasmOpcode opcode,
13771cb0ef41Sopenharmony_ci                SimdLaneImmediate<validate>& imm) {
13781cb0ef41Sopenharmony_ci    uint8_t num_lanes = 0;
13791cb0ef41Sopenharmony_ci    switch (opcode) {
13801cb0ef41Sopenharmony_ci      case kExprF64x2ExtractLane:
13811cb0ef41Sopenharmony_ci      case kExprF64x2ReplaceLane:
13821cb0ef41Sopenharmony_ci      case kExprI64x2ExtractLane:
13831cb0ef41Sopenharmony_ci      case kExprI64x2ReplaceLane:
13841cb0ef41Sopenharmony_ci      case kExprS128Load64Lane:
13851cb0ef41Sopenharmony_ci      case kExprS128Store64Lane:
13861cb0ef41Sopenharmony_ci        num_lanes = 2;
13871cb0ef41Sopenharmony_ci        break;
13881cb0ef41Sopenharmony_ci      case kExprF32x4ExtractLane:
13891cb0ef41Sopenharmony_ci      case kExprF32x4ReplaceLane:
13901cb0ef41Sopenharmony_ci      case kExprI32x4ExtractLane:
13911cb0ef41Sopenharmony_ci      case kExprI32x4ReplaceLane:
13921cb0ef41Sopenharmony_ci      case kExprS128Load32Lane:
13931cb0ef41Sopenharmony_ci      case kExprS128Store32Lane:
13941cb0ef41Sopenharmony_ci        num_lanes = 4;
13951cb0ef41Sopenharmony_ci        break;
13961cb0ef41Sopenharmony_ci      case kExprI16x8ExtractLaneS:
13971cb0ef41Sopenharmony_ci      case kExprI16x8ExtractLaneU:
13981cb0ef41Sopenharmony_ci      case kExprI16x8ReplaceLane:
13991cb0ef41Sopenharmony_ci      case kExprS128Load16Lane:
14001cb0ef41Sopenharmony_ci      case kExprS128Store16Lane:
14011cb0ef41Sopenharmony_ci        num_lanes = 8;
14021cb0ef41Sopenharmony_ci        break;
14031cb0ef41Sopenharmony_ci      case kExprI8x16ExtractLaneS:
14041cb0ef41Sopenharmony_ci      case kExprI8x16ExtractLaneU:
14051cb0ef41Sopenharmony_ci      case kExprI8x16ReplaceLane:
14061cb0ef41Sopenharmony_ci      case kExprS128Load8Lane:
14071cb0ef41Sopenharmony_ci      case kExprS128Store8Lane:
14081cb0ef41Sopenharmony_ci        num_lanes = 16;
14091cb0ef41Sopenharmony_ci        break;
14101cb0ef41Sopenharmony_ci      default:
14111cb0ef41Sopenharmony_ci        UNREACHABLE();
14121cb0ef41Sopenharmony_ci        break;
14131cb0ef41Sopenharmony_ci    }
14141cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
14151cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid lane index");
14161cb0ef41Sopenharmony_ci      return false;
14171cb0ef41Sopenharmony_ci    } else {
14181cb0ef41Sopenharmony_ci      return true;
14191cb0ef41Sopenharmony_ci    }
14201cb0ef41Sopenharmony_ci  }
14211cb0ef41Sopenharmony_ci
14221cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, Simd128Immediate<validate>& imm) {
14231cb0ef41Sopenharmony_ci    uint8_t max_lane = 0;
14241cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < kSimd128Size; ++i) {
14251cb0ef41Sopenharmony_ci      max_lane = std::max(max_lane, imm.value[i]);
14261cb0ef41Sopenharmony_ci    }
14271cb0ef41Sopenharmony_ci    // Shuffle indices must be in [0..31] for a 16 lane shuffle.
14281cb0ef41Sopenharmony_ci    if (!VALIDATE(max_lane < 2 * kSimd128Size)) {
14291cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid shuffle mask");
14301cb0ef41Sopenharmony_ci      return false;
14311cb0ef41Sopenharmony_ci    }
14321cb0ef41Sopenharmony_ci    return true;
14331cb0ef41Sopenharmony_ci  }
14341cb0ef41Sopenharmony_ci
14351cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, BlockTypeImmediate<validate>& imm) {
14361cb0ef41Sopenharmony_ci    if (imm.type != kWasmBottom) return true;
14371cb0ef41Sopenharmony_ci    if (!VALIDATE(module_->has_signature(imm.sig_index))) {
14381cb0ef41Sopenharmony_ci      DecodeError(pc, "block type index %u is not a signature definition",
14391cb0ef41Sopenharmony_ci                  imm.sig_index);
14401cb0ef41Sopenharmony_ci      return false;
14411cb0ef41Sopenharmony_ci    }
14421cb0ef41Sopenharmony_ci    imm.sig = module_->signature(imm.sig_index);
14431cb0ef41Sopenharmony_ci    return true;
14441cb0ef41Sopenharmony_ci  }
14451cb0ef41Sopenharmony_ci
14461cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, MemoryIndexImmediate<validate>& imm) {
14471cb0ef41Sopenharmony_ci    if (!VALIDATE(this->module_->has_memory)) {
14481cb0ef41Sopenharmony_ci      this->DecodeError(pc, "memory instruction with no memory");
14491cb0ef41Sopenharmony_ci      return false;
14501cb0ef41Sopenharmony_ci    }
14511cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index == uint8_t{0})) {
14521cb0ef41Sopenharmony_ci      DecodeError(pc, "expected memory index 0, found %u", imm.index);
14531cb0ef41Sopenharmony_ci      return false;
14541cb0ef41Sopenharmony_ci    }
14551cb0ef41Sopenharmony_ci    return true;
14561cb0ef41Sopenharmony_ci  }
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, MemoryAccessImmediate<validate>& imm) {
14591cb0ef41Sopenharmony_ci    if (!VALIDATE(this->module_->has_memory)) {
14601cb0ef41Sopenharmony_ci      this->DecodeError(pc, "memory instruction with no memory");
14611cb0ef41Sopenharmony_ci      return false;
14621cb0ef41Sopenharmony_ci    }
14631cb0ef41Sopenharmony_ci    return true;
14641cb0ef41Sopenharmony_ci  }
14651cb0ef41Sopenharmony_ci
14661cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, MemoryInitImmediate<validate>& imm) {
14671cb0ef41Sopenharmony_ci    return ValidateDataSegment(pc, imm.data_segment) &&
14681cb0ef41Sopenharmony_ci           Validate(pc + imm.data_segment.length, imm.memory);
14691cb0ef41Sopenharmony_ci  }
14701cb0ef41Sopenharmony_ci
14711cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, MemoryCopyImmediate<validate>& imm) {
14721cb0ef41Sopenharmony_ci    return Validate(pc, imm.memory_src) &&
14731cb0ef41Sopenharmony_ci           Validate(pc + imm.memory_src.length, imm.memory_dst);
14741cb0ef41Sopenharmony_ci  }
14751cb0ef41Sopenharmony_ci
14761cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, TableInitImmediate<validate>& imm) {
14771cb0ef41Sopenharmony_ci    if (!ValidateElementSegment(pc, imm.element_segment)) return false;
14781cb0ef41Sopenharmony_ci    if (!ValidateTable(pc + imm.element_segment.length, imm.table)) {
14791cb0ef41Sopenharmony_ci      return false;
14801cb0ef41Sopenharmony_ci    }
14811cb0ef41Sopenharmony_ci    ValueType elem_type =
14821cb0ef41Sopenharmony_ci        module_->elem_segments[imm.element_segment.index].type;
14831cb0ef41Sopenharmony_ci    if (!VALIDATE(IsSubtypeOf(elem_type, module_->tables[imm.table.index].type,
14841cb0ef41Sopenharmony_ci                              module_))) {
14851cb0ef41Sopenharmony_ci      DecodeError(pc, "table %u is not a super-type of %s", imm.table.index,
14861cb0ef41Sopenharmony_ci                  elem_type.name().c_str());
14871cb0ef41Sopenharmony_ci      return false;
14881cb0ef41Sopenharmony_ci    }
14891cb0ef41Sopenharmony_ci    return true;
14901cb0ef41Sopenharmony_ci  }
14911cb0ef41Sopenharmony_ci
14921cb0ef41Sopenharmony_ci  bool Validate(const byte* pc, TableCopyImmediate<validate>& imm) {
14931cb0ef41Sopenharmony_ci    if (!ValidateTable(pc, imm.table_src)) return false;
14941cb0ef41Sopenharmony_ci    if (!ValidateTable(pc + imm.table_src.length, imm.table_dst)) return false;
14951cb0ef41Sopenharmony_ci    ValueType src_type = module_->tables[imm.table_src.index].type;
14961cb0ef41Sopenharmony_ci    if (!VALIDATE(IsSubtypeOf(
14971cb0ef41Sopenharmony_ci            src_type, module_->tables[imm.table_dst.index].type, module_))) {
14981cb0ef41Sopenharmony_ci      DecodeError(pc, "table %u is not a super-type of %s", imm.table_dst.index,
14991cb0ef41Sopenharmony_ci                  src_type.name().c_str());
15001cb0ef41Sopenharmony_ci      return false;
15011cb0ef41Sopenharmony_ci    }
15021cb0ef41Sopenharmony_ci    return true;
15031cb0ef41Sopenharmony_ci  }
15041cb0ef41Sopenharmony_ci
15051cb0ef41Sopenharmony_ci  // The following Validate* functions all validate an IndexImmediate, albeit
15061cb0ef41Sopenharmony_ci  // differently according to context.
15071cb0ef41Sopenharmony_ci  bool ValidateTable(const byte* pc, IndexImmediate<validate>& imm) {
15081cb0ef41Sopenharmony_ci    if (imm.index > 0 || imm.length > 1) {
15091cb0ef41Sopenharmony_ci      this->detected_->Add(kFeature_reftypes);
15101cb0ef41Sopenharmony_ci    }
15111cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->tables.size())) {
15121cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid table index: %u", imm.index);
15131cb0ef41Sopenharmony_ci      return false;
15141cb0ef41Sopenharmony_ci    }
15151cb0ef41Sopenharmony_ci    return true;
15161cb0ef41Sopenharmony_ci  }
15171cb0ef41Sopenharmony_ci
15181cb0ef41Sopenharmony_ci  bool ValidateElementSegment(const byte* pc, IndexImmediate<validate>& imm) {
15191cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->elem_segments.size())) {
15201cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid element segment index: %u", imm.index);
15211cb0ef41Sopenharmony_ci      return false;
15221cb0ef41Sopenharmony_ci    }
15231cb0ef41Sopenharmony_ci    return true;
15241cb0ef41Sopenharmony_ci  }
15251cb0ef41Sopenharmony_ci
15261cb0ef41Sopenharmony_ci  bool ValidateLocal(const byte* pc, IndexImmediate<validate>& imm) {
15271cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < num_locals())) {
15281cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid local index: %u", imm.index);
15291cb0ef41Sopenharmony_ci      return false;
15301cb0ef41Sopenharmony_ci    }
15311cb0ef41Sopenharmony_ci    return true;
15321cb0ef41Sopenharmony_ci  }
15331cb0ef41Sopenharmony_ci
15341cb0ef41Sopenharmony_ci  bool ValidateType(const byte* pc, IndexImmediate<validate>& imm) {
15351cb0ef41Sopenharmony_ci    if (!VALIDATE(module_->has_type(imm.index))) {
15361cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid type index: %u", imm.index);
15371cb0ef41Sopenharmony_ci      return false;
15381cb0ef41Sopenharmony_ci    }
15391cb0ef41Sopenharmony_ci    return true;
15401cb0ef41Sopenharmony_ci  }
15411cb0ef41Sopenharmony_ci
15421cb0ef41Sopenharmony_ci  bool ValidateSignature(const byte* pc, IndexImmediate<validate>& imm) {
15431cb0ef41Sopenharmony_ci    if (!VALIDATE(module_->has_signature(imm.index))) {
15441cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid signature index: %u", imm.index);
15451cb0ef41Sopenharmony_ci      return false;
15461cb0ef41Sopenharmony_ci    }
15471cb0ef41Sopenharmony_ci    return true;
15481cb0ef41Sopenharmony_ci  }
15491cb0ef41Sopenharmony_ci
15501cb0ef41Sopenharmony_ci  bool ValidateFunction(const byte* pc, IndexImmediate<validate>& imm) {
15511cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->functions.size())) {
15521cb0ef41Sopenharmony_ci      DecodeError(pc, "function index #%u is out of bounds", imm.index);
15531cb0ef41Sopenharmony_ci      return false;
15541cb0ef41Sopenharmony_ci    }
15551cb0ef41Sopenharmony_ci    if (decoding_mode == kFunctionBody &&
15561cb0ef41Sopenharmony_ci        !VALIDATE(module_->functions[imm.index].declared)) {
15571cb0ef41Sopenharmony_ci      DecodeError(pc, "undeclared reference to function #%u", imm.index);
15581cb0ef41Sopenharmony_ci      return false;
15591cb0ef41Sopenharmony_ci    }
15601cb0ef41Sopenharmony_ci    return true;
15611cb0ef41Sopenharmony_ci  }
15621cb0ef41Sopenharmony_ci
15631cb0ef41Sopenharmony_ci  bool ValidateDataSegment(const byte* pc, IndexImmediate<validate>& imm) {
15641cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.index < module_->num_declared_data_segments)) {
15651cb0ef41Sopenharmony_ci      DecodeError(pc, "invalid data segment index: %u", imm.index);
15661cb0ef41Sopenharmony_ci      return false;
15671cb0ef41Sopenharmony_ci    }
15681cb0ef41Sopenharmony_ci    return true;
15691cb0ef41Sopenharmony_ci  }
15701cb0ef41Sopenharmony_ci
15711cb0ef41Sopenharmony_ci  // Returns the length of the opcode under {pc}.
15721cb0ef41Sopenharmony_ci  static uint32_t OpcodeLength(WasmDecoder* decoder, const byte* pc) {
15731cb0ef41Sopenharmony_ci    WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
15741cb0ef41Sopenharmony_ci    // We don't have information about the module here, so we just assume that
15751cb0ef41Sopenharmony_ci    // memory64 is enabled when parsing memory access immediates. This is
15761cb0ef41Sopenharmony_ci    // backwards-compatible; decode errors will be detected at another time when
15771cb0ef41Sopenharmony_ci    // actually decoding that opcode.
15781cb0ef41Sopenharmony_ci    constexpr bool kConservativelyAssumeMemory64 = true;
15791cb0ef41Sopenharmony_ci    switch (opcode) {
15801cb0ef41Sopenharmony_ci      /********** Control opcodes **********/
15811cb0ef41Sopenharmony_ci      case kExprUnreachable:
15821cb0ef41Sopenharmony_ci      case kExprNop:
15831cb0ef41Sopenharmony_ci      case kExprNopForTestingUnsupportedInLiftoff:
15841cb0ef41Sopenharmony_ci      case kExprElse:
15851cb0ef41Sopenharmony_ci      case kExprEnd:
15861cb0ef41Sopenharmony_ci      case kExprReturn:
15871cb0ef41Sopenharmony_ci        return 1;
15881cb0ef41Sopenharmony_ci      case kExprTry:
15891cb0ef41Sopenharmony_ci      case kExprIf:
15901cb0ef41Sopenharmony_ci      case kExprLoop:
15911cb0ef41Sopenharmony_ci      case kExprBlock: {
15921cb0ef41Sopenharmony_ci        BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
15931cb0ef41Sopenharmony_ci                                         nullptr);
15941cb0ef41Sopenharmony_ci        return 1 + imm.length;
15951cb0ef41Sopenharmony_ci      }
15961cb0ef41Sopenharmony_ci      case kExprRethrow:
15971cb0ef41Sopenharmony_ci      case kExprBr:
15981cb0ef41Sopenharmony_ci      case kExprBrIf:
15991cb0ef41Sopenharmony_ci      case kExprBrOnNull:
16001cb0ef41Sopenharmony_ci      case kExprBrOnNonNull:
16011cb0ef41Sopenharmony_ci      case kExprDelegate: {
16021cb0ef41Sopenharmony_ci        BranchDepthImmediate<validate> imm(decoder, pc + 1);
16031cb0ef41Sopenharmony_ci        return 1 + imm.length;
16041cb0ef41Sopenharmony_ci      }
16051cb0ef41Sopenharmony_ci      case kExprBrTable: {
16061cb0ef41Sopenharmony_ci        BranchTableImmediate<validate> imm(decoder, pc + 1);
16071cb0ef41Sopenharmony_ci        BranchTableIterator<validate> iterator(decoder, imm);
16081cb0ef41Sopenharmony_ci        return 1 + iterator.length();
16091cb0ef41Sopenharmony_ci      }
16101cb0ef41Sopenharmony_ci      case kExprThrow:
16111cb0ef41Sopenharmony_ci      case kExprCatch: {
16121cb0ef41Sopenharmony_ci        TagIndexImmediate<validate> imm(decoder, pc + 1);
16131cb0ef41Sopenharmony_ci        return 1 + imm.length;
16141cb0ef41Sopenharmony_ci      }
16151cb0ef41Sopenharmony_ci      case kExprLet: {
16161cb0ef41Sopenharmony_ci        BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
16171cb0ef41Sopenharmony_ci                                         nullptr);
16181cb0ef41Sopenharmony_ci        uint32_t locals_length;
16191cb0ef41Sopenharmony_ci        int new_locals_count = decoder->DecodeLocals(
16201cb0ef41Sopenharmony_ci            pc + 1 + imm.length, &locals_length, base::Optional<uint32_t>());
16211cb0ef41Sopenharmony_ci        return 1 + imm.length + ((new_locals_count >= 0) ? locals_length : 0);
16221cb0ef41Sopenharmony_ci      }
16231cb0ef41Sopenharmony_ci
16241cb0ef41Sopenharmony_ci      /********** Misc opcodes **********/
16251cb0ef41Sopenharmony_ci      case kExprCallFunction:
16261cb0ef41Sopenharmony_ci      case kExprReturnCall: {
16271cb0ef41Sopenharmony_ci        CallFunctionImmediate<validate> imm(decoder, pc + 1);
16281cb0ef41Sopenharmony_ci        return 1 + imm.length;
16291cb0ef41Sopenharmony_ci      }
16301cb0ef41Sopenharmony_ci      case kExprCallIndirect:
16311cb0ef41Sopenharmony_ci      case kExprReturnCallIndirect: {
16321cb0ef41Sopenharmony_ci        CallIndirectImmediate<validate> imm(decoder, pc + 1);
16331cb0ef41Sopenharmony_ci        return 1 + imm.length;
16341cb0ef41Sopenharmony_ci      }
16351cb0ef41Sopenharmony_ci      case kExprCallRef:
16361cb0ef41Sopenharmony_ci      case kExprReturnCallRef:
16371cb0ef41Sopenharmony_ci      case kExprDrop:
16381cb0ef41Sopenharmony_ci      case kExprSelect:
16391cb0ef41Sopenharmony_ci      case kExprCatchAll:
16401cb0ef41Sopenharmony_ci        return 1;
16411cb0ef41Sopenharmony_ci      case kExprSelectWithType: {
16421cb0ef41Sopenharmony_ci        SelectTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
16431cb0ef41Sopenharmony_ci                                          nullptr);
16441cb0ef41Sopenharmony_ci        return 1 + imm.length;
16451cb0ef41Sopenharmony_ci      }
16461cb0ef41Sopenharmony_ci
16471cb0ef41Sopenharmony_ci      case kExprLocalGet:
16481cb0ef41Sopenharmony_ci      case kExprLocalSet:
16491cb0ef41Sopenharmony_ci      case kExprLocalTee: {
16501cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(decoder, pc + 1, "local index");
16511cb0ef41Sopenharmony_ci        return 1 + imm.length;
16521cb0ef41Sopenharmony_ci      }
16531cb0ef41Sopenharmony_ci      case kExprGlobalGet:
16541cb0ef41Sopenharmony_ci      case kExprGlobalSet: {
16551cb0ef41Sopenharmony_ci        GlobalIndexImmediate<validate> imm(decoder, pc + 1);
16561cb0ef41Sopenharmony_ci        return 1 + imm.length;
16571cb0ef41Sopenharmony_ci      }
16581cb0ef41Sopenharmony_ci      case kExprTableGet:
16591cb0ef41Sopenharmony_ci      case kExprTableSet: {
16601cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(decoder, pc + 1, "table index");
16611cb0ef41Sopenharmony_ci        return 1 + imm.length;
16621cb0ef41Sopenharmony_ci      }
16631cb0ef41Sopenharmony_ci      case kExprI32Const: {
16641cb0ef41Sopenharmony_ci        ImmI32Immediate<validate> imm(decoder, pc + 1);
16651cb0ef41Sopenharmony_ci        return 1 + imm.length;
16661cb0ef41Sopenharmony_ci      }
16671cb0ef41Sopenharmony_ci      case kExprI64Const: {
16681cb0ef41Sopenharmony_ci        ImmI64Immediate<validate> imm(decoder, pc + 1);
16691cb0ef41Sopenharmony_ci        return 1 + imm.length;
16701cb0ef41Sopenharmony_ci      }
16711cb0ef41Sopenharmony_ci      case kExprF32Const:
16721cb0ef41Sopenharmony_ci        return 5;
16731cb0ef41Sopenharmony_ci      case kExprF64Const:
16741cb0ef41Sopenharmony_ci        return 9;
16751cb0ef41Sopenharmony_ci      case kExprRefNull: {
16761cb0ef41Sopenharmony_ci        HeapTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
16771cb0ef41Sopenharmony_ci                                        nullptr);
16781cb0ef41Sopenharmony_ci        return 1 + imm.length;
16791cb0ef41Sopenharmony_ci      }
16801cb0ef41Sopenharmony_ci      case kExprRefIsNull: {
16811cb0ef41Sopenharmony_ci        return 1;
16821cb0ef41Sopenharmony_ci      }
16831cb0ef41Sopenharmony_ci      case kExprRefFunc: {
16841cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(decoder, pc + 1, "function index");
16851cb0ef41Sopenharmony_ci        return 1 + imm.length;
16861cb0ef41Sopenharmony_ci      }
16871cb0ef41Sopenharmony_ci      case kExprRefAsNonNull:
16881cb0ef41Sopenharmony_ci        return 1;
16891cb0ef41Sopenharmony_ci
16901cb0ef41Sopenharmony_ci#define DECLARE_OPCODE_CASE(name, ...) case kExpr##name:
16911cb0ef41Sopenharmony_ci        // clang-format off
16921cb0ef41Sopenharmony_ci      /********** Simple and memory opcodes **********/
16931cb0ef41Sopenharmony_ci      FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
16941cb0ef41Sopenharmony_ci      FOREACH_SIMPLE_PROTOTYPE_OPCODE(DECLARE_OPCODE_CASE)
16951cb0ef41Sopenharmony_ci        return 1;
16961cb0ef41Sopenharmony_ci      FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
16971cb0ef41Sopenharmony_ci      FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) {
16981cb0ef41Sopenharmony_ci        MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX,
16991cb0ef41Sopenharmony_ci                                            kConservativelyAssumeMemory64);
17001cb0ef41Sopenharmony_ci        return 1 + imm.length;
17011cb0ef41Sopenharmony_ci      }
17021cb0ef41Sopenharmony_ci      // clang-format on
17031cb0ef41Sopenharmony_ci      case kExprMemoryGrow:
17041cb0ef41Sopenharmony_ci      case kExprMemorySize: {
17051cb0ef41Sopenharmony_ci        MemoryIndexImmediate<validate> imm(decoder, pc + 1);
17061cb0ef41Sopenharmony_ci        return 1 + imm.length;
17071cb0ef41Sopenharmony_ci      }
17081cb0ef41Sopenharmony_ci
17091cb0ef41Sopenharmony_ci      /********** Prefixed opcodes **********/
17101cb0ef41Sopenharmony_ci      case kNumericPrefix: {
17111cb0ef41Sopenharmony_ci        uint32_t length = 0;
17121cb0ef41Sopenharmony_ci        opcode = decoder->read_prefixed_opcode<validate>(pc, &length);
17131cb0ef41Sopenharmony_ci        switch (opcode) {
17141cb0ef41Sopenharmony_ci          case kExprI32SConvertSatF32:
17151cb0ef41Sopenharmony_ci          case kExprI32UConvertSatF32:
17161cb0ef41Sopenharmony_ci          case kExprI32SConvertSatF64:
17171cb0ef41Sopenharmony_ci          case kExprI32UConvertSatF64:
17181cb0ef41Sopenharmony_ci          case kExprI64SConvertSatF32:
17191cb0ef41Sopenharmony_ci          case kExprI64UConvertSatF32:
17201cb0ef41Sopenharmony_ci          case kExprI64SConvertSatF64:
17211cb0ef41Sopenharmony_ci          case kExprI64UConvertSatF64:
17221cb0ef41Sopenharmony_ci            return length;
17231cb0ef41Sopenharmony_ci          case kExprMemoryInit: {
17241cb0ef41Sopenharmony_ci            MemoryInitImmediate<validate> imm(decoder, pc + length);
17251cb0ef41Sopenharmony_ci            return length + imm.length;
17261cb0ef41Sopenharmony_ci          }
17271cb0ef41Sopenharmony_ci          case kExprDataDrop: {
17281cb0ef41Sopenharmony_ci            IndexImmediate<validate> imm(decoder, pc + length,
17291cb0ef41Sopenharmony_ci                                         "data segment index");
17301cb0ef41Sopenharmony_ci            return length + imm.length;
17311cb0ef41Sopenharmony_ci          }
17321cb0ef41Sopenharmony_ci          case kExprMemoryCopy: {
17331cb0ef41Sopenharmony_ci            MemoryCopyImmediate<validate> imm(decoder, pc + length);
17341cb0ef41Sopenharmony_ci            return length + imm.length;
17351cb0ef41Sopenharmony_ci          }
17361cb0ef41Sopenharmony_ci          case kExprMemoryFill: {
17371cb0ef41Sopenharmony_ci            MemoryIndexImmediate<validate> imm(decoder, pc + length);
17381cb0ef41Sopenharmony_ci            return length + imm.length;
17391cb0ef41Sopenharmony_ci          }
17401cb0ef41Sopenharmony_ci          case kExprTableInit: {
17411cb0ef41Sopenharmony_ci            TableInitImmediate<validate> imm(decoder, pc + length);
17421cb0ef41Sopenharmony_ci            return length + imm.length;
17431cb0ef41Sopenharmony_ci          }
17441cb0ef41Sopenharmony_ci          case kExprElemDrop: {
17451cb0ef41Sopenharmony_ci            IndexImmediate<validate> imm(decoder, pc + length,
17461cb0ef41Sopenharmony_ci                                         "element segment index");
17471cb0ef41Sopenharmony_ci            return length + imm.length;
17481cb0ef41Sopenharmony_ci          }
17491cb0ef41Sopenharmony_ci          case kExprTableCopy: {
17501cb0ef41Sopenharmony_ci            TableCopyImmediate<validate> imm(decoder, pc + length);
17511cb0ef41Sopenharmony_ci            return length + imm.length;
17521cb0ef41Sopenharmony_ci          }
17531cb0ef41Sopenharmony_ci          case kExprTableGrow:
17541cb0ef41Sopenharmony_ci          case kExprTableSize:
17551cb0ef41Sopenharmony_ci          case kExprTableFill: {
17561cb0ef41Sopenharmony_ci            IndexImmediate<validate> imm(decoder, pc + length, "table index");
17571cb0ef41Sopenharmony_ci            return length + imm.length;
17581cb0ef41Sopenharmony_ci          }
17591cb0ef41Sopenharmony_ci          default:
17601cb0ef41Sopenharmony_ci            if (validate) {
17611cb0ef41Sopenharmony_ci              decoder->DecodeError(pc, "invalid numeric opcode");
17621cb0ef41Sopenharmony_ci            }
17631cb0ef41Sopenharmony_ci            return length;
17641cb0ef41Sopenharmony_ci        }
17651cb0ef41Sopenharmony_ci      }
17661cb0ef41Sopenharmony_ci      case kSimdPrefix: {
17671cb0ef41Sopenharmony_ci        uint32_t length = 0;
17681cb0ef41Sopenharmony_ci        opcode = decoder->read_prefixed_opcode<validate>(pc, &length);
17691cb0ef41Sopenharmony_ci        switch (opcode) {
17701cb0ef41Sopenharmony_ci          // clang-format off
17711cb0ef41Sopenharmony_ci          FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
17721cb0ef41Sopenharmony_ci            return length;
17731cb0ef41Sopenharmony_ci          FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
17741cb0ef41Sopenharmony_ci            return length + 1;
17751cb0ef41Sopenharmony_ci          FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE) {
17761cb0ef41Sopenharmony_ci            MemoryAccessImmediate<validate> imm(decoder, pc + length,
17771cb0ef41Sopenharmony_ci                                                UINT32_MAX,
17781cb0ef41Sopenharmony_ci                                                kConservativelyAssumeMemory64);
17791cb0ef41Sopenharmony_ci            return length + imm.length;
17801cb0ef41Sopenharmony_ci          }
17811cb0ef41Sopenharmony_ci          FOREACH_SIMD_MEM_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) {
17821cb0ef41Sopenharmony_ci            MemoryAccessImmediate<validate> imm(
17831cb0ef41Sopenharmony_ci                decoder, pc + length, UINT32_MAX,
17841cb0ef41Sopenharmony_ci                kConservativelyAssumeMemory64);
17851cb0ef41Sopenharmony_ci            // 1 more byte for lane index immediate.
17861cb0ef41Sopenharmony_ci            return length + imm.length + 1;
17871cb0ef41Sopenharmony_ci          }
17881cb0ef41Sopenharmony_ci          // clang-format on
17891cb0ef41Sopenharmony_ci          // Shuffles require a byte per lane, or 16 immediate bytes.
17901cb0ef41Sopenharmony_ci          case kExprS128Const:
17911cb0ef41Sopenharmony_ci          case kExprI8x16Shuffle:
17921cb0ef41Sopenharmony_ci            return length + kSimd128Size;
17931cb0ef41Sopenharmony_ci          default:
17941cb0ef41Sopenharmony_ci            if (validate) {
17951cb0ef41Sopenharmony_ci              decoder->DecodeError(pc, "invalid SIMD opcode");
17961cb0ef41Sopenharmony_ci            }
17971cb0ef41Sopenharmony_ci            return length;
17981cb0ef41Sopenharmony_ci        }
17991cb0ef41Sopenharmony_ci      }
18001cb0ef41Sopenharmony_ci      case kAtomicPrefix: {
18011cb0ef41Sopenharmony_ci        uint32_t length = 0;
18021cb0ef41Sopenharmony_ci        opcode = decoder->read_prefixed_opcode<validate>(pc, &length,
18031cb0ef41Sopenharmony_ci                                                         "atomic_index");
18041cb0ef41Sopenharmony_ci        switch (opcode) {
18051cb0ef41Sopenharmony_ci          FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE) {
18061cb0ef41Sopenharmony_ci            MemoryAccessImmediate<validate> imm(decoder, pc + length,
18071cb0ef41Sopenharmony_ci                                                UINT32_MAX,
18081cb0ef41Sopenharmony_ci                                                kConservativelyAssumeMemory64);
18091cb0ef41Sopenharmony_ci            return length + imm.length;
18101cb0ef41Sopenharmony_ci          }
18111cb0ef41Sopenharmony_ci          FOREACH_ATOMIC_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) {
18121cb0ef41Sopenharmony_ci            return length + 1;
18131cb0ef41Sopenharmony_ci          }
18141cb0ef41Sopenharmony_ci          default:
18151cb0ef41Sopenharmony_ci            if (validate) {
18161cb0ef41Sopenharmony_ci              decoder->DecodeError(pc, "invalid Atomics opcode");
18171cb0ef41Sopenharmony_ci            }
18181cb0ef41Sopenharmony_ci            return length;
18191cb0ef41Sopenharmony_ci        }
18201cb0ef41Sopenharmony_ci      }
18211cb0ef41Sopenharmony_ci      case kGCPrefix: {
18221cb0ef41Sopenharmony_ci        uint32_t length = 0;
18231cb0ef41Sopenharmony_ci        opcode =
18241cb0ef41Sopenharmony_ci            decoder->read_prefixed_opcode<validate>(pc, &length, "gc_index");
18251cb0ef41Sopenharmony_ci        switch (opcode) {
18261cb0ef41Sopenharmony_ci          case kExprStructNew:
18271cb0ef41Sopenharmony_ci          case kExprStructNewWithRtt:
18281cb0ef41Sopenharmony_ci          case kExprStructNewDefault:
18291cb0ef41Sopenharmony_ci          case kExprStructNewDefaultWithRtt: {
18301cb0ef41Sopenharmony_ci            StructIndexImmediate<validate> imm(decoder, pc + length);
18311cb0ef41Sopenharmony_ci            return length + imm.length;
18321cb0ef41Sopenharmony_ci          }
18331cb0ef41Sopenharmony_ci          case kExprStructGet:
18341cb0ef41Sopenharmony_ci          case kExprStructGetS:
18351cb0ef41Sopenharmony_ci          case kExprStructGetU:
18361cb0ef41Sopenharmony_ci          case kExprStructSet: {
18371cb0ef41Sopenharmony_ci            FieldImmediate<validate> imm(decoder, pc + length);
18381cb0ef41Sopenharmony_ci            return length + imm.length;
18391cb0ef41Sopenharmony_ci          }
18401cb0ef41Sopenharmony_ci          case kExprArrayNew:
18411cb0ef41Sopenharmony_ci          case kExprArrayNewWithRtt:
18421cb0ef41Sopenharmony_ci          case kExprArrayNewDefault:
18431cb0ef41Sopenharmony_ci          case kExprArrayNewDefaultWithRtt:
18441cb0ef41Sopenharmony_ci          case kExprArrayGet:
18451cb0ef41Sopenharmony_ci          case kExprArrayGetS:
18461cb0ef41Sopenharmony_ci          case kExprArrayGetU:
18471cb0ef41Sopenharmony_ci          case kExprArraySet:
18481cb0ef41Sopenharmony_ci          case kExprArrayLen: {
18491cb0ef41Sopenharmony_ci            ArrayIndexImmediate<validate> imm(decoder, pc + length);
18501cb0ef41Sopenharmony_ci            return length + imm.length;
18511cb0ef41Sopenharmony_ci          }
18521cb0ef41Sopenharmony_ci          case kExprArrayInit:
18531cb0ef41Sopenharmony_ci          case kExprArrayInitStatic: {
18541cb0ef41Sopenharmony_ci            ArrayIndexImmediate<validate> array_imm(decoder, pc + length);
18551cb0ef41Sopenharmony_ci            IndexImmediate<validate> length_imm(
18561cb0ef41Sopenharmony_ci                decoder, pc + length + array_imm.length, "array length");
18571cb0ef41Sopenharmony_ci            return length + array_imm.length + length_imm.length;
18581cb0ef41Sopenharmony_ci          }
18591cb0ef41Sopenharmony_ci          case kExprArrayCopy: {
18601cb0ef41Sopenharmony_ci            ArrayIndexImmediate<validate> dst_imm(decoder, pc + length);
18611cb0ef41Sopenharmony_ci            ArrayIndexImmediate<validate> src_imm(decoder,
18621cb0ef41Sopenharmony_ci                                                  pc + length + dst_imm.length);
18631cb0ef41Sopenharmony_ci            return length + dst_imm.length + src_imm.length;
18641cb0ef41Sopenharmony_ci          }
18651cb0ef41Sopenharmony_ci          case kExprArrayInitFromData:
18661cb0ef41Sopenharmony_ci          case kExprArrayInitFromDataStatic: {
18671cb0ef41Sopenharmony_ci            ArrayIndexImmediate<validate> array_imm(decoder, pc + length);
18681cb0ef41Sopenharmony_ci            IndexImmediate<validate> data_imm(
18691cb0ef41Sopenharmony_ci                decoder, pc + length + array_imm.length, "data segment index");
18701cb0ef41Sopenharmony_ci            return length + array_imm.length + data_imm.length;
18711cb0ef41Sopenharmony_ci          }
18721cb0ef41Sopenharmony_ci          case kExprBrOnCast:
18731cb0ef41Sopenharmony_ci          case kExprBrOnCastFail:
18741cb0ef41Sopenharmony_ci          case kExprBrOnData:
18751cb0ef41Sopenharmony_ci          case kExprBrOnFunc:
18761cb0ef41Sopenharmony_ci          case kExprBrOnI31: {
18771cb0ef41Sopenharmony_ci            BranchDepthImmediate<validate> imm(decoder, pc + length);
18781cb0ef41Sopenharmony_ci            return length + imm.length;
18791cb0ef41Sopenharmony_ci          }
18801cb0ef41Sopenharmony_ci          case kExprRttCanon:
18811cb0ef41Sopenharmony_ci          case kExprRefTestStatic:
18821cb0ef41Sopenharmony_ci          case kExprRefCastStatic:
18831cb0ef41Sopenharmony_ci          case kExprBrOnCastStatic:
18841cb0ef41Sopenharmony_ci          case kExprBrOnCastStaticFail: {
18851cb0ef41Sopenharmony_ci            IndexImmediate<validate> imm(decoder, pc + length, "type index");
18861cb0ef41Sopenharmony_ci            return length + imm.length;
18871cb0ef41Sopenharmony_ci          }
18881cb0ef41Sopenharmony_ci          case kExprI31New:
18891cb0ef41Sopenharmony_ci          case kExprI31GetS:
18901cb0ef41Sopenharmony_ci          case kExprI31GetU:
18911cb0ef41Sopenharmony_ci          case kExprRefAsData:
18921cb0ef41Sopenharmony_ci          case kExprRefAsFunc:
18931cb0ef41Sopenharmony_ci          case kExprRefAsI31:
18941cb0ef41Sopenharmony_ci          case kExprRefIsData:
18951cb0ef41Sopenharmony_ci          case kExprRefIsFunc:
18961cb0ef41Sopenharmony_ci          case kExprRefIsI31:
18971cb0ef41Sopenharmony_ci          case kExprRefTest:
18981cb0ef41Sopenharmony_ci          case kExprRefCast:
18991cb0ef41Sopenharmony_ci            return length;
19001cb0ef41Sopenharmony_ci          default:
19011cb0ef41Sopenharmony_ci            // This is unreachable except for malformed modules.
19021cb0ef41Sopenharmony_ci            if (validate) {
19031cb0ef41Sopenharmony_ci              decoder->DecodeError(pc, "invalid gc opcode");
19041cb0ef41Sopenharmony_ci            }
19051cb0ef41Sopenharmony_ci            return length;
19061cb0ef41Sopenharmony_ci        }
19071cb0ef41Sopenharmony_ci      }
19081cb0ef41Sopenharmony_ci
19091cb0ef41Sopenharmony_ci        // clang-format off
19101cb0ef41Sopenharmony_ci      /********** Asmjs opcodes **********/
19111cb0ef41Sopenharmony_ci      FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
19121cb0ef41Sopenharmony_ci        return 1;
19131cb0ef41Sopenharmony_ci
19141cb0ef41Sopenharmony_ci      // Prefixed opcodes (already handled, included here for completeness of
19151cb0ef41Sopenharmony_ci      // switch)
19161cb0ef41Sopenharmony_ci      FOREACH_SIMD_OPCODE(DECLARE_OPCODE_CASE)
19171cb0ef41Sopenharmony_ci      FOREACH_NUMERIC_OPCODE(DECLARE_OPCODE_CASE, DECLARE_OPCODE_CASE)
19181cb0ef41Sopenharmony_ci      FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
19191cb0ef41Sopenharmony_ci      FOREACH_ATOMIC_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
19201cb0ef41Sopenharmony_ci      FOREACH_GC_OPCODE(DECLARE_OPCODE_CASE)
19211cb0ef41Sopenharmony_ci        UNREACHABLE();
19221cb0ef41Sopenharmony_ci        // clang-format on
19231cb0ef41Sopenharmony_ci#undef DECLARE_OPCODE_CASE
19241cb0ef41Sopenharmony_ci    }
19251cb0ef41Sopenharmony_ci    // Invalid modules will reach this point.
19261cb0ef41Sopenharmony_ci    if (validate) {
19271cb0ef41Sopenharmony_ci      decoder->DecodeError(pc, "invalid opcode");
19281cb0ef41Sopenharmony_ci    }
19291cb0ef41Sopenharmony_ci    return 1;
19301cb0ef41Sopenharmony_ci  }
19311cb0ef41Sopenharmony_ci
19321cb0ef41Sopenharmony_ci  // TODO(clemensb): This is only used by the interpreter; move there.
19331cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
19341cb0ef41Sopenharmony_ci    WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
19351cb0ef41Sopenharmony_ci    // Handle "simple" opcodes with a fixed signature first.
19361cb0ef41Sopenharmony_ci    const FunctionSig* sig = WasmOpcodes::Signature(opcode);
19371cb0ef41Sopenharmony_ci    if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
19381cb0ef41Sopenharmony_ci    if (sig) return {sig->parameter_count(), sig->return_count()};
19391cb0ef41Sopenharmony_ci
19401cb0ef41Sopenharmony_ci#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
19411cb0ef41Sopenharmony_ci    // clang-format off
19421cb0ef41Sopenharmony_ci    switch (opcode) {
19431cb0ef41Sopenharmony_ci      case kExprSelect:
19441cb0ef41Sopenharmony_ci      case kExprSelectWithType:
19451cb0ef41Sopenharmony_ci        return {3, 1};
19461cb0ef41Sopenharmony_ci      case kExprTableSet:
19471cb0ef41Sopenharmony_ci      FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
19481cb0ef41Sopenharmony_ci        return {2, 0};
19491cb0ef41Sopenharmony_ci      FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
19501cb0ef41Sopenharmony_ci      case kExprTableGet:
19511cb0ef41Sopenharmony_ci      case kExprLocalTee:
19521cb0ef41Sopenharmony_ci      case kExprMemoryGrow:
19531cb0ef41Sopenharmony_ci      case kExprRefAsNonNull:
19541cb0ef41Sopenharmony_ci      case kExprBrOnNull:
19551cb0ef41Sopenharmony_ci      case kExprRefIsNull:
19561cb0ef41Sopenharmony_ci        return {1, 1};
19571cb0ef41Sopenharmony_ci      case kExprLocalSet:
19581cb0ef41Sopenharmony_ci      case kExprGlobalSet:
19591cb0ef41Sopenharmony_ci      case kExprDrop:
19601cb0ef41Sopenharmony_ci      case kExprBrIf:
19611cb0ef41Sopenharmony_ci      case kExprBrTable:
19621cb0ef41Sopenharmony_ci      case kExprIf:
19631cb0ef41Sopenharmony_ci      case kExprBrOnNonNull:
19641cb0ef41Sopenharmony_ci        return {1, 0};
19651cb0ef41Sopenharmony_ci      case kExprLocalGet:
19661cb0ef41Sopenharmony_ci      case kExprGlobalGet:
19671cb0ef41Sopenharmony_ci      case kExprI32Const:
19681cb0ef41Sopenharmony_ci      case kExprI64Const:
19691cb0ef41Sopenharmony_ci      case kExprF32Const:
19701cb0ef41Sopenharmony_ci      case kExprF64Const:
19711cb0ef41Sopenharmony_ci      case kExprRefNull:
19721cb0ef41Sopenharmony_ci      case kExprRefFunc:
19731cb0ef41Sopenharmony_ci      case kExprMemorySize:
19741cb0ef41Sopenharmony_ci        return {0, 1};
19751cb0ef41Sopenharmony_ci      case kExprCallFunction: {
19761cb0ef41Sopenharmony_ci        CallFunctionImmediate<validate> imm(this, pc + 1);
19771cb0ef41Sopenharmony_ci        CHECK(Validate(pc + 1, imm));
19781cb0ef41Sopenharmony_ci        return {imm.sig->parameter_count(), imm.sig->return_count()};
19791cb0ef41Sopenharmony_ci      }
19801cb0ef41Sopenharmony_ci      case kExprCallIndirect: {
19811cb0ef41Sopenharmony_ci        CallIndirectImmediate<validate> imm(this, pc + 1);
19821cb0ef41Sopenharmony_ci        CHECK(Validate(pc + 1, imm));
19831cb0ef41Sopenharmony_ci        // Indirect calls pop an additional argument for the table index.
19841cb0ef41Sopenharmony_ci        return {imm.sig->parameter_count() + 1,
19851cb0ef41Sopenharmony_ci                imm.sig->return_count()};
19861cb0ef41Sopenharmony_ci      }
19871cb0ef41Sopenharmony_ci      case kExprThrow: {
19881cb0ef41Sopenharmony_ci        TagIndexImmediate<validate> imm(this, pc + 1);
19891cb0ef41Sopenharmony_ci        CHECK(Validate(pc + 1, imm));
19901cb0ef41Sopenharmony_ci        DCHECK_EQ(0, imm.tag->sig->return_count());
19911cb0ef41Sopenharmony_ci        return {imm.tag->sig->parameter_count(), 0};
19921cb0ef41Sopenharmony_ci      }
19931cb0ef41Sopenharmony_ci      case kExprBr:
19941cb0ef41Sopenharmony_ci      case kExprBlock:
19951cb0ef41Sopenharmony_ci      case kExprLoop:
19961cb0ef41Sopenharmony_ci      case kExprEnd:
19971cb0ef41Sopenharmony_ci      case kExprElse:
19981cb0ef41Sopenharmony_ci      case kExprTry:
19991cb0ef41Sopenharmony_ci      case kExprCatch:
20001cb0ef41Sopenharmony_ci      case kExprCatchAll:
20011cb0ef41Sopenharmony_ci      case kExprDelegate:
20021cb0ef41Sopenharmony_ci      case kExprRethrow:
20031cb0ef41Sopenharmony_ci      case kExprNop:
20041cb0ef41Sopenharmony_ci      case kExprNopForTestingUnsupportedInLiftoff:
20051cb0ef41Sopenharmony_ci      case kExprReturn:
20061cb0ef41Sopenharmony_ci      case kExprReturnCall:
20071cb0ef41Sopenharmony_ci      case kExprReturnCallIndirect:
20081cb0ef41Sopenharmony_ci      case kExprUnreachable:
20091cb0ef41Sopenharmony_ci        return {0, 0};
20101cb0ef41Sopenharmony_ci      case kExprLet:
20111cb0ef41Sopenharmony_ci        // TODO(7748): Implement
20121cb0ef41Sopenharmony_ci        return {0, 0};
20131cb0ef41Sopenharmony_ci      case kNumericPrefix:
20141cb0ef41Sopenharmony_ci      case kAtomicPrefix:
20151cb0ef41Sopenharmony_ci      case kSimdPrefix: {
20161cb0ef41Sopenharmony_ci        opcode = this->read_prefixed_opcode<validate>(pc);
20171cb0ef41Sopenharmony_ci        switch (opcode) {
20181cb0ef41Sopenharmony_ci          FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
20191cb0ef41Sopenharmony_ci            return {1, 1};
20201cb0ef41Sopenharmony_ci          FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
20211cb0ef41Sopenharmony_ci          FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
20221cb0ef41Sopenharmony_ci            return {2, 1};
20231cb0ef41Sopenharmony_ci          FOREACH_SIMD_CONST_OPCODE(DECLARE_OPCODE_CASE)
20241cb0ef41Sopenharmony_ci            return {0, 1};
20251cb0ef41Sopenharmony_ci          // Special case numeric opcodes without fixed signature.
20261cb0ef41Sopenharmony_ci          case kExprMemoryInit:
20271cb0ef41Sopenharmony_ci          case kExprMemoryCopy:
20281cb0ef41Sopenharmony_ci          case kExprMemoryFill:
20291cb0ef41Sopenharmony_ci            return {3, 0};
20301cb0ef41Sopenharmony_ci          case kExprTableGrow:
20311cb0ef41Sopenharmony_ci            return {2, 1};
20321cb0ef41Sopenharmony_ci          case kExprTableFill:
20331cb0ef41Sopenharmony_ci            return {3, 0};
20341cb0ef41Sopenharmony_ci          default: {
20351cb0ef41Sopenharmony_ci            sig = WasmOpcodes::Signature(opcode);
20361cb0ef41Sopenharmony_ci            DCHECK_NOT_NULL(sig);
20371cb0ef41Sopenharmony_ci            return {sig->parameter_count(), sig->return_count()};
20381cb0ef41Sopenharmony_ci          }
20391cb0ef41Sopenharmony_ci        }
20401cb0ef41Sopenharmony_ci      }
20411cb0ef41Sopenharmony_ci      case kGCPrefix: {
20421cb0ef41Sopenharmony_ci        opcode = this->read_prefixed_opcode<validate>(pc);
20431cb0ef41Sopenharmony_ci        switch (opcode) {
20441cb0ef41Sopenharmony_ci          case kExprStructNewDefaultWithRtt:
20451cb0ef41Sopenharmony_ci          case kExprStructGet:
20461cb0ef41Sopenharmony_ci          case kExprStructGetS:
20471cb0ef41Sopenharmony_ci          case kExprStructGetU:
20481cb0ef41Sopenharmony_ci          case kExprI31New:
20491cb0ef41Sopenharmony_ci          case kExprI31GetS:
20501cb0ef41Sopenharmony_ci          case kExprI31GetU:
20511cb0ef41Sopenharmony_ci          case kExprArrayNewDefault:
20521cb0ef41Sopenharmony_ci          case kExprArrayLen:
20531cb0ef41Sopenharmony_ci          case kExprRefTestStatic:
20541cb0ef41Sopenharmony_ci          case kExprRefCastStatic:
20551cb0ef41Sopenharmony_ci          case kExprBrOnCastStatic:
20561cb0ef41Sopenharmony_ci          case kExprBrOnCastStaticFail:
20571cb0ef41Sopenharmony_ci            return {1, 1};
20581cb0ef41Sopenharmony_ci          case kExprStructSet:
20591cb0ef41Sopenharmony_ci            return {2, 0};
20601cb0ef41Sopenharmony_ci          case kExprArrayNew:
20611cb0ef41Sopenharmony_ci          case kExprArrayNewDefaultWithRtt:
20621cb0ef41Sopenharmony_ci          case kExprArrayInitFromDataStatic:
20631cb0ef41Sopenharmony_ci          case kExprArrayGet:
20641cb0ef41Sopenharmony_ci          case kExprArrayGetS:
20651cb0ef41Sopenharmony_ci          case kExprArrayGetU:
20661cb0ef41Sopenharmony_ci          case kExprRefTest:
20671cb0ef41Sopenharmony_ci          case kExprRefCast:
20681cb0ef41Sopenharmony_ci          case kExprBrOnCast:
20691cb0ef41Sopenharmony_ci          case kExprBrOnCastFail:
20701cb0ef41Sopenharmony_ci            return {2, 1};
20711cb0ef41Sopenharmony_ci          case kExprArraySet:
20721cb0ef41Sopenharmony_ci            return {3, 0};
20731cb0ef41Sopenharmony_ci          case kExprArrayCopy:
20741cb0ef41Sopenharmony_ci            return {5, 0};
20751cb0ef41Sopenharmony_ci          case kExprRttCanon:
20761cb0ef41Sopenharmony_ci          case kExprStructNewDefault:
20771cb0ef41Sopenharmony_ci            return {0, 1};
20781cb0ef41Sopenharmony_ci          case kExprArrayNewWithRtt:
20791cb0ef41Sopenharmony_ci          case kExprArrayInitFromData:
20801cb0ef41Sopenharmony_ci            return {3, 1};
20811cb0ef41Sopenharmony_ci          case kExprStructNewWithRtt: {
20821cb0ef41Sopenharmony_ci            StructIndexImmediate<validate> imm(this, pc + 2);
20831cb0ef41Sopenharmony_ci            CHECK(Validate(pc + 2, imm));
20841cb0ef41Sopenharmony_ci            return {imm.struct_type->field_count() + 1, 1};
20851cb0ef41Sopenharmony_ci          }
20861cb0ef41Sopenharmony_ci          case kExprStructNew: {
20871cb0ef41Sopenharmony_ci            StructIndexImmediate<validate> imm(this, pc + 2);
20881cb0ef41Sopenharmony_ci            CHECK(Validate(pc + 2, imm));
20891cb0ef41Sopenharmony_ci            return {imm.struct_type->field_count(), 1};
20901cb0ef41Sopenharmony_ci          }
20911cb0ef41Sopenharmony_ci          case kExprArrayInit:
20921cb0ef41Sopenharmony_ci          case kExprArrayInitStatic: {
20931cb0ef41Sopenharmony_ci            ArrayIndexImmediate<validate> array_imm(this, pc + 2);
20941cb0ef41Sopenharmony_ci            IndexImmediate<validate> length_imm(this, pc + 2 + array_imm.length,
20951cb0ef41Sopenharmony_ci                                                "array length");
20961cb0ef41Sopenharmony_ci            return {length_imm.index + (opcode == kExprArrayInit ? 1 : 0), 1};
20971cb0ef41Sopenharmony_ci          }
20981cb0ef41Sopenharmony_ci          default:
20991cb0ef41Sopenharmony_ci            UNREACHABLE();
21001cb0ef41Sopenharmony_ci        }
21011cb0ef41Sopenharmony_ci      }
21021cb0ef41Sopenharmony_ci      default:
21031cb0ef41Sopenharmony_ci        FATAL("unimplemented opcode: %x (%s)", opcode,
21041cb0ef41Sopenharmony_ci              WasmOpcodes::OpcodeName(opcode));
21051cb0ef41Sopenharmony_ci        return {0, 0};
21061cb0ef41Sopenharmony_ci    }
21071cb0ef41Sopenharmony_ci#undef DECLARE_OPCODE_CASE
21081cb0ef41Sopenharmony_ci    // clang-format on
21091cb0ef41Sopenharmony_ci  }
21101cb0ef41Sopenharmony_ci
21111cb0ef41Sopenharmony_ci  bool is_local_initialized(uint32_t local_index) {
21121cb0ef41Sopenharmony_ci    return initialized_locals_[local_index];
21131cb0ef41Sopenharmony_ci  }
21141cb0ef41Sopenharmony_ci
21151cb0ef41Sopenharmony_ci  void set_local_initialized(uint32_t local_index) {
21161cb0ef41Sopenharmony_ci    if (!enabled_.has_nn_locals()) return;
21171cb0ef41Sopenharmony_ci    // This implicitly covers defaultable locals too (which are always
21181cb0ef41Sopenharmony_ci    // initialized).
21191cb0ef41Sopenharmony_ci    if (is_local_initialized(local_index)) return;
21201cb0ef41Sopenharmony_ci    initialized_locals_[local_index] = true;
21211cb0ef41Sopenharmony_ci    locals_initializers_stack_.push_back(local_index);
21221cb0ef41Sopenharmony_ci  }
21231cb0ef41Sopenharmony_ci
21241cb0ef41Sopenharmony_ci  uint32_t locals_initialization_stack_depth() const {
21251cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(locals_initializers_stack_.size());
21261cb0ef41Sopenharmony_ci  }
21271cb0ef41Sopenharmony_ci
21281cb0ef41Sopenharmony_ci  void RollbackLocalsInitialization(uint32_t previous_stack_height) {
21291cb0ef41Sopenharmony_ci    if (!enabled_.has_nn_locals()) return;
21301cb0ef41Sopenharmony_ci    while (locals_initializers_stack_.size() > previous_stack_height) {
21311cb0ef41Sopenharmony_ci      uint32_t local_index = locals_initializers_stack_.back();
21321cb0ef41Sopenharmony_ci      locals_initializers_stack_.pop_back();
21331cb0ef41Sopenharmony_ci      initialized_locals_[local_index] = false;
21341cb0ef41Sopenharmony_ci    }
21351cb0ef41Sopenharmony_ci  }
21361cb0ef41Sopenharmony_ci
21371cb0ef41Sopenharmony_ci  void InitializeInitializedLocalsTracking(int non_defaultable_locals) {
21381cb0ef41Sopenharmony_ci    initialized_locals_.assign(num_locals_, false);
21391cb0ef41Sopenharmony_ci    // Parameters count as initialized...
21401cb0ef41Sopenharmony_ci    const uint32_t num_params = static_cast<uint32_t>(sig_->parameter_count());
21411cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < num_params; i++) {
21421cb0ef41Sopenharmony_ci      initialized_locals_[i] = true;
21431cb0ef41Sopenharmony_ci    }
21441cb0ef41Sopenharmony_ci    // ...and so do defaultable locals.
21451cb0ef41Sopenharmony_ci    for (uint32_t i = num_params; i < num_locals_; i++) {
21461cb0ef41Sopenharmony_ci      if (local_types_[i].is_defaultable()) initialized_locals_[i] = true;
21471cb0ef41Sopenharmony_ci    }
21481cb0ef41Sopenharmony_ci    if (non_defaultable_locals == 0) return;
21491cb0ef41Sopenharmony_ci    locals_initializers_stack_.reserve(non_defaultable_locals);
21501cb0ef41Sopenharmony_ci  }
21511cb0ef41Sopenharmony_ci
21521cb0ef41Sopenharmony_ci  // The {Zone} is implicitly stored in the {ZoneAllocator} which is part of
21531cb0ef41Sopenharmony_ci  // this {ZoneVector}. Hence save one field and just get it from there if
21541cb0ef41Sopenharmony_ci  // needed (see {zone()} accessor below).
21551cb0ef41Sopenharmony_ci  ZoneVector<ValueType> local_types_;
21561cb0ef41Sopenharmony_ci
21571cb0ef41Sopenharmony_ci  // Cached value, for speed (yes, it's measurably faster to load this value
21581cb0ef41Sopenharmony_ci  // than to load the start and end pointer from a vector, subtract and shift).
21591cb0ef41Sopenharmony_ci  uint32_t num_locals_ = 0;
21601cb0ef41Sopenharmony_ci
21611cb0ef41Sopenharmony_ci  // Indicates whether the local with the given index is currently initialized.
21621cb0ef41Sopenharmony_ci  // Entries for defaultable locals are meaningless; we have a bit for each
21631cb0ef41Sopenharmony_ci  // local because we expect that the effort required to densify this bit
21641cb0ef41Sopenharmony_ci  // vector would more than offset the memory savings.
21651cb0ef41Sopenharmony_ci  ZoneVector<bool> initialized_locals_;
21661cb0ef41Sopenharmony_ci  // Keeps track of initializing assignments to non-defaultable locals that
21671cb0ef41Sopenharmony_ci  // happened, so they can be discarded at the end of the current block.
21681cb0ef41Sopenharmony_ci  // Contains no duplicates, so the size of this stack is bounded (and pre-
21691cb0ef41Sopenharmony_ci  // allocated) to the number of non-defaultable locals in the function.
21701cb0ef41Sopenharmony_ci  ZoneVector<uint32_t> locals_initializers_stack_;
21711cb0ef41Sopenharmony_ci
21721cb0ef41Sopenharmony_ci  const WasmModule* module_;
21731cb0ef41Sopenharmony_ci  const WasmFeatures enabled_;
21741cb0ef41Sopenharmony_ci  WasmFeatures* detected_;
21751cb0ef41Sopenharmony_ci  const FunctionSig* sig_;
21761cb0ef41Sopenharmony_ci};
21771cb0ef41Sopenharmony_ci
21781cb0ef41Sopenharmony_ci// Only call this in contexts where {current_code_reachable_and_ok_} is known to
21791cb0ef41Sopenharmony_ci// hold.
21801cb0ef41Sopenharmony_ci#define CALL_INTERFACE(name, ...)                         \
21811cb0ef41Sopenharmony_ci  do {                                                    \
21821cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());                            \
21831cb0ef41Sopenharmony_ci    DCHECK(current_code_reachable_and_ok_);               \
21841cb0ef41Sopenharmony_ci    DCHECK_EQ(current_code_reachable_and_ok_,             \
21851cb0ef41Sopenharmony_ci              this->ok() && control_.back().reachable()); \
21861cb0ef41Sopenharmony_ci    interface_.name(this, ##__VA_ARGS__);                 \
21871cb0ef41Sopenharmony_ci  } while (false)
21881cb0ef41Sopenharmony_ci#define CALL_INTERFACE_IF_OK_AND_REACHABLE(name, ...)     \
21891cb0ef41Sopenharmony_ci  do {                                                    \
21901cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());                            \
21911cb0ef41Sopenharmony_ci    DCHECK_EQ(current_code_reachable_and_ok_,             \
21921cb0ef41Sopenharmony_ci              this->ok() && control_.back().reachable()); \
21931cb0ef41Sopenharmony_ci    if (V8_LIKELY(current_code_reachable_and_ok_)) {      \
21941cb0ef41Sopenharmony_ci      interface_.name(this, ##__VA_ARGS__);               \
21951cb0ef41Sopenharmony_ci    }                                                     \
21961cb0ef41Sopenharmony_ci  } while (false)
21971cb0ef41Sopenharmony_ci#define CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(name, ...)    \
21981cb0ef41Sopenharmony_ci  do {                                                          \
21991cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());                                  \
22001cb0ef41Sopenharmony_ci    if (VALIDATE(this->ok()) &&                                 \
22011cb0ef41Sopenharmony_ci        (control_.size() == 1 || control_at(1)->reachable())) { \
22021cb0ef41Sopenharmony_ci      interface_.name(this, ##__VA_ARGS__);                     \
22031cb0ef41Sopenharmony_ci    }                                                           \
22041cb0ef41Sopenharmony_ci  } while (false)
22051cb0ef41Sopenharmony_ci
22061cb0ef41Sopenharmony_citemplate <Decoder::ValidateFlag validate, typename Interface,
22071cb0ef41Sopenharmony_ci          DecodingMode decoding_mode = kFunctionBody>
22081cb0ef41Sopenharmony_ciclass WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
22091cb0ef41Sopenharmony_ci  using Value = typename Interface::Value;
22101cb0ef41Sopenharmony_ci  using Control = typename Interface::Control;
22111cb0ef41Sopenharmony_ci  using ArgVector = base::Vector<Value>;
22121cb0ef41Sopenharmony_ci  using ReturnVector = base::SmallVector<Value, 2>;
22131cb0ef41Sopenharmony_ci
22141cb0ef41Sopenharmony_ci  // All Value types should be trivially copyable for performance. We push, pop,
22151cb0ef41Sopenharmony_ci  // and store them in local variables.
22161cb0ef41Sopenharmony_ci  ASSERT_TRIVIALLY_COPYABLE(Value);
22171cb0ef41Sopenharmony_ci
22181cb0ef41Sopenharmony_ci public:
22191cb0ef41Sopenharmony_ci  template <typename... InterfaceArgs>
22201cb0ef41Sopenharmony_ci  WasmFullDecoder(Zone* zone, const WasmModule* module,
22211cb0ef41Sopenharmony_ci                  const WasmFeatures& enabled, WasmFeatures* detected,
22221cb0ef41Sopenharmony_ci                  const FunctionBody& body, InterfaceArgs&&... interface_args)
22231cb0ef41Sopenharmony_ci      : WasmDecoder<validate, decoding_mode>(zone, module, enabled, detected,
22241cb0ef41Sopenharmony_ci                                             body.sig, body.start, body.end,
22251cb0ef41Sopenharmony_ci                                             body.offset),
22261cb0ef41Sopenharmony_ci        interface_(std::forward<InterfaceArgs>(interface_args)...),
22271cb0ef41Sopenharmony_ci        control_(zone) {}
22281cb0ef41Sopenharmony_ci
22291cb0ef41Sopenharmony_ci  Interface& interface() { return interface_; }
22301cb0ef41Sopenharmony_ci
22311cb0ef41Sopenharmony_ci  bool Decode() {
22321cb0ef41Sopenharmony_ci    DCHECK_EQ(stack_end_, stack_);
22331cb0ef41Sopenharmony_ci    DCHECK(control_.empty());
22341cb0ef41Sopenharmony_ci    DCHECK_LE(this->pc_, this->end_);
22351cb0ef41Sopenharmony_ci    DCHECK_EQ(this->num_locals(), 0);
22361cb0ef41Sopenharmony_ci
22371cb0ef41Sopenharmony_ci    locals_offset_ = this->pc_offset();
22381cb0ef41Sopenharmony_ci    this->InitializeLocalsFromSig();
22391cb0ef41Sopenharmony_ci    uint32_t params_count = static_cast<uint32_t>(this->num_locals());
22401cb0ef41Sopenharmony_ci    uint32_t locals_length;
22411cb0ef41Sopenharmony_ci    this->DecodeLocals(this->pc(), &locals_length, params_count);
22421cb0ef41Sopenharmony_ci    if (this->failed()) return TraceFailed();
22431cb0ef41Sopenharmony_ci    this->consume_bytes(locals_length);
22441cb0ef41Sopenharmony_ci    int non_defaultable = 0;
22451cb0ef41Sopenharmony_ci    for (uint32_t index = params_count; index < this->num_locals(); index++) {
22461cb0ef41Sopenharmony_ci      if (!VALIDATE(this->enabled_.has_nn_locals() ||
22471cb0ef41Sopenharmony_ci                    this->enabled_.has_unsafe_nn_locals() ||
22481cb0ef41Sopenharmony_ci                    this->local_type(index).is_defaultable())) {
22491cb0ef41Sopenharmony_ci        this->DecodeError(
22501cb0ef41Sopenharmony_ci            "Cannot define function-level local of non-defaultable type %s",
22511cb0ef41Sopenharmony_ci            this->local_type(index).name().c_str());
22521cb0ef41Sopenharmony_ci        return this->TraceFailed();
22531cb0ef41Sopenharmony_ci      }
22541cb0ef41Sopenharmony_ci      if (!this->local_type(index).is_defaultable()) non_defaultable++;
22551cb0ef41Sopenharmony_ci    }
22561cb0ef41Sopenharmony_ci    this->InitializeInitializedLocalsTracking(non_defaultable);
22571cb0ef41Sopenharmony_ci
22581cb0ef41Sopenharmony_ci    // Cannot use CALL_INTERFACE_* macros because control is empty.
22591cb0ef41Sopenharmony_ci    interface().StartFunction(this);
22601cb0ef41Sopenharmony_ci    DecodeFunctionBody();
22611cb0ef41Sopenharmony_ci    if (this->failed()) return TraceFailed();
22621cb0ef41Sopenharmony_ci
22631cb0ef41Sopenharmony_ci    if (!VALIDATE(control_.empty())) {
22641cb0ef41Sopenharmony_ci      if (control_.size() > 1) {
22651cb0ef41Sopenharmony_ci        this->DecodeError(control_.back().pc(),
22661cb0ef41Sopenharmony_ci                          "unterminated control structure");
22671cb0ef41Sopenharmony_ci      } else {
22681cb0ef41Sopenharmony_ci        this->DecodeError("function body must end with \"end\" opcode");
22691cb0ef41Sopenharmony_ci      }
22701cb0ef41Sopenharmony_ci      return TraceFailed();
22711cb0ef41Sopenharmony_ci    }
22721cb0ef41Sopenharmony_ci    // Cannot use CALL_INTERFACE_* macros because control is empty.
22731cb0ef41Sopenharmony_ci    interface().FinishFunction(this);
22741cb0ef41Sopenharmony_ci    if (this->failed()) return TraceFailed();
22751cb0ef41Sopenharmony_ci
22761cb0ef41Sopenharmony_ci    TRACE("wasm-decode ok\n\n");
22771cb0ef41Sopenharmony_ci    return true;
22781cb0ef41Sopenharmony_ci  }
22791cb0ef41Sopenharmony_ci
22801cb0ef41Sopenharmony_ci  bool TraceFailed() {
22811cb0ef41Sopenharmony_ci    if (this->error_.offset()) {
22821cb0ef41Sopenharmony_ci      TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_.offset(),
22831cb0ef41Sopenharmony_ci            this->GetBufferRelativeOffset(this->error_.offset()),
22841cb0ef41Sopenharmony_ci            this->error_.message().c_str());
22851cb0ef41Sopenharmony_ci    } else {
22861cb0ef41Sopenharmony_ci      TRACE("wasm-error: %s\n\n", this->error_.message().c_str());
22871cb0ef41Sopenharmony_ci    }
22881cb0ef41Sopenharmony_ci    return false;
22891cb0ef41Sopenharmony_ci  }
22901cb0ef41Sopenharmony_ci
22911cb0ef41Sopenharmony_ci  const char* SafeOpcodeNameAt(const byte* pc) {
22921cb0ef41Sopenharmony_ci    if (!pc) return "<null>";
22931cb0ef41Sopenharmony_ci    if (pc >= this->end_) return "<end>";
22941cb0ef41Sopenharmony_ci    WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
22951cb0ef41Sopenharmony_ci    if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
22961cb0ef41Sopenharmony_ci      return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(opcode));
22971cb0ef41Sopenharmony_ci    }
22981cb0ef41Sopenharmony_ci    opcode = this->template read_prefixed_opcode<Decoder::kFullValidation>(pc);
22991cb0ef41Sopenharmony_ci    return WasmOpcodes::OpcodeName(opcode);
23001cb0ef41Sopenharmony_ci  }
23011cb0ef41Sopenharmony_ci
23021cb0ef41Sopenharmony_ci  WasmCodePosition position() const {
23031cb0ef41Sopenharmony_ci    int offset = static_cast<int>(this->pc_ - this->start_);
23041cb0ef41Sopenharmony_ci    DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
23051cb0ef41Sopenharmony_ci    return offset;
23061cb0ef41Sopenharmony_ci  }
23071cb0ef41Sopenharmony_ci
23081cb0ef41Sopenharmony_ci  uint32_t control_depth() const {
23091cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(control_.size());
23101cb0ef41Sopenharmony_ci  }
23111cb0ef41Sopenharmony_ci
23121cb0ef41Sopenharmony_ci  Control* control_at(uint32_t depth) {
23131cb0ef41Sopenharmony_ci    DCHECK_GT(control_.size(), depth);
23141cb0ef41Sopenharmony_ci    return &control_.back() - depth;
23151cb0ef41Sopenharmony_ci  }
23161cb0ef41Sopenharmony_ci
23171cb0ef41Sopenharmony_ci  uint32_t stack_size() const {
23181cb0ef41Sopenharmony_ci    DCHECK_GE(stack_end_, stack_);
23191cb0ef41Sopenharmony_ci    DCHECK_GE(kMaxUInt32, stack_end_ - stack_);
23201cb0ef41Sopenharmony_ci    return static_cast<uint32_t>(stack_end_ - stack_);
23211cb0ef41Sopenharmony_ci  }
23221cb0ef41Sopenharmony_ci
23231cb0ef41Sopenharmony_ci  Value* stack_value(uint32_t depth) const {
23241cb0ef41Sopenharmony_ci    DCHECK_LT(0, depth);
23251cb0ef41Sopenharmony_ci    DCHECK_GE(stack_size(), depth);
23261cb0ef41Sopenharmony_ci    return stack_end_ - depth;
23271cb0ef41Sopenharmony_ci  }
23281cb0ef41Sopenharmony_ci
23291cb0ef41Sopenharmony_ci  int32_t current_catch() const { return current_catch_; }
23301cb0ef41Sopenharmony_ci
23311cb0ef41Sopenharmony_ci  uint32_t control_depth_of_current_catch() const {
23321cb0ef41Sopenharmony_ci    return control_depth() - 1 - current_catch();
23331cb0ef41Sopenharmony_ci  }
23341cb0ef41Sopenharmony_ci
23351cb0ef41Sopenharmony_ci  void SetSucceedingCodeDynamicallyUnreachable() {
23361cb0ef41Sopenharmony_ci    Control* current = &control_.back();
23371cb0ef41Sopenharmony_ci    if (current->reachable()) {
23381cb0ef41Sopenharmony_ci      current->reachability = kSpecOnlyReachable;
23391cb0ef41Sopenharmony_ci      current_code_reachable_and_ok_ = false;
23401cb0ef41Sopenharmony_ci    }
23411cb0ef41Sopenharmony_ci  }
23421cb0ef41Sopenharmony_ci
23431cb0ef41Sopenharmony_ci  uint32_t pc_relative_offset() const {
23441cb0ef41Sopenharmony_ci    return this->pc_offset() - locals_offset_;
23451cb0ef41Sopenharmony_ci  }
23461cb0ef41Sopenharmony_ci
23471cb0ef41Sopenharmony_ci  void DecodeFunctionBody() {
23481cb0ef41Sopenharmony_ci    TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n", this->start(),
23491cb0ef41Sopenharmony_ci          this->end(), this->pc_offset(),
23501cb0ef41Sopenharmony_ci          static_cast<int>(this->end() - this->start()));
23511cb0ef41Sopenharmony_ci
23521cb0ef41Sopenharmony_ci    // Set up initial function block.
23531cb0ef41Sopenharmony_ci    {
23541cb0ef41Sopenharmony_ci      DCHECK(control_.empty());
23551cb0ef41Sopenharmony_ci      constexpr uint32_t kLocalsCount = 0;
23561cb0ef41Sopenharmony_ci      constexpr uint32_t kStackDepth = 0;
23571cb0ef41Sopenharmony_ci      constexpr uint32_t kInitStackDepth = 0;
23581cb0ef41Sopenharmony_ci      control_.emplace_back(kControlBlock, kLocalsCount, kStackDepth,
23591cb0ef41Sopenharmony_ci                            kInitStackDepth, this->pc_, kReachable);
23601cb0ef41Sopenharmony_ci      Control* c = &control_.back();
23611cb0ef41Sopenharmony_ci      if (decoding_mode == kFunctionBody) {
23621cb0ef41Sopenharmony_ci        InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
23631cb0ef41Sopenharmony_ci        InitMerge(&c->end_merge,
23641cb0ef41Sopenharmony_ci                  static_cast<uint32_t>(this->sig_->return_count()),
23651cb0ef41Sopenharmony_ci                  [&](uint32_t i) {
23661cb0ef41Sopenharmony_ci                    return Value{this->pc_, this->sig_->GetReturn(i)};
23671cb0ef41Sopenharmony_ci                  });
23681cb0ef41Sopenharmony_ci      } else {
23691cb0ef41Sopenharmony_ci        DCHECK_EQ(this->sig_->parameter_count(), 0);
23701cb0ef41Sopenharmony_ci        DCHECK_EQ(this->sig_->return_count(), 1);
23711cb0ef41Sopenharmony_ci        c->start_merge.arity = 0;
23721cb0ef41Sopenharmony_ci        c->end_merge.arity = 1;
23731cb0ef41Sopenharmony_ci        c->end_merge.vals.first = Value{this->pc_, this->sig_->GetReturn(0)};
23741cb0ef41Sopenharmony_ci      }
23751cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(StartFunctionBody, c);
23761cb0ef41Sopenharmony_ci    }
23771cb0ef41Sopenharmony_ci
23781cb0ef41Sopenharmony_ci    // Decode the function body.
23791cb0ef41Sopenharmony_ci    while (this->pc_ < this->end_) {
23801cb0ef41Sopenharmony_ci      // Most operations only grow the stack by at least one element (unary and
23811cb0ef41Sopenharmony_ci      // binary operations, local.get, constants, ...). Thus check that there is
23821cb0ef41Sopenharmony_ci      // enough space for those operations centrally, and avoid any bounds
23831cb0ef41Sopenharmony_ci      // checks in those operations.
23841cb0ef41Sopenharmony_ci      EnsureStackSpace(1);
23851cb0ef41Sopenharmony_ci      uint8_t first_byte = *this->pc_;
23861cb0ef41Sopenharmony_ci      WasmOpcode opcode = static_cast<WasmOpcode>(first_byte);
23871cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(NextInstruction, opcode);
23881cb0ef41Sopenharmony_ci      int len;
23891cb0ef41Sopenharmony_ci      // Allowing two of the most common decoding functions to get inlined
23901cb0ef41Sopenharmony_ci      // appears to be the sweet spot.
23911cb0ef41Sopenharmony_ci      // Handling _all_ opcodes via a giant switch-statement has been tried
23921cb0ef41Sopenharmony_ci      // and found to be slower than calling through the handler table.
23931cb0ef41Sopenharmony_ci      if (opcode == kExprLocalGet) {
23941cb0ef41Sopenharmony_ci        len = WasmFullDecoder::DecodeLocalGet(this, opcode);
23951cb0ef41Sopenharmony_ci      } else if (opcode == kExprI32Const) {
23961cb0ef41Sopenharmony_ci        len = WasmFullDecoder::DecodeI32Const(this, opcode);
23971cb0ef41Sopenharmony_ci      } else {
23981cb0ef41Sopenharmony_ci        OpcodeHandler handler = GetOpcodeHandler(first_byte);
23991cb0ef41Sopenharmony_ci        len = (*handler)(this, opcode);
24001cb0ef41Sopenharmony_ci      }
24011cb0ef41Sopenharmony_ci      this->pc_ += len;
24021cb0ef41Sopenharmony_ci    }
24031cb0ef41Sopenharmony_ci
24041cb0ef41Sopenharmony_ci    if (!VALIDATE(this->pc_ == this->end_)) {
24051cb0ef41Sopenharmony_ci      this->DecodeError("Beyond end of code");
24061cb0ef41Sopenharmony_ci    }
24071cb0ef41Sopenharmony_ci  }
24081cb0ef41Sopenharmony_ci
24091cb0ef41Sopenharmony_ci private:
24101cb0ef41Sopenharmony_ci  uint32_t locals_offset_ = 0;
24111cb0ef41Sopenharmony_ci  Interface interface_;
24121cb0ef41Sopenharmony_ci
24131cb0ef41Sopenharmony_ci  // The value stack, stored as individual pointers for maximum performance.
24141cb0ef41Sopenharmony_ci  Value* stack_ = nullptr;
24151cb0ef41Sopenharmony_ci  Value* stack_end_ = nullptr;
24161cb0ef41Sopenharmony_ci  Value* stack_capacity_end_ = nullptr;
24171cb0ef41Sopenharmony_ci  ASSERT_TRIVIALLY_COPYABLE(Value);
24181cb0ef41Sopenharmony_ci
24191cb0ef41Sopenharmony_ci  // stack of blocks, loops, and ifs.
24201cb0ef41Sopenharmony_ci  ZoneVector<Control> control_;
24211cb0ef41Sopenharmony_ci
24221cb0ef41Sopenharmony_ci  // Controls whether code should be generated for the current block (basically
24231cb0ef41Sopenharmony_ci  // a cache for {ok() && control_.back().reachable()}).
24241cb0ef41Sopenharmony_ci  bool current_code_reachable_and_ok_ = true;
24251cb0ef41Sopenharmony_ci
24261cb0ef41Sopenharmony_ci  // Depth of the current try block.
24271cb0ef41Sopenharmony_ci  int32_t current_catch_ = -1;
24281cb0ef41Sopenharmony_ci
24291cb0ef41Sopenharmony_ci  static Value UnreachableValue(const uint8_t* pc) {
24301cb0ef41Sopenharmony_ci    return Value{pc, kWasmBottom};
24311cb0ef41Sopenharmony_ci  }
24321cb0ef41Sopenharmony_ci
24331cb0ef41Sopenharmony_ci  bool CheckSimdFeatureFlagOpcode(WasmOpcode opcode) {
24341cb0ef41Sopenharmony_ci    if (!FLAG_experimental_wasm_relaxed_simd &&
24351cb0ef41Sopenharmony_ci        WasmOpcodes::IsRelaxedSimdOpcode(opcode)) {
24361cb0ef41Sopenharmony_ci      this->DecodeError(
24371cb0ef41Sopenharmony_ci          "simd opcode not available, enable with --experimental-relaxed-simd");
24381cb0ef41Sopenharmony_ci      return false;
24391cb0ef41Sopenharmony_ci    }
24401cb0ef41Sopenharmony_ci
24411cb0ef41Sopenharmony_ci    return true;
24421cb0ef41Sopenharmony_ci  }
24431cb0ef41Sopenharmony_ci
24441cb0ef41Sopenharmony_ci  MemoryAccessImmediate<validate> MakeMemoryAccessImmediate(
24451cb0ef41Sopenharmony_ci      uint32_t pc_offset, uint32_t max_alignment) {
24461cb0ef41Sopenharmony_ci    return MemoryAccessImmediate<validate>(
24471cb0ef41Sopenharmony_ci        this, this->pc_ + pc_offset, max_alignment, this->module_->is_memory64);
24481cb0ef41Sopenharmony_ci  }
24491cb0ef41Sopenharmony_ci
24501cb0ef41Sopenharmony_ci#ifdef DEBUG
24511cb0ef41Sopenharmony_ci  class TraceLine {
24521cb0ef41Sopenharmony_ci   public:
24531cb0ef41Sopenharmony_ci    explicit TraceLine(WasmFullDecoder* decoder) : decoder_(decoder) {
24541cb0ef41Sopenharmony_ci      WasmOpcode opcode = static_cast<WasmOpcode>(*decoder->pc());
24551cb0ef41Sopenharmony_ci      if (!WasmOpcodes::IsPrefixOpcode(opcode)) AppendOpcode(opcode);
24561cb0ef41Sopenharmony_ci    }
24571cb0ef41Sopenharmony_ci
24581cb0ef41Sopenharmony_ci    void AppendOpcode(WasmOpcode opcode) {
24591cb0ef41Sopenharmony_ci      DCHECK(!WasmOpcodes::IsPrefixOpcode(opcode));
24601cb0ef41Sopenharmony_ci      Append(TRACE_INST_FORMAT, decoder_->startrel(decoder_->pc_),
24611cb0ef41Sopenharmony_ci             WasmOpcodes::OpcodeName(opcode));
24621cb0ef41Sopenharmony_ci    }
24631cb0ef41Sopenharmony_ci
24641cb0ef41Sopenharmony_ci    ~TraceLine() {
24651cb0ef41Sopenharmony_ci      if (!FLAG_trace_wasm_decoder) return;
24661cb0ef41Sopenharmony_ci      AppendStackState();
24671cb0ef41Sopenharmony_ci      PrintF("%.*s\n", len_, buffer_);
24681cb0ef41Sopenharmony_ci    }
24691cb0ef41Sopenharmony_ci
24701cb0ef41Sopenharmony_ci    // Appends a formatted string.
24711cb0ef41Sopenharmony_ci    PRINTF_FORMAT(2, 3)
24721cb0ef41Sopenharmony_ci    void Append(const char* format, ...) {
24731cb0ef41Sopenharmony_ci      if (!FLAG_trace_wasm_decoder) return;
24741cb0ef41Sopenharmony_ci      va_list va_args;
24751cb0ef41Sopenharmony_ci      va_start(va_args, format);
24761cb0ef41Sopenharmony_ci      size_t remaining_len = kMaxLen - len_;
24771cb0ef41Sopenharmony_ci      base::Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
24781cb0ef41Sopenharmony_ci      int len = base::VSNPrintF(remaining_msg_space, format, va_args);
24791cb0ef41Sopenharmony_ci      va_end(va_args);
24801cb0ef41Sopenharmony_ci      len_ += len < 0 ? remaining_len : len;
24811cb0ef41Sopenharmony_ci    }
24821cb0ef41Sopenharmony_ci
24831cb0ef41Sopenharmony_ci   private:
24841cb0ef41Sopenharmony_ci    void AppendStackState() {
24851cb0ef41Sopenharmony_ci      DCHECK(FLAG_trace_wasm_decoder);
24861cb0ef41Sopenharmony_ci      Append(" ");
24871cb0ef41Sopenharmony_ci      for (Control& c : decoder_->control_) {
24881cb0ef41Sopenharmony_ci        switch (c.kind) {
24891cb0ef41Sopenharmony_ci          case kControlIf:
24901cb0ef41Sopenharmony_ci            Append("I");
24911cb0ef41Sopenharmony_ci            break;
24921cb0ef41Sopenharmony_ci          case kControlBlock:
24931cb0ef41Sopenharmony_ci            Append("B");
24941cb0ef41Sopenharmony_ci            break;
24951cb0ef41Sopenharmony_ci          case kControlLoop:
24961cb0ef41Sopenharmony_ci            Append("L");
24971cb0ef41Sopenharmony_ci            break;
24981cb0ef41Sopenharmony_ci          case kControlTry:
24991cb0ef41Sopenharmony_ci            Append("T");
25001cb0ef41Sopenharmony_ci            break;
25011cb0ef41Sopenharmony_ci          case kControlIfElse:
25021cb0ef41Sopenharmony_ci            Append("E");
25031cb0ef41Sopenharmony_ci            break;
25041cb0ef41Sopenharmony_ci          case kControlTryCatch:
25051cb0ef41Sopenharmony_ci            Append("C");
25061cb0ef41Sopenharmony_ci            break;
25071cb0ef41Sopenharmony_ci          case kControlTryCatchAll:
25081cb0ef41Sopenharmony_ci            Append("A");
25091cb0ef41Sopenharmony_ci            break;
25101cb0ef41Sopenharmony_ci          case kControlLet:
25111cb0ef41Sopenharmony_ci            Append("D");
25121cb0ef41Sopenharmony_ci            break;
25131cb0ef41Sopenharmony_ci        }
25141cb0ef41Sopenharmony_ci        if (c.start_merge.arity) Append("%u-", c.start_merge.arity);
25151cb0ef41Sopenharmony_ci        Append("%u", c.end_merge.arity);
25161cb0ef41Sopenharmony_ci        if (!c.reachable()) Append("%c", c.unreachable() ? '*' : '#');
25171cb0ef41Sopenharmony_ci      }
25181cb0ef41Sopenharmony_ci      Append(" | ");
25191cb0ef41Sopenharmony_ci      for (size_t i = 0; i < decoder_->stack_size(); ++i) {
25201cb0ef41Sopenharmony_ci        Value& val = decoder_->stack_[i];
25211cb0ef41Sopenharmony_ci        Append(" %c", val.type.short_name());
25221cb0ef41Sopenharmony_ci      }
25231cb0ef41Sopenharmony_ci    }
25241cb0ef41Sopenharmony_ci
25251cb0ef41Sopenharmony_ci    static constexpr int kMaxLen = 512;
25261cb0ef41Sopenharmony_ci
25271cb0ef41Sopenharmony_ci    char buffer_[kMaxLen];
25281cb0ef41Sopenharmony_ci    int len_ = 0;
25291cb0ef41Sopenharmony_ci    WasmFullDecoder* const decoder_;
25301cb0ef41Sopenharmony_ci  };
25311cb0ef41Sopenharmony_ci#else
25321cb0ef41Sopenharmony_ci  class TraceLine {
25331cb0ef41Sopenharmony_ci   public:
25341cb0ef41Sopenharmony_ci    explicit TraceLine(WasmFullDecoder*) {}
25351cb0ef41Sopenharmony_ci
25361cb0ef41Sopenharmony_ci    void AppendOpcode(WasmOpcode) {}
25371cb0ef41Sopenharmony_ci
25381cb0ef41Sopenharmony_ci    PRINTF_FORMAT(2, 3)
25391cb0ef41Sopenharmony_ci    void Append(const char* format, ...) {}
25401cb0ef41Sopenharmony_ci  };
25411cb0ef41Sopenharmony_ci#endif
25421cb0ef41Sopenharmony_ci
25431cb0ef41Sopenharmony_ci#define DECODE(name)                                                     \
25441cb0ef41Sopenharmony_ci  static int Decode##name(WasmFullDecoder* decoder, WasmOpcode opcode) { \
25451cb0ef41Sopenharmony_ci    TraceLine trace_msg(decoder);                                        \
25461cb0ef41Sopenharmony_ci    return decoder->Decode##name##Impl(&trace_msg, opcode);              \
25471cb0ef41Sopenharmony_ci  }                                                                      \
25481cb0ef41Sopenharmony_ci  V8_INLINE int Decode##name##Impl(TraceLine* trace_msg, WasmOpcode opcode)
25491cb0ef41Sopenharmony_ci
25501cb0ef41Sopenharmony_ci  DECODE(Nop) { return 1; }
25511cb0ef41Sopenharmony_ci
25521cb0ef41Sopenharmony_ci  DECODE(NopForTestingUnsupportedInLiftoff) {
25531cb0ef41Sopenharmony_ci    if (!VALIDATE(FLAG_enable_testing_opcode_in_wasm)) {
25541cb0ef41Sopenharmony_ci      this->DecodeError("Invalid opcode 0x%x", opcode);
25551cb0ef41Sopenharmony_ci      return 0;
25561cb0ef41Sopenharmony_ci    }
25571cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(NopForTestingUnsupportedInLiftoff);
25581cb0ef41Sopenharmony_ci    return 1;
25591cb0ef41Sopenharmony_ci  }
25601cb0ef41Sopenharmony_ci
25611cb0ef41Sopenharmony_ci#define BUILD_SIMPLE_OPCODE(op, _, sig) \
25621cb0ef41Sopenharmony_ci  DECODE(op) { return BuildSimpleOperator_##sig(kExpr##op); }
25631cb0ef41Sopenharmony_ci  FOREACH_SIMPLE_NON_CONST_OPCODE(BUILD_SIMPLE_OPCODE)
25641cb0ef41Sopenharmony_ci#undef BUILD_SIMPLE_OPCODE
25651cb0ef41Sopenharmony_ci
25661cb0ef41Sopenharmony_ci#define BUILD_SIMPLE_OPCODE(op, _, sig)                     \
25671cb0ef41Sopenharmony_ci  DECODE(op) {                                              \
25681cb0ef41Sopenharmony_ci    if (decoding_mode == kInitExpression) {                 \
25691cb0ef41Sopenharmony_ci      if (!VALIDATE(this->enabled_.has_extended_const())) { \
25701cb0ef41Sopenharmony_ci        NonConstError(this, kExpr##op);                     \
25711cb0ef41Sopenharmony_ci        return 0;                                           \
25721cb0ef41Sopenharmony_ci      }                                                     \
25731cb0ef41Sopenharmony_ci    }                                                       \
25741cb0ef41Sopenharmony_ci    return BuildSimpleOperator_##sig(kExpr##op);            \
25751cb0ef41Sopenharmony_ci  }
25761cb0ef41Sopenharmony_ci  FOREACH_SIMPLE_EXTENDED_CONST_OPCODE(BUILD_SIMPLE_OPCODE)
25771cb0ef41Sopenharmony_ci#undef BUILD_SIMPLE_OPCODE
25781cb0ef41Sopenharmony_ci
25791cb0ef41Sopenharmony_ci  DECODE(Block) {
25801cb0ef41Sopenharmony_ci    BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
25811cb0ef41Sopenharmony_ci                                     this->module_);
25821cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
25831cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig);
25841cb0ef41Sopenharmony_ci    Control* block = PushControl(kControlBlock, 0, args.length());
25851cb0ef41Sopenharmony_ci    SetBlockType(block, imm, args.begin());
25861cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Block, block);
25871cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
25881cb0ef41Sopenharmony_ci    PushMergeValues(block, &block->start_merge);
25891cb0ef41Sopenharmony_ci    return 1 + imm.length;
25901cb0ef41Sopenharmony_ci  }
25911cb0ef41Sopenharmony_ci
25921cb0ef41Sopenharmony_ci  DECODE(Rethrow) {
25931cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(eh);
25941cb0ef41Sopenharmony_ci    BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
25951cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
25961cb0ef41Sopenharmony_ci    Control* c = control_at(imm.depth);
25971cb0ef41Sopenharmony_ci    if (!VALIDATE(c->is_try_catchall() || c->is_try_catch())) {
25981cb0ef41Sopenharmony_ci      this->error("rethrow not targeting catch or catch-all");
25991cb0ef41Sopenharmony_ci      return 0;
26001cb0ef41Sopenharmony_ci    }
26011cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Rethrow, c);
26021cb0ef41Sopenharmony_ci    EndControl();
26031cb0ef41Sopenharmony_ci    return 1 + imm.length;
26041cb0ef41Sopenharmony_ci  }
26051cb0ef41Sopenharmony_ci
26061cb0ef41Sopenharmony_ci  DECODE(Throw) {
26071cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(eh);
26081cb0ef41Sopenharmony_ci    TagIndexImmediate<validate> imm(this, this->pc_ + 1);
26091cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
26101cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.tag->ToFunctionSig());
26111cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Throw, imm, base::VectorOf(args));
26121cb0ef41Sopenharmony_ci    DropArgs(imm.tag->ToFunctionSig());
26131cb0ef41Sopenharmony_ci    EndControl();
26141cb0ef41Sopenharmony_ci    return 1 + imm.length;
26151cb0ef41Sopenharmony_ci  }
26161cb0ef41Sopenharmony_ci
26171cb0ef41Sopenharmony_ci  DECODE(Try) {
26181cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(eh);
26191cb0ef41Sopenharmony_ci    BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
26201cb0ef41Sopenharmony_ci                                     this->module_);
26211cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
26221cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig);
26231cb0ef41Sopenharmony_ci    Control* try_block = PushControl(kControlTry, 0, args.length());
26241cb0ef41Sopenharmony_ci    SetBlockType(try_block, imm, args.begin());
26251cb0ef41Sopenharmony_ci    try_block->previous_catch = current_catch_;
26261cb0ef41Sopenharmony_ci    current_catch_ = static_cast<int>(control_depth() - 1);
26271cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Try, try_block);
26281cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
26291cb0ef41Sopenharmony_ci    PushMergeValues(try_block, &try_block->start_merge);
26301cb0ef41Sopenharmony_ci    return 1 + imm.length;
26311cb0ef41Sopenharmony_ci  }
26321cb0ef41Sopenharmony_ci
26331cb0ef41Sopenharmony_ci  DECODE(Catch) {
26341cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(eh);
26351cb0ef41Sopenharmony_ci    TagIndexImmediate<validate> imm(this, this->pc_ + 1);
26361cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
26371cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
26381cb0ef41Sopenharmony_ci    Control* c = &control_.back();
26391cb0ef41Sopenharmony_ci    if (!VALIDATE(c->is_try())) {
26401cb0ef41Sopenharmony_ci      this->DecodeError("catch does not match a try");
26411cb0ef41Sopenharmony_ci      return 0;
26421cb0ef41Sopenharmony_ci    }
26431cb0ef41Sopenharmony_ci    if (!VALIDATE(!c->is_try_catchall())) {
26441cb0ef41Sopenharmony_ci      this->DecodeError("catch after catch-all for try");
26451cb0ef41Sopenharmony_ci      return 0;
26461cb0ef41Sopenharmony_ci    }
26471cb0ef41Sopenharmony_ci    FallThrough();
26481cb0ef41Sopenharmony_ci    c->kind = kControlTryCatch;
26491cb0ef41Sopenharmony_ci    // TODO(jkummerow): Consider moving the stack manipulation after the
26501cb0ef41Sopenharmony_ci    // INTERFACE call for consistency.
26511cb0ef41Sopenharmony_ci    DCHECK_LE(stack_ + c->stack_depth, stack_end_);
26521cb0ef41Sopenharmony_ci    stack_end_ = stack_ + c->stack_depth;
26531cb0ef41Sopenharmony_ci    c->reachability = control_at(1)->innerReachability();
26541cb0ef41Sopenharmony_ci    const WasmTagSig* sig = imm.tag->sig;
26551cb0ef41Sopenharmony_ci    EnsureStackSpace(static_cast<int>(sig->parameter_count()));
26561cb0ef41Sopenharmony_ci    for (ValueType type : sig->parameters()) Push(CreateValue(type));
26571cb0ef41Sopenharmony_ci    base::Vector<Value> values(stack_ + c->stack_depth, sig->parameter_count());
26581cb0ef41Sopenharmony_ci    current_catch_ = c->previous_catch;  // Pop try scope.
26591cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(CatchException, imm, c, values);
26601cb0ef41Sopenharmony_ci    current_code_reachable_and_ok_ = this->ok() && c->reachable();
26611cb0ef41Sopenharmony_ci    return 1 + imm.length;
26621cb0ef41Sopenharmony_ci  }
26631cb0ef41Sopenharmony_ci
26641cb0ef41Sopenharmony_ci  DECODE(Delegate) {
26651cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(eh);
26661cb0ef41Sopenharmony_ci    BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
26671cb0ef41Sopenharmony_ci    // -1 because the current try block is not included in the count.
26681cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_depth() - 1)) return 0;
26691cb0ef41Sopenharmony_ci    Control* c = &control_.back();
26701cb0ef41Sopenharmony_ci    if (!VALIDATE(c->is_incomplete_try())) {
26711cb0ef41Sopenharmony_ci      this->DecodeError("delegate does not match a try");
26721cb0ef41Sopenharmony_ci      return 0;
26731cb0ef41Sopenharmony_ci    }
26741cb0ef41Sopenharmony_ci    // +1 because the current try block is not included in the count.
26751cb0ef41Sopenharmony_ci    uint32_t target_depth = imm.depth + 1;
26761cb0ef41Sopenharmony_ci    while (target_depth < control_depth() - 1 &&
26771cb0ef41Sopenharmony_ci           (!control_at(target_depth)->is_try() ||
26781cb0ef41Sopenharmony_ci            control_at(target_depth)->is_try_catch() ||
26791cb0ef41Sopenharmony_ci            control_at(target_depth)->is_try_catchall())) {
26801cb0ef41Sopenharmony_ci      target_depth++;
26811cb0ef41Sopenharmony_ci    }
26821cb0ef41Sopenharmony_ci    FallThrough();
26831cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(Delegate, target_depth, c);
26841cb0ef41Sopenharmony_ci    current_catch_ = c->previous_catch;
26851cb0ef41Sopenharmony_ci    EndControl();
26861cb0ef41Sopenharmony_ci    PopControl();
26871cb0ef41Sopenharmony_ci    return 1 + imm.length;
26881cb0ef41Sopenharmony_ci  }
26891cb0ef41Sopenharmony_ci
26901cb0ef41Sopenharmony_ci  DECODE(CatchAll) {
26911cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(eh);
26921cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
26931cb0ef41Sopenharmony_ci    Control* c = &control_.back();
26941cb0ef41Sopenharmony_ci    if (!VALIDATE(c->is_try())) {
26951cb0ef41Sopenharmony_ci      this->DecodeError("catch-all does not match a try");
26961cb0ef41Sopenharmony_ci      return 0;
26971cb0ef41Sopenharmony_ci    }
26981cb0ef41Sopenharmony_ci    if (!VALIDATE(!c->is_try_catchall())) {
26991cb0ef41Sopenharmony_ci      this->error("catch-all already present for try");
27001cb0ef41Sopenharmony_ci      return 0;
27011cb0ef41Sopenharmony_ci    }
27021cb0ef41Sopenharmony_ci    FallThrough();
27031cb0ef41Sopenharmony_ci    c->kind = kControlTryCatchAll;
27041cb0ef41Sopenharmony_ci    c->reachability = control_at(1)->innerReachability();
27051cb0ef41Sopenharmony_ci    current_catch_ = c->previous_catch;  // Pop try scope.
27061cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(CatchAll, c);
27071cb0ef41Sopenharmony_ci    stack_end_ = stack_ + c->stack_depth;
27081cb0ef41Sopenharmony_ci    current_code_reachable_and_ok_ = this->ok() && c->reachable();
27091cb0ef41Sopenharmony_ci    return 1;
27101cb0ef41Sopenharmony_ci  }
27111cb0ef41Sopenharmony_ci
27121cb0ef41Sopenharmony_ci  DECODE(BrOnNull) {
27131cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(typed_funcref);
27141cb0ef41Sopenharmony_ci    BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
27151cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
27161cb0ef41Sopenharmony_ci    Value ref_object = Peek(0);
27171cb0ef41Sopenharmony_ci    Control* c = control_at(imm.depth);
27181cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckBranch<true>(c, 1))) return 0;
27191cb0ef41Sopenharmony_ci    switch (ref_object.type.kind()) {
27201cb0ef41Sopenharmony_ci      case kBottom:
27211cb0ef41Sopenharmony_ci        // We are in a polymorphic stack. Leave the stack as it is.
27221cb0ef41Sopenharmony_ci        DCHECK(!current_code_reachable_and_ok_);
27231cb0ef41Sopenharmony_ci        break;
27241cb0ef41Sopenharmony_ci      case kRef:
27251cb0ef41Sopenharmony_ci        // For a non-nullable value, we won't take the branch, and can leave
27261cb0ef41Sopenharmony_ci        // the stack as it is.
27271cb0ef41Sopenharmony_ci        break;
27281cb0ef41Sopenharmony_ci      case kOptRef: {
27291cb0ef41Sopenharmony_ci        Value result = CreateValue(
27301cb0ef41Sopenharmony_ci            ValueType::Ref(ref_object.type.heap_type(), kNonNullable));
27311cb0ef41Sopenharmony_ci        // The result of br_on_null has the same value as the argument (but a
27321cb0ef41Sopenharmony_ci        // non-nullable type).
27331cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
27341cb0ef41Sopenharmony_ci          CALL_INTERFACE(BrOnNull, ref_object, imm.depth, false, &result);
27351cb0ef41Sopenharmony_ci          c->br_merge()->reached = true;
27361cb0ef41Sopenharmony_ci        }
27371cb0ef41Sopenharmony_ci        // In unreachable code, we still have to push a value of the correct
27381cb0ef41Sopenharmony_ci        // type onto the stack.
27391cb0ef41Sopenharmony_ci        Drop(ref_object);
27401cb0ef41Sopenharmony_ci        Push(result);
27411cb0ef41Sopenharmony_ci        break;
27421cb0ef41Sopenharmony_ci      }
27431cb0ef41Sopenharmony_ci      default:
27441cb0ef41Sopenharmony_ci        PopTypeError(0, ref_object, "object reference");
27451cb0ef41Sopenharmony_ci        return 0;
27461cb0ef41Sopenharmony_ci    }
27471cb0ef41Sopenharmony_ci    return 1 + imm.length;
27481cb0ef41Sopenharmony_ci  }
27491cb0ef41Sopenharmony_ci
27501cb0ef41Sopenharmony_ci  DECODE(BrOnNonNull) {
27511cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(gc);
27521cb0ef41Sopenharmony_ci    BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
27531cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
27541cb0ef41Sopenharmony_ci    Value ref_object = Peek(0, 0, kWasmAnyRef);
27551cb0ef41Sopenharmony_ci    Drop(ref_object);
27561cb0ef41Sopenharmony_ci    // Typechecking the branch and creating the branch merges requires the
27571cb0ef41Sopenharmony_ci    // non-null value on the stack, so we push it temporarily.
27581cb0ef41Sopenharmony_ci    Value result = CreateValue(ref_object.type.AsNonNull());
27591cb0ef41Sopenharmony_ci    Push(result);
27601cb0ef41Sopenharmony_ci    Control* c = control_at(imm.depth);
27611cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckBranch<true>(c, 0))) return 0;
27621cb0ef41Sopenharmony_ci    switch (ref_object.type.kind()) {
27631cb0ef41Sopenharmony_ci      case kBottom:
27641cb0ef41Sopenharmony_ci        // We are in unreachable code. Do nothing.
27651cb0ef41Sopenharmony_ci        DCHECK(!current_code_reachable_and_ok_);
27661cb0ef41Sopenharmony_ci        break;
27671cb0ef41Sopenharmony_ci      case kRef:
27681cb0ef41Sopenharmony_ci        // For a non-nullable value, we always take the branch.
27691cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
27701cb0ef41Sopenharmony_ci          CALL_INTERFACE(Forward, ref_object, stack_value(1));
27711cb0ef41Sopenharmony_ci          CALL_INTERFACE(BrOrRet, imm.depth, 0);
27721cb0ef41Sopenharmony_ci          // We know that the following code is not reachable, but according
27731cb0ef41Sopenharmony_ci          // to the spec it technically is. Set it to spec-only reachable.
27741cb0ef41Sopenharmony_ci          SetSucceedingCodeDynamicallyUnreachable();
27751cb0ef41Sopenharmony_ci          c->br_merge()->reached = true;
27761cb0ef41Sopenharmony_ci        }
27771cb0ef41Sopenharmony_ci        break;
27781cb0ef41Sopenharmony_ci      case kOptRef: {
27791cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
27801cb0ef41Sopenharmony_ci          CALL_INTERFACE(Forward, ref_object, stack_value(1));
27811cb0ef41Sopenharmony_ci          CALL_INTERFACE(BrOnNonNull, ref_object, imm.depth);
27821cb0ef41Sopenharmony_ci          c->br_merge()->reached = true;
27831cb0ef41Sopenharmony_ci        }
27841cb0ef41Sopenharmony_ci        break;
27851cb0ef41Sopenharmony_ci      }
27861cb0ef41Sopenharmony_ci      default:
27871cb0ef41Sopenharmony_ci        PopTypeError(0, ref_object, "object reference");
27881cb0ef41Sopenharmony_ci        return 0;
27891cb0ef41Sopenharmony_ci    }
27901cb0ef41Sopenharmony_ci    // If we stay in the branch, {ref_object} is null. Drop it from the stack.
27911cb0ef41Sopenharmony_ci    Drop(result);
27921cb0ef41Sopenharmony_ci    return 1 + imm.length;
27931cb0ef41Sopenharmony_ci  }
27941cb0ef41Sopenharmony_ci
27951cb0ef41Sopenharmony_ci  DECODE(Let) {
27961cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(typed_funcref);
27971cb0ef41Sopenharmony_ci    BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
27981cb0ef41Sopenharmony_ci                                     this->module_);
27991cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
28001cb0ef41Sopenharmony_ci    // Temporarily add the let-defined values to the beginning of the function
28011cb0ef41Sopenharmony_ci    // locals.
28021cb0ef41Sopenharmony_ci    uint32_t locals_length;
28031cb0ef41Sopenharmony_ci    int new_locals_count =
28041cb0ef41Sopenharmony_ci        this->DecodeLocals(this->pc() + 1 + imm.length, &locals_length, 0);
28051cb0ef41Sopenharmony_ci    if (new_locals_count < 0) {
28061cb0ef41Sopenharmony_ci      return 0;
28071cb0ef41Sopenharmony_ci    }
28081cb0ef41Sopenharmony_ci    ArgVector let_local_values =
28091cb0ef41Sopenharmony_ci        PeekArgs(base::VectorOf(this->local_types_.data(), new_locals_count));
28101cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig, new_locals_count);
28111cb0ef41Sopenharmony_ci    Control* let_block = PushControl(kControlLet, new_locals_count,
28121cb0ef41Sopenharmony_ci                                     let_local_values.length() + args.length());
28131cb0ef41Sopenharmony_ci    SetBlockType(let_block, imm, args.begin());
28141cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Block, let_block);
28151cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(AllocateLocals,
28161cb0ef41Sopenharmony_ci                                       base::VectorOf(let_local_values));
28171cb0ef41Sopenharmony_ci    Drop(new_locals_count);  // Drop {let_local_values}.
28181cb0ef41Sopenharmony_ci    DropArgs(imm.sig);       // Drop {args}.
28191cb0ef41Sopenharmony_ci    PushMergeValues(let_block, &let_block->start_merge);
28201cb0ef41Sopenharmony_ci    return 1 + imm.length + locals_length;
28211cb0ef41Sopenharmony_ci  }
28221cb0ef41Sopenharmony_ci
28231cb0ef41Sopenharmony_ci  DECODE(Loop) {
28241cb0ef41Sopenharmony_ci    BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
28251cb0ef41Sopenharmony_ci                                     this->module_);
28261cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
28271cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig);
28281cb0ef41Sopenharmony_ci    Control* block = PushControl(kControlLoop, 0, args.length());
28291cb0ef41Sopenharmony_ci    SetBlockType(&control_.back(), imm, args.begin());
28301cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Loop, block);
28311cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
28321cb0ef41Sopenharmony_ci    PushMergeValues(block, &block->start_merge);
28331cb0ef41Sopenharmony_ci    return 1 + imm.length;
28341cb0ef41Sopenharmony_ci  }
28351cb0ef41Sopenharmony_ci
28361cb0ef41Sopenharmony_ci  DECODE(If) {
28371cb0ef41Sopenharmony_ci    BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
28381cb0ef41Sopenharmony_ci                                     this->module_);
28391cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
28401cb0ef41Sopenharmony_ci    Value cond = Peek(0, 0, kWasmI32);
28411cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig, 1);
28421cb0ef41Sopenharmony_ci    if (!VALIDATE(this->ok())) return 0;
28431cb0ef41Sopenharmony_ci    Control* if_block = PushControl(kControlIf, 0, 1 + args.length());
28441cb0ef41Sopenharmony_ci    SetBlockType(if_block, imm, args.begin());
28451cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(If, cond, if_block);
28461cb0ef41Sopenharmony_ci    Drop(cond);
28471cb0ef41Sopenharmony_ci    DropArgs(imm.sig);  // Drop {args}.
28481cb0ef41Sopenharmony_ci    PushMergeValues(if_block, &if_block->start_merge);
28491cb0ef41Sopenharmony_ci    return 1 + imm.length;
28501cb0ef41Sopenharmony_ci  }
28511cb0ef41Sopenharmony_ci
28521cb0ef41Sopenharmony_ci  DECODE(Else) {
28531cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
28541cb0ef41Sopenharmony_ci    Control* c = &control_.back();
28551cb0ef41Sopenharmony_ci    if (!VALIDATE(c->is_if())) {
28561cb0ef41Sopenharmony_ci      this->DecodeError("else does not match an if");
28571cb0ef41Sopenharmony_ci      return 0;
28581cb0ef41Sopenharmony_ci    }
28591cb0ef41Sopenharmony_ci    if (!VALIDATE(c->is_onearmed_if())) {
28601cb0ef41Sopenharmony_ci      this->DecodeError("else already present for if");
28611cb0ef41Sopenharmony_ci      return 0;
28621cb0ef41Sopenharmony_ci    }
28631cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckFallThru())) return 0;
28641cb0ef41Sopenharmony_ci    c->kind = kControlIfElse;
28651cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(Else, c);
28661cb0ef41Sopenharmony_ci    if (c->reachable()) c->end_merge.reached = true;
28671cb0ef41Sopenharmony_ci    PushMergeValues(c, &c->start_merge);
28681cb0ef41Sopenharmony_ci    c->reachability = control_at(1)->innerReachability();
28691cb0ef41Sopenharmony_ci    current_code_reachable_and_ok_ = this->ok() && c->reachable();
28701cb0ef41Sopenharmony_ci    return 1;
28711cb0ef41Sopenharmony_ci  }
28721cb0ef41Sopenharmony_ci
28731cb0ef41Sopenharmony_ci  DECODE(End) {
28741cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
28751cb0ef41Sopenharmony_ci    if (decoding_mode == kFunctionBody) {
28761cb0ef41Sopenharmony_ci      Control* c = &control_.back();
28771cb0ef41Sopenharmony_ci      if (c->is_incomplete_try()) {
28781cb0ef41Sopenharmony_ci        // Catch-less try, fall through to the implicit catch-all.
28791cb0ef41Sopenharmony_ci        c->kind = kControlTryCatch;
28801cb0ef41Sopenharmony_ci        current_catch_ = c->previous_catch;  // Pop try scope.
28811cb0ef41Sopenharmony_ci      }
28821cb0ef41Sopenharmony_ci      if (c->is_try_catch()) {
28831cb0ef41Sopenharmony_ci        // Emulate catch-all + re-throw.
28841cb0ef41Sopenharmony_ci        FallThrough();
28851cb0ef41Sopenharmony_ci        c->reachability = control_at(1)->innerReachability();
28861cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(CatchAll, c);
28871cb0ef41Sopenharmony_ci        current_code_reachable_and_ok_ =
28881cb0ef41Sopenharmony_ci            this->ok() && control_.back().reachable();
28891cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(Rethrow, c);
28901cb0ef41Sopenharmony_ci        EndControl();
28911cb0ef41Sopenharmony_ci        PopControl();
28921cb0ef41Sopenharmony_ci        return 1;
28931cb0ef41Sopenharmony_ci      }
28941cb0ef41Sopenharmony_ci      if (c->is_onearmed_if()) {
28951cb0ef41Sopenharmony_ci        if (!VALIDATE(TypeCheckOneArmedIf(c))) return 0;
28961cb0ef41Sopenharmony_ci      }
28971cb0ef41Sopenharmony_ci
28981cb0ef41Sopenharmony_ci      if (c->is_let()) {
28991cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(DeallocateLocals, c->locals_count);
29001cb0ef41Sopenharmony_ci        this->local_types_.erase(this->local_types_.begin(),
29011cb0ef41Sopenharmony_ci                                 this->local_types_.begin() + c->locals_count);
29021cb0ef41Sopenharmony_ci        this->num_locals_ -= c->locals_count;
29031cb0ef41Sopenharmony_ci      }
29041cb0ef41Sopenharmony_ci    }
29051cb0ef41Sopenharmony_ci
29061cb0ef41Sopenharmony_ci    if (control_.size() == 1) {
29071cb0ef41Sopenharmony_ci      // We need to call this first because the interface might set
29081cb0ef41Sopenharmony_ci      // {this->end_}, making the next check pass.
29091cb0ef41Sopenharmony_ci      DoReturn<kStrictCounting, decoding_mode == kFunctionBody
29101cb0ef41Sopenharmony_ci                                    ? kFallthroughMerge
29111cb0ef41Sopenharmony_ci                                    : kInitExprMerge>();
29121cb0ef41Sopenharmony_ci      // If at the last (implicit) control, check we are at end.
29131cb0ef41Sopenharmony_ci      if (!VALIDATE(this->pc_ + 1 == this->end_)) {
29141cb0ef41Sopenharmony_ci        this->DecodeError(this->pc_ + 1, "trailing code after function end");
29151cb0ef41Sopenharmony_ci        return 0;
29161cb0ef41Sopenharmony_ci      }
29171cb0ef41Sopenharmony_ci      // The result of the block is the return value.
29181cb0ef41Sopenharmony_ci      trace_msg->Append("\n" TRACE_INST_FORMAT, startrel(this->pc_),
29191cb0ef41Sopenharmony_ci                        "(implicit) return");
29201cb0ef41Sopenharmony_ci      control_.clear();
29211cb0ef41Sopenharmony_ci      return 1;
29221cb0ef41Sopenharmony_ci    }
29231cb0ef41Sopenharmony_ci
29241cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckFallThru())) return 0;
29251cb0ef41Sopenharmony_ci    PopControl();
29261cb0ef41Sopenharmony_ci    return 1;
29271cb0ef41Sopenharmony_ci  }
29281cb0ef41Sopenharmony_ci
29291cb0ef41Sopenharmony_ci  DECODE(Select) {
29301cb0ef41Sopenharmony_ci    Value cond = Peek(0, 2, kWasmI32);
29311cb0ef41Sopenharmony_ci    Value fval = Peek(1);
29321cb0ef41Sopenharmony_ci    Value tval = Peek(2, 0, fval.type);
29331cb0ef41Sopenharmony_ci    ValueType type = tval.type == kWasmBottom ? fval.type : tval.type;
29341cb0ef41Sopenharmony_ci    if (!VALIDATE(!type.is_reference())) {
29351cb0ef41Sopenharmony_ci      this->DecodeError(
29361cb0ef41Sopenharmony_ci          "select without type is only valid for value type inputs");
29371cb0ef41Sopenharmony_ci      return 0;
29381cb0ef41Sopenharmony_ci    }
29391cb0ef41Sopenharmony_ci    Value result = CreateValue(type);
29401cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Select, cond, fval, tval, &result);
29411cb0ef41Sopenharmony_ci    Drop(3);
29421cb0ef41Sopenharmony_ci    Push(result);
29431cb0ef41Sopenharmony_ci    return 1;
29441cb0ef41Sopenharmony_ci  }
29451cb0ef41Sopenharmony_ci
29461cb0ef41Sopenharmony_ci  DECODE(SelectWithType) {
29471cb0ef41Sopenharmony_ci    this->detected_->Add(kFeature_reftypes);
29481cb0ef41Sopenharmony_ci    SelectTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
29491cb0ef41Sopenharmony_ci                                      this->module_);
29501cb0ef41Sopenharmony_ci    if (this->failed()) return 0;
29511cb0ef41Sopenharmony_ci    Value cond = Peek(0, 2, kWasmI32);
29521cb0ef41Sopenharmony_ci    Value fval = Peek(1, 1, imm.type);
29531cb0ef41Sopenharmony_ci    Value tval = Peek(2, 0, imm.type);
29541cb0ef41Sopenharmony_ci    Value result = CreateValue(imm.type);
29551cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Select, cond, fval, tval, &result);
29561cb0ef41Sopenharmony_ci    Drop(3);
29571cb0ef41Sopenharmony_ci    Push(result);
29581cb0ef41Sopenharmony_ci    return 1 + imm.length;
29591cb0ef41Sopenharmony_ci  }
29601cb0ef41Sopenharmony_ci
29611cb0ef41Sopenharmony_ci  DECODE(Br) {
29621cb0ef41Sopenharmony_ci    BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
29631cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
29641cb0ef41Sopenharmony_ci    Control* c = control_at(imm.depth);
29651cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckBranch<false>(c, 0))) return 0;
29661cb0ef41Sopenharmony_ci    if (V8_LIKELY(current_code_reachable_and_ok_)) {
29671cb0ef41Sopenharmony_ci      CALL_INTERFACE(BrOrRet, imm.depth, 0);
29681cb0ef41Sopenharmony_ci      c->br_merge()->reached = true;
29691cb0ef41Sopenharmony_ci    }
29701cb0ef41Sopenharmony_ci    EndControl();
29711cb0ef41Sopenharmony_ci    return 1 + imm.length;
29721cb0ef41Sopenharmony_ci  }
29731cb0ef41Sopenharmony_ci
29741cb0ef41Sopenharmony_ci  DECODE(BrIf) {
29751cb0ef41Sopenharmony_ci    BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
29761cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
29771cb0ef41Sopenharmony_ci    Value cond = Peek(0, 0, kWasmI32);
29781cb0ef41Sopenharmony_ci    Control* c = control_at(imm.depth);
29791cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckBranch<true>(c, 1))) return 0;
29801cb0ef41Sopenharmony_ci    if (V8_LIKELY(current_code_reachable_and_ok_)) {
29811cb0ef41Sopenharmony_ci      CALL_INTERFACE(BrIf, cond, imm.depth);
29821cb0ef41Sopenharmony_ci      c->br_merge()->reached = true;
29831cb0ef41Sopenharmony_ci    }
29841cb0ef41Sopenharmony_ci    Drop(cond);
29851cb0ef41Sopenharmony_ci    return 1 + imm.length;
29861cb0ef41Sopenharmony_ci  }
29871cb0ef41Sopenharmony_ci
29881cb0ef41Sopenharmony_ci  DECODE(BrTable) {
29891cb0ef41Sopenharmony_ci    BranchTableImmediate<validate> imm(this, this->pc_ + 1);
29901cb0ef41Sopenharmony_ci    BranchTableIterator<validate> iterator(this, imm);
29911cb0ef41Sopenharmony_ci    Value key = Peek(0, 0, kWasmI32);
29921cb0ef41Sopenharmony_ci    if (this->failed()) return 0;
29931cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
29941cb0ef41Sopenharmony_ci
29951cb0ef41Sopenharmony_ci    // Cache the branch targets during the iteration, so that we can set
29961cb0ef41Sopenharmony_ci    // all branch targets as reachable after the {CALL_INTERFACE} call.
29971cb0ef41Sopenharmony_ci    std::vector<bool> br_targets(control_.size());
29981cb0ef41Sopenharmony_ci
29991cb0ef41Sopenharmony_ci    uint32_t arity = 0;
30001cb0ef41Sopenharmony_ci
30011cb0ef41Sopenharmony_ci    while (iterator.has_next()) {
30021cb0ef41Sopenharmony_ci      const uint32_t index = iterator.cur_index();
30031cb0ef41Sopenharmony_ci      const byte* pos = iterator.pc();
30041cb0ef41Sopenharmony_ci      const uint32_t target = iterator.next();
30051cb0ef41Sopenharmony_ci      if (!VALIDATE(target < control_depth())) {
30061cb0ef41Sopenharmony_ci        this->DecodeError(pos, "invalid branch depth: %u", target);
30071cb0ef41Sopenharmony_ci        return 0;
30081cb0ef41Sopenharmony_ci      }
30091cb0ef41Sopenharmony_ci      // Avoid redundant branch target checks.
30101cb0ef41Sopenharmony_ci      if (br_targets[target]) continue;
30111cb0ef41Sopenharmony_ci      br_targets[target] = true;
30121cb0ef41Sopenharmony_ci
30131cb0ef41Sopenharmony_ci      if (validate) {
30141cb0ef41Sopenharmony_ci        if (index == 0) {
30151cb0ef41Sopenharmony_ci          arity = control_at(target)->br_merge()->arity;
30161cb0ef41Sopenharmony_ci        } else if (!VALIDATE(control_at(target)->br_merge()->arity == arity)) {
30171cb0ef41Sopenharmony_ci          this->DecodeError(
30181cb0ef41Sopenharmony_ci              pos, "br_table: label arity inconsistent with previous arity %d",
30191cb0ef41Sopenharmony_ci              arity);
30201cb0ef41Sopenharmony_ci          return 0;
30211cb0ef41Sopenharmony_ci        }
30221cb0ef41Sopenharmony_ci        if (!VALIDATE(TypeCheckBranch<false>(control_at(target), 1))) return 0;
30231cb0ef41Sopenharmony_ci      }
30241cb0ef41Sopenharmony_ci    }
30251cb0ef41Sopenharmony_ci
30261cb0ef41Sopenharmony_ci    if (V8_LIKELY(current_code_reachable_and_ok_)) {
30271cb0ef41Sopenharmony_ci      CALL_INTERFACE(BrTable, imm, key);
30281cb0ef41Sopenharmony_ci
30291cb0ef41Sopenharmony_ci      for (uint32_t i = 0; i < control_depth(); ++i) {
30301cb0ef41Sopenharmony_ci        control_at(i)->br_merge()->reached |= br_targets[i];
30311cb0ef41Sopenharmony_ci      }
30321cb0ef41Sopenharmony_ci    }
30331cb0ef41Sopenharmony_ci    Drop(key);
30341cb0ef41Sopenharmony_ci    EndControl();
30351cb0ef41Sopenharmony_ci    return 1 + iterator.length();
30361cb0ef41Sopenharmony_ci  }
30371cb0ef41Sopenharmony_ci
30381cb0ef41Sopenharmony_ci  DECODE(Return) {
30391cb0ef41Sopenharmony_ci    return DoReturn<kNonStrictCounting, kReturnMerge>() ? 1 : 0;
30401cb0ef41Sopenharmony_ci  }
30411cb0ef41Sopenharmony_ci
30421cb0ef41Sopenharmony_ci  DECODE(Unreachable) {
30431cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Trap, TrapReason::kTrapUnreachable);
30441cb0ef41Sopenharmony_ci    EndControl();
30451cb0ef41Sopenharmony_ci    return 1;
30461cb0ef41Sopenharmony_ci  }
30471cb0ef41Sopenharmony_ci
30481cb0ef41Sopenharmony_ci  DECODE(I32Const) {
30491cb0ef41Sopenharmony_ci    ImmI32Immediate<validate> imm(this, this->pc_ + 1);
30501cb0ef41Sopenharmony_ci    Value value = CreateValue(kWasmI32);
30511cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(I32Const, &value, imm.value);
30521cb0ef41Sopenharmony_ci    Push(value);
30531cb0ef41Sopenharmony_ci    return 1 + imm.length;
30541cb0ef41Sopenharmony_ci  }
30551cb0ef41Sopenharmony_ci
30561cb0ef41Sopenharmony_ci  DECODE(I64Const) {
30571cb0ef41Sopenharmony_ci    ImmI64Immediate<validate> imm(this, this->pc_ + 1);
30581cb0ef41Sopenharmony_ci    Value value = CreateValue(kWasmI64);
30591cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(I64Const, &value, imm.value);
30601cb0ef41Sopenharmony_ci    Push(value);
30611cb0ef41Sopenharmony_ci    return 1 + imm.length;
30621cb0ef41Sopenharmony_ci  }
30631cb0ef41Sopenharmony_ci
30641cb0ef41Sopenharmony_ci  DECODE(F32Const) {
30651cb0ef41Sopenharmony_ci    ImmF32Immediate<validate> imm(this, this->pc_ + 1);
30661cb0ef41Sopenharmony_ci    Value value = CreateValue(kWasmF32);
30671cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(F32Const, &value, imm.value);
30681cb0ef41Sopenharmony_ci    Push(value);
30691cb0ef41Sopenharmony_ci    return 1 + imm.length;
30701cb0ef41Sopenharmony_ci  }
30711cb0ef41Sopenharmony_ci
30721cb0ef41Sopenharmony_ci  DECODE(F64Const) {
30731cb0ef41Sopenharmony_ci    ImmF64Immediate<validate> imm(this, this->pc_ + 1);
30741cb0ef41Sopenharmony_ci    Value value = CreateValue(kWasmF64);
30751cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(F64Const, &value, imm.value);
30761cb0ef41Sopenharmony_ci    Push(value);
30771cb0ef41Sopenharmony_ci    return 1 + imm.length;
30781cb0ef41Sopenharmony_ci  }
30791cb0ef41Sopenharmony_ci
30801cb0ef41Sopenharmony_ci  DECODE(RefNull) {
30811cb0ef41Sopenharmony_ci    this->detected_->Add(kFeature_reftypes);
30821cb0ef41Sopenharmony_ci    HeapTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
30831cb0ef41Sopenharmony_ci                                    this->module_);
30841cb0ef41Sopenharmony_ci    if (!VALIDATE(this->ok())) return 0;
30851cb0ef41Sopenharmony_ci    ValueType type = ValueType::Ref(imm.type, kNullable);
30861cb0ef41Sopenharmony_ci    Value value = CreateValue(type);
30871cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(RefNull, type, &value);
30881cb0ef41Sopenharmony_ci    Push(value);
30891cb0ef41Sopenharmony_ci    return 1 + imm.length;
30901cb0ef41Sopenharmony_ci  }
30911cb0ef41Sopenharmony_ci
30921cb0ef41Sopenharmony_ci  DECODE(RefIsNull) {
30931cb0ef41Sopenharmony_ci    this->detected_->Add(kFeature_reftypes);
30941cb0ef41Sopenharmony_ci    Value value = Peek(0);
30951cb0ef41Sopenharmony_ci    Value result = CreateValue(kWasmI32);
30961cb0ef41Sopenharmony_ci    switch (value.type.kind()) {
30971cb0ef41Sopenharmony_ci      case kOptRef:
30981cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(UnOp, kExprRefIsNull, value,
30991cb0ef41Sopenharmony_ci                                           &result);
31001cb0ef41Sopenharmony_ci        Drop(value);
31011cb0ef41Sopenharmony_ci        Push(result);
31021cb0ef41Sopenharmony_ci        return 1;
31031cb0ef41Sopenharmony_ci      case kBottom:
31041cb0ef41Sopenharmony_ci        // We are in unreachable code, the return value does not matter.
31051cb0ef41Sopenharmony_ci      case kRef:
31061cb0ef41Sopenharmony_ci        // For non-nullable references, the result is always false.
31071cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(Drop);
31081cb0ef41Sopenharmony_ci        Drop(value);
31091cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(I32Const, &result, 0);
31101cb0ef41Sopenharmony_ci        Push(result);
31111cb0ef41Sopenharmony_ci        return 1;
31121cb0ef41Sopenharmony_ci      default:
31131cb0ef41Sopenharmony_ci        if (validate) {
31141cb0ef41Sopenharmony_ci          PopTypeError(0, value, "reference type");
31151cb0ef41Sopenharmony_ci          return 0;
31161cb0ef41Sopenharmony_ci        }
31171cb0ef41Sopenharmony_ci        UNREACHABLE();
31181cb0ef41Sopenharmony_ci    }
31191cb0ef41Sopenharmony_ci  }
31201cb0ef41Sopenharmony_ci
31211cb0ef41Sopenharmony_ci  DECODE(RefFunc) {
31221cb0ef41Sopenharmony_ci    this->detected_->Add(kFeature_reftypes);
31231cb0ef41Sopenharmony_ci    IndexImmediate<validate> imm(this, this->pc_ + 1, "function index");
31241cb0ef41Sopenharmony_ci    if (!this->ValidateFunction(this->pc_ + 1, imm)) return 0;
31251cb0ef41Sopenharmony_ci    HeapType heap_type(this->enabled_.has_typed_funcref()
31261cb0ef41Sopenharmony_ci                           ? this->module_->functions[imm.index].sig_index
31271cb0ef41Sopenharmony_ci                           : HeapType::kFunc);
31281cb0ef41Sopenharmony_ci    Value value = CreateValue(ValueType::Ref(heap_type, kNonNullable));
31291cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(RefFunc, imm.index, &value);
31301cb0ef41Sopenharmony_ci    Push(value);
31311cb0ef41Sopenharmony_ci    return 1 + imm.length;
31321cb0ef41Sopenharmony_ci  }
31331cb0ef41Sopenharmony_ci
31341cb0ef41Sopenharmony_ci  DECODE(RefAsNonNull) {
31351cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(typed_funcref);
31361cb0ef41Sopenharmony_ci    Value value = Peek(0);
31371cb0ef41Sopenharmony_ci    switch (value.type.kind()) {
31381cb0ef41Sopenharmony_ci      case kBottom:
31391cb0ef41Sopenharmony_ci        // We are in unreachable code. Forward the bottom value.
31401cb0ef41Sopenharmony_ci      case kRef:
31411cb0ef41Sopenharmony_ci        // A non-nullable value can remain as-is.
31421cb0ef41Sopenharmony_ci        return 1;
31431cb0ef41Sopenharmony_ci      case kOptRef: {
31441cb0ef41Sopenharmony_ci        Value result =
31451cb0ef41Sopenharmony_ci            CreateValue(ValueType::Ref(value.type.heap_type(), kNonNullable));
31461cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(RefAsNonNull, value, &result);
31471cb0ef41Sopenharmony_ci        Drop(value);
31481cb0ef41Sopenharmony_ci        Push(result);
31491cb0ef41Sopenharmony_ci        return 1;
31501cb0ef41Sopenharmony_ci      }
31511cb0ef41Sopenharmony_ci      default:
31521cb0ef41Sopenharmony_ci        if (validate) {
31531cb0ef41Sopenharmony_ci          PopTypeError(0, value, "reference type");
31541cb0ef41Sopenharmony_ci        }
31551cb0ef41Sopenharmony_ci        return 0;
31561cb0ef41Sopenharmony_ci    }
31571cb0ef41Sopenharmony_ci  }
31581cb0ef41Sopenharmony_ci
31591cb0ef41Sopenharmony_ci  V8_INLINE DECODE(LocalGet) {
31601cb0ef41Sopenharmony_ci    IndexImmediate<validate> imm(this, this->pc_ + 1, "local index");
31611cb0ef41Sopenharmony_ci    if (!this->ValidateLocal(this->pc_ + 1, imm)) return 0;
31621cb0ef41Sopenharmony_ci    if (!VALIDATE(!this->enabled_.has_nn_locals() ||
31631cb0ef41Sopenharmony_ci                  this->is_local_initialized(imm.index))) {
31641cb0ef41Sopenharmony_ci      this->DecodeError(this->pc_, "uninitialized non-defaultable local: %u",
31651cb0ef41Sopenharmony_ci                        imm.index);
31661cb0ef41Sopenharmony_ci      return 0;
31671cb0ef41Sopenharmony_ci    }
31681cb0ef41Sopenharmony_ci    Value value = CreateValue(this->local_type(imm.index));
31691cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(LocalGet, &value, imm);
31701cb0ef41Sopenharmony_ci    Push(value);
31711cb0ef41Sopenharmony_ci    return 1 + imm.length;
31721cb0ef41Sopenharmony_ci  }
31731cb0ef41Sopenharmony_ci
31741cb0ef41Sopenharmony_ci  DECODE(LocalSet) {
31751cb0ef41Sopenharmony_ci    IndexImmediate<validate> imm(this, this->pc_ + 1, "local index");
31761cb0ef41Sopenharmony_ci    if (!this->ValidateLocal(this->pc_ + 1, imm)) return 0;
31771cb0ef41Sopenharmony_ci    Value value = Peek(0, 0, this->local_type(imm.index));
31781cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(LocalSet, value, imm);
31791cb0ef41Sopenharmony_ci    Drop(value);
31801cb0ef41Sopenharmony_ci    this->set_local_initialized(imm.index);
31811cb0ef41Sopenharmony_ci    return 1 + imm.length;
31821cb0ef41Sopenharmony_ci  }
31831cb0ef41Sopenharmony_ci
31841cb0ef41Sopenharmony_ci  DECODE(LocalTee) {
31851cb0ef41Sopenharmony_ci    IndexImmediate<validate> imm(this, this->pc_ + 1, "local index");
31861cb0ef41Sopenharmony_ci    if (!this->ValidateLocal(this->pc_ + 1, imm)) return 0;
31871cb0ef41Sopenharmony_ci    ValueType local_type = this->local_type(imm.index);
31881cb0ef41Sopenharmony_ci    Value value = Peek(0, 0, local_type);
31891cb0ef41Sopenharmony_ci    Value result = CreateValue(local_type);
31901cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(LocalTee, value, &result, imm);
31911cb0ef41Sopenharmony_ci    Drop(value);
31921cb0ef41Sopenharmony_ci    Push(result);
31931cb0ef41Sopenharmony_ci    this->set_local_initialized(imm.index);
31941cb0ef41Sopenharmony_ci    return 1 + imm.length;
31951cb0ef41Sopenharmony_ci  }
31961cb0ef41Sopenharmony_ci
31971cb0ef41Sopenharmony_ci  DECODE(Drop) {
31981cb0ef41Sopenharmony_ci    Peek(0);
31991cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(Drop);
32001cb0ef41Sopenharmony_ci    Drop(1);
32011cb0ef41Sopenharmony_ci    return 1;
32021cb0ef41Sopenharmony_ci  }
32031cb0ef41Sopenharmony_ci
32041cb0ef41Sopenharmony_ci  DECODE(GlobalGet) {
32051cb0ef41Sopenharmony_ci    GlobalIndexImmediate<validate> imm(this, this->pc_ + 1);
32061cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
32071cb0ef41Sopenharmony_ci    Value result = CreateValue(imm.global->type);
32081cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(GlobalGet, &result, imm);
32091cb0ef41Sopenharmony_ci    Push(result);
32101cb0ef41Sopenharmony_ci    return 1 + imm.length;
32111cb0ef41Sopenharmony_ci  }
32121cb0ef41Sopenharmony_ci
32131cb0ef41Sopenharmony_ci  DECODE(GlobalSet) {
32141cb0ef41Sopenharmony_ci    GlobalIndexImmediate<validate> imm(this, this->pc_ + 1);
32151cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
32161cb0ef41Sopenharmony_ci    if (!VALIDATE(imm.global->mutability)) {
32171cb0ef41Sopenharmony_ci      this->DecodeError("immutable global #%u cannot be assigned", imm.index);
32181cb0ef41Sopenharmony_ci      return 0;
32191cb0ef41Sopenharmony_ci    }
32201cb0ef41Sopenharmony_ci    Value value = Peek(0, 0, imm.global->type);
32211cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(GlobalSet, value, imm);
32221cb0ef41Sopenharmony_ci    Drop(value);
32231cb0ef41Sopenharmony_ci    return 1 + imm.length;
32241cb0ef41Sopenharmony_ci  }
32251cb0ef41Sopenharmony_ci
32261cb0ef41Sopenharmony_ci  DECODE(TableGet) {
32271cb0ef41Sopenharmony_ci    this->detected_->Add(kFeature_reftypes);
32281cb0ef41Sopenharmony_ci    IndexImmediate<validate> imm(this, this->pc_ + 1, "table index");
32291cb0ef41Sopenharmony_ci    if (!this->ValidateTable(this->pc_ + 1, imm)) return 0;
32301cb0ef41Sopenharmony_ci    Value index = Peek(0, 0, kWasmI32);
32311cb0ef41Sopenharmony_ci    Value result = CreateValue(this->module_->tables[imm.index].type);
32321cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(TableGet, index, &result, imm);
32331cb0ef41Sopenharmony_ci    Drop(index);
32341cb0ef41Sopenharmony_ci    Push(result);
32351cb0ef41Sopenharmony_ci    return 1 + imm.length;
32361cb0ef41Sopenharmony_ci  }
32371cb0ef41Sopenharmony_ci
32381cb0ef41Sopenharmony_ci  DECODE(TableSet) {
32391cb0ef41Sopenharmony_ci    this->detected_->Add(kFeature_reftypes);
32401cb0ef41Sopenharmony_ci    IndexImmediate<validate> imm(this, this->pc_ + 1, "table index");
32411cb0ef41Sopenharmony_ci    if (!this->ValidateTable(this->pc_ + 1, imm)) return 0;
32421cb0ef41Sopenharmony_ci    Value value = Peek(0, 1, this->module_->tables[imm.index].type);
32431cb0ef41Sopenharmony_ci    Value index = Peek(1, 0, kWasmI32);
32441cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(TableSet, index, value, imm);
32451cb0ef41Sopenharmony_ci    Drop(2);
32461cb0ef41Sopenharmony_ci    return 1 + imm.length;
32471cb0ef41Sopenharmony_ci  }
32481cb0ef41Sopenharmony_ci
32491cb0ef41Sopenharmony_ci  DECODE(LoadMem) {
32501cb0ef41Sopenharmony_ci    // Hard-code the list of load types. The opcodes are highly unlikely to
32511cb0ef41Sopenharmony_ci    // ever change, and we have some checks here to guard against that.
32521cb0ef41Sopenharmony_ci    static_assert(sizeof(LoadType) == sizeof(uint8_t), "LoadType is compact");
32531cb0ef41Sopenharmony_ci    static constexpr uint8_t kMinOpcode = kExprI32LoadMem;
32541cb0ef41Sopenharmony_ci    static constexpr uint8_t kMaxOpcode = kExprI64LoadMem32U;
32551cb0ef41Sopenharmony_ci    static constexpr LoadType kLoadTypes[] = {
32561cb0ef41Sopenharmony_ci        LoadType::kI32Load,    LoadType::kI64Load,    LoadType::kF32Load,
32571cb0ef41Sopenharmony_ci        LoadType::kF64Load,    LoadType::kI32Load8S,  LoadType::kI32Load8U,
32581cb0ef41Sopenharmony_ci        LoadType::kI32Load16S, LoadType::kI32Load16U, LoadType::kI64Load8S,
32591cb0ef41Sopenharmony_ci        LoadType::kI64Load8U,  LoadType::kI64Load16S, LoadType::kI64Load16U,
32601cb0ef41Sopenharmony_ci        LoadType::kI64Load32S, LoadType::kI64Load32U};
32611cb0ef41Sopenharmony_ci    STATIC_ASSERT(arraysize(kLoadTypes) == kMaxOpcode - kMinOpcode + 1);
32621cb0ef41Sopenharmony_ci    DCHECK_LE(kMinOpcode, opcode);
32631cb0ef41Sopenharmony_ci    DCHECK_GE(kMaxOpcode, opcode);
32641cb0ef41Sopenharmony_ci    return DecodeLoadMem(kLoadTypes[opcode - kMinOpcode]);
32651cb0ef41Sopenharmony_ci  }
32661cb0ef41Sopenharmony_ci
32671cb0ef41Sopenharmony_ci  DECODE(StoreMem) {
32681cb0ef41Sopenharmony_ci    // Hard-code the list of store types. The opcodes are highly unlikely to
32691cb0ef41Sopenharmony_ci    // ever change, and we have some checks here to guard against that.
32701cb0ef41Sopenharmony_ci    static_assert(sizeof(StoreType) == sizeof(uint8_t), "StoreType is compact");
32711cb0ef41Sopenharmony_ci    static constexpr uint8_t kMinOpcode = kExprI32StoreMem;
32721cb0ef41Sopenharmony_ci    static constexpr uint8_t kMaxOpcode = kExprI64StoreMem32;
32731cb0ef41Sopenharmony_ci    static constexpr StoreType kStoreTypes[] = {
32741cb0ef41Sopenharmony_ci        StoreType::kI32Store,  StoreType::kI64Store,   StoreType::kF32Store,
32751cb0ef41Sopenharmony_ci        StoreType::kF64Store,  StoreType::kI32Store8,  StoreType::kI32Store16,
32761cb0ef41Sopenharmony_ci        StoreType::kI64Store8, StoreType::kI64Store16, StoreType::kI64Store32};
32771cb0ef41Sopenharmony_ci    STATIC_ASSERT(arraysize(kStoreTypes) == kMaxOpcode - kMinOpcode + 1);
32781cb0ef41Sopenharmony_ci    DCHECK_LE(kMinOpcode, opcode);
32791cb0ef41Sopenharmony_ci    DCHECK_GE(kMaxOpcode, opcode);
32801cb0ef41Sopenharmony_ci    return DecodeStoreMem(kStoreTypes[opcode - kMinOpcode]);
32811cb0ef41Sopenharmony_ci  }
32821cb0ef41Sopenharmony_ci
32831cb0ef41Sopenharmony_ci  DECODE(MemoryGrow) {
32841cb0ef41Sopenharmony_ci    MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
32851cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
32861cb0ef41Sopenharmony_ci    // This opcode will not be emitted by the asm translator.
32871cb0ef41Sopenharmony_ci    DCHECK_EQ(kWasmOrigin, this->module_->origin);
32881cb0ef41Sopenharmony_ci    ValueType mem_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
32891cb0ef41Sopenharmony_ci    Value value = Peek(0, 0, mem_type);
32901cb0ef41Sopenharmony_ci    Value result = CreateValue(mem_type);
32911cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryGrow, value, &result);
32921cb0ef41Sopenharmony_ci    Drop(value);
32931cb0ef41Sopenharmony_ci    Push(result);
32941cb0ef41Sopenharmony_ci    return 1 + imm.length;
32951cb0ef41Sopenharmony_ci  }
32961cb0ef41Sopenharmony_ci
32971cb0ef41Sopenharmony_ci  DECODE(MemorySize) {
32981cb0ef41Sopenharmony_ci    MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
32991cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
33001cb0ef41Sopenharmony_ci    ValueType result_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
33011cb0ef41Sopenharmony_ci    Value result = CreateValue(result_type);
33021cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(CurrentMemoryPages, &result);
33031cb0ef41Sopenharmony_ci    Push(result);
33041cb0ef41Sopenharmony_ci    return 1 + imm.length;
33051cb0ef41Sopenharmony_ci  }
33061cb0ef41Sopenharmony_ci
33071cb0ef41Sopenharmony_ci  DECODE(CallFunction) {
33081cb0ef41Sopenharmony_ci    CallFunctionImmediate<validate> imm(this, this->pc_ + 1);
33091cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
33101cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig);
33111cb0ef41Sopenharmony_ci    ReturnVector returns = CreateReturnValues(imm.sig);
33121cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(CallDirect, imm, args.begin(),
33131cb0ef41Sopenharmony_ci                                       returns.begin());
33141cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
33151cb0ef41Sopenharmony_ci    PushReturns(returns);
33161cb0ef41Sopenharmony_ci    return 1 + imm.length;
33171cb0ef41Sopenharmony_ci  }
33181cb0ef41Sopenharmony_ci
33191cb0ef41Sopenharmony_ci  DECODE(CallIndirect) {
33201cb0ef41Sopenharmony_ci    CallIndirectImmediate<validate> imm(this, this->pc_ + 1);
33211cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
33221cb0ef41Sopenharmony_ci    Value index =
33231cb0ef41Sopenharmony_ci        Peek(0, static_cast<int>(imm.sig->parameter_count()), kWasmI32);
33241cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig, 1);
33251cb0ef41Sopenharmony_ci    ReturnVector returns = CreateReturnValues(imm.sig);
33261cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(CallIndirect, index, imm, args.begin(),
33271cb0ef41Sopenharmony_ci                                       returns.begin());
33281cb0ef41Sopenharmony_ci    Drop(index);
33291cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
33301cb0ef41Sopenharmony_ci    PushReturns(returns);
33311cb0ef41Sopenharmony_ci    return 1 + imm.length;
33321cb0ef41Sopenharmony_ci  }
33331cb0ef41Sopenharmony_ci
33341cb0ef41Sopenharmony_ci  DECODE(ReturnCall) {
33351cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(return_call);
33361cb0ef41Sopenharmony_ci    CallFunctionImmediate<validate> imm(this, this->pc_ + 1);
33371cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
33381cb0ef41Sopenharmony_ci    if (!VALIDATE(this->CanReturnCall(imm.sig))) {
33391cb0ef41Sopenharmony_ci      this->DecodeError("%s: %s", WasmOpcodes::OpcodeName(kExprReturnCall),
33401cb0ef41Sopenharmony_ci                        "tail call type error");
33411cb0ef41Sopenharmony_ci      return 0;
33421cb0ef41Sopenharmony_ci    }
33431cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig);
33441cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(ReturnCall, imm, args.begin());
33451cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
33461cb0ef41Sopenharmony_ci    EndControl();
33471cb0ef41Sopenharmony_ci    return 1 + imm.length;
33481cb0ef41Sopenharmony_ci  }
33491cb0ef41Sopenharmony_ci
33501cb0ef41Sopenharmony_ci  DECODE(ReturnCallIndirect) {
33511cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(return_call);
33521cb0ef41Sopenharmony_ci    CallIndirectImmediate<validate> imm(this, this->pc_ + 1);
33531cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + 1, imm)) return 0;
33541cb0ef41Sopenharmony_ci    if (!VALIDATE(this->CanReturnCall(imm.sig))) {
33551cb0ef41Sopenharmony_ci      this->DecodeError("%s: %s",
33561cb0ef41Sopenharmony_ci                        WasmOpcodes::OpcodeName(kExprReturnCallIndirect),
33571cb0ef41Sopenharmony_ci                        "tail call return types mismatch");
33581cb0ef41Sopenharmony_ci      return 0;
33591cb0ef41Sopenharmony_ci    }
33601cb0ef41Sopenharmony_ci    Value index = Peek(0, 0, kWasmI32);
33611cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(imm.sig, 1);
33621cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(ReturnCallIndirect, index, imm,
33631cb0ef41Sopenharmony_ci                                       args.begin());
33641cb0ef41Sopenharmony_ci    Drop(index);
33651cb0ef41Sopenharmony_ci    DropArgs(imm.sig);
33661cb0ef41Sopenharmony_ci    EndControl();
33671cb0ef41Sopenharmony_ci    return 1 + imm.length;
33681cb0ef41Sopenharmony_ci  }
33691cb0ef41Sopenharmony_ci
33701cb0ef41Sopenharmony_ci  DECODE(CallRef) {
33711cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(typed_funcref);
33721cb0ef41Sopenharmony_ci    Value func_ref = Peek(0);
33731cb0ef41Sopenharmony_ci    ValueType func_type = func_ref.type;
33741cb0ef41Sopenharmony_ci    if (func_type == kWasmBottom) {
33751cb0ef41Sopenharmony_ci      // We are in unreachable code, maintain the polymorphic stack.
33761cb0ef41Sopenharmony_ci      return 1;
33771cb0ef41Sopenharmony_ci    }
33781cb0ef41Sopenharmony_ci    if (!VALIDATE(func_type.is_object_reference() && func_type.has_index() &&
33791cb0ef41Sopenharmony_ci                  this->module_->has_signature(func_type.ref_index()))) {
33801cb0ef41Sopenharmony_ci      PopTypeError(0, func_ref, "function reference");
33811cb0ef41Sopenharmony_ci      return 0;
33821cb0ef41Sopenharmony_ci    }
33831cb0ef41Sopenharmony_ci    const FunctionSig* sig = this->module_->signature(func_type.ref_index());
33841cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(sig, 1);
33851cb0ef41Sopenharmony_ci    ReturnVector returns = CreateReturnValues(sig);
33861cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(CallRef, func_ref, sig,
33871cb0ef41Sopenharmony_ci                                       func_type.ref_index(), args.begin(),
33881cb0ef41Sopenharmony_ci                                       returns.begin());
33891cb0ef41Sopenharmony_ci    Drop(func_ref);
33901cb0ef41Sopenharmony_ci    DropArgs(sig);
33911cb0ef41Sopenharmony_ci    PushReturns(returns);
33921cb0ef41Sopenharmony_ci    return 1;
33931cb0ef41Sopenharmony_ci  }
33941cb0ef41Sopenharmony_ci
33951cb0ef41Sopenharmony_ci  DECODE(ReturnCallRef) {
33961cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(typed_funcref);
33971cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(return_call);
33981cb0ef41Sopenharmony_ci    Value func_ref = Peek(0);
33991cb0ef41Sopenharmony_ci    ValueType func_type = func_ref.type;
34001cb0ef41Sopenharmony_ci    if (func_type == kWasmBottom) {
34011cb0ef41Sopenharmony_ci      // We are in unreachable code, maintain the polymorphic stack.
34021cb0ef41Sopenharmony_ci      return 1;
34031cb0ef41Sopenharmony_ci    }
34041cb0ef41Sopenharmony_ci    if (!VALIDATE(func_type.is_object_reference() && func_type.has_index() &&
34051cb0ef41Sopenharmony_ci                  this->module_->has_signature(func_type.ref_index()))) {
34061cb0ef41Sopenharmony_ci      PopTypeError(0, func_ref, "function reference");
34071cb0ef41Sopenharmony_ci      return 0;
34081cb0ef41Sopenharmony_ci    }
34091cb0ef41Sopenharmony_ci    const FunctionSig* sig = this->module_->signature(func_type.ref_index());
34101cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(sig, 1);
34111cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(ReturnCallRef, func_ref, sig,
34121cb0ef41Sopenharmony_ci                                       func_type.ref_index(), args.begin());
34131cb0ef41Sopenharmony_ci    Drop(func_ref);
34141cb0ef41Sopenharmony_ci    DropArgs(sig);
34151cb0ef41Sopenharmony_ci    EndControl();
34161cb0ef41Sopenharmony_ci    return 1;
34171cb0ef41Sopenharmony_ci  }
34181cb0ef41Sopenharmony_ci
34191cb0ef41Sopenharmony_ci  DECODE(Numeric) {
34201cb0ef41Sopenharmony_ci    uint32_t opcode_length = 0;
34211cb0ef41Sopenharmony_ci    WasmOpcode full_opcode = this->template read_prefixed_opcode<validate>(
34221cb0ef41Sopenharmony_ci        this->pc_, &opcode_length, "numeric index");
34231cb0ef41Sopenharmony_ci    if (full_opcode == kExprTableGrow || full_opcode == kExprTableSize ||
34241cb0ef41Sopenharmony_ci        full_opcode == kExprTableFill) {
34251cb0ef41Sopenharmony_ci      this->detected_->Add(kFeature_reftypes);
34261cb0ef41Sopenharmony_ci    }
34271cb0ef41Sopenharmony_ci    trace_msg->AppendOpcode(full_opcode);
34281cb0ef41Sopenharmony_ci    return DecodeNumericOpcode(full_opcode, opcode_length);
34291cb0ef41Sopenharmony_ci  }
34301cb0ef41Sopenharmony_ci
34311cb0ef41Sopenharmony_ci  DECODE(Simd) {
34321cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(simd);
34331cb0ef41Sopenharmony_ci    if (!CheckHardwareSupportsSimd()) {
34341cb0ef41Sopenharmony_ci      if (FLAG_correctness_fuzzer_suppressions) {
34351cb0ef41Sopenharmony_ci        FATAL("Aborting on missing Wasm SIMD support");
34361cb0ef41Sopenharmony_ci      }
34371cb0ef41Sopenharmony_ci      this->DecodeError("Wasm SIMD unsupported");
34381cb0ef41Sopenharmony_ci      return 0;
34391cb0ef41Sopenharmony_ci    }
34401cb0ef41Sopenharmony_ci    uint32_t opcode_length = 0;
34411cb0ef41Sopenharmony_ci    WasmOpcode full_opcode = this->template read_prefixed_opcode<validate>(
34421cb0ef41Sopenharmony_ci        this->pc_, &opcode_length);
34431cb0ef41Sopenharmony_ci    if (!VALIDATE(this->ok())) return 0;
34441cb0ef41Sopenharmony_ci    trace_msg->AppendOpcode(full_opcode);
34451cb0ef41Sopenharmony_ci    if (!CheckSimdFeatureFlagOpcode(full_opcode)) {
34461cb0ef41Sopenharmony_ci      return 0;
34471cb0ef41Sopenharmony_ci    }
34481cb0ef41Sopenharmony_ci    return DecodeSimdOpcode(full_opcode, opcode_length);
34491cb0ef41Sopenharmony_ci  }
34501cb0ef41Sopenharmony_ci
34511cb0ef41Sopenharmony_ci  DECODE(Atomic) {
34521cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(threads);
34531cb0ef41Sopenharmony_ci    uint32_t opcode_length = 0;
34541cb0ef41Sopenharmony_ci    WasmOpcode full_opcode = this->template read_prefixed_opcode<validate>(
34551cb0ef41Sopenharmony_ci        this->pc_, &opcode_length, "atomic index");
34561cb0ef41Sopenharmony_ci    trace_msg->AppendOpcode(full_opcode);
34571cb0ef41Sopenharmony_ci    return DecodeAtomicOpcode(full_opcode, opcode_length);
34581cb0ef41Sopenharmony_ci  }
34591cb0ef41Sopenharmony_ci
34601cb0ef41Sopenharmony_ci  DECODE(GC) {
34611cb0ef41Sopenharmony_ci    CHECK_PROTOTYPE_OPCODE(gc);
34621cb0ef41Sopenharmony_ci    uint32_t opcode_length = 0;
34631cb0ef41Sopenharmony_ci    WasmOpcode full_opcode = this->template read_prefixed_opcode<validate>(
34641cb0ef41Sopenharmony_ci        this->pc_, &opcode_length, "gc index");
34651cb0ef41Sopenharmony_ci    trace_msg->AppendOpcode(full_opcode);
34661cb0ef41Sopenharmony_ci    return DecodeGCOpcode(full_opcode, opcode_length);
34671cb0ef41Sopenharmony_ci  }
34681cb0ef41Sopenharmony_ci
34691cb0ef41Sopenharmony_ci#define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
34701cb0ef41Sopenharmony_ci  DECODE(name) { return BuildSimplePrototypeOperator(opcode); }
34711cb0ef41Sopenharmony_ci  FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
34721cb0ef41Sopenharmony_ci#undef SIMPLE_PROTOTYPE_CASE
34731cb0ef41Sopenharmony_ci
34741cb0ef41Sopenharmony_ci  DECODE(UnknownOrAsmJs) {
34751cb0ef41Sopenharmony_ci    // Deal with special asmjs opcodes.
34761cb0ef41Sopenharmony_ci    if (!VALIDATE(is_asmjs_module(this->module_))) {
34771cb0ef41Sopenharmony_ci      this->DecodeError("Invalid opcode 0x%x", opcode);
34781cb0ef41Sopenharmony_ci      return 0;
34791cb0ef41Sopenharmony_ci    }
34801cb0ef41Sopenharmony_ci    const FunctionSig* sig = WasmOpcodes::AsmjsSignature(opcode);
34811cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(sig);
34821cb0ef41Sopenharmony_ci    return BuildSimpleOperator(opcode, sig);
34831cb0ef41Sopenharmony_ci  }
34841cb0ef41Sopenharmony_ci
34851cb0ef41Sopenharmony_ci#undef DECODE
34861cb0ef41Sopenharmony_ci
34871cb0ef41Sopenharmony_ci  static int NonConstError(WasmFullDecoder* decoder, WasmOpcode opcode) {
34881cb0ef41Sopenharmony_ci    decoder->DecodeError("opcode %s is not allowed in init. expressions",
34891cb0ef41Sopenharmony_ci                         WasmOpcodes::OpcodeName(opcode));
34901cb0ef41Sopenharmony_ci    return 0;
34911cb0ef41Sopenharmony_ci  }
34921cb0ef41Sopenharmony_ci
34931cb0ef41Sopenharmony_ci  using OpcodeHandler = int (*)(WasmFullDecoder*, WasmOpcode);
34941cb0ef41Sopenharmony_ci
34951cb0ef41Sopenharmony_ci  // Ideally we would use template specialization for the different opcodes, but
34961cb0ef41Sopenharmony_ci  // GCC does not allow to specialize templates in class scope
34971cb0ef41Sopenharmony_ci  // (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282), and specializing
34981cb0ef41Sopenharmony_ci  // outside the class is not allowed for non-specialized classes.
34991cb0ef41Sopenharmony_ci  // Hence just list all implementations explicitly here, which also gives more
35001cb0ef41Sopenharmony_ci  // freedom to use the same implementation for different opcodes.
35011cb0ef41Sopenharmony_ci#define DECODE_IMPL(opcode) DECODE_IMPL2(kExpr##opcode, opcode)
35021cb0ef41Sopenharmony_ci#define DECODE_IMPL2(opcode, name)            \
35031cb0ef41Sopenharmony_ci  if (idx == opcode) {                        \
35041cb0ef41Sopenharmony_ci    if (decoding_mode == kInitExpression) {   \
35051cb0ef41Sopenharmony_ci      return &WasmFullDecoder::NonConstError; \
35061cb0ef41Sopenharmony_ci    } else {                                  \
35071cb0ef41Sopenharmony_ci      return &WasmFullDecoder::Decode##name;  \
35081cb0ef41Sopenharmony_ci    }                                         \
35091cb0ef41Sopenharmony_ci  }
35101cb0ef41Sopenharmony_ci#define DECODE_IMPL_CONST(opcode) DECODE_IMPL_CONST2(kExpr##opcode, opcode)
35111cb0ef41Sopenharmony_ci#define DECODE_IMPL_CONST2(opcode, name) \
35121cb0ef41Sopenharmony_ci  if (idx == opcode) return &WasmFullDecoder::Decode##name
35131cb0ef41Sopenharmony_ci
35141cb0ef41Sopenharmony_ci  static constexpr OpcodeHandler GetOpcodeHandlerTableEntry(size_t idx) {
35151cb0ef41Sopenharmony_ci    DECODE_IMPL(Nop);
35161cb0ef41Sopenharmony_ci#define BUILD_SIMPLE_OPCODE(op, _, sig) DECODE_IMPL(op);
35171cb0ef41Sopenharmony_ci    FOREACH_SIMPLE_NON_CONST_OPCODE(BUILD_SIMPLE_OPCODE)
35181cb0ef41Sopenharmony_ci#undef BUILD_SIMPLE_OPCODE
35191cb0ef41Sopenharmony_ci#define BUILD_SIMPLE_EXTENDED_CONST_OPCODE(op, _, sig) DECODE_IMPL_CONST(op);
35201cb0ef41Sopenharmony_ci    FOREACH_SIMPLE_EXTENDED_CONST_OPCODE(BUILD_SIMPLE_EXTENDED_CONST_OPCODE)
35211cb0ef41Sopenharmony_ci#undef BUILD_SIMPLE_EXTENDED_CONST_OPCODE
35221cb0ef41Sopenharmony_ci    DECODE_IMPL(Block);
35231cb0ef41Sopenharmony_ci    DECODE_IMPL(Rethrow);
35241cb0ef41Sopenharmony_ci    DECODE_IMPL(Throw);
35251cb0ef41Sopenharmony_ci    DECODE_IMPL(Try);
35261cb0ef41Sopenharmony_ci    DECODE_IMPL(Catch);
35271cb0ef41Sopenharmony_ci    DECODE_IMPL(Delegate);
35281cb0ef41Sopenharmony_ci    DECODE_IMPL(CatchAll);
35291cb0ef41Sopenharmony_ci    DECODE_IMPL(BrOnNull);
35301cb0ef41Sopenharmony_ci    DECODE_IMPL(BrOnNonNull);
35311cb0ef41Sopenharmony_ci    DECODE_IMPL(Let);
35321cb0ef41Sopenharmony_ci    DECODE_IMPL(Loop);
35331cb0ef41Sopenharmony_ci    DECODE_IMPL(If);
35341cb0ef41Sopenharmony_ci    DECODE_IMPL(Else);
35351cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(End);
35361cb0ef41Sopenharmony_ci    DECODE_IMPL(Select);
35371cb0ef41Sopenharmony_ci    DECODE_IMPL(SelectWithType);
35381cb0ef41Sopenharmony_ci    DECODE_IMPL(Br);
35391cb0ef41Sopenharmony_ci    DECODE_IMPL(BrIf);
35401cb0ef41Sopenharmony_ci    DECODE_IMPL(BrTable);
35411cb0ef41Sopenharmony_ci    DECODE_IMPL(Return);
35421cb0ef41Sopenharmony_ci    DECODE_IMPL(Unreachable);
35431cb0ef41Sopenharmony_ci    DECODE_IMPL(NopForTestingUnsupportedInLiftoff);
35441cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(I32Const);
35451cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(I64Const);
35461cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(F32Const);
35471cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(F64Const);
35481cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(RefNull);
35491cb0ef41Sopenharmony_ci    DECODE_IMPL(RefIsNull);
35501cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(RefFunc);
35511cb0ef41Sopenharmony_ci    DECODE_IMPL(RefAsNonNull);
35521cb0ef41Sopenharmony_ci    DECODE_IMPL(LocalGet);
35531cb0ef41Sopenharmony_ci    DECODE_IMPL(LocalSet);
35541cb0ef41Sopenharmony_ci    DECODE_IMPL(LocalTee);
35551cb0ef41Sopenharmony_ci    DECODE_IMPL(Drop);
35561cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST(GlobalGet);
35571cb0ef41Sopenharmony_ci    DECODE_IMPL(GlobalSet);
35581cb0ef41Sopenharmony_ci    DECODE_IMPL(TableGet);
35591cb0ef41Sopenharmony_ci    DECODE_IMPL(TableSet);
35601cb0ef41Sopenharmony_ci#define DECODE_LOAD_MEM(op, ...) DECODE_IMPL2(kExpr##op, LoadMem);
35611cb0ef41Sopenharmony_ci    FOREACH_LOAD_MEM_OPCODE(DECODE_LOAD_MEM)
35621cb0ef41Sopenharmony_ci#undef DECODE_LOAD_MEM
35631cb0ef41Sopenharmony_ci#define DECODE_STORE_MEM(op, ...) DECODE_IMPL2(kExpr##op, StoreMem);
35641cb0ef41Sopenharmony_ci    FOREACH_STORE_MEM_OPCODE(DECODE_STORE_MEM)
35651cb0ef41Sopenharmony_ci#undef DECODE_LOAD_MEM
35661cb0ef41Sopenharmony_ci    DECODE_IMPL(MemoryGrow);
35671cb0ef41Sopenharmony_ci    DECODE_IMPL(MemorySize);
35681cb0ef41Sopenharmony_ci    DECODE_IMPL(CallFunction);
35691cb0ef41Sopenharmony_ci    DECODE_IMPL(CallIndirect);
35701cb0ef41Sopenharmony_ci    DECODE_IMPL(ReturnCall);
35711cb0ef41Sopenharmony_ci    DECODE_IMPL(ReturnCallIndirect);
35721cb0ef41Sopenharmony_ci    DECODE_IMPL(CallRef);
35731cb0ef41Sopenharmony_ci    DECODE_IMPL(ReturnCallRef);
35741cb0ef41Sopenharmony_ci    DECODE_IMPL2(kNumericPrefix, Numeric);
35751cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST2(kSimdPrefix, Simd);
35761cb0ef41Sopenharmony_ci    DECODE_IMPL2(kAtomicPrefix, Atomic);
35771cb0ef41Sopenharmony_ci    DECODE_IMPL_CONST2(kGCPrefix, GC);
35781cb0ef41Sopenharmony_ci#define SIMPLE_PROTOTYPE_CASE(name, opc, sig) DECODE_IMPL(name);
35791cb0ef41Sopenharmony_ci    FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
35801cb0ef41Sopenharmony_ci#undef SIMPLE_PROTOTYPE_CASE
35811cb0ef41Sopenharmony_ci    return &WasmFullDecoder::DecodeUnknownOrAsmJs;
35821cb0ef41Sopenharmony_ci  }
35831cb0ef41Sopenharmony_ci
35841cb0ef41Sopenharmony_ci#undef DECODE_IMPL
35851cb0ef41Sopenharmony_ci#undef DECODE_IMPL2
35861cb0ef41Sopenharmony_ci
35871cb0ef41Sopenharmony_ci  OpcodeHandler GetOpcodeHandler(uint8_t opcode) {
35881cb0ef41Sopenharmony_ci    static constexpr std::array<OpcodeHandler, 256> kOpcodeHandlers =
35891cb0ef41Sopenharmony_ci        base::make_array<256>(GetOpcodeHandlerTableEntry);
35901cb0ef41Sopenharmony_ci    return kOpcodeHandlers[opcode];
35911cb0ef41Sopenharmony_ci  }
35921cb0ef41Sopenharmony_ci
35931cb0ef41Sopenharmony_ci  void EndControl() {
35941cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
35951cb0ef41Sopenharmony_ci    Control* current = &control_.back();
35961cb0ef41Sopenharmony_ci    DCHECK_LE(stack_ + current->stack_depth, stack_end_);
35971cb0ef41Sopenharmony_ci    stack_end_ = stack_ + current->stack_depth;
35981cb0ef41Sopenharmony_ci    current->reachability = kUnreachable;
35991cb0ef41Sopenharmony_ci    current_code_reachable_and_ok_ = false;
36001cb0ef41Sopenharmony_ci  }
36011cb0ef41Sopenharmony_ci
36021cb0ef41Sopenharmony_ci  template <typename func>
36031cb0ef41Sopenharmony_ci  void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
36041cb0ef41Sopenharmony_ci    merge->arity = arity;
36051cb0ef41Sopenharmony_ci    if (arity == 1) {
36061cb0ef41Sopenharmony_ci      merge->vals.first = get_val(0);
36071cb0ef41Sopenharmony_ci    } else if (arity > 1) {
36081cb0ef41Sopenharmony_ci      merge->vals.array = this->zone()->template NewArray<Value>(arity);
36091cb0ef41Sopenharmony_ci      for (uint32_t i = 0; i < arity; i++) {
36101cb0ef41Sopenharmony_ci        merge->vals.array[i] = get_val(i);
36111cb0ef41Sopenharmony_ci      }
36121cb0ef41Sopenharmony_ci    }
36131cb0ef41Sopenharmony_ci  }
36141cb0ef41Sopenharmony_ci
36151cb0ef41Sopenharmony_ci  // Initializes start- and end-merges of {c} with values according to the
36161cb0ef41Sopenharmony_ci  // in- and out-types of {c} respectively.
36171cb0ef41Sopenharmony_ci  void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm,
36181cb0ef41Sopenharmony_ci                    Value* args) {
36191cb0ef41Sopenharmony_ci    const byte* pc = this->pc_;
36201cb0ef41Sopenharmony_ci    InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
36211cb0ef41Sopenharmony_ci      return Value{pc, imm.out_type(i)};
36221cb0ef41Sopenharmony_ci    });
36231cb0ef41Sopenharmony_ci    InitMerge(&c->start_merge, imm.in_arity(), [&imm, args](uint32_t i) {
36241cb0ef41Sopenharmony_ci      // The merge needs to be instantiated with Values of the correct
36251cb0ef41Sopenharmony_ci      // type, even if the actual Value is bottom/unreachable or has
36261cb0ef41Sopenharmony_ci      // a subtype of the static type.
36271cb0ef41Sopenharmony_ci      // So we copy-construct a new Value, and update its type.
36281cb0ef41Sopenharmony_ci      Value value = args[i];
36291cb0ef41Sopenharmony_ci      value.type = imm.in_type(i);
36301cb0ef41Sopenharmony_ci      return value;
36311cb0ef41Sopenharmony_ci    });
36321cb0ef41Sopenharmony_ci  }
36331cb0ef41Sopenharmony_ci
36341cb0ef41Sopenharmony_ci  // In reachable code, check if there are at least {count} values on the stack.
36351cb0ef41Sopenharmony_ci  // In unreachable code, if there are less than {count} values on the stack,
36361cb0ef41Sopenharmony_ci  // insert a number of unreachable values underneath the current values equal
36371cb0ef41Sopenharmony_ci  // to the difference, and return that number.
36381cb0ef41Sopenharmony_ci  V8_INLINE int EnsureStackArguments(int count) {
36391cb0ef41Sopenharmony_ci    uint32_t limit = control_.back().stack_depth;
36401cb0ef41Sopenharmony_ci    if (V8_LIKELY(stack_size() >= count + limit)) return 0;
36411cb0ef41Sopenharmony_ci    return EnsureStackArguments_Slow(count, limit);
36421cb0ef41Sopenharmony_ci  }
36431cb0ef41Sopenharmony_ci
36441cb0ef41Sopenharmony_ci  V8_NOINLINE int EnsureStackArguments_Slow(int count, uint32_t limit) {
36451cb0ef41Sopenharmony_ci    if (!VALIDATE(control_.back().unreachable())) {
36461cb0ef41Sopenharmony_ci      NotEnoughArgumentsError(count, stack_size() - limit);
36471cb0ef41Sopenharmony_ci    }
36481cb0ef41Sopenharmony_ci    // Silently create unreachable values out of thin air underneath the
36491cb0ef41Sopenharmony_ci    // existing stack values. To do so, we have to move existing stack values
36501cb0ef41Sopenharmony_ci    // upwards in the stack, then instantiate the new Values as
36511cb0ef41Sopenharmony_ci    // {UnreachableValue}.
36521cb0ef41Sopenharmony_ci    int current_values = stack_size() - limit;
36531cb0ef41Sopenharmony_ci    int additional_values = count - current_values;
36541cb0ef41Sopenharmony_ci    DCHECK_GT(additional_values, 0);
36551cb0ef41Sopenharmony_ci    EnsureStackSpace(additional_values);
36561cb0ef41Sopenharmony_ci    stack_end_ += additional_values;
36571cb0ef41Sopenharmony_ci    Value* stack_base = stack_value(current_values + additional_values);
36581cb0ef41Sopenharmony_ci    for (int i = current_values - 1; i >= 0; i--) {
36591cb0ef41Sopenharmony_ci      stack_base[additional_values + i] = stack_base[i];
36601cb0ef41Sopenharmony_ci    }
36611cb0ef41Sopenharmony_ci    for (int i = 0; i < additional_values; i++) {
36621cb0ef41Sopenharmony_ci      stack_base[i] = UnreachableValue(this->pc_);
36631cb0ef41Sopenharmony_ci    }
36641cb0ef41Sopenharmony_ci    return additional_values;
36651cb0ef41Sopenharmony_ci  }
36661cb0ef41Sopenharmony_ci
36671cb0ef41Sopenharmony_ci  // Peeks arguments as required by signature.
36681cb0ef41Sopenharmony_ci  V8_INLINE ArgVector PeekArgs(const FunctionSig* sig, int depth = 0) {
36691cb0ef41Sopenharmony_ci    int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
36701cb0ef41Sopenharmony_ci    if (count == 0) return {};
36711cb0ef41Sopenharmony_ci    EnsureStackArguments(depth + count);
36721cb0ef41Sopenharmony_ci    ArgVector args(stack_value(depth + count), count);
36731cb0ef41Sopenharmony_ci    for (int i = 0; i < count; i++) {
36741cb0ef41Sopenharmony_ci      ValidateArgType(args, i, sig->GetParam(i));
36751cb0ef41Sopenharmony_ci    }
36761cb0ef41Sopenharmony_ci    return args;
36771cb0ef41Sopenharmony_ci  }
36781cb0ef41Sopenharmony_ci  // Drops a number of stack elements equal to the {sig}'s parameter count (0 if
36791cb0ef41Sopenharmony_ci  // {sig} is null), or all of them if less are present.
36801cb0ef41Sopenharmony_ci  V8_INLINE void DropArgs(const FunctionSig* sig) {
36811cb0ef41Sopenharmony_ci    int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
36821cb0ef41Sopenharmony_ci    Drop(count);
36831cb0ef41Sopenharmony_ci  }
36841cb0ef41Sopenharmony_ci
36851cb0ef41Sopenharmony_ci  V8_INLINE ArgVector PeekArgs(const StructType* type, int depth = 0) {
36861cb0ef41Sopenharmony_ci    int count = static_cast<int>(type->field_count());
36871cb0ef41Sopenharmony_ci    if (count == 0) return {};
36881cb0ef41Sopenharmony_ci    EnsureStackArguments(depth + count);
36891cb0ef41Sopenharmony_ci    ArgVector args(stack_value(depth + count), count);
36901cb0ef41Sopenharmony_ci    for (int i = 0; i < count; i++) {
36911cb0ef41Sopenharmony_ci      ValidateArgType(args, i, type->field(i).Unpacked());
36921cb0ef41Sopenharmony_ci    }
36931cb0ef41Sopenharmony_ci    return args;
36941cb0ef41Sopenharmony_ci  }
36951cb0ef41Sopenharmony_ci  // Drops a number of stack elements equal to the struct's field count, or all
36961cb0ef41Sopenharmony_ci  // of them if less are present.
36971cb0ef41Sopenharmony_ci  V8_INLINE void DropArgs(const StructType* type) {
36981cb0ef41Sopenharmony_ci    Drop(static_cast<int>(type->field_count()));
36991cb0ef41Sopenharmony_ci  }
37001cb0ef41Sopenharmony_ci
37011cb0ef41Sopenharmony_ci  V8_INLINE ArgVector PeekArgs(base::Vector<ValueType> arg_types) {
37021cb0ef41Sopenharmony_ci    int size = static_cast<int>(arg_types.size());
37031cb0ef41Sopenharmony_ci    EnsureStackArguments(size);
37041cb0ef41Sopenharmony_ci    ArgVector args(stack_value(size), arg_types.size());
37051cb0ef41Sopenharmony_ci    for (int i = 0; i < size; i++) {
37061cb0ef41Sopenharmony_ci      ValidateArgType(args, i, arg_types[i]);
37071cb0ef41Sopenharmony_ci    }
37081cb0ef41Sopenharmony_ci    return args;
37091cb0ef41Sopenharmony_ci  }
37101cb0ef41Sopenharmony_ci
37111cb0ef41Sopenharmony_ci  ValueType GetReturnType(const FunctionSig* sig) {
37121cb0ef41Sopenharmony_ci    DCHECK_GE(1, sig->return_count());
37131cb0ef41Sopenharmony_ci    return sig->return_count() == 0 ? kWasmVoid : sig->GetReturn();
37141cb0ef41Sopenharmony_ci  }
37151cb0ef41Sopenharmony_ci
37161cb0ef41Sopenharmony_ci  // TODO(jkummerow): Consider refactoring control stack management so
37171cb0ef41Sopenharmony_ci  // that {drop_values} is never needed. That would require decoupling
37181cb0ef41Sopenharmony_ci  // creation of the Control object from setting of its stack depth.
37191cb0ef41Sopenharmony_ci  Control* PushControl(ControlKind kind, uint32_t locals_count = 0,
37201cb0ef41Sopenharmony_ci                       uint32_t drop_values = 0) {
37211cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
37221cb0ef41Sopenharmony_ci    Reachability reachability = control_.back().innerReachability();
37231cb0ef41Sopenharmony_ci    // In unreachable code, we may run out of stack.
37241cb0ef41Sopenharmony_ci    uint32_t stack_depth =
37251cb0ef41Sopenharmony_ci        stack_size() >= drop_values ? stack_size() - drop_values : 0;
37261cb0ef41Sopenharmony_ci    stack_depth = std::max(stack_depth, control_.back().stack_depth);
37271cb0ef41Sopenharmony_ci    uint32_t init_stack_depth = this->locals_initialization_stack_depth();
37281cb0ef41Sopenharmony_ci    control_.emplace_back(kind, locals_count, stack_depth, init_stack_depth,
37291cb0ef41Sopenharmony_ci                          this->pc_, reachability);
37301cb0ef41Sopenharmony_ci    current_code_reachable_and_ok_ = this->ok() && reachability == kReachable;
37311cb0ef41Sopenharmony_ci    return &control_.back();
37321cb0ef41Sopenharmony_ci  }
37331cb0ef41Sopenharmony_ci
37341cb0ef41Sopenharmony_ci  void PopControl() {
37351cb0ef41Sopenharmony_ci    // This cannot be the outermost control block.
37361cb0ef41Sopenharmony_ci    DCHECK_LT(1, control_.size());
37371cb0ef41Sopenharmony_ci    Control* c = &control_.back();
37381cb0ef41Sopenharmony_ci    DCHECK_LE(stack_ + c->stack_depth, stack_end_);
37391cb0ef41Sopenharmony_ci
37401cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(PopControl, c);
37411cb0ef41Sopenharmony_ci
37421cb0ef41Sopenharmony_ci    // - In non-unreachable code, a loop just leaves the values on the stack.
37431cb0ef41Sopenharmony_ci    // - In unreachable code, it is not guaranteed that we have Values of the
37441cb0ef41Sopenharmony_ci    //   correct types on the stack, so we have to make sure we do. Their values
37451cb0ef41Sopenharmony_ci    //   do not matter, so we might as well push the (uninitialized) values of
37461cb0ef41Sopenharmony_ci    //   the loop's end merge.
37471cb0ef41Sopenharmony_ci    if (!c->is_loop() || c->unreachable()) {
37481cb0ef41Sopenharmony_ci      PushMergeValues(c, &c->end_merge);
37491cb0ef41Sopenharmony_ci    }
37501cb0ef41Sopenharmony_ci    this->RollbackLocalsInitialization(c->init_stack_depth);
37511cb0ef41Sopenharmony_ci
37521cb0ef41Sopenharmony_ci    bool parent_reached =
37531cb0ef41Sopenharmony_ci        c->reachable() || c->end_merge.reached || c->is_onearmed_if();
37541cb0ef41Sopenharmony_ci    control_.pop_back();
37551cb0ef41Sopenharmony_ci    // If the parent block was reachable before, but the popped control does not
37561cb0ef41Sopenharmony_ci    // return to here, this block becomes "spec only reachable".
37571cb0ef41Sopenharmony_ci    if (!parent_reached) SetSucceedingCodeDynamicallyUnreachable();
37581cb0ef41Sopenharmony_ci    current_code_reachable_and_ok_ = this->ok() && control_.back().reachable();
37591cb0ef41Sopenharmony_ci  }
37601cb0ef41Sopenharmony_ci
37611cb0ef41Sopenharmony_ci  int DecodeLoadMem(LoadType type, int prefix_len = 1) {
37621cb0ef41Sopenharmony_ci    MemoryAccessImmediate<validate> imm =
37631cb0ef41Sopenharmony_ci        MakeMemoryAccessImmediate(prefix_len, type.size_log_2());
37641cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + prefix_len, imm)) return 0;
37651cb0ef41Sopenharmony_ci    ValueType index_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
37661cb0ef41Sopenharmony_ci    Value index = Peek(0, 0, index_type);
37671cb0ef41Sopenharmony_ci    Value result = CreateValue(type.value_type());
37681cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(LoadMem, type, imm, index, &result);
37691cb0ef41Sopenharmony_ci    Drop(index);
37701cb0ef41Sopenharmony_ci    Push(result);
37711cb0ef41Sopenharmony_ci    return prefix_len + imm.length;
37721cb0ef41Sopenharmony_ci  }
37731cb0ef41Sopenharmony_ci
37741cb0ef41Sopenharmony_ci  int DecodeLoadTransformMem(LoadType type, LoadTransformationKind transform,
37751cb0ef41Sopenharmony_ci                             uint32_t opcode_length) {
37761cb0ef41Sopenharmony_ci    // Load extends always load 64-bits.
37771cb0ef41Sopenharmony_ci    uint32_t max_alignment =
37781cb0ef41Sopenharmony_ci        transform == LoadTransformationKind::kExtend ? 3 : type.size_log_2();
37791cb0ef41Sopenharmony_ci    MemoryAccessImmediate<validate> imm =
37801cb0ef41Sopenharmony_ci        MakeMemoryAccessImmediate(opcode_length, max_alignment);
37811cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
37821cb0ef41Sopenharmony_ci    ValueType index_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
37831cb0ef41Sopenharmony_ci    Value index = Peek(0, 0, index_type);
37841cb0ef41Sopenharmony_ci    Value result = CreateValue(kWasmS128);
37851cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(LoadTransform, type, transform, imm,
37861cb0ef41Sopenharmony_ci                                       index, &result);
37871cb0ef41Sopenharmony_ci    Drop(index);
37881cb0ef41Sopenharmony_ci    Push(result);
37891cb0ef41Sopenharmony_ci    return opcode_length + imm.length;
37901cb0ef41Sopenharmony_ci  }
37911cb0ef41Sopenharmony_ci
37921cb0ef41Sopenharmony_ci  int DecodeLoadLane(WasmOpcode opcode, LoadType type, uint32_t opcode_length) {
37931cb0ef41Sopenharmony_ci    MemoryAccessImmediate<validate> mem_imm =
37941cb0ef41Sopenharmony_ci        MakeMemoryAccessImmediate(opcode_length, type.size_log_2());
37951cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + opcode_length, mem_imm)) return 0;
37961cb0ef41Sopenharmony_ci    SimdLaneImmediate<validate> lane_imm(
37971cb0ef41Sopenharmony_ci        this, this->pc_ + opcode_length + mem_imm.length);
37981cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + opcode_length, opcode, lane_imm)) return 0;
37991cb0ef41Sopenharmony_ci    Value v128 = Peek(0, 1, kWasmS128);
38001cb0ef41Sopenharmony_ci    Value index = Peek(1, 0, kWasmI32);
38011cb0ef41Sopenharmony_ci
38021cb0ef41Sopenharmony_ci    Value result = CreateValue(kWasmS128);
38031cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(LoadLane, type, v128, index, mem_imm,
38041cb0ef41Sopenharmony_ci                                       lane_imm.lane, &result);
38051cb0ef41Sopenharmony_ci    Drop(2);
38061cb0ef41Sopenharmony_ci    Push(result);
38071cb0ef41Sopenharmony_ci    return opcode_length + mem_imm.length + lane_imm.length;
38081cb0ef41Sopenharmony_ci  }
38091cb0ef41Sopenharmony_ci
38101cb0ef41Sopenharmony_ci  int DecodeStoreLane(WasmOpcode opcode, StoreType type,
38111cb0ef41Sopenharmony_ci                      uint32_t opcode_length) {
38121cb0ef41Sopenharmony_ci    MemoryAccessImmediate<validate> mem_imm =
38131cb0ef41Sopenharmony_ci        MakeMemoryAccessImmediate(opcode_length, type.size_log_2());
38141cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + opcode_length, mem_imm)) return 0;
38151cb0ef41Sopenharmony_ci    SimdLaneImmediate<validate> lane_imm(
38161cb0ef41Sopenharmony_ci        this, this->pc_ + opcode_length + mem_imm.length);
38171cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + opcode_length, opcode, lane_imm)) return 0;
38181cb0ef41Sopenharmony_ci    Value v128 = Peek(0, 1, kWasmS128);
38191cb0ef41Sopenharmony_ci    Value index = Peek(1, 0, kWasmI32);
38201cb0ef41Sopenharmony_ci
38211cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(StoreLane, type, mem_imm, index, v128,
38221cb0ef41Sopenharmony_ci                                       lane_imm.lane);
38231cb0ef41Sopenharmony_ci    Drop(2);
38241cb0ef41Sopenharmony_ci    return opcode_length + mem_imm.length + lane_imm.length;
38251cb0ef41Sopenharmony_ci  }
38261cb0ef41Sopenharmony_ci
38271cb0ef41Sopenharmony_ci  int DecodeStoreMem(StoreType store, int prefix_len = 1) {
38281cb0ef41Sopenharmony_ci    MemoryAccessImmediate<validate> imm =
38291cb0ef41Sopenharmony_ci        MakeMemoryAccessImmediate(prefix_len, store.size_log_2());
38301cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + prefix_len, imm)) return 0;
38311cb0ef41Sopenharmony_ci    Value value = Peek(0, 1, store.value_type());
38321cb0ef41Sopenharmony_ci    ValueType index_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
38331cb0ef41Sopenharmony_ci    Value index = Peek(1, 0, index_type);
38341cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(StoreMem, store, imm, index, value);
38351cb0ef41Sopenharmony_ci    Drop(2);
38361cb0ef41Sopenharmony_ci    return prefix_len + imm.length;
38371cb0ef41Sopenharmony_ci  }
38381cb0ef41Sopenharmony_ci
38391cb0ef41Sopenharmony_ci  uint32_t SimdConstOp(uint32_t opcode_length) {
38401cb0ef41Sopenharmony_ci    Simd128Immediate<validate> imm(this, this->pc_ + opcode_length);
38411cb0ef41Sopenharmony_ci    Value result = CreateValue(kWasmS128);
38421cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(S128Const, imm, &result);
38431cb0ef41Sopenharmony_ci    Push(result);
38441cb0ef41Sopenharmony_ci    return opcode_length + kSimd128Size;
38451cb0ef41Sopenharmony_ci  }
38461cb0ef41Sopenharmony_ci
38471cb0ef41Sopenharmony_ci  uint32_t SimdExtractLane(WasmOpcode opcode, ValueType type,
38481cb0ef41Sopenharmony_ci                           uint32_t opcode_length) {
38491cb0ef41Sopenharmony_ci    SimdLaneImmediate<validate> imm(this, this->pc_ + opcode_length);
38501cb0ef41Sopenharmony_ci    if (this->Validate(this->pc_ + opcode_length, opcode, imm)) {
38511cb0ef41Sopenharmony_ci      Value inputs[] = {Peek(0, 0, kWasmS128)};
38521cb0ef41Sopenharmony_ci      Value result = CreateValue(type);
38531cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(SimdLaneOp, opcode, imm,
38541cb0ef41Sopenharmony_ci                                         base::ArrayVector(inputs), &result);
38551cb0ef41Sopenharmony_ci      Drop(1);
38561cb0ef41Sopenharmony_ci      Push(result);
38571cb0ef41Sopenharmony_ci    }
38581cb0ef41Sopenharmony_ci    return opcode_length + imm.length;
38591cb0ef41Sopenharmony_ci  }
38601cb0ef41Sopenharmony_ci
38611cb0ef41Sopenharmony_ci  uint32_t SimdReplaceLane(WasmOpcode opcode, ValueType type,
38621cb0ef41Sopenharmony_ci                           uint32_t opcode_length) {
38631cb0ef41Sopenharmony_ci    SimdLaneImmediate<validate> imm(this, this->pc_ + opcode_length);
38641cb0ef41Sopenharmony_ci    if (this->Validate(this->pc_ + opcode_length, opcode, imm)) {
38651cb0ef41Sopenharmony_ci      Value inputs[2] = {Peek(1, 0, kWasmS128), Peek(0, 1, type)};
38661cb0ef41Sopenharmony_ci      Value result = CreateValue(kWasmS128);
38671cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(SimdLaneOp, opcode, imm,
38681cb0ef41Sopenharmony_ci                                         base::ArrayVector(inputs), &result);
38691cb0ef41Sopenharmony_ci      Drop(2);
38701cb0ef41Sopenharmony_ci      Push(result);
38711cb0ef41Sopenharmony_ci    }
38721cb0ef41Sopenharmony_ci    return opcode_length + imm.length;
38731cb0ef41Sopenharmony_ci  }
38741cb0ef41Sopenharmony_ci
38751cb0ef41Sopenharmony_ci  uint32_t Simd8x16ShuffleOp(uint32_t opcode_length) {
38761cb0ef41Sopenharmony_ci    Simd128Immediate<validate> imm(this, this->pc_ + opcode_length);
38771cb0ef41Sopenharmony_ci    if (this->Validate(this->pc_ + opcode_length, imm)) {
38781cb0ef41Sopenharmony_ci      Value input1 = Peek(0, 1, kWasmS128);
38791cb0ef41Sopenharmony_ci      Value input0 = Peek(1, 0, kWasmS128);
38801cb0ef41Sopenharmony_ci      Value result = CreateValue(kWasmS128);
38811cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
38821cb0ef41Sopenharmony_ci                                         &result);
38831cb0ef41Sopenharmony_ci      Drop(2);
38841cb0ef41Sopenharmony_ci      Push(result);
38851cb0ef41Sopenharmony_ci    }
38861cb0ef41Sopenharmony_ci    return opcode_length + 16;
38871cb0ef41Sopenharmony_ci  }
38881cb0ef41Sopenharmony_ci
38891cb0ef41Sopenharmony_ci  uint32_t DecodeSimdOpcode(WasmOpcode opcode, uint32_t opcode_length) {
38901cb0ef41Sopenharmony_ci    if (decoding_mode == kInitExpression) {
38911cb0ef41Sopenharmony_ci      // Currently, only s128.const is allowed in initializer expressions.
38921cb0ef41Sopenharmony_ci      if (opcode != kExprS128Const) {
38931cb0ef41Sopenharmony_ci        this->DecodeError("opcode %s is not allowed in init. expressions",
38941cb0ef41Sopenharmony_ci                          this->SafeOpcodeNameAt(this->pc()));
38951cb0ef41Sopenharmony_ci        return 0;
38961cb0ef41Sopenharmony_ci      }
38971cb0ef41Sopenharmony_ci      return SimdConstOp(opcode_length);
38981cb0ef41Sopenharmony_ci    }
38991cb0ef41Sopenharmony_ci    // opcode_length is the number of bytes that this SIMD-specific opcode takes
39001cb0ef41Sopenharmony_ci    // up in the LEB128 encoded form.
39011cb0ef41Sopenharmony_ci    switch (opcode) {
39021cb0ef41Sopenharmony_ci      case kExprF64x2ExtractLane:
39031cb0ef41Sopenharmony_ci        return SimdExtractLane(opcode, kWasmF64, opcode_length);
39041cb0ef41Sopenharmony_ci      case kExprF32x4ExtractLane:
39051cb0ef41Sopenharmony_ci        return SimdExtractLane(opcode, kWasmF32, opcode_length);
39061cb0ef41Sopenharmony_ci      case kExprI64x2ExtractLane:
39071cb0ef41Sopenharmony_ci        return SimdExtractLane(opcode, kWasmI64, opcode_length);
39081cb0ef41Sopenharmony_ci      case kExprI32x4ExtractLane:
39091cb0ef41Sopenharmony_ci      case kExprI16x8ExtractLaneS:
39101cb0ef41Sopenharmony_ci      case kExprI16x8ExtractLaneU:
39111cb0ef41Sopenharmony_ci      case kExprI8x16ExtractLaneS:
39121cb0ef41Sopenharmony_ci      case kExprI8x16ExtractLaneU:
39131cb0ef41Sopenharmony_ci        return SimdExtractLane(opcode, kWasmI32, opcode_length);
39141cb0ef41Sopenharmony_ci      case kExprF64x2ReplaceLane:
39151cb0ef41Sopenharmony_ci        return SimdReplaceLane(opcode, kWasmF64, opcode_length);
39161cb0ef41Sopenharmony_ci      case kExprF32x4ReplaceLane:
39171cb0ef41Sopenharmony_ci        return SimdReplaceLane(opcode, kWasmF32, opcode_length);
39181cb0ef41Sopenharmony_ci      case kExprI64x2ReplaceLane:
39191cb0ef41Sopenharmony_ci        return SimdReplaceLane(opcode, kWasmI64, opcode_length);
39201cb0ef41Sopenharmony_ci      case kExprI32x4ReplaceLane:
39211cb0ef41Sopenharmony_ci      case kExprI16x8ReplaceLane:
39221cb0ef41Sopenharmony_ci      case kExprI8x16ReplaceLane:
39231cb0ef41Sopenharmony_ci        return SimdReplaceLane(opcode, kWasmI32, opcode_length);
39241cb0ef41Sopenharmony_ci      case kExprI8x16Shuffle:
39251cb0ef41Sopenharmony_ci        return Simd8x16ShuffleOp(opcode_length);
39261cb0ef41Sopenharmony_ci      case kExprS128LoadMem:
39271cb0ef41Sopenharmony_ci        return DecodeLoadMem(LoadType::kS128Load, opcode_length);
39281cb0ef41Sopenharmony_ci      case kExprS128StoreMem:
39291cb0ef41Sopenharmony_ci        return DecodeStoreMem(StoreType::kS128Store, opcode_length);
39301cb0ef41Sopenharmony_ci      case kExprS128Load32Zero:
39311cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load,
39321cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kZeroExtend,
39331cb0ef41Sopenharmony_ci                                      opcode_length);
39341cb0ef41Sopenharmony_ci      case kExprS128Load64Zero:
39351cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI64Load,
39361cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kZeroExtend,
39371cb0ef41Sopenharmony_ci                                      opcode_length);
39381cb0ef41Sopenharmony_ci      case kExprS128Load8Splat:
39391cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load8S,
39401cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kSplat,
39411cb0ef41Sopenharmony_ci                                      opcode_length);
39421cb0ef41Sopenharmony_ci      case kExprS128Load16Splat:
39431cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load16S,
39441cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kSplat,
39451cb0ef41Sopenharmony_ci                                      opcode_length);
39461cb0ef41Sopenharmony_ci      case kExprS128Load32Splat:
39471cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(
39481cb0ef41Sopenharmony_ci            LoadType::kI32Load, LoadTransformationKind::kSplat, opcode_length);
39491cb0ef41Sopenharmony_ci      case kExprS128Load64Splat:
39501cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(
39511cb0ef41Sopenharmony_ci            LoadType::kI64Load, LoadTransformationKind::kSplat, opcode_length);
39521cb0ef41Sopenharmony_ci      case kExprS128Load8x8S:
39531cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load8S,
39541cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kExtend,
39551cb0ef41Sopenharmony_ci                                      opcode_length);
39561cb0ef41Sopenharmony_ci      case kExprS128Load8x8U:
39571cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load8U,
39581cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kExtend,
39591cb0ef41Sopenharmony_ci                                      opcode_length);
39601cb0ef41Sopenharmony_ci      case kExprS128Load16x4S:
39611cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load16S,
39621cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kExtend,
39631cb0ef41Sopenharmony_ci                                      opcode_length);
39641cb0ef41Sopenharmony_ci      case kExprS128Load16x4U:
39651cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI32Load16U,
39661cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kExtend,
39671cb0ef41Sopenharmony_ci                                      opcode_length);
39681cb0ef41Sopenharmony_ci      case kExprS128Load32x2S:
39691cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI64Load32S,
39701cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kExtend,
39711cb0ef41Sopenharmony_ci                                      opcode_length);
39721cb0ef41Sopenharmony_ci      case kExprS128Load32x2U:
39731cb0ef41Sopenharmony_ci        return DecodeLoadTransformMem(LoadType::kI64Load32U,
39741cb0ef41Sopenharmony_ci                                      LoadTransformationKind::kExtend,
39751cb0ef41Sopenharmony_ci                                      opcode_length);
39761cb0ef41Sopenharmony_ci      case kExprS128Load8Lane: {
39771cb0ef41Sopenharmony_ci        return DecodeLoadLane(opcode, LoadType::kI32Load8S, opcode_length);
39781cb0ef41Sopenharmony_ci      }
39791cb0ef41Sopenharmony_ci      case kExprS128Load16Lane: {
39801cb0ef41Sopenharmony_ci        return DecodeLoadLane(opcode, LoadType::kI32Load16S, opcode_length);
39811cb0ef41Sopenharmony_ci      }
39821cb0ef41Sopenharmony_ci      case kExprS128Load32Lane: {
39831cb0ef41Sopenharmony_ci        return DecodeLoadLane(opcode, LoadType::kI32Load, opcode_length);
39841cb0ef41Sopenharmony_ci      }
39851cb0ef41Sopenharmony_ci      case kExprS128Load64Lane: {
39861cb0ef41Sopenharmony_ci        return DecodeLoadLane(opcode, LoadType::kI64Load, opcode_length);
39871cb0ef41Sopenharmony_ci      }
39881cb0ef41Sopenharmony_ci      case kExprS128Store8Lane: {
39891cb0ef41Sopenharmony_ci        return DecodeStoreLane(opcode, StoreType::kI32Store8, opcode_length);
39901cb0ef41Sopenharmony_ci      }
39911cb0ef41Sopenharmony_ci      case kExprS128Store16Lane: {
39921cb0ef41Sopenharmony_ci        return DecodeStoreLane(opcode, StoreType::kI32Store16, opcode_length);
39931cb0ef41Sopenharmony_ci      }
39941cb0ef41Sopenharmony_ci      case kExprS128Store32Lane: {
39951cb0ef41Sopenharmony_ci        return DecodeStoreLane(opcode, StoreType::kI32Store, opcode_length);
39961cb0ef41Sopenharmony_ci      }
39971cb0ef41Sopenharmony_ci      case kExprS128Store64Lane: {
39981cb0ef41Sopenharmony_ci        return DecodeStoreLane(opcode, StoreType::kI64Store, opcode_length);
39991cb0ef41Sopenharmony_ci      }
40001cb0ef41Sopenharmony_ci      case kExprS128Const:
40011cb0ef41Sopenharmony_ci        return SimdConstOp(opcode_length);
40021cb0ef41Sopenharmony_ci      default: {
40031cb0ef41Sopenharmony_ci        const FunctionSig* sig = WasmOpcodes::Signature(opcode);
40041cb0ef41Sopenharmony_ci        if (!VALIDATE(sig != nullptr)) {
40051cb0ef41Sopenharmony_ci          this->DecodeError("invalid simd opcode");
40061cb0ef41Sopenharmony_ci          return 0;
40071cb0ef41Sopenharmony_ci        }
40081cb0ef41Sopenharmony_ci        ArgVector args = PeekArgs(sig);
40091cb0ef41Sopenharmony_ci        if (sig->return_count() == 0) {
40101cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(SimdOp, opcode,
40111cb0ef41Sopenharmony_ci                                             base::VectorOf(args), nullptr);
40121cb0ef41Sopenharmony_ci          DropArgs(sig);
40131cb0ef41Sopenharmony_ci        } else {
40141cb0ef41Sopenharmony_ci          ReturnVector results = CreateReturnValues(sig);
40151cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(
40161cb0ef41Sopenharmony_ci              SimdOp, opcode, base::VectorOf(args), results.begin());
40171cb0ef41Sopenharmony_ci          DropArgs(sig);
40181cb0ef41Sopenharmony_ci          PushReturns(results);
40191cb0ef41Sopenharmony_ci        }
40201cb0ef41Sopenharmony_ci        return opcode_length;
40211cb0ef41Sopenharmony_ci      }
40221cb0ef41Sopenharmony_ci    }
40231cb0ef41Sopenharmony_ci  }
40241cb0ef41Sopenharmony_ci
40251cb0ef41Sopenharmony_ci  // Checks if types are unrelated, thus type checking will always fail. Does
40261cb0ef41Sopenharmony_ci  // not account for nullability.
40271cb0ef41Sopenharmony_ci  bool TypeCheckAlwaysFails(Value obj, Value rtt) {
40281cb0ef41Sopenharmony_ci    return !IsSubtypeOf(ValueType::Ref(rtt.type.ref_index(), kNonNullable),
40291cb0ef41Sopenharmony_ci                        obj.type, this->module_) &&
40301cb0ef41Sopenharmony_ci           !IsSubtypeOf(obj.type,
40311cb0ef41Sopenharmony_ci                        ValueType::Ref(rtt.type.ref_index(), kNullable),
40321cb0ef41Sopenharmony_ci                        this->module_);
40331cb0ef41Sopenharmony_ci  }
40341cb0ef41Sopenharmony_ci
40351cb0ef41Sopenharmony_ci  // Checks it {obj} is a nominal type which is a subtype of {rtt}'s index, thus
40361cb0ef41Sopenharmony_ci  // checking will always succeed. Does not account for nullability.
40371cb0ef41Sopenharmony_ci  bool TypeCheckAlwaysSucceeds(Value obj, Value rtt) {
40381cb0ef41Sopenharmony_ci    return obj.type.has_index() &&
40391cb0ef41Sopenharmony_ci           this->module_->has_supertype(obj.type.ref_index()) &&
40401cb0ef41Sopenharmony_ci           IsSubtypeOf(obj.type,
40411cb0ef41Sopenharmony_ci                       ValueType::Ref(rtt.type.ref_index(), kNullable),
40421cb0ef41Sopenharmony_ci                       this->module_);
40431cb0ef41Sopenharmony_ci  }
40441cb0ef41Sopenharmony_ci
40451cb0ef41Sopenharmony_ci#define NON_CONST_ONLY                                                 \
40461cb0ef41Sopenharmony_ci  if (decoding_mode == kInitExpression) {                              \
40471cb0ef41Sopenharmony_ci    this->DecodeError("opcode %s is not allowed in init. expressions", \
40481cb0ef41Sopenharmony_ci                      this->SafeOpcodeNameAt(this->pc()));             \
40491cb0ef41Sopenharmony_ci    return 0;                                                          \
40501cb0ef41Sopenharmony_ci  }
40511cb0ef41Sopenharmony_ci
40521cb0ef41Sopenharmony_ci  int DecodeGCOpcode(WasmOpcode opcode, uint32_t opcode_length) {
40531cb0ef41Sopenharmony_ci    switch (opcode) {
40541cb0ef41Sopenharmony_ci      case kExprStructNew:
40551cb0ef41Sopenharmony_ci      case kExprStructNewWithRtt: {
40561cb0ef41Sopenharmony_ci        StructIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
40571cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
40581cb0ef41Sopenharmony_ci        ValueType rtt_type = ValueType::Rtt(imm.index);
40591cb0ef41Sopenharmony_ci        Value rtt = opcode == kExprStructNew
40601cb0ef41Sopenharmony_ci                        ? CreateValue(rtt_type)
40611cb0ef41Sopenharmony_ci                        : Peek(0, imm.struct_type->field_count(), rtt_type);
40621cb0ef41Sopenharmony_ci        if (opcode == kExprStructNew) {
40631cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
40641cb0ef41Sopenharmony_ci          Push(rtt);
40651cb0ef41Sopenharmony_ci        }
40661cb0ef41Sopenharmony_ci        ArgVector args = PeekArgs(imm.struct_type, 1);
40671cb0ef41Sopenharmony_ci        Value value = CreateValue(ValueType::Ref(imm.index, kNonNullable));
40681cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(StructNewWithRtt, imm, rtt,
40691cb0ef41Sopenharmony_ci                                           args.begin(), &value);
40701cb0ef41Sopenharmony_ci        Drop(rtt);
40711cb0ef41Sopenharmony_ci        DropArgs(imm.struct_type);
40721cb0ef41Sopenharmony_ci        Push(value);
40731cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
40741cb0ef41Sopenharmony_ci      }
40751cb0ef41Sopenharmony_ci      case kExprStructNewDefault:
40761cb0ef41Sopenharmony_ci      case kExprStructNewDefaultWithRtt: {
40771cb0ef41Sopenharmony_ci        StructIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
40781cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
40791cb0ef41Sopenharmony_ci        if (validate) {
40801cb0ef41Sopenharmony_ci          for (uint32_t i = 0; i < imm.struct_type->field_count(); i++) {
40811cb0ef41Sopenharmony_ci            ValueType ftype = imm.struct_type->field(i);
40821cb0ef41Sopenharmony_ci            if (!VALIDATE(ftype.is_defaultable())) {
40831cb0ef41Sopenharmony_ci              this->DecodeError(
40841cb0ef41Sopenharmony_ci                  "%s: struct type %d has field %d of non-defaultable type %s",
40851cb0ef41Sopenharmony_ci                  WasmOpcodes::OpcodeName(opcode), imm.index, i,
40861cb0ef41Sopenharmony_ci                  ftype.name().c_str());
40871cb0ef41Sopenharmony_ci              return 0;
40881cb0ef41Sopenharmony_ci            }
40891cb0ef41Sopenharmony_ci          }
40901cb0ef41Sopenharmony_ci        }
40911cb0ef41Sopenharmony_ci        ValueType rtt_type = ValueType::Rtt(imm.index);
40921cb0ef41Sopenharmony_ci        Value rtt = opcode == kExprStructNewDefault ? CreateValue(rtt_type)
40931cb0ef41Sopenharmony_ci                                                    : Peek(0, 0, rtt_type);
40941cb0ef41Sopenharmony_ci        if (opcode == kExprStructNewDefault) {
40951cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
40961cb0ef41Sopenharmony_ci          Push(rtt);
40971cb0ef41Sopenharmony_ci        }
40981cb0ef41Sopenharmony_ci        Value value = CreateValue(ValueType::Ref(imm.index, kNonNullable));
40991cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(StructNewDefault, imm, rtt, &value);
41001cb0ef41Sopenharmony_ci        Drop(rtt);
41011cb0ef41Sopenharmony_ci        Push(value);
41021cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
41031cb0ef41Sopenharmony_ci      }
41041cb0ef41Sopenharmony_ci      case kExprStructGet: {
41051cb0ef41Sopenharmony_ci        NON_CONST_ONLY
41061cb0ef41Sopenharmony_ci        FieldImmediate<validate> field(this, this->pc_ + opcode_length);
41071cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, field)) return 0;
41081cb0ef41Sopenharmony_ci        ValueType field_type =
41091cb0ef41Sopenharmony_ci            field.struct_imm.struct_type->field(field.field_imm.index);
41101cb0ef41Sopenharmony_ci        if (!VALIDATE(!field_type.is_packed())) {
41111cb0ef41Sopenharmony_ci          this->DecodeError(
41121cb0ef41Sopenharmony_ci              "struct.get: Immediate field %d of type %d has packed type %s. "
41131cb0ef41Sopenharmony_ci              "Use struct.get_s or struct.get_u instead.",
41141cb0ef41Sopenharmony_ci              field.field_imm.index, field.struct_imm.index,
41151cb0ef41Sopenharmony_ci              field_type.name().c_str());
41161cb0ef41Sopenharmony_ci          return 0;
41171cb0ef41Sopenharmony_ci        }
41181cb0ef41Sopenharmony_ci        Value struct_obj =
41191cb0ef41Sopenharmony_ci            Peek(0, 0, ValueType::Ref(field.struct_imm.index, kNullable));
41201cb0ef41Sopenharmony_ci        Value value = CreateValue(field_type);
41211cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(StructGet, struct_obj, field, true,
41221cb0ef41Sopenharmony_ci                                           &value);
41231cb0ef41Sopenharmony_ci        Drop(struct_obj);
41241cb0ef41Sopenharmony_ci        Push(value);
41251cb0ef41Sopenharmony_ci        return opcode_length + field.length;
41261cb0ef41Sopenharmony_ci      }
41271cb0ef41Sopenharmony_ci      case kExprStructGetU:
41281cb0ef41Sopenharmony_ci      case kExprStructGetS: {
41291cb0ef41Sopenharmony_ci        NON_CONST_ONLY
41301cb0ef41Sopenharmony_ci        FieldImmediate<validate> field(this, this->pc_ + opcode_length);
41311cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, field)) return 0;
41321cb0ef41Sopenharmony_ci        ValueType field_type =
41331cb0ef41Sopenharmony_ci            field.struct_imm.struct_type->field(field.field_imm.index);
41341cb0ef41Sopenharmony_ci        if (!VALIDATE(field_type.is_packed())) {
41351cb0ef41Sopenharmony_ci          this->DecodeError(
41361cb0ef41Sopenharmony_ci              "%s: Immediate field %d of type %d has non-packed type %s. Use "
41371cb0ef41Sopenharmony_ci              "struct.get instead.",
41381cb0ef41Sopenharmony_ci              WasmOpcodes::OpcodeName(opcode), field.field_imm.index,
41391cb0ef41Sopenharmony_ci              field.struct_imm.index, field_type.name().c_str());
41401cb0ef41Sopenharmony_ci          return 0;
41411cb0ef41Sopenharmony_ci        }
41421cb0ef41Sopenharmony_ci        Value struct_obj =
41431cb0ef41Sopenharmony_ci            Peek(0, 0, ValueType::Ref(field.struct_imm.index, kNullable));
41441cb0ef41Sopenharmony_ci        Value value = CreateValue(field_type.Unpacked());
41451cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(StructGet, struct_obj, field,
41461cb0ef41Sopenharmony_ci                                           opcode == kExprStructGetS, &value);
41471cb0ef41Sopenharmony_ci        Drop(struct_obj);
41481cb0ef41Sopenharmony_ci        Push(value);
41491cb0ef41Sopenharmony_ci        return opcode_length + field.length;
41501cb0ef41Sopenharmony_ci      }
41511cb0ef41Sopenharmony_ci      case kExprStructSet: {
41521cb0ef41Sopenharmony_ci        NON_CONST_ONLY
41531cb0ef41Sopenharmony_ci        FieldImmediate<validate> field(this, this->pc_ + opcode_length);
41541cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, field)) return 0;
41551cb0ef41Sopenharmony_ci        const StructType* struct_type = field.struct_imm.struct_type;
41561cb0ef41Sopenharmony_ci        if (!VALIDATE(struct_type->mutability(field.field_imm.index))) {
41571cb0ef41Sopenharmony_ci          this->DecodeError("struct.set: Field %d of type %d is immutable.",
41581cb0ef41Sopenharmony_ci                            field.field_imm.index, field.struct_imm.index);
41591cb0ef41Sopenharmony_ci          return 0;
41601cb0ef41Sopenharmony_ci        }
41611cb0ef41Sopenharmony_ci        Value field_value =
41621cb0ef41Sopenharmony_ci            Peek(0, 1, struct_type->field(field.field_imm.index).Unpacked());
41631cb0ef41Sopenharmony_ci        Value struct_obj =
41641cb0ef41Sopenharmony_ci            Peek(1, 0, ValueType::Ref(field.struct_imm.index, kNullable));
41651cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(StructSet, struct_obj, field,
41661cb0ef41Sopenharmony_ci                                           field_value);
41671cb0ef41Sopenharmony_ci        Drop(2);
41681cb0ef41Sopenharmony_ci        return opcode_length + field.length;
41691cb0ef41Sopenharmony_ci      }
41701cb0ef41Sopenharmony_ci      case kExprArrayNew:
41711cb0ef41Sopenharmony_ci      case kExprArrayNewWithRtt: {
41721cb0ef41Sopenharmony_ci        NON_CONST_ONLY
41731cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
41741cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
41751cb0ef41Sopenharmony_ci        ValueType rtt_type = ValueType::Rtt(imm.index);
41761cb0ef41Sopenharmony_ci        Value rtt = opcode == kExprArrayNew ? CreateValue(rtt_type)
41771cb0ef41Sopenharmony_ci                                            : Peek(0, 2, rtt_type);
41781cb0ef41Sopenharmony_ci        if (opcode == kExprArrayNew) {
41791cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
41801cb0ef41Sopenharmony_ci          Push(rtt);
41811cb0ef41Sopenharmony_ci        }
41821cb0ef41Sopenharmony_ci        Value length = Peek(1, 1, kWasmI32);
41831cb0ef41Sopenharmony_ci        Value initial_value =
41841cb0ef41Sopenharmony_ci            Peek(2, 0, imm.array_type->element_type().Unpacked());
41851cb0ef41Sopenharmony_ci        Value value = CreateValue(ValueType::Ref(imm.index, kNonNullable));
41861cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayNewWithRtt, imm, length,
41871cb0ef41Sopenharmony_ci                                           initial_value, rtt, &value);
41881cb0ef41Sopenharmony_ci        Drop(3);  // rtt, length, initial_value.
41891cb0ef41Sopenharmony_ci        Push(value);
41901cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
41911cb0ef41Sopenharmony_ci      }
41921cb0ef41Sopenharmony_ci      case kExprArrayNewDefault:
41931cb0ef41Sopenharmony_ci      case kExprArrayNewDefaultWithRtt: {
41941cb0ef41Sopenharmony_ci        NON_CONST_ONLY
41951cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
41961cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
41971cb0ef41Sopenharmony_ci        if (!VALIDATE(imm.array_type->element_type().is_defaultable())) {
41981cb0ef41Sopenharmony_ci          this->DecodeError(
41991cb0ef41Sopenharmony_ci              "%s: array type %d has non-defaultable element type %s",
42001cb0ef41Sopenharmony_ci              WasmOpcodes::OpcodeName(opcode), imm.index,
42011cb0ef41Sopenharmony_ci              imm.array_type->element_type().name().c_str());
42021cb0ef41Sopenharmony_ci          return 0;
42031cb0ef41Sopenharmony_ci        }
42041cb0ef41Sopenharmony_ci        ValueType rtt_type = ValueType::Rtt(imm.index);
42051cb0ef41Sopenharmony_ci        Value rtt = opcode == kExprArrayNewDefault ? CreateValue(rtt_type)
42061cb0ef41Sopenharmony_ci                                                   : Peek(0, 1, rtt_type);
42071cb0ef41Sopenharmony_ci        if (opcode == kExprArrayNewDefault) {
42081cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
42091cb0ef41Sopenharmony_ci          Push(rtt);
42101cb0ef41Sopenharmony_ci        }
42111cb0ef41Sopenharmony_ci        Value length = Peek(1, 0, kWasmI32);
42121cb0ef41Sopenharmony_ci        Value value = CreateValue(ValueType::Ref(imm.index, kNonNullable));
42131cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayNewDefault, imm, length, rtt,
42141cb0ef41Sopenharmony_ci                                           &value);
42151cb0ef41Sopenharmony_ci        Drop(2);  // rtt, length
42161cb0ef41Sopenharmony_ci        Push(value);
42171cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
42181cb0ef41Sopenharmony_ci      }
42191cb0ef41Sopenharmony_ci      case kExprArrayInitFromData:
42201cb0ef41Sopenharmony_ci      case kExprArrayInitFromDataStatic: {
42211cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> array_imm(this,
42221cb0ef41Sopenharmony_ci                                                this->pc_ + opcode_length);
42231cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, array_imm)) return 0;
42241cb0ef41Sopenharmony_ci        ValueType element_type = array_imm.array_type->element_type();
42251cb0ef41Sopenharmony_ci        if (element_type.is_reference()) {
42261cb0ef41Sopenharmony_ci          this->DecodeError(
42271cb0ef41Sopenharmony_ci              "array.init_from_data can only be used with value-type arrays, "
42281cb0ef41Sopenharmony_ci              "found array type #%d instead",
42291cb0ef41Sopenharmony_ci              array_imm.index);
42301cb0ef41Sopenharmony_ci          return 0;
42311cb0ef41Sopenharmony_ci        }
42321cb0ef41Sopenharmony_ci#if V8_TARGET_BIG_ENDIAN
42331cb0ef41Sopenharmony_ci        // Byte sequences in data segments are interpreted as little endian for
42341cb0ef41Sopenharmony_ci        // the purposes of this instruction. This means that those will have to
42351cb0ef41Sopenharmony_ci        // be transformed in big endian architectures. TODO(7748): Implement.
42361cb0ef41Sopenharmony_ci        if (element_type.value_kind_size() > 1) {
42371cb0ef41Sopenharmony_ci          UNIMPLEMENTED();
42381cb0ef41Sopenharmony_ci        }
42391cb0ef41Sopenharmony_ci#endif
42401cb0ef41Sopenharmony_ci        const byte* data_index_pc =
42411cb0ef41Sopenharmony_ci            this->pc_ + opcode_length + array_imm.length;
42421cb0ef41Sopenharmony_ci        IndexImmediate<validate> data_segment(this, data_index_pc,
42431cb0ef41Sopenharmony_ci                                              "data segment");
42441cb0ef41Sopenharmony_ci        if (!this->ValidateDataSegment(data_index_pc, data_segment)) return 0;
42451cb0ef41Sopenharmony_ci
42461cb0ef41Sopenharmony_ci        ValueType rtt_type = ValueType::Rtt(array_imm.index);
42471cb0ef41Sopenharmony_ci        Value rtt = opcode == kExprArrayInitFromDataStatic
42481cb0ef41Sopenharmony_ci                        ? CreateValue(rtt_type)
42491cb0ef41Sopenharmony_ci                        : Peek(0, 2, rtt_type);
42501cb0ef41Sopenharmony_ci        if (opcode == kExprArrayInitFromDataStatic) {
42511cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, array_imm.index, &rtt);
42521cb0ef41Sopenharmony_ci          Push(rtt);
42531cb0ef41Sopenharmony_ci        }
42541cb0ef41Sopenharmony_ci
42551cb0ef41Sopenharmony_ci        Value length = Peek(1, 1, kWasmI32);
42561cb0ef41Sopenharmony_ci        Value offset = Peek(2, 0, kWasmI32);
42571cb0ef41Sopenharmony_ci
42581cb0ef41Sopenharmony_ci        Value array =
42591cb0ef41Sopenharmony_ci            CreateValue(ValueType::Ref(array_imm.index, kNonNullable));
42601cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayInitFromData, array_imm,
42611cb0ef41Sopenharmony_ci                                           data_segment, offset, length, rtt,
42621cb0ef41Sopenharmony_ci                                           &array);
42631cb0ef41Sopenharmony_ci        Drop(3);  // rtt, length, offset
42641cb0ef41Sopenharmony_ci        Push(array);
42651cb0ef41Sopenharmony_ci        return opcode_length + array_imm.length + data_segment.length;
42661cb0ef41Sopenharmony_ci      }
42671cb0ef41Sopenharmony_ci      case kExprArrayGetS:
42681cb0ef41Sopenharmony_ci      case kExprArrayGetU: {
42691cb0ef41Sopenharmony_ci        NON_CONST_ONLY
42701cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
42711cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
42721cb0ef41Sopenharmony_ci        if (!VALIDATE(imm.array_type->element_type().is_packed())) {
42731cb0ef41Sopenharmony_ci          this->DecodeError(
42741cb0ef41Sopenharmony_ci              "%s: Immediate array type %d has non-packed type %s. Use "
42751cb0ef41Sopenharmony_ci              "array.get instead.",
42761cb0ef41Sopenharmony_ci              WasmOpcodes::OpcodeName(opcode), imm.index,
42771cb0ef41Sopenharmony_ci              imm.array_type->element_type().name().c_str());
42781cb0ef41Sopenharmony_ci          return 0;
42791cb0ef41Sopenharmony_ci        }
42801cb0ef41Sopenharmony_ci        Value index = Peek(0, 1, kWasmI32);
42811cb0ef41Sopenharmony_ci        Value array_obj = Peek(1, 0, ValueType::Ref(imm.index, kNullable));
42821cb0ef41Sopenharmony_ci        Value value = CreateValue(imm.array_type->element_type().Unpacked());
42831cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayGet, array_obj, imm, index,
42841cb0ef41Sopenharmony_ci                                           opcode == kExprArrayGetS, &value);
42851cb0ef41Sopenharmony_ci        Drop(2);  // index, array_obj
42861cb0ef41Sopenharmony_ci        Push(value);
42871cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
42881cb0ef41Sopenharmony_ci      }
42891cb0ef41Sopenharmony_ci      case kExprArrayGet: {
42901cb0ef41Sopenharmony_ci        NON_CONST_ONLY
42911cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
42921cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
42931cb0ef41Sopenharmony_ci        if (!VALIDATE(!imm.array_type->element_type().is_packed())) {
42941cb0ef41Sopenharmony_ci          this->DecodeError(
42951cb0ef41Sopenharmony_ci              "array.get: Immediate array type %d has packed type %s. Use "
42961cb0ef41Sopenharmony_ci              "array.get_s or array.get_u instead.",
42971cb0ef41Sopenharmony_ci              imm.index, imm.array_type->element_type().name().c_str());
42981cb0ef41Sopenharmony_ci          return 0;
42991cb0ef41Sopenharmony_ci        }
43001cb0ef41Sopenharmony_ci        Value index = Peek(0, 1, kWasmI32);
43011cb0ef41Sopenharmony_ci        Value array_obj = Peek(1, 0, ValueType::Ref(imm.index, kNullable));
43021cb0ef41Sopenharmony_ci        Value value = CreateValue(imm.array_type->element_type());
43031cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayGet, array_obj, imm, index,
43041cb0ef41Sopenharmony_ci                                           true, &value);
43051cb0ef41Sopenharmony_ci        Drop(2);  // index, array_obj
43061cb0ef41Sopenharmony_ci        Push(value);
43071cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
43081cb0ef41Sopenharmony_ci      }
43091cb0ef41Sopenharmony_ci      case kExprArraySet: {
43101cb0ef41Sopenharmony_ci        NON_CONST_ONLY
43111cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
43121cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
43131cb0ef41Sopenharmony_ci        if (!VALIDATE(imm.array_type->mutability())) {
43141cb0ef41Sopenharmony_ci          this->DecodeError("array.set: immediate array type %d is immutable",
43151cb0ef41Sopenharmony_ci                            imm.index);
43161cb0ef41Sopenharmony_ci          return 0;
43171cb0ef41Sopenharmony_ci        }
43181cb0ef41Sopenharmony_ci        Value value = Peek(0, 2, imm.array_type->element_type().Unpacked());
43191cb0ef41Sopenharmony_ci        Value index = Peek(1, 1, kWasmI32);
43201cb0ef41Sopenharmony_ci        Value array_obj = Peek(2, 0, ValueType::Ref(imm.index, kNullable));
43211cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArraySet, array_obj, imm, index,
43221cb0ef41Sopenharmony_ci                                           value);
43231cb0ef41Sopenharmony_ci        Drop(3);
43241cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
43251cb0ef41Sopenharmony_ci      }
43261cb0ef41Sopenharmony_ci      case kExprArrayLen: {
43271cb0ef41Sopenharmony_ci        NON_CONST_ONLY
43281cb0ef41Sopenharmony_ci        // Read but ignore an immediate array type index.
43291cb0ef41Sopenharmony_ci        // TODO(7748): Remove this once we are ready to make breaking changes.
43301cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
43311cb0ef41Sopenharmony_ci        Value array_obj =
43321cb0ef41Sopenharmony_ci            Peek(0, 0, ValueType::Ref(HeapType::kArray, kNullable));
43331cb0ef41Sopenharmony_ci        Value value = CreateValue(kWasmI32);
43341cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayLen, array_obj, &value);
43351cb0ef41Sopenharmony_ci        Drop(array_obj);
43361cb0ef41Sopenharmony_ci        Push(value);
43371cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
43381cb0ef41Sopenharmony_ci      }
43391cb0ef41Sopenharmony_ci      case kExprArrayCopy: {
43401cb0ef41Sopenharmony_ci        NON_CONST_ONLY
43411cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> dst_imm(this, this->pc_ + opcode_length);
43421cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, dst_imm)) return 0;
43431cb0ef41Sopenharmony_ci        if (!VALIDATE(dst_imm.array_type->mutability())) {
43441cb0ef41Sopenharmony_ci          this->DecodeError(
43451cb0ef41Sopenharmony_ci              "array.copy: immediate destination array type #%d is immutable",
43461cb0ef41Sopenharmony_ci              dst_imm.index);
43471cb0ef41Sopenharmony_ci          return 0;
43481cb0ef41Sopenharmony_ci        }
43491cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> src_imm(
43501cb0ef41Sopenharmony_ci            this, this->pc_ + opcode_length + dst_imm.length);
43511cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length + dst_imm.length,
43521cb0ef41Sopenharmony_ci                            src_imm)) {
43531cb0ef41Sopenharmony_ci          return 0;
43541cb0ef41Sopenharmony_ci        }
43551cb0ef41Sopenharmony_ci        if (!IsSubtypeOf(src_imm.array_type->element_type(),
43561cb0ef41Sopenharmony_ci                         dst_imm.array_type->element_type(), this->module_)) {
43571cb0ef41Sopenharmony_ci          this->DecodeError(
43581cb0ef41Sopenharmony_ci              "array.copy: source array's #%d element type is not a subtype of "
43591cb0ef41Sopenharmony_ci              "destination array's #%d element type",
43601cb0ef41Sopenharmony_ci              src_imm.index, dst_imm.index);
43611cb0ef41Sopenharmony_ci          return 0;
43621cb0ef41Sopenharmony_ci        }
43631cb0ef41Sopenharmony_ci        // [dst, dst_index, src, src_index, length]
43641cb0ef41Sopenharmony_ci        Value dst = Peek(4, 0, ValueType::Ref(dst_imm.index, kNullable));
43651cb0ef41Sopenharmony_ci        Value dst_index = Peek(3, 1, kWasmI32);
43661cb0ef41Sopenharmony_ci        Value src = Peek(2, 2, ValueType::Ref(src_imm.index, kNullable));
43671cb0ef41Sopenharmony_ci        Value src_index = Peek(1, 3, kWasmI32);
43681cb0ef41Sopenharmony_ci        Value length = Peek(0, 4, kWasmI32);
43691cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayCopy, dst, dst_index, src,
43701cb0ef41Sopenharmony_ci                                           src_index, length);
43711cb0ef41Sopenharmony_ci        Drop(5);
43721cb0ef41Sopenharmony_ci        return opcode_length + dst_imm.length + src_imm.length;
43731cb0ef41Sopenharmony_ci      }
43741cb0ef41Sopenharmony_ci      case kExprArrayInit:
43751cb0ef41Sopenharmony_ci      case kExprArrayInitStatic: {
43761cb0ef41Sopenharmony_ci        ArrayIndexImmediate<validate> array_imm(this,
43771cb0ef41Sopenharmony_ci                                                this->pc_ + opcode_length);
43781cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, array_imm)) return 0;
43791cb0ef41Sopenharmony_ci        IndexImmediate<validate> length_imm(
43801cb0ef41Sopenharmony_ci            this, this->pc_ + opcode_length + array_imm.length,
43811cb0ef41Sopenharmony_ci            "array.init length");
43821cb0ef41Sopenharmony_ci        uint32_t elem_count = length_imm.index;
43831cb0ef41Sopenharmony_ci        if (!VALIDATE(elem_count <= kV8MaxWasmArrayInitLength)) {
43841cb0ef41Sopenharmony_ci          this->DecodeError(
43851cb0ef41Sopenharmony_ci              "Requested length %u for array.init too large, maximum is %zu",
43861cb0ef41Sopenharmony_ci              length_imm.index, kV8MaxWasmArrayInitLength);
43871cb0ef41Sopenharmony_ci          return 0;
43881cb0ef41Sopenharmony_ci        }
43891cb0ef41Sopenharmony_ci        Value rtt = opcode == kExprArrayInit
43901cb0ef41Sopenharmony_ci                        ? Peek(0, elem_count, ValueType::Rtt(array_imm.index))
43911cb0ef41Sopenharmony_ci                        : CreateValue(ValueType::Rtt(array_imm.index));
43921cb0ef41Sopenharmony_ci        if (opcode == kExprArrayInitStatic) {
43931cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, array_imm.index, &rtt);
43941cb0ef41Sopenharmony_ci          Push(rtt);
43951cb0ef41Sopenharmony_ci        }
43961cb0ef41Sopenharmony_ci        ValueType element_type = array_imm.array_type->element_type();
43971cb0ef41Sopenharmony_ci        std::vector<ValueType> element_types(elem_count,
43981cb0ef41Sopenharmony_ci                                             element_type.Unpacked());
43991cb0ef41Sopenharmony_ci        FunctionSig element_sig(0, elem_count, element_types.data());
44001cb0ef41Sopenharmony_ci        ArgVector elements = PeekArgs(&element_sig, 1);
44011cb0ef41Sopenharmony_ci        Value result =
44021cb0ef41Sopenharmony_ci            CreateValue(ValueType::Ref(array_imm.index, kNonNullable));
44031cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ArrayInit, array_imm, elements, rtt,
44041cb0ef41Sopenharmony_ci                                           &result);
44051cb0ef41Sopenharmony_ci        Drop(elem_count + 1);
44061cb0ef41Sopenharmony_ci        Push(result);
44071cb0ef41Sopenharmony_ci        return opcode_length + array_imm.length + length_imm.length;
44081cb0ef41Sopenharmony_ci      }
44091cb0ef41Sopenharmony_ci      case kExprI31New: {
44101cb0ef41Sopenharmony_ci        NON_CONST_ONLY
44111cb0ef41Sopenharmony_ci        Value input = Peek(0, 0, kWasmI32);
44121cb0ef41Sopenharmony_ci        Value value = CreateValue(kWasmI31Ref);
44131cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(I31New, input, &value);
44141cb0ef41Sopenharmony_ci        Drop(input);
44151cb0ef41Sopenharmony_ci        Push(value);
44161cb0ef41Sopenharmony_ci        return opcode_length;
44171cb0ef41Sopenharmony_ci      }
44181cb0ef41Sopenharmony_ci      case kExprI31GetS: {
44191cb0ef41Sopenharmony_ci        NON_CONST_ONLY
44201cb0ef41Sopenharmony_ci        Value i31 = Peek(0, 0, kWasmI31Ref);
44211cb0ef41Sopenharmony_ci        Value value = CreateValue(kWasmI32);
44221cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(I31GetS, i31, &value);
44231cb0ef41Sopenharmony_ci        Drop(i31);
44241cb0ef41Sopenharmony_ci        Push(value);
44251cb0ef41Sopenharmony_ci        return opcode_length;
44261cb0ef41Sopenharmony_ci      }
44271cb0ef41Sopenharmony_ci      case kExprI31GetU: {
44281cb0ef41Sopenharmony_ci        NON_CONST_ONLY
44291cb0ef41Sopenharmony_ci        Value i31 = Peek(0, 0, kWasmI31Ref);
44301cb0ef41Sopenharmony_ci        Value value = CreateValue(kWasmI32);
44311cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(I31GetU, i31, &value);
44321cb0ef41Sopenharmony_ci        Drop(i31);
44331cb0ef41Sopenharmony_ci        Push(value);
44341cb0ef41Sopenharmony_ci        return opcode_length;
44351cb0ef41Sopenharmony_ci      }
44361cb0ef41Sopenharmony_ci      case kExprRttCanon: {
44371cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
44381cb0ef41Sopenharmony_ci                                     "type index");
44391cb0ef41Sopenharmony_ci        if (!this->ValidateType(this->pc_ + opcode_length, imm)) return 0;
44401cb0ef41Sopenharmony_ci        Value value = CreateValue(ValueType::Rtt(imm.index));
44411cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &value);
44421cb0ef41Sopenharmony_ci        Push(value);
44431cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
44441cb0ef41Sopenharmony_ci      }
44451cb0ef41Sopenharmony_ci      case kExprRefTest:
44461cb0ef41Sopenharmony_ci      case kExprRefTestStatic: {
44471cb0ef41Sopenharmony_ci        NON_CONST_ONLY
44481cb0ef41Sopenharmony_ci        // "Tests whether {obj}'s runtime type is a runtime subtype of {rtt}."
44491cb0ef41Sopenharmony_ci        Value rtt = Peek(0);  // This is safe for the ...Static instruction.
44501cb0ef41Sopenharmony_ci        if (opcode == kExprRefTestStatic) {
44511cb0ef41Sopenharmony_ci          IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
44521cb0ef41Sopenharmony_ci                                       "type index");
44531cb0ef41Sopenharmony_ci          if (!this->ValidateType(this->pc_ + opcode_length, imm)) return 0;
44541cb0ef41Sopenharmony_ci          opcode_length += imm.length;
44551cb0ef41Sopenharmony_ci          rtt = CreateValue(ValueType::Rtt(imm.index));
44561cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
44571cb0ef41Sopenharmony_ci          Push(rtt);
44581cb0ef41Sopenharmony_ci        } else {
44591cb0ef41Sopenharmony_ci          DCHECK_EQ(opcode, kExprRefTest);
44601cb0ef41Sopenharmony_ci          if (!VALIDATE(rtt.type.is_rtt() || rtt.type.is_bottom())) {
44611cb0ef41Sopenharmony_ci            PopTypeError(1, rtt, "rtt");
44621cb0ef41Sopenharmony_ci            return 0;
44631cb0ef41Sopenharmony_ci          }
44641cb0ef41Sopenharmony_ci        }
44651cb0ef41Sopenharmony_ci        Value obj = Peek(1);
44661cb0ef41Sopenharmony_ci        Value value = CreateValue(kWasmI32);
44671cb0ef41Sopenharmony_ci        if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
44681cb0ef41Sopenharmony_ci                      IsSubtypeOf(obj.type,
44691cb0ef41Sopenharmony_ci                                  ValueType::Ref(HeapType::kData, kNullable),
44701cb0ef41Sopenharmony_ci                                  this->module_) ||
44711cb0ef41Sopenharmony_ci                      obj.type.is_bottom())) {
44721cb0ef41Sopenharmony_ci          PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
44731cb0ef41Sopenharmony_ci          return 0;
44741cb0ef41Sopenharmony_ci        }
44751cb0ef41Sopenharmony_ci        if (current_code_reachable_and_ok_) {
44761cb0ef41Sopenharmony_ci          // This logic ensures that code generation can assume that functions
44771cb0ef41Sopenharmony_ci          // can only be cast to function types, and data objects to data types.
44781cb0ef41Sopenharmony_ci          if (V8_UNLIKELY(TypeCheckAlwaysSucceeds(obj, rtt))) {
44791cb0ef41Sopenharmony_ci            // Drop rtt.
44801cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);
44811cb0ef41Sopenharmony_ci            // Type checking can still fail for null.
44821cb0ef41Sopenharmony_ci            if (obj.type.is_nullable()) {
44831cb0ef41Sopenharmony_ci              // We abuse ref.as_non_null, which isn't otherwise used as a unary
44841cb0ef41Sopenharmony_ci              // operator, as a sentinel for the negation of ref.is_null.
44851cb0ef41Sopenharmony_ci              CALL_INTERFACE(UnOp, kExprRefAsNonNull, obj, &value);
44861cb0ef41Sopenharmony_ci            } else {
44871cb0ef41Sopenharmony_ci              CALL_INTERFACE(Drop);
44881cb0ef41Sopenharmony_ci              CALL_INTERFACE(I32Const, &value, 1);
44891cb0ef41Sopenharmony_ci            }
44901cb0ef41Sopenharmony_ci          } else if (V8_UNLIKELY(TypeCheckAlwaysFails(obj, rtt))) {
44911cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);
44921cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);
44931cb0ef41Sopenharmony_ci            CALL_INTERFACE(I32Const, &value, 0);
44941cb0ef41Sopenharmony_ci          } else {
44951cb0ef41Sopenharmony_ci            CALL_INTERFACE(RefTest, obj, rtt, &value);
44961cb0ef41Sopenharmony_ci          }
44971cb0ef41Sopenharmony_ci        }
44981cb0ef41Sopenharmony_ci        Drop(2);
44991cb0ef41Sopenharmony_ci        Push(value);
45001cb0ef41Sopenharmony_ci        return opcode_length;
45011cb0ef41Sopenharmony_ci      }
45021cb0ef41Sopenharmony_ci      case kExprRefCast:
45031cb0ef41Sopenharmony_ci      case kExprRefCastStatic: {
45041cb0ef41Sopenharmony_ci        NON_CONST_ONLY
45051cb0ef41Sopenharmony_ci        Value rtt = Peek(0);  // This is safe for the ...Static instruction.
45061cb0ef41Sopenharmony_ci        if (opcode == kExprRefCastStatic) {
45071cb0ef41Sopenharmony_ci          IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
45081cb0ef41Sopenharmony_ci                                       "type index");
45091cb0ef41Sopenharmony_ci          if (!this->ValidateType(this->pc_ + opcode_length, imm)) return 0;
45101cb0ef41Sopenharmony_ci          opcode_length += imm.length;
45111cb0ef41Sopenharmony_ci          rtt = CreateValue(ValueType::Rtt(imm.index));
45121cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
45131cb0ef41Sopenharmony_ci          Push(rtt);
45141cb0ef41Sopenharmony_ci        } else {
45151cb0ef41Sopenharmony_ci          DCHECK_EQ(opcode, kExprRefCast);
45161cb0ef41Sopenharmony_ci          if (!VALIDATE(rtt.type.is_rtt() || rtt.type.is_bottom())) {
45171cb0ef41Sopenharmony_ci            PopTypeError(1, rtt, "rtt");
45181cb0ef41Sopenharmony_ci            return 0;
45191cb0ef41Sopenharmony_ci          }
45201cb0ef41Sopenharmony_ci        }
45211cb0ef41Sopenharmony_ci        Value obj = Peek(1);
45221cb0ef41Sopenharmony_ci        if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
45231cb0ef41Sopenharmony_ci                      IsSubtypeOf(obj.type,
45241cb0ef41Sopenharmony_ci                                  ValueType::Ref(HeapType::kData, kNullable),
45251cb0ef41Sopenharmony_ci                                  this->module_) ||
45261cb0ef41Sopenharmony_ci                      obj.type.is_bottom())) {
45271cb0ef41Sopenharmony_ci          PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
45281cb0ef41Sopenharmony_ci          return 0;
45291cb0ef41Sopenharmony_ci        }
45301cb0ef41Sopenharmony_ci        // If either value is bottom, we emit the most specific type possible.
45311cb0ef41Sopenharmony_ci        Value value =
45321cb0ef41Sopenharmony_ci            CreateValue(rtt.type.is_bottom()
45331cb0ef41Sopenharmony_ci                            ? kWasmBottom
45341cb0ef41Sopenharmony_ci                            : ValueType::Ref(rtt.type.ref_index(),
45351cb0ef41Sopenharmony_ci                                             obj.type.is_bottom()
45361cb0ef41Sopenharmony_ci                                                 ? kNonNullable
45371cb0ef41Sopenharmony_ci                                                 : obj.type.nullability()));
45381cb0ef41Sopenharmony_ci        if (current_code_reachable_and_ok_) {
45391cb0ef41Sopenharmony_ci          // This logic ensures that code generation can assume that functions
45401cb0ef41Sopenharmony_ci          // can only be cast to function types, and data objects to data types.
45411cb0ef41Sopenharmony_ci          if (V8_UNLIKELY(TypeCheckAlwaysSucceeds(obj, rtt))) {
45421cb0ef41Sopenharmony_ci            // Drop the rtt from the stack, then forward the object value to the
45431cb0ef41Sopenharmony_ci            // result.
45441cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);
45451cb0ef41Sopenharmony_ci            CALL_INTERFACE(Forward, obj, &value);
45461cb0ef41Sopenharmony_ci          } else if (V8_UNLIKELY(TypeCheckAlwaysFails(obj, rtt))) {
45471cb0ef41Sopenharmony_ci            // Unrelated types. The only way this will not trap is if the object
45481cb0ef41Sopenharmony_ci            // is null.
45491cb0ef41Sopenharmony_ci            if (obj.type.is_nullable()) {
45501cb0ef41Sopenharmony_ci              // Drop rtt from the stack, then assert that obj is null.
45511cb0ef41Sopenharmony_ci              CALL_INTERFACE(Drop);
45521cb0ef41Sopenharmony_ci              CALL_INTERFACE(AssertNull, obj, &value);
45531cb0ef41Sopenharmony_ci            } else {
45541cb0ef41Sopenharmony_ci              CALL_INTERFACE(Trap, TrapReason::kTrapIllegalCast);
45551cb0ef41Sopenharmony_ci              // We know that the following code is not reachable, but according
45561cb0ef41Sopenharmony_ci              // to the spec it technically is. Set it to spec-only reachable.
45571cb0ef41Sopenharmony_ci              SetSucceedingCodeDynamicallyUnreachable();
45581cb0ef41Sopenharmony_ci            }
45591cb0ef41Sopenharmony_ci          } else {
45601cb0ef41Sopenharmony_ci            CALL_INTERFACE(RefCast, obj, rtt, &value);
45611cb0ef41Sopenharmony_ci          }
45621cb0ef41Sopenharmony_ci        }
45631cb0ef41Sopenharmony_ci        Drop(2);
45641cb0ef41Sopenharmony_ci        Push(value);
45651cb0ef41Sopenharmony_ci        return opcode_length;
45661cb0ef41Sopenharmony_ci      }
45671cb0ef41Sopenharmony_ci      case kExprBrOnCast:
45681cb0ef41Sopenharmony_ci      case kExprBrOnCastStatic: {
45691cb0ef41Sopenharmony_ci        NON_CONST_ONLY
45701cb0ef41Sopenharmony_ci        BranchDepthImmediate<validate> branch_depth(this,
45711cb0ef41Sopenharmony_ci                                                    this->pc_ + opcode_length);
45721cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, branch_depth,
45731cb0ef41Sopenharmony_ci                            control_.size())) {
45741cb0ef41Sopenharmony_ci          return 0;
45751cb0ef41Sopenharmony_ci        }
45761cb0ef41Sopenharmony_ci        uint32_t pc_offset = opcode_length + branch_depth.length;
45771cb0ef41Sopenharmony_ci        Value rtt = Peek(0);  // This is safe for the ...Static instruction.
45781cb0ef41Sopenharmony_ci        if (opcode == kExprBrOnCastStatic) {
45791cb0ef41Sopenharmony_ci          IndexImmediate<validate> imm(this, this->pc_ + pc_offset,
45801cb0ef41Sopenharmony_ci                                       "type index");
45811cb0ef41Sopenharmony_ci          if (!this->ValidateType(this->pc_ + opcode_length, imm)) return 0;
45821cb0ef41Sopenharmony_ci          pc_offset += imm.length;
45831cb0ef41Sopenharmony_ci          rtt = CreateValue(ValueType::Rtt(imm.index));
45841cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
45851cb0ef41Sopenharmony_ci          Push(rtt);
45861cb0ef41Sopenharmony_ci        } else {
45871cb0ef41Sopenharmony_ci          DCHECK_EQ(opcode, kExprBrOnCast);
45881cb0ef41Sopenharmony_ci          if (!VALIDATE(rtt.type.is_rtt() || rtt.type.is_bottom())) {
45891cb0ef41Sopenharmony_ci            PopTypeError(1, rtt, "rtt");
45901cb0ef41Sopenharmony_ci            return 0;
45911cb0ef41Sopenharmony_ci          }
45921cb0ef41Sopenharmony_ci        }
45931cb0ef41Sopenharmony_ci        Value obj = Peek(1);
45941cb0ef41Sopenharmony_ci        if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
45951cb0ef41Sopenharmony_ci                      IsSubtypeOf(obj.type,
45961cb0ef41Sopenharmony_ci                                  ValueType::Ref(HeapType::kData, kNullable),
45971cb0ef41Sopenharmony_ci                                  this->module_) ||
45981cb0ef41Sopenharmony_ci                      obj.type.is_bottom())) {
45991cb0ef41Sopenharmony_ci          PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
46001cb0ef41Sopenharmony_ci          return 0;
46011cb0ef41Sopenharmony_ci        }
46021cb0ef41Sopenharmony_ci        Control* c = control_at(branch_depth.depth);
46031cb0ef41Sopenharmony_ci        if (c->br_merge()->arity == 0) {
46041cb0ef41Sopenharmony_ci          this->DecodeError(
46051cb0ef41Sopenharmony_ci              "br_on_cast must target a branch of arity at least 1");
46061cb0ef41Sopenharmony_ci          return 0;
46071cb0ef41Sopenharmony_ci        }
46081cb0ef41Sopenharmony_ci        // Attention: contrary to most other instructions, we modify the
46091cb0ef41Sopenharmony_ci        // stack before calling the interface function. This makes it
46101cb0ef41Sopenharmony_ci        // significantly more convenient to pass around the values that
46111cb0ef41Sopenharmony_ci        // will be on the stack when the branch is taken.
46121cb0ef41Sopenharmony_ci        // TODO(jkummerow): Reconsider this choice.
46131cb0ef41Sopenharmony_ci        Drop(2);  // {obj} and {rtt}.
46141cb0ef41Sopenharmony_ci        Value result_on_branch = CreateValue(
46151cb0ef41Sopenharmony_ci            rtt.type.is_bottom()
46161cb0ef41Sopenharmony_ci                ? kWasmBottom
46171cb0ef41Sopenharmony_ci                : ValueType::Ref(rtt.type.ref_index(), kNonNullable));
46181cb0ef41Sopenharmony_ci        Push(result_on_branch);
46191cb0ef41Sopenharmony_ci        // The {value_on_branch} parameter we pass to the interface must
46201cb0ef41Sopenharmony_ci        // be pointer-identical to the object on the stack, so we can't
46211cb0ef41Sopenharmony_ci        // reuse {result_on_branch} which was passed-by-value to {Push}.
46221cb0ef41Sopenharmony_ci        Value* value_on_branch = stack_value(1);
46231cb0ef41Sopenharmony_ci        if (!VALIDATE(TypeCheckBranch<true>(c, 0))) return 0;
46241cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
46251cb0ef41Sopenharmony_ci          // This logic ensures that code generation can assume that functions
46261cb0ef41Sopenharmony_ci          // can only be cast to function types, and data objects to data types.
46271cb0ef41Sopenharmony_ci          if (V8_UNLIKELY(TypeCheckAlwaysSucceeds(obj, rtt))) {
46281cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);  // rtt
46291cb0ef41Sopenharmony_ci            CALL_INTERFACE(Forward, obj, value_on_branch);
46301cb0ef41Sopenharmony_ci            // The branch will still not be taken on null.
46311cb0ef41Sopenharmony_ci            if (obj.type.is_nullable()) {
46321cb0ef41Sopenharmony_ci              CALL_INTERFACE(BrOnNonNull, obj, branch_depth.depth);
46331cb0ef41Sopenharmony_ci            } else {
46341cb0ef41Sopenharmony_ci              CALL_INTERFACE(BrOrRet, branch_depth.depth, 0);
46351cb0ef41Sopenharmony_ci              // We know that the following code is not reachable, but according
46361cb0ef41Sopenharmony_ci              // to the spec it technically is. Set it to spec-only reachable.
46371cb0ef41Sopenharmony_ci              SetSucceedingCodeDynamicallyUnreachable();
46381cb0ef41Sopenharmony_ci            }
46391cb0ef41Sopenharmony_ci            c->br_merge()->reached = true;
46401cb0ef41Sopenharmony_ci          } else if (V8_LIKELY(!TypeCheckAlwaysFails(obj, rtt))) {
46411cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnCast, obj, rtt, value_on_branch,
46421cb0ef41Sopenharmony_ci                           branch_depth.depth);
46431cb0ef41Sopenharmony_ci            c->br_merge()->reached = true;
46441cb0ef41Sopenharmony_ci          }
46451cb0ef41Sopenharmony_ci          // Otherwise the types are unrelated. Do not branch.
46461cb0ef41Sopenharmony_ci        }
46471cb0ef41Sopenharmony_ci
46481cb0ef41Sopenharmony_ci        Drop(result_on_branch);
46491cb0ef41Sopenharmony_ci        Push(obj);  // Restore stack state on fallthrough.
46501cb0ef41Sopenharmony_ci        return pc_offset;
46511cb0ef41Sopenharmony_ci      }
46521cb0ef41Sopenharmony_ci      case kExprBrOnCastFail:
46531cb0ef41Sopenharmony_ci      case kExprBrOnCastStaticFail: {
46541cb0ef41Sopenharmony_ci        NON_CONST_ONLY
46551cb0ef41Sopenharmony_ci        BranchDepthImmediate<validate> branch_depth(this,
46561cb0ef41Sopenharmony_ci                                                    this->pc_ + opcode_length);
46571cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, branch_depth,
46581cb0ef41Sopenharmony_ci                            control_.size())) {
46591cb0ef41Sopenharmony_ci          return 0;
46601cb0ef41Sopenharmony_ci        }
46611cb0ef41Sopenharmony_ci        uint32_t pc_offset = opcode_length + branch_depth.length;
46621cb0ef41Sopenharmony_ci        Value rtt = Peek(0);  // This is safe for the ...Static instruction.
46631cb0ef41Sopenharmony_ci        if (opcode == kExprBrOnCastStaticFail) {
46641cb0ef41Sopenharmony_ci          IndexImmediate<validate> imm(this, this->pc_ + pc_offset,
46651cb0ef41Sopenharmony_ci                                       "type index");
46661cb0ef41Sopenharmony_ci          if (!this->ValidateType(this->pc_ + opcode_length, imm)) return 0;
46671cb0ef41Sopenharmony_ci          pc_offset += imm.length;
46681cb0ef41Sopenharmony_ci          rtt = CreateValue(ValueType::Rtt(imm.index));
46691cb0ef41Sopenharmony_ci          CALL_INTERFACE_IF_OK_AND_REACHABLE(RttCanon, imm.index, &rtt);
46701cb0ef41Sopenharmony_ci          Push(rtt);
46711cb0ef41Sopenharmony_ci        } else {
46721cb0ef41Sopenharmony_ci          DCHECK_EQ(opcode, kExprBrOnCastFail);
46731cb0ef41Sopenharmony_ci          if (!VALIDATE(rtt.type.is_rtt() || rtt.type.is_bottom())) {
46741cb0ef41Sopenharmony_ci            PopTypeError(1, rtt, "rtt");
46751cb0ef41Sopenharmony_ci            return 0;
46761cb0ef41Sopenharmony_ci          }
46771cb0ef41Sopenharmony_ci        }
46781cb0ef41Sopenharmony_ci        Value obj = Peek(1);
46791cb0ef41Sopenharmony_ci        if (!VALIDATE(IsSubtypeOf(obj.type, kWasmFuncRef, this->module_) ||
46801cb0ef41Sopenharmony_ci                      IsSubtypeOf(obj.type,
46811cb0ef41Sopenharmony_ci                                  ValueType::Ref(HeapType::kData, kNullable),
46821cb0ef41Sopenharmony_ci                                  this->module_) ||
46831cb0ef41Sopenharmony_ci                      obj.type.is_bottom())) {
46841cb0ef41Sopenharmony_ci          PopTypeError(0, obj, "subtype of (ref null func) or (ref null data)");
46851cb0ef41Sopenharmony_ci          return 0;
46861cb0ef41Sopenharmony_ci        }
46871cb0ef41Sopenharmony_ci        Control* c = control_at(branch_depth.depth);
46881cb0ef41Sopenharmony_ci        if (c->br_merge()->arity == 0) {
46891cb0ef41Sopenharmony_ci          this->DecodeError(
46901cb0ef41Sopenharmony_ci              "br_on_cast_fail must target a branch of arity at least 1");
46911cb0ef41Sopenharmony_ci          return 0;
46921cb0ef41Sopenharmony_ci        }
46931cb0ef41Sopenharmony_ci        // Attention: contrary to most other instructions, we modify the stack
46941cb0ef41Sopenharmony_ci        // before calling the interface function. This makes it significantly
46951cb0ef41Sopenharmony_ci        // more convenient to pass around the values that will be on the stack
46961cb0ef41Sopenharmony_ci        // when the branch is taken. In this case, we leave {obj} on the stack
46971cb0ef41Sopenharmony_ci        // to type check the branch.
46981cb0ef41Sopenharmony_ci        // TODO(jkummerow): Reconsider this choice.
46991cb0ef41Sopenharmony_ci        Drop(rtt);
47001cb0ef41Sopenharmony_ci        if (!VALIDATE(TypeCheckBranch<true>(c, 0))) return 0;
47011cb0ef41Sopenharmony_ci        Value result_on_fallthrough = CreateValue(
47021cb0ef41Sopenharmony_ci            rtt.type.is_bottom()
47031cb0ef41Sopenharmony_ci                ? kWasmBottom
47041cb0ef41Sopenharmony_ci                : ValueType::Ref(rtt.type.ref_index(), kNonNullable));
47051cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
47061cb0ef41Sopenharmony_ci          // This logic ensures that code generation can assume that functions
47071cb0ef41Sopenharmony_ci          // can only be cast to function types, and data objects to data types.
47081cb0ef41Sopenharmony_ci          if (V8_UNLIKELY(TypeCheckAlwaysFails(obj, rtt))) {
47091cb0ef41Sopenharmony_ci            // Drop {rtt} in the interface.
47101cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);
47111cb0ef41Sopenharmony_ci            // Otherwise the types are unrelated. Always branch.
47121cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOrRet, branch_depth.depth, 0);
47131cb0ef41Sopenharmony_ci            // We know that the following code is not reachable, but according
47141cb0ef41Sopenharmony_ci            // to the spec it technically is. Set it to spec-only reachable.
47151cb0ef41Sopenharmony_ci            SetSucceedingCodeDynamicallyUnreachable();
47161cb0ef41Sopenharmony_ci            c->br_merge()->reached = true;
47171cb0ef41Sopenharmony_ci          } else if (V8_UNLIKELY(TypeCheckAlwaysSucceeds(obj, rtt))) {
47181cb0ef41Sopenharmony_ci            // Drop {rtt} in the interface.
47191cb0ef41Sopenharmony_ci            CALL_INTERFACE(Drop);
47201cb0ef41Sopenharmony_ci            // The branch can still be taken on null.
47211cb0ef41Sopenharmony_ci            if (obj.type.is_nullable()) {
47221cb0ef41Sopenharmony_ci              CALL_INTERFACE(BrOnNull, obj, branch_depth.depth, true,
47231cb0ef41Sopenharmony_ci                             &result_on_fallthrough);
47241cb0ef41Sopenharmony_ci              c->br_merge()->reached = true;
47251cb0ef41Sopenharmony_ci            } else {
47261cb0ef41Sopenharmony_ci              // Drop {obj} in the interface.
47271cb0ef41Sopenharmony_ci              CALL_INTERFACE(Drop);
47281cb0ef41Sopenharmony_ci            }
47291cb0ef41Sopenharmony_ci          } else {
47301cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnCastFail, obj, rtt, &result_on_fallthrough,
47311cb0ef41Sopenharmony_ci                           branch_depth.depth);
47321cb0ef41Sopenharmony_ci            c->br_merge()->reached = true;
47331cb0ef41Sopenharmony_ci          }
47341cb0ef41Sopenharmony_ci          // Otherwise, the type check always succeeds. Do not branch.
47351cb0ef41Sopenharmony_ci        }
47361cb0ef41Sopenharmony_ci        // Make sure the correct value is on the stack state on fallthrough.
47371cb0ef41Sopenharmony_ci        Drop(obj);
47381cb0ef41Sopenharmony_ci        Push(result_on_fallthrough);
47391cb0ef41Sopenharmony_ci        return pc_offset;
47401cb0ef41Sopenharmony_ci      }
47411cb0ef41Sopenharmony_ci#define ABSTRACT_TYPE_CHECK(h_type)                                            \
47421cb0ef41Sopenharmony_ci  case kExprRefIs##h_type: {                                                   \
47431cb0ef41Sopenharmony_ci    NON_CONST_ONLY                                                             \
47441cb0ef41Sopenharmony_ci    Value arg = Peek(0, 0, kWasmAnyRef);                                       \
47451cb0ef41Sopenharmony_ci    if (this->failed()) return 0;                                              \
47461cb0ef41Sopenharmony_ci    Value result = CreateValue(kWasmI32);                                      \
47471cb0ef41Sopenharmony_ci    if (V8_LIKELY(current_code_reachable_and_ok_)) {                           \
47481cb0ef41Sopenharmony_ci      if (IsHeapSubtypeOf(arg.type.heap_representation(), HeapType::k##h_type, \
47491cb0ef41Sopenharmony_ci                          this->module_)) {                                    \
47501cb0ef41Sopenharmony_ci        if (arg.type.is_nullable()) {                                          \
47511cb0ef41Sopenharmony_ci          /* We abuse ref.as_non_null, which isn't otherwise used as a unary   \
47521cb0ef41Sopenharmony_ci           * operator, as a sentinel for the negation of ref.is_null. */       \
47531cb0ef41Sopenharmony_ci          CALL_INTERFACE(UnOp, kExprRefAsNonNull, arg, &result);               \
47541cb0ef41Sopenharmony_ci        } else {                                                               \
47551cb0ef41Sopenharmony_ci          CALL_INTERFACE(Drop);                                                \
47561cb0ef41Sopenharmony_ci          CALL_INTERFACE(I32Const, &result, 1);                                \
47571cb0ef41Sopenharmony_ci        }                                                                      \
47581cb0ef41Sopenharmony_ci      } else if (!IsHeapSubtypeOf(HeapType::k##h_type,                         \
47591cb0ef41Sopenharmony_ci                                  arg.type.heap_representation(),              \
47601cb0ef41Sopenharmony_ci                                  this->module_)) {                            \
47611cb0ef41Sopenharmony_ci        CALL_INTERFACE(Drop);                                                  \
47621cb0ef41Sopenharmony_ci        CALL_INTERFACE(I32Const, &result, 0);                                  \
47631cb0ef41Sopenharmony_ci      } else {                                                                 \
47641cb0ef41Sopenharmony_ci        CALL_INTERFACE(RefIs##h_type, arg, &result);                           \
47651cb0ef41Sopenharmony_ci      }                                                                        \
47661cb0ef41Sopenharmony_ci    }                                                                          \
47671cb0ef41Sopenharmony_ci    Drop(arg);                                                                 \
47681cb0ef41Sopenharmony_ci    Push(result);                                                              \
47691cb0ef41Sopenharmony_ci    return opcode_length;                                                      \
47701cb0ef41Sopenharmony_ci  }
47711cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CHECK(Data)
47721cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CHECK(Func)
47731cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CHECK(I31)
47741cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CHECK(Array)
47751cb0ef41Sopenharmony_ci#undef ABSTRACT_TYPE_CHECK
47761cb0ef41Sopenharmony_ci
47771cb0ef41Sopenharmony_ci#define ABSTRACT_TYPE_CAST(h_type)                                             \
47781cb0ef41Sopenharmony_ci  case kExprRefAs##h_type: {                                                   \
47791cb0ef41Sopenharmony_ci    NON_CONST_ONLY                                                             \
47801cb0ef41Sopenharmony_ci    Value arg = Peek(0, 0, kWasmAnyRef);                                       \
47811cb0ef41Sopenharmony_ci    ValueType non_nullable_abstract_type =                                     \
47821cb0ef41Sopenharmony_ci        ValueType::Ref(HeapType::k##h_type, kNonNullable);                     \
47831cb0ef41Sopenharmony_ci    Value result = CreateValue(non_nullable_abstract_type);                    \
47841cb0ef41Sopenharmony_ci    if (V8_LIKELY(current_code_reachable_and_ok_)) {                           \
47851cb0ef41Sopenharmony_ci      if (IsHeapSubtypeOf(arg.type.heap_representation(), HeapType::k##h_type, \
47861cb0ef41Sopenharmony_ci                          this->module_)) {                                    \
47871cb0ef41Sopenharmony_ci        if (arg.type.is_nullable()) {                                          \
47881cb0ef41Sopenharmony_ci          CALL_INTERFACE(RefAsNonNull, arg, &result);                          \
47891cb0ef41Sopenharmony_ci        } else {                                                               \
47901cb0ef41Sopenharmony_ci          CALL_INTERFACE(Forward, arg, &result);                               \
47911cb0ef41Sopenharmony_ci        }                                                                      \
47921cb0ef41Sopenharmony_ci      } else if (!IsHeapSubtypeOf(HeapType::k##h_type,                         \
47931cb0ef41Sopenharmony_ci                                  arg.type.heap_representation(),              \
47941cb0ef41Sopenharmony_ci                                  this->module_)) {                            \
47951cb0ef41Sopenharmony_ci        CALL_INTERFACE(Trap, TrapReason::kTrapIllegalCast);                    \
47961cb0ef41Sopenharmony_ci        /* We know that the following code is not reachable, but according */  \
47971cb0ef41Sopenharmony_ci        /* to the spec it technically is. Set it to spec-only reachable. */    \
47981cb0ef41Sopenharmony_ci        SetSucceedingCodeDynamicallyUnreachable();                             \
47991cb0ef41Sopenharmony_ci      } else {                                                                 \
48001cb0ef41Sopenharmony_ci        CALL_INTERFACE(RefAs##h_type, arg, &result);                           \
48011cb0ef41Sopenharmony_ci      }                                                                        \
48021cb0ef41Sopenharmony_ci    }                                                                          \
48031cb0ef41Sopenharmony_ci    Drop(arg);                                                                 \
48041cb0ef41Sopenharmony_ci    Push(result);                                                              \
48051cb0ef41Sopenharmony_ci    return opcode_length;                                                      \
48061cb0ef41Sopenharmony_ci  }
48071cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CAST(Data)
48081cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CAST(Func)
48091cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CAST(I31)
48101cb0ef41Sopenharmony_ci        ABSTRACT_TYPE_CAST(Array)
48111cb0ef41Sopenharmony_ci#undef ABSTRACT_TYPE_CAST
48121cb0ef41Sopenharmony_ci
48131cb0ef41Sopenharmony_ci      case kExprBrOnData:
48141cb0ef41Sopenharmony_ci      case kExprBrOnFunc:
48151cb0ef41Sopenharmony_ci      case kExprBrOnArray:
48161cb0ef41Sopenharmony_ci      case kExprBrOnI31: {
48171cb0ef41Sopenharmony_ci        NON_CONST_ONLY
48181cb0ef41Sopenharmony_ci        BranchDepthImmediate<validate> branch_depth(this,
48191cb0ef41Sopenharmony_ci                                                    this->pc_ + opcode_length);
48201cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, branch_depth,
48211cb0ef41Sopenharmony_ci                            control_.size())) {
48221cb0ef41Sopenharmony_ci          return 0;
48231cb0ef41Sopenharmony_ci        }
48241cb0ef41Sopenharmony_ci
48251cb0ef41Sopenharmony_ci        Control* c = control_at(branch_depth.depth);
48261cb0ef41Sopenharmony_ci        if (c->br_merge()->arity == 0) {
48271cb0ef41Sopenharmony_ci          this->DecodeError("%s must target a branch of arity at least 1",
48281cb0ef41Sopenharmony_ci                            SafeOpcodeNameAt(this->pc_));
48291cb0ef41Sopenharmony_ci          return 0;
48301cb0ef41Sopenharmony_ci        }
48311cb0ef41Sopenharmony_ci
48321cb0ef41Sopenharmony_ci        // Attention: contrary to most other instructions, we modify the
48331cb0ef41Sopenharmony_ci        // stack before calling the interface function. This makes it
48341cb0ef41Sopenharmony_ci        // significantly more convenient to pass around the values that
48351cb0ef41Sopenharmony_ci        // will be on the stack when the branch is taken.
48361cb0ef41Sopenharmony_ci        // TODO(jkummerow): Reconsider this choice.
48371cb0ef41Sopenharmony_ci        Value obj = Peek(0, 0, kWasmAnyRef);
48381cb0ef41Sopenharmony_ci        Drop(obj);
48391cb0ef41Sopenharmony_ci        HeapType::Representation heap_type =
48401cb0ef41Sopenharmony_ci            opcode == kExprBrOnFunc
48411cb0ef41Sopenharmony_ci                ? HeapType::kFunc
48421cb0ef41Sopenharmony_ci                : opcode == kExprBrOnData
48431cb0ef41Sopenharmony_ci                      ? HeapType::kData
48441cb0ef41Sopenharmony_ci                      : opcode == kExprBrOnArray ? HeapType::kArray
48451cb0ef41Sopenharmony_ci                                                 : HeapType::kI31;
48461cb0ef41Sopenharmony_ci        Value result_on_branch =
48471cb0ef41Sopenharmony_ci            CreateValue(ValueType::Ref(heap_type, kNonNullable));
48481cb0ef41Sopenharmony_ci        Push(result_on_branch);
48491cb0ef41Sopenharmony_ci        if (!VALIDATE(TypeCheckBranch<true>(c, 0))) return 0;
48501cb0ef41Sopenharmony_ci        // The {value_on_branch} parameter we pass to the interface must be
48511cb0ef41Sopenharmony_ci        // pointer-identical to the object on the stack, so we can't reuse
48521cb0ef41Sopenharmony_ci        // {result_on_branch} which was passed-by-value to {Push}.
48531cb0ef41Sopenharmony_ci        Value* value_on_branch = stack_value(1);
48541cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
48551cb0ef41Sopenharmony_ci          if (opcode == kExprBrOnFunc) {
48561cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnFunc, obj, value_on_branch, branch_depth.depth);
48571cb0ef41Sopenharmony_ci          } else if (opcode == kExprBrOnData) {
48581cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnData, obj, value_on_branch, branch_depth.depth);
48591cb0ef41Sopenharmony_ci          } else if (opcode == kExprBrOnArray) {
48601cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnArray, obj, value_on_branch, branch_depth.depth);
48611cb0ef41Sopenharmony_ci          } else {
48621cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnI31, obj, value_on_branch, branch_depth.depth);
48631cb0ef41Sopenharmony_ci          }
48641cb0ef41Sopenharmony_ci          c->br_merge()->reached = true;
48651cb0ef41Sopenharmony_ci        }
48661cb0ef41Sopenharmony_ci        Drop(result_on_branch);
48671cb0ef41Sopenharmony_ci        Push(obj);  // Restore stack state on fallthrough.
48681cb0ef41Sopenharmony_ci        return opcode_length + branch_depth.length;
48691cb0ef41Sopenharmony_ci      }
48701cb0ef41Sopenharmony_ci      case kExprBrOnNonData:
48711cb0ef41Sopenharmony_ci      case kExprBrOnNonFunc:
48721cb0ef41Sopenharmony_ci      case kExprBrOnNonArray:
48731cb0ef41Sopenharmony_ci      case kExprBrOnNonI31: {
48741cb0ef41Sopenharmony_ci        NON_CONST_ONLY
48751cb0ef41Sopenharmony_ci        BranchDepthImmediate<validate> branch_depth(this,
48761cb0ef41Sopenharmony_ci                                                    this->pc_ + opcode_length);
48771cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, branch_depth,
48781cb0ef41Sopenharmony_ci                            control_.size())) {
48791cb0ef41Sopenharmony_ci          return 0;
48801cb0ef41Sopenharmony_ci        }
48811cb0ef41Sopenharmony_ci
48821cb0ef41Sopenharmony_ci        Control* c = control_at(branch_depth.depth);
48831cb0ef41Sopenharmony_ci        if (c->br_merge()->arity == 0) {
48841cb0ef41Sopenharmony_ci          this->DecodeError("%s must target a branch of arity at least 1",
48851cb0ef41Sopenharmony_ci                            SafeOpcodeNameAt(this->pc_));
48861cb0ef41Sopenharmony_ci          return 0;
48871cb0ef41Sopenharmony_ci        }
48881cb0ef41Sopenharmony_ci        if (!VALIDATE(TypeCheckBranch<true>(c, 0))) return 0;
48891cb0ef41Sopenharmony_ci
48901cb0ef41Sopenharmony_ci        Value obj = Peek(0, 0, kWasmAnyRef);
48911cb0ef41Sopenharmony_ci        HeapType::Representation heap_type =
48921cb0ef41Sopenharmony_ci            opcode == kExprBrOnNonFunc
48931cb0ef41Sopenharmony_ci                ? HeapType::kFunc
48941cb0ef41Sopenharmony_ci                : opcode == kExprBrOnNonData
48951cb0ef41Sopenharmony_ci                      ? HeapType::kData
48961cb0ef41Sopenharmony_ci                      : opcode == kExprBrOnNonArray ? HeapType::kArray
48971cb0ef41Sopenharmony_ci                                                    : HeapType::kI31;
48981cb0ef41Sopenharmony_ci        Value value_on_fallthrough =
48991cb0ef41Sopenharmony_ci            CreateValue(ValueType::Ref(heap_type, kNonNullable));
49001cb0ef41Sopenharmony_ci
49011cb0ef41Sopenharmony_ci        if (V8_LIKELY(current_code_reachable_and_ok_)) {
49021cb0ef41Sopenharmony_ci          if (opcode == kExprBrOnNonFunc) {
49031cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnNonFunc, obj, &value_on_fallthrough,
49041cb0ef41Sopenharmony_ci                           branch_depth.depth);
49051cb0ef41Sopenharmony_ci          } else if (opcode == kExprBrOnNonData) {
49061cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnNonData, obj, &value_on_fallthrough,
49071cb0ef41Sopenharmony_ci                           branch_depth.depth);
49081cb0ef41Sopenharmony_ci          } else if (opcode == kExprBrOnNonArray) {
49091cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnNonArray, obj, &value_on_fallthrough,
49101cb0ef41Sopenharmony_ci                           branch_depth.depth);
49111cb0ef41Sopenharmony_ci          } else {
49121cb0ef41Sopenharmony_ci            CALL_INTERFACE(BrOnNonI31, obj, &value_on_fallthrough,
49131cb0ef41Sopenharmony_ci                           branch_depth.depth);
49141cb0ef41Sopenharmony_ci          }
49151cb0ef41Sopenharmony_ci          c->br_merge()->reached = true;
49161cb0ef41Sopenharmony_ci        }
49171cb0ef41Sopenharmony_ci        Drop(obj);
49181cb0ef41Sopenharmony_ci        Push(value_on_fallthrough);
49191cb0ef41Sopenharmony_ci        return opcode_length + branch_depth.length;
49201cb0ef41Sopenharmony_ci      }
49211cb0ef41Sopenharmony_ci      default:
49221cb0ef41Sopenharmony_ci        this->DecodeError("invalid gc opcode: %x", opcode);
49231cb0ef41Sopenharmony_ci        return 0;
49241cb0ef41Sopenharmony_ci    }
49251cb0ef41Sopenharmony_ci  }
49261cb0ef41Sopenharmony_ci#undef NON_CONST_ONLY
49271cb0ef41Sopenharmony_ci
49281cb0ef41Sopenharmony_ci  uint32_t DecodeAtomicOpcode(WasmOpcode opcode, uint32_t opcode_length) {
49291cb0ef41Sopenharmony_ci    ValueType ret_type;
49301cb0ef41Sopenharmony_ci    const FunctionSig* sig = WasmOpcodes::Signature(opcode);
49311cb0ef41Sopenharmony_ci    if (!VALIDATE(sig != nullptr)) {
49321cb0ef41Sopenharmony_ci      this->DecodeError("invalid atomic opcode");
49331cb0ef41Sopenharmony_ci      return 0;
49341cb0ef41Sopenharmony_ci    }
49351cb0ef41Sopenharmony_ci    MachineType memtype;
49361cb0ef41Sopenharmony_ci    switch (opcode) {
49371cb0ef41Sopenharmony_ci#define CASE_ATOMIC_STORE_OP(Name, Type)          \
49381cb0ef41Sopenharmony_ci  case kExpr##Name: {                             \
49391cb0ef41Sopenharmony_ci    memtype = MachineType::Type();                \
49401cb0ef41Sopenharmony_ci    ret_type = kWasmVoid;                         \
49411cb0ef41Sopenharmony_ci    break; /* to generic mem access code below */ \
49421cb0ef41Sopenharmony_ci  }
49431cb0ef41Sopenharmony_ci      ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
49441cb0ef41Sopenharmony_ci#undef CASE_ATOMIC_OP
49451cb0ef41Sopenharmony_ci#define CASE_ATOMIC_OP(Name, Type)                \
49461cb0ef41Sopenharmony_ci  case kExpr##Name: {                             \
49471cb0ef41Sopenharmony_ci    memtype = MachineType::Type();                \
49481cb0ef41Sopenharmony_ci    ret_type = GetReturnType(sig);                \
49491cb0ef41Sopenharmony_ci    break; /* to generic mem access code below */ \
49501cb0ef41Sopenharmony_ci  }
49511cb0ef41Sopenharmony_ci      ATOMIC_OP_LIST(CASE_ATOMIC_OP)
49521cb0ef41Sopenharmony_ci#undef CASE_ATOMIC_OP
49531cb0ef41Sopenharmony_ci      case kExprAtomicFence: {
49541cb0ef41Sopenharmony_ci        byte zero =
49551cb0ef41Sopenharmony_ci            this->template read_u8<validate>(this->pc_ + opcode_length, "zero");
49561cb0ef41Sopenharmony_ci        if (!VALIDATE(zero == 0)) {
49571cb0ef41Sopenharmony_ci          this->DecodeError(this->pc_ + opcode_length,
49581cb0ef41Sopenharmony_ci                            "invalid atomic operand");
49591cb0ef41Sopenharmony_ci          return 0;
49601cb0ef41Sopenharmony_ci        }
49611cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(AtomicFence);
49621cb0ef41Sopenharmony_ci        return 1 + opcode_length;
49631cb0ef41Sopenharmony_ci      }
49641cb0ef41Sopenharmony_ci      default:
49651cb0ef41Sopenharmony_ci        this->DecodeError("invalid atomic opcode");
49661cb0ef41Sopenharmony_ci        return 0;
49671cb0ef41Sopenharmony_ci    }
49681cb0ef41Sopenharmony_ci
49691cb0ef41Sopenharmony_ci    MemoryAccessImmediate<validate> imm = MakeMemoryAccessImmediate(
49701cb0ef41Sopenharmony_ci        opcode_length, ElementSizeLog2Of(memtype.representation()));
49711cb0ef41Sopenharmony_ci    if (!this->Validate(this->pc_ + opcode_length, imm)) return false;
49721cb0ef41Sopenharmony_ci
49731cb0ef41Sopenharmony_ci    // TODO(10949): Fix this for memory64 (index type should be kWasmI64
49741cb0ef41Sopenharmony_ci    // then).
49751cb0ef41Sopenharmony_ci    CHECK(!this->module_->is_memory64);
49761cb0ef41Sopenharmony_ci    ArgVector args = PeekArgs(sig);
49771cb0ef41Sopenharmony_ci    if (ret_type == kWasmVoid) {
49781cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(AtomicOp, opcode, base::VectorOf(args),
49791cb0ef41Sopenharmony_ci                                         imm, nullptr);
49801cb0ef41Sopenharmony_ci      DropArgs(sig);
49811cb0ef41Sopenharmony_ci    } else {
49821cb0ef41Sopenharmony_ci      Value result = CreateValue(GetReturnType(sig));
49831cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(AtomicOp, opcode, base::VectorOf(args),
49841cb0ef41Sopenharmony_ci                                         imm, &result);
49851cb0ef41Sopenharmony_ci      DropArgs(sig);
49861cb0ef41Sopenharmony_ci      Push(result);
49871cb0ef41Sopenharmony_ci    }
49881cb0ef41Sopenharmony_ci    return opcode_length + imm.length;
49891cb0ef41Sopenharmony_ci  }
49901cb0ef41Sopenharmony_ci
49911cb0ef41Sopenharmony_ci  unsigned DecodeNumericOpcode(WasmOpcode opcode, uint32_t opcode_length) {
49921cb0ef41Sopenharmony_ci    const FunctionSig* sig = WasmOpcodes::Signature(opcode);
49931cb0ef41Sopenharmony_ci    switch (opcode) {
49941cb0ef41Sopenharmony_ci      case kExprI32SConvertSatF32:
49951cb0ef41Sopenharmony_ci      case kExprI32UConvertSatF32:
49961cb0ef41Sopenharmony_ci      case kExprI32SConvertSatF64:
49971cb0ef41Sopenharmony_ci      case kExprI32UConvertSatF64:
49981cb0ef41Sopenharmony_ci      case kExprI64SConvertSatF32:
49991cb0ef41Sopenharmony_ci      case kExprI64UConvertSatF32:
50001cb0ef41Sopenharmony_ci      case kExprI64SConvertSatF64:
50011cb0ef41Sopenharmony_ci      case kExprI64UConvertSatF64: {
50021cb0ef41Sopenharmony_ci        BuildSimpleOperator(opcode, sig);
50031cb0ef41Sopenharmony_ci        return opcode_length;
50041cb0ef41Sopenharmony_ci      }
50051cb0ef41Sopenharmony_ci      case kExprMemoryInit: {
50061cb0ef41Sopenharmony_ci        MemoryInitImmediate<validate> imm(this, this->pc_ + opcode_length);
50071cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
50081cb0ef41Sopenharmony_ci        ValueType mem_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
50091cb0ef41Sopenharmony_ci        Value size = Peek(0, 2, kWasmI32);
50101cb0ef41Sopenharmony_ci        Value offset = Peek(1, 1, kWasmI32);
50111cb0ef41Sopenharmony_ci        Value dst = Peek(2, 0, mem_type);
50121cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryInit, imm, dst, offset, size);
50131cb0ef41Sopenharmony_ci        Drop(3);
50141cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50151cb0ef41Sopenharmony_ci      }
50161cb0ef41Sopenharmony_ci      case kExprDataDrop: {
50171cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
50181cb0ef41Sopenharmony_ci                                     "data segment index");
50191cb0ef41Sopenharmony_ci        if (!this->ValidateDataSegment(this->pc_ + opcode_length, imm)) {
50201cb0ef41Sopenharmony_ci          return 0;
50211cb0ef41Sopenharmony_ci        }
50221cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(DataDrop, imm);
50231cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50241cb0ef41Sopenharmony_ci      }
50251cb0ef41Sopenharmony_ci      case kExprMemoryCopy: {
50261cb0ef41Sopenharmony_ci        MemoryCopyImmediate<validate> imm(this, this->pc_ + opcode_length);
50271cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
50281cb0ef41Sopenharmony_ci        ValueType mem_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
50291cb0ef41Sopenharmony_ci        Value size = Peek(0, 2, mem_type);
50301cb0ef41Sopenharmony_ci        Value src = Peek(1, 1, mem_type);
50311cb0ef41Sopenharmony_ci        Value dst = Peek(2, 0, mem_type);
50321cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryCopy, imm, dst, src, size);
50331cb0ef41Sopenharmony_ci        Drop(3);
50341cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50351cb0ef41Sopenharmony_ci      }
50361cb0ef41Sopenharmony_ci      case kExprMemoryFill: {
50371cb0ef41Sopenharmony_ci        MemoryIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
50381cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
50391cb0ef41Sopenharmony_ci        ValueType mem_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
50401cb0ef41Sopenharmony_ci        Value size = Peek(0, 2, mem_type);
50411cb0ef41Sopenharmony_ci        Value value = Peek(1, 1, kWasmI32);
50421cb0ef41Sopenharmony_ci        Value dst = Peek(2, 0, mem_type);
50431cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryFill, imm, dst, value, size);
50441cb0ef41Sopenharmony_ci        Drop(3);
50451cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50461cb0ef41Sopenharmony_ci      }
50471cb0ef41Sopenharmony_ci      case kExprTableInit: {
50481cb0ef41Sopenharmony_ci        TableInitImmediate<validate> imm(this, this->pc_ + opcode_length);
50491cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
50501cb0ef41Sopenharmony_ci        ArgVector args = PeekArgs(sig);
50511cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(TableInit, imm,
50521cb0ef41Sopenharmony_ci                                           base::VectorOf(args));
50531cb0ef41Sopenharmony_ci        DropArgs(sig);
50541cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50551cb0ef41Sopenharmony_ci      }
50561cb0ef41Sopenharmony_ci      case kExprElemDrop: {
50571cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
50581cb0ef41Sopenharmony_ci                                     "element segment index");
50591cb0ef41Sopenharmony_ci        if (!this->ValidateElementSegment(this->pc_ + opcode_length, imm)) {
50601cb0ef41Sopenharmony_ci          return 0;
50611cb0ef41Sopenharmony_ci        }
50621cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(ElemDrop, imm);
50631cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50641cb0ef41Sopenharmony_ci      }
50651cb0ef41Sopenharmony_ci      case kExprTableCopy: {
50661cb0ef41Sopenharmony_ci        TableCopyImmediate<validate> imm(this, this->pc_ + opcode_length);
50671cb0ef41Sopenharmony_ci        if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
50681cb0ef41Sopenharmony_ci        ArgVector args = PeekArgs(sig);
50691cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(TableCopy, imm,
50701cb0ef41Sopenharmony_ci                                           base::VectorOf(args));
50711cb0ef41Sopenharmony_ci        DropArgs(sig);
50721cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50731cb0ef41Sopenharmony_ci      }
50741cb0ef41Sopenharmony_ci      case kExprTableGrow: {
50751cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
50761cb0ef41Sopenharmony_ci                                     "table index");
50771cb0ef41Sopenharmony_ci        if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0;
50781cb0ef41Sopenharmony_ci        Value delta = Peek(0, 1, kWasmI32);
50791cb0ef41Sopenharmony_ci        Value value = Peek(1, 0, this->module_->tables[imm.index].type);
50801cb0ef41Sopenharmony_ci        Value result = CreateValue(kWasmI32);
50811cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(TableGrow, imm, value, delta,
50821cb0ef41Sopenharmony_ci                                           &result);
50831cb0ef41Sopenharmony_ci        Drop(2);
50841cb0ef41Sopenharmony_ci        Push(result);
50851cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50861cb0ef41Sopenharmony_ci      }
50871cb0ef41Sopenharmony_ci      case kExprTableSize: {
50881cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
50891cb0ef41Sopenharmony_ci                                     "table index");
50901cb0ef41Sopenharmony_ci        if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0;
50911cb0ef41Sopenharmony_ci        Value result = CreateValue(kWasmI32);
50921cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(TableSize, imm, &result);
50931cb0ef41Sopenharmony_ci        Push(result);
50941cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
50951cb0ef41Sopenharmony_ci      }
50961cb0ef41Sopenharmony_ci      case kExprTableFill: {
50971cb0ef41Sopenharmony_ci        IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
50981cb0ef41Sopenharmony_ci                                     "table index");
50991cb0ef41Sopenharmony_ci        if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0;
51001cb0ef41Sopenharmony_ci        Value count = Peek(0, 2, kWasmI32);
51011cb0ef41Sopenharmony_ci        Value value = Peek(1, 1, this->module_->tables[imm.index].type);
51021cb0ef41Sopenharmony_ci        Value start = Peek(2, 0, kWasmI32);
51031cb0ef41Sopenharmony_ci        CALL_INTERFACE_IF_OK_AND_REACHABLE(TableFill, imm, start, value, count);
51041cb0ef41Sopenharmony_ci        Drop(3);
51051cb0ef41Sopenharmony_ci        return opcode_length + imm.length;
51061cb0ef41Sopenharmony_ci      }
51071cb0ef41Sopenharmony_ci      default:
51081cb0ef41Sopenharmony_ci        this->DecodeError("invalid numeric opcode");
51091cb0ef41Sopenharmony_ci        return 0;
51101cb0ef41Sopenharmony_ci    }
51111cb0ef41Sopenharmony_ci  }
51121cb0ef41Sopenharmony_ci
51131cb0ef41Sopenharmony_ci  V8_INLINE void EnsureStackSpace(int slots_needed) {
51141cb0ef41Sopenharmony_ci    if (V8_LIKELY(stack_capacity_end_ - stack_end_ >= slots_needed)) return;
51151cb0ef41Sopenharmony_ci    GrowStackSpace(slots_needed);
51161cb0ef41Sopenharmony_ci  }
51171cb0ef41Sopenharmony_ci
51181cb0ef41Sopenharmony_ci  V8_NOINLINE void GrowStackSpace(int slots_needed) {
51191cb0ef41Sopenharmony_ci    size_t new_stack_capacity =
51201cb0ef41Sopenharmony_ci        std::max(size_t{8},
51211cb0ef41Sopenharmony_ci                 base::bits::RoundUpToPowerOfTwo(stack_size() + slots_needed));
51221cb0ef41Sopenharmony_ci    Value* new_stack =
51231cb0ef41Sopenharmony_ci        this->zone()->template NewArray<Value>(new_stack_capacity);
51241cb0ef41Sopenharmony_ci    if (stack_) {
51251cb0ef41Sopenharmony_ci      std::copy(stack_, stack_end_, new_stack);
51261cb0ef41Sopenharmony_ci      this->zone()->DeleteArray(stack_, stack_capacity_end_ - stack_);
51271cb0ef41Sopenharmony_ci    }
51281cb0ef41Sopenharmony_ci    stack_end_ = new_stack + (stack_end_ - stack_);
51291cb0ef41Sopenharmony_ci    stack_ = new_stack;
51301cb0ef41Sopenharmony_ci    stack_capacity_end_ = new_stack + new_stack_capacity;
51311cb0ef41Sopenharmony_ci  }
51321cb0ef41Sopenharmony_ci
51331cb0ef41Sopenharmony_ci  V8_INLINE Value CreateValue(ValueType type) { return Value{this->pc_, type}; }
51341cb0ef41Sopenharmony_ci  V8_INLINE void Push(Value value) {
51351cb0ef41Sopenharmony_ci    DCHECK_NE(kWasmVoid, value.type);
51361cb0ef41Sopenharmony_ci    // {EnsureStackSpace} should have been called before, either in the central
51371cb0ef41Sopenharmony_ci    // decoding loop, or individually if more than one element is pushed.
51381cb0ef41Sopenharmony_ci    DCHECK_GT(stack_capacity_end_, stack_end_);
51391cb0ef41Sopenharmony_ci    *stack_end_ = value;
51401cb0ef41Sopenharmony_ci    ++stack_end_;
51411cb0ef41Sopenharmony_ci  }
51421cb0ef41Sopenharmony_ci
51431cb0ef41Sopenharmony_ci  void PushMergeValues(Control* c, Merge<Value>* merge) {
51441cb0ef41Sopenharmony_ci    if (decoding_mode == kInitExpression) return;
51451cb0ef41Sopenharmony_ci    DCHECK_EQ(c, &control_.back());
51461cb0ef41Sopenharmony_ci    DCHECK(merge == &c->start_merge || merge == &c->end_merge);
51471cb0ef41Sopenharmony_ci    DCHECK_LE(stack_ + c->stack_depth, stack_end_);
51481cb0ef41Sopenharmony_ci    stack_end_ = stack_ + c->stack_depth;
51491cb0ef41Sopenharmony_ci    if (merge->arity == 1) {
51501cb0ef41Sopenharmony_ci      // {EnsureStackSpace} should have been called before in the central
51511cb0ef41Sopenharmony_ci      // decoding loop.
51521cb0ef41Sopenharmony_ci      DCHECK_GT(stack_capacity_end_, stack_end_);
51531cb0ef41Sopenharmony_ci      *stack_end_++ = merge->vals.first;
51541cb0ef41Sopenharmony_ci    } else {
51551cb0ef41Sopenharmony_ci      EnsureStackSpace(merge->arity);
51561cb0ef41Sopenharmony_ci      for (uint32_t i = 0; i < merge->arity; i++) {
51571cb0ef41Sopenharmony_ci        *stack_end_++ = merge->vals.array[i];
51581cb0ef41Sopenharmony_ci      }
51591cb0ef41Sopenharmony_ci    }
51601cb0ef41Sopenharmony_ci    DCHECK_EQ(c->stack_depth + merge->arity, stack_size());
51611cb0ef41Sopenharmony_ci  }
51621cb0ef41Sopenharmony_ci
51631cb0ef41Sopenharmony_ci  V8_INLINE ReturnVector CreateReturnValues(const FunctionSig* sig) {
51641cb0ef41Sopenharmony_ci    size_t return_count = sig->return_count();
51651cb0ef41Sopenharmony_ci    ReturnVector values(return_count);
51661cb0ef41Sopenharmony_ci    std::transform(sig->returns().begin(), sig->returns().end(), values.begin(),
51671cb0ef41Sopenharmony_ci                   [this](ValueType type) { return CreateValue(type); });
51681cb0ef41Sopenharmony_ci    return values;
51691cb0ef41Sopenharmony_ci  }
51701cb0ef41Sopenharmony_ci  V8_INLINE void PushReturns(ReturnVector values) {
51711cb0ef41Sopenharmony_ci    EnsureStackSpace(static_cast<int>(values.size()));
51721cb0ef41Sopenharmony_ci    for (Value& value : values) Push(value);
51731cb0ef41Sopenharmony_ci  }
51741cb0ef41Sopenharmony_ci
51751cb0ef41Sopenharmony_ci  // We do not inline these functions because doing so causes a large binary
51761cb0ef41Sopenharmony_ci  // size increase. Not inlining them should not create a performance
51771cb0ef41Sopenharmony_ci  // degradation, because their invocations are guarded by V8_LIKELY.
51781cb0ef41Sopenharmony_ci  V8_NOINLINE void PopTypeError(int index, Value val, const char* expected) {
51791cb0ef41Sopenharmony_ci    this->DecodeError(val.pc(), "%s[%d] expected %s, found %s of type %s",
51801cb0ef41Sopenharmony_ci                      SafeOpcodeNameAt(this->pc_), index, expected,
51811cb0ef41Sopenharmony_ci                      SafeOpcodeNameAt(val.pc()), val.type.name().c_str());
51821cb0ef41Sopenharmony_ci  }
51831cb0ef41Sopenharmony_ci
51841cb0ef41Sopenharmony_ci  V8_NOINLINE void PopTypeError(int index, Value val, std::string expected) {
51851cb0ef41Sopenharmony_ci    PopTypeError(index, val, expected.c_str());
51861cb0ef41Sopenharmony_ci  }
51871cb0ef41Sopenharmony_ci
51881cb0ef41Sopenharmony_ci  V8_NOINLINE void PopTypeError(int index, Value val, ValueType expected) {
51891cb0ef41Sopenharmony_ci    PopTypeError(index, val, ("type " + expected.name()).c_str());
51901cb0ef41Sopenharmony_ci  }
51911cb0ef41Sopenharmony_ci
51921cb0ef41Sopenharmony_ci  V8_NOINLINE void NotEnoughArgumentsError(int needed, int actual) {
51931cb0ef41Sopenharmony_ci    DCHECK_LT(0, needed);
51941cb0ef41Sopenharmony_ci    DCHECK_LE(0, actual);
51951cb0ef41Sopenharmony_ci    DCHECK_LT(actual, needed);
51961cb0ef41Sopenharmony_ci    this->DecodeError(
51971cb0ef41Sopenharmony_ci        "not enough arguments on the stack for %s (need %d, got %d)",
51981cb0ef41Sopenharmony_ci        SafeOpcodeNameAt(this->pc_), needed, actual);
51991cb0ef41Sopenharmony_ci  }
52001cb0ef41Sopenharmony_ci
52011cb0ef41Sopenharmony_ci  V8_INLINE Value Peek(int depth, int index, ValueType expected) {
52021cb0ef41Sopenharmony_ci    Value val = Peek(depth);
52031cb0ef41Sopenharmony_ci    if (!VALIDATE(IsSubtypeOf(val.type, expected, this->module_) ||
52041cb0ef41Sopenharmony_ci                  val.type == kWasmBottom || expected == kWasmBottom)) {
52051cb0ef41Sopenharmony_ci      PopTypeError(index, val, expected);
52061cb0ef41Sopenharmony_ci    }
52071cb0ef41Sopenharmony_ci    return val;
52081cb0ef41Sopenharmony_ci  }
52091cb0ef41Sopenharmony_ci
52101cb0ef41Sopenharmony_ci  V8_INLINE Value Peek(int depth) {
52111cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
52121cb0ef41Sopenharmony_ci    uint32_t limit = control_.back().stack_depth;
52131cb0ef41Sopenharmony_ci    if (V8_UNLIKELY(stack_size() <= limit + depth)) {
52141cb0ef41Sopenharmony_ci      // Peeking past the current control start in reachable code.
52151cb0ef41Sopenharmony_ci      if (!VALIDATE(decoding_mode == kFunctionBody &&
52161cb0ef41Sopenharmony_ci                    control_.back().unreachable())) {
52171cb0ef41Sopenharmony_ci        NotEnoughArgumentsError(depth + 1, stack_size() - limit);
52181cb0ef41Sopenharmony_ci      }
52191cb0ef41Sopenharmony_ci      return UnreachableValue(this->pc_);
52201cb0ef41Sopenharmony_ci    }
52211cb0ef41Sopenharmony_ci    DCHECK_LE(stack_, stack_end_ - depth - 1);
52221cb0ef41Sopenharmony_ci    return *(stack_end_ - depth - 1);
52231cb0ef41Sopenharmony_ci  }
52241cb0ef41Sopenharmony_ci
52251cb0ef41Sopenharmony_ci  V8_INLINE void ValidateArgType(ArgVector args, int index,
52261cb0ef41Sopenharmony_ci                                 ValueType expected) {
52271cb0ef41Sopenharmony_ci    Value val = args[index];
52281cb0ef41Sopenharmony_ci    if (!VALIDATE(IsSubtypeOf(val.type, expected, this->module_) ||
52291cb0ef41Sopenharmony_ci                  val.type == kWasmBottom || expected == kWasmBottom)) {
52301cb0ef41Sopenharmony_ci      PopTypeError(index, val, expected);
52311cb0ef41Sopenharmony_ci    }
52321cb0ef41Sopenharmony_ci  }
52331cb0ef41Sopenharmony_ci
52341cb0ef41Sopenharmony_ci  // Drop the top {count} stack elements, or all of them if less than {count}
52351cb0ef41Sopenharmony_ci  // are present.
52361cb0ef41Sopenharmony_ci  V8_INLINE void Drop(int count = 1) {
52371cb0ef41Sopenharmony_ci    DCHECK(!control_.empty());
52381cb0ef41Sopenharmony_ci    uint32_t limit = control_.back().stack_depth;
52391cb0ef41Sopenharmony_ci    if (V8_UNLIKELY(stack_size() < limit + count)) {
52401cb0ef41Sopenharmony_ci      // Pop what we can.
52411cb0ef41Sopenharmony_ci      count = std::min(count, static_cast<int>(stack_size() - limit));
52421cb0ef41Sopenharmony_ci    }
52431cb0ef41Sopenharmony_ci    DCHECK_LE(stack_, stack_end_ - count);
52441cb0ef41Sopenharmony_ci    stack_end_ -= count;
52451cb0ef41Sopenharmony_ci  }
52461cb0ef41Sopenharmony_ci  // Drop the top stack element if present. Takes a Value input for more
52471cb0ef41Sopenharmony_ci  // descriptive call sites.
52481cb0ef41Sopenharmony_ci  V8_INLINE void Drop(const Value& /* unused */) { Drop(1); }
52491cb0ef41Sopenharmony_ci
52501cb0ef41Sopenharmony_ci  enum StackElementsCountMode : bool {
52511cb0ef41Sopenharmony_ci    kNonStrictCounting = false,
52521cb0ef41Sopenharmony_ci    kStrictCounting = true
52531cb0ef41Sopenharmony_ci  };
52541cb0ef41Sopenharmony_ci
52551cb0ef41Sopenharmony_ci  enum MergeType {
52561cb0ef41Sopenharmony_ci    kBranchMerge,
52571cb0ef41Sopenharmony_ci    kReturnMerge,
52581cb0ef41Sopenharmony_ci    kFallthroughMerge,
52591cb0ef41Sopenharmony_ci    kInitExprMerge
52601cb0ef41Sopenharmony_ci  };
52611cb0ef41Sopenharmony_ci
52621cb0ef41Sopenharmony_ci  // - If the current code is reachable, check if the current stack values are
52631cb0ef41Sopenharmony_ci  //   compatible with {merge} based on their number and types. Disregard the
52641cb0ef41Sopenharmony_ci  //   first {drop_values} on the stack. If {strict_count}, check that
52651cb0ef41Sopenharmony_ci  //   #(stack elements) == {merge->arity}, otherwise
52661cb0ef41Sopenharmony_ci  //   #(stack elements) >= {merge->arity}.
52671cb0ef41Sopenharmony_ci  // - If the current code is unreachable, check if any values that may exist on
52681cb0ef41Sopenharmony_ci  //   top of the stack are compatible with {merge}. If {push_branch_values},
52691cb0ef41Sopenharmony_ci  //   push back to the stack values based on the type of {merge} (this is
52701cb0ef41Sopenharmony_ci  //   needed for conditional branches due to their typing rules, and
52711cb0ef41Sopenharmony_ci  //   fallthroughs so that the outer control finds the expected values on the
52721cb0ef41Sopenharmony_ci  //   stack). TODO(manoskouk): We expect the unreachable-code behavior to
52731cb0ef41Sopenharmony_ci  //   change, either due to relaxation of dead code verification, or the
52741cb0ef41Sopenharmony_ci  //   introduction of subtyping.
52751cb0ef41Sopenharmony_ci  template <StackElementsCountMode strict_count, bool push_branch_values,
52761cb0ef41Sopenharmony_ci            MergeType merge_type>
52771cb0ef41Sopenharmony_ci  bool TypeCheckStackAgainstMerge(uint32_t drop_values, Merge<Value>* merge) {
52781cb0ef41Sopenharmony_ci    static_assert(validate, "Call this function only within VALIDATE");
52791cb0ef41Sopenharmony_ci    constexpr const char* merge_description =
52801cb0ef41Sopenharmony_ci        merge_type == kBranchMerge
52811cb0ef41Sopenharmony_ci            ? "branch"
52821cb0ef41Sopenharmony_ci            : merge_type == kReturnMerge
52831cb0ef41Sopenharmony_ci                  ? "return"
52841cb0ef41Sopenharmony_ci                  : merge_type == kInitExprMerge ? "init. expression"
52851cb0ef41Sopenharmony_ci                                                 : "fallthru";
52861cb0ef41Sopenharmony_ci    uint32_t arity = merge->arity;
52871cb0ef41Sopenharmony_ci    uint32_t actual = stack_size() - control_.back().stack_depth;
52881cb0ef41Sopenharmony_ci    // Here we have to check for !unreachable(), because we need to typecheck as
52891cb0ef41Sopenharmony_ci    // if the current code is reachable even if it is spec-only reachable.
52901cb0ef41Sopenharmony_ci    if (V8_LIKELY(decoding_mode == kInitExpression ||
52911cb0ef41Sopenharmony_ci                  !control_.back().unreachable())) {
52921cb0ef41Sopenharmony_ci      if (V8_UNLIKELY(strict_count ? actual != drop_values + arity
52931cb0ef41Sopenharmony_ci                                   : actual < drop_values + arity)) {
52941cb0ef41Sopenharmony_ci        this->DecodeError("expected %u elements on the stack for %s, found %u",
52951cb0ef41Sopenharmony_ci                          arity, merge_description,
52961cb0ef41Sopenharmony_ci                          actual >= drop_values ? actual - drop_values : 0);
52971cb0ef41Sopenharmony_ci        return false;
52981cb0ef41Sopenharmony_ci      }
52991cb0ef41Sopenharmony_ci      // Typecheck the topmost {merge->arity} values on the stack.
53001cb0ef41Sopenharmony_ci      Value* stack_values = stack_end_ - (arity + drop_values);
53011cb0ef41Sopenharmony_ci      for (uint32_t i = 0; i < arity; ++i) {
53021cb0ef41Sopenharmony_ci        Value& val = stack_values[i];
53031cb0ef41Sopenharmony_ci        Value& old = (*merge)[i];
53041cb0ef41Sopenharmony_ci        if (!IsSubtypeOf(val.type, old.type, this->module_)) {
53051cb0ef41Sopenharmony_ci          this->DecodeError("type error in %s[%u] (expected %s, got %s)",
53061cb0ef41Sopenharmony_ci                            merge_description, i, old.type.name().c_str(),
53071cb0ef41Sopenharmony_ci                            val.type.name().c_str());
53081cb0ef41Sopenharmony_ci          return false;
53091cb0ef41Sopenharmony_ci        }
53101cb0ef41Sopenharmony_ci      }
53111cb0ef41Sopenharmony_ci      return true;
53121cb0ef41Sopenharmony_ci    }
53131cb0ef41Sopenharmony_ci    // Unreachable code validation starts here.
53141cb0ef41Sopenharmony_ci    if (V8_UNLIKELY(strict_count && actual > drop_values + arity)) {
53151cb0ef41Sopenharmony_ci      this->DecodeError("expected %u elements on the stack for %s, found %u",
53161cb0ef41Sopenharmony_ci                        arity, merge_description,
53171cb0ef41Sopenharmony_ci                        actual >= drop_values ? actual - drop_values : 0);
53181cb0ef41Sopenharmony_ci      return false;
53191cb0ef41Sopenharmony_ci    }
53201cb0ef41Sopenharmony_ci    // TODO(manoskouk): Use similar code as above if we keep unreachable checks.
53211cb0ef41Sopenharmony_ci    for (int i = arity - 1, depth = drop_values; i >= 0; --i, ++depth) {
53221cb0ef41Sopenharmony_ci      Peek(depth, i, (*merge)[i].type);
53231cb0ef41Sopenharmony_ci    }
53241cb0ef41Sopenharmony_ci    if (push_branch_values) {
53251cb0ef41Sopenharmony_ci      uint32_t inserted_value_count =
53261cb0ef41Sopenharmony_ci          static_cast<uint32_t>(EnsureStackArguments(drop_values + arity));
53271cb0ef41Sopenharmony_ci      if (inserted_value_count > 0) {
53281cb0ef41Sopenharmony_ci        // EnsureStackSpace may have inserted unreachable values into the bottom
53291cb0ef41Sopenharmony_ci        // of the stack. If so, mark them with the correct type. If drop values
53301cb0ef41Sopenharmony_ci        // were also inserted, disregard them, as they will be dropped anyway.
53311cb0ef41Sopenharmony_ci        Value* stack_base = stack_value(drop_values + arity);
53321cb0ef41Sopenharmony_ci        for (uint32_t i = 0; i < std::min(arity, inserted_value_count); i++) {
53331cb0ef41Sopenharmony_ci          if (stack_base[i].type == kWasmBottom) {
53341cb0ef41Sopenharmony_ci            stack_base[i].type = (*merge)[i].type;
53351cb0ef41Sopenharmony_ci          }
53361cb0ef41Sopenharmony_ci        }
53371cb0ef41Sopenharmony_ci      }
53381cb0ef41Sopenharmony_ci    }
53391cb0ef41Sopenharmony_ci    return this->ok();
53401cb0ef41Sopenharmony_ci  }
53411cb0ef41Sopenharmony_ci
53421cb0ef41Sopenharmony_ci  template <StackElementsCountMode strict_count, MergeType merge_type>
53431cb0ef41Sopenharmony_ci  bool DoReturn() {
53441cb0ef41Sopenharmony_ci    if (!VALIDATE((TypeCheckStackAgainstMerge<strict_count, false, merge_type>(
53451cb0ef41Sopenharmony_ci            0, &control_.front().end_merge)))) {
53461cb0ef41Sopenharmony_ci      return false;
53471cb0ef41Sopenharmony_ci    }
53481cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(current_code_reachable_and_ok_,
53491cb0ef41Sopenharmony_ci                   stack_size() >= this->sig_->return_count());
53501cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(DoReturn, 0);
53511cb0ef41Sopenharmony_ci    EndControl();
53521cb0ef41Sopenharmony_ci    return true;
53531cb0ef41Sopenharmony_ci  }
53541cb0ef41Sopenharmony_ci
53551cb0ef41Sopenharmony_ci  int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
53561cb0ef41Sopenharmony_ci
53571cb0ef41Sopenharmony_ci  void FallThrough() {
53581cb0ef41Sopenharmony_ci    Control* c = &control_.back();
53591cb0ef41Sopenharmony_ci    DCHECK_NE(c->kind, kControlLoop);
53601cb0ef41Sopenharmony_ci    if (!VALIDATE(TypeCheckFallThru())) return;
53611cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(FallThruTo, c);
53621cb0ef41Sopenharmony_ci    if (c->reachable()) c->end_merge.reached = true;
53631cb0ef41Sopenharmony_ci  }
53641cb0ef41Sopenharmony_ci
53651cb0ef41Sopenharmony_ci  bool TypeCheckOneArmedIf(Control* c) {
53661cb0ef41Sopenharmony_ci    static_assert(validate, "Call this function only within VALIDATE");
53671cb0ef41Sopenharmony_ci    DCHECK(c->is_onearmed_if());
53681cb0ef41Sopenharmony_ci    if (c->end_merge.arity != c->start_merge.arity) {
53691cb0ef41Sopenharmony_ci      this->DecodeError(c->pc(),
53701cb0ef41Sopenharmony_ci                        "start-arity and end-arity of one-armed if must match");
53711cb0ef41Sopenharmony_ci      return false;
53721cb0ef41Sopenharmony_ci    }
53731cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < c->start_merge.arity; ++i) {
53741cb0ef41Sopenharmony_ci      Value& start = c->start_merge[i];
53751cb0ef41Sopenharmony_ci      Value& end = c->end_merge[i];
53761cb0ef41Sopenharmony_ci      if (!IsSubtypeOf(start.type, end.type, this->module_)) {
53771cb0ef41Sopenharmony_ci        this->DecodeError("type error in merge[%u] (expected %s, got %s)", i,
53781cb0ef41Sopenharmony_ci                          end.type.name().c_str(), start.type.name().c_str());
53791cb0ef41Sopenharmony_ci        return false;
53801cb0ef41Sopenharmony_ci      }
53811cb0ef41Sopenharmony_ci    }
53821cb0ef41Sopenharmony_ci    return true;
53831cb0ef41Sopenharmony_ci  }
53841cb0ef41Sopenharmony_ci
53851cb0ef41Sopenharmony_ci  bool TypeCheckFallThru() {
53861cb0ef41Sopenharmony_ci    static_assert(validate, "Call this function only within VALIDATE");
53871cb0ef41Sopenharmony_ci    return TypeCheckStackAgainstMerge<kStrictCounting, true, kFallthroughMerge>(
53881cb0ef41Sopenharmony_ci        0, &control_.back().end_merge);
53891cb0ef41Sopenharmony_ci  }
53901cb0ef41Sopenharmony_ci
53911cb0ef41Sopenharmony_ci  // If the current code is reachable, check if the current stack values are
53921cb0ef41Sopenharmony_ci  // compatible with a jump to {c}, based on their number and types.
53931cb0ef41Sopenharmony_ci  // Otherwise, we have a polymorphic stack: check if any values that may exist
53941cb0ef41Sopenharmony_ci  // on top of the stack are compatible with {c}. If {push_branch_values},
53951cb0ef41Sopenharmony_ci  // push back to the stack values based on the type of {c} (this is needed for
53961cb0ef41Sopenharmony_ci  // conditional branches due to their typing rules, and fallthroughs so that
53971cb0ef41Sopenharmony_ci  // the outer control finds enough values on the stack).
53981cb0ef41Sopenharmony_ci  // {drop_values} is the number of stack values that will be dropped before the
53991cb0ef41Sopenharmony_ci  // branch is taken. This is currently 1 for for br (condition), br_table
54001cb0ef41Sopenharmony_ci  // (index) and br_on_null (reference), and 0 for all other branches.
54011cb0ef41Sopenharmony_ci  template <bool push_branch_values>
54021cb0ef41Sopenharmony_ci  bool TypeCheckBranch(Control* c, uint32_t drop_values) {
54031cb0ef41Sopenharmony_ci    static_assert(validate, "Call this function only within VALIDATE");
54041cb0ef41Sopenharmony_ci    return TypeCheckStackAgainstMerge<kNonStrictCounting, push_branch_values,
54051cb0ef41Sopenharmony_ci                                      kBranchMerge>(drop_values, c->br_merge());
54061cb0ef41Sopenharmony_ci  }
54071cb0ef41Sopenharmony_ci
54081cb0ef41Sopenharmony_ci  void onFirstError() override {
54091cb0ef41Sopenharmony_ci    this->end_ = this->pc_;  // Terminate decoding loop.
54101cb0ef41Sopenharmony_ci    this->current_code_reachable_and_ok_ = false;
54111cb0ef41Sopenharmony_ci    TRACE(" !%s\n", this->error_.message().c_str());
54121cb0ef41Sopenharmony_ci    // Cannot use CALL_INTERFACE_* macros because we emitted an error.
54131cb0ef41Sopenharmony_ci    interface().OnFirstError(this);
54141cb0ef41Sopenharmony_ci  }
54151cb0ef41Sopenharmony_ci
54161cb0ef41Sopenharmony_ci  int BuildSimplePrototypeOperator(WasmOpcode opcode) {
54171cb0ef41Sopenharmony_ci    if (opcode == kExprRefEq) {
54181cb0ef41Sopenharmony_ci      CHECK_PROTOTYPE_OPCODE(gc);
54191cb0ef41Sopenharmony_ci    }
54201cb0ef41Sopenharmony_ci    const FunctionSig* sig = WasmOpcodes::Signature(opcode);
54211cb0ef41Sopenharmony_ci    return BuildSimpleOperator(opcode, sig);
54221cb0ef41Sopenharmony_ci  }
54231cb0ef41Sopenharmony_ci
54241cb0ef41Sopenharmony_ci  int BuildSimpleOperator(WasmOpcode opcode, const FunctionSig* sig) {
54251cb0ef41Sopenharmony_ci    DCHECK_GE(1, sig->return_count());
54261cb0ef41Sopenharmony_ci    if (sig->parameter_count() == 1) {
54271cb0ef41Sopenharmony_ci      // All current simple unary operators have exactly 1 return value.
54281cb0ef41Sopenharmony_ci      DCHECK_EQ(1, sig->return_count());
54291cb0ef41Sopenharmony_ci      return BuildSimpleOperator(opcode, sig->GetReturn(0), sig->GetParam(0));
54301cb0ef41Sopenharmony_ci    } else {
54311cb0ef41Sopenharmony_ci      DCHECK_EQ(2, sig->parameter_count());
54321cb0ef41Sopenharmony_ci      ValueType ret = sig->return_count() == 0 ? kWasmVoid : sig->GetReturn(0);
54331cb0ef41Sopenharmony_ci      return BuildSimpleOperator(opcode, ret, sig->GetParam(0),
54341cb0ef41Sopenharmony_ci                                 sig->GetParam(1));
54351cb0ef41Sopenharmony_ci    }
54361cb0ef41Sopenharmony_ci  }
54371cb0ef41Sopenharmony_ci
54381cb0ef41Sopenharmony_ci  int BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
54391cb0ef41Sopenharmony_ci                          ValueType arg_type) {
54401cb0ef41Sopenharmony_ci    DCHECK_NE(kWasmVoid, return_type);
54411cb0ef41Sopenharmony_ci    Value val = Peek(0, 0, arg_type);
54421cb0ef41Sopenharmony_ci    Value ret = CreateValue(return_type);
54431cb0ef41Sopenharmony_ci    CALL_INTERFACE_IF_OK_AND_REACHABLE(UnOp, opcode, val, &ret);
54441cb0ef41Sopenharmony_ci    Drop(val);
54451cb0ef41Sopenharmony_ci    Push(ret);
54461cb0ef41Sopenharmony_ci    return 1;
54471cb0ef41Sopenharmony_ci  }
54481cb0ef41Sopenharmony_ci
54491cb0ef41Sopenharmony_ci  int BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
54501cb0ef41Sopenharmony_ci                          ValueType lhs_type, ValueType rhs_type) {
54511cb0ef41Sopenharmony_ci    Value rval = Peek(0, 1, rhs_type);
54521cb0ef41Sopenharmony_ci    Value lval = Peek(1, 0, lhs_type);
54531cb0ef41Sopenharmony_ci    if (return_type == kWasmVoid) {
54541cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(BinOp, opcode, lval, rval, nullptr);
54551cb0ef41Sopenharmony_ci      Drop(2);
54561cb0ef41Sopenharmony_ci    } else {
54571cb0ef41Sopenharmony_ci      Value ret = CreateValue(return_type);
54581cb0ef41Sopenharmony_ci      CALL_INTERFACE_IF_OK_AND_REACHABLE(BinOp, opcode, lval, rval, &ret);
54591cb0ef41Sopenharmony_ci      Drop(2);
54601cb0ef41Sopenharmony_ci      Push(ret);
54611cb0ef41Sopenharmony_ci    }
54621cb0ef41Sopenharmony_ci    return 1;
54631cb0ef41Sopenharmony_ci  }
54641cb0ef41Sopenharmony_ci
54651cb0ef41Sopenharmony_ci#define DEFINE_SIMPLE_SIG_OPERATOR(sig, ...)         \
54661cb0ef41Sopenharmony_ci  int BuildSimpleOperator_##sig(WasmOpcode opcode) { \
54671cb0ef41Sopenharmony_ci    return BuildSimpleOperator(opcode, __VA_ARGS__); \
54681cb0ef41Sopenharmony_ci  }
54691cb0ef41Sopenharmony_ci  FOREACH_SIGNATURE(DEFINE_SIMPLE_SIG_OPERATOR)
54701cb0ef41Sopenharmony_ci#undef DEFINE_SIMPLE_SIG_OPERATOR
54711cb0ef41Sopenharmony_ci};
54721cb0ef41Sopenharmony_ci
54731cb0ef41Sopenharmony_ciclass EmptyInterface {
54741cb0ef41Sopenharmony_ci public:
54751cb0ef41Sopenharmony_ci  static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
54761cb0ef41Sopenharmony_ci  static constexpr DecodingMode decoding_mode = kFunctionBody;
54771cb0ef41Sopenharmony_ci  using Value = ValueBase<validate>;
54781cb0ef41Sopenharmony_ci  using Control = ControlBase<Value, validate>;
54791cb0ef41Sopenharmony_ci  using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
54801cb0ef41Sopenharmony_ci
54811cb0ef41Sopenharmony_ci#define DEFINE_EMPTY_CALLBACK(name, ...) \
54821cb0ef41Sopenharmony_ci  void name(FullDecoder* decoder, ##__VA_ARGS__) {}
54831cb0ef41Sopenharmony_ci  INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
54841cb0ef41Sopenharmony_ci#undef DEFINE_EMPTY_CALLBACK
54851cb0ef41Sopenharmony_ci};
54861cb0ef41Sopenharmony_ci
54871cb0ef41Sopenharmony_ci#undef CALL_INTERFACE_IF_OK_AND_REACHABLE
54881cb0ef41Sopenharmony_ci#undef CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE
54891cb0ef41Sopenharmony_ci#undef TRACE
54901cb0ef41Sopenharmony_ci#undef TRACE_INST_FORMAT
54911cb0ef41Sopenharmony_ci#undef VALIDATE
54921cb0ef41Sopenharmony_ci#undef CHECK_PROTOTYPE_OPCODE
54931cb0ef41Sopenharmony_ci
54941cb0ef41Sopenharmony_ci}  // namespace wasm
54951cb0ef41Sopenharmony_ci}  // namespace internal
54961cb0ef41Sopenharmony_ci}  // namespace v8
54971cb0ef41Sopenharmony_ci
54981cb0ef41Sopenharmony_ci#endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
5499