/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
*
* Copyright 2016 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "wasm/WasmValidate.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Span.h"
#include "mozilla/Utf8.h"
#include "js/Printf.h"
#include "js/String.h" // JS::MaxStringLength
#include "vm/JSContext.h"
#include "vm/Realm.h"
#include "wasm/WasmDump.h"
#include "wasm/WasmInitExpr.h"
#include "wasm/WasmOpIter.h"
#include "wasm/WasmTypeDecls.h"
using namespace js;
using namespace js::jit;
using namespace js::wasm;
using mozilla::AsChars;
using mozilla::CheckedInt;
using mozilla::IsUtf8;
using mozilla::Maybe;
using mozilla::Nothing;
using mozilla::Some;
using mozilla::Span;
// Misc helpers.
bool wasm::EncodeLocalEntries(Encoder& e,
const ValTypeVector& locals) {
if (locals.length() > MaxLocals) {
return false;
}
uint32_t numLocalEntries = 0;
if (locals.length()) {
ValType prev = locals[0];
numLocalEntries++;
for (ValType t : locals) {
if (t != prev) {
numLocalEntries++;
prev = t;
}
}
}
if (!e.writeVarU32(numLocalEntries)) {
return false;
}
if (numLocalEntries) {
ValType prev = locals[0];
uint32_t count = 1;
for (uint32_t i = 1; i < locals.length(); i++, count++) {
if (prev != locals[i]) {
if (!e.writeVarU32(count)) {
return false;
}
if (!e.writeValType(prev)) {
return false;
}
prev = locals[i];
count = 0;
}
}
if (!e.writeVarU32(count)) {
return false;
}
if (!e.writeValType(prev)) {
return false;
}
}
return true;
}
bool wasm::DecodeLocalEntriesWithParams(Decoder& d,
const CodeMetadata& codeMeta,
uint32_t funcIndex,
ValTypeVector* locals) {
uint32_t numLocalEntries;
if (!d.readVarU32(&numLocalEntries)) {
return d.fail(
"failed to read number of local entries");
}
if (!locals->appendAll(codeMeta.getFuncType(funcIndex).args())) {
return false;
}
for (uint32_t i = 0; i < numLocalEntries; i++) {
uint32_t count;
if (!d.readVarU32(&count)) {
return d.fail(
"failed to read local entry count");
}
if (MaxLocals - locals->length() < count) {
return d.fail(
"too many locals");
}
ValType type;
if (!d.readValType(*codeMeta.types, codeMeta.features(), &type)) {
return false;
}
if (!locals->appendN(type, count)) {
return false;
}
}
return true;
}
bool wasm::DecodeValidatedLocalEntries(
const TypeContext& types, Decoder& d,
ValTypeVector* locals) {
uint32_t numLocalEntries;
MOZ_ALWAYS_TRUE(d.readVarU32(&numLocalEntries));
for (uint32_t i = 0; i < numLocalEntries; i++) {
uint32_t count = d.uncheckedReadVarU32();
MOZ_ASSERT(MaxLocals - locals->length() >= count);
if (!locals->appendN(d.uncheckedReadValType(types), count)) {
return false;
}
}
return true;
}
bool wasm::CheckIsSubtypeOf(Decoder& d,
const CodeMetadata& codeMeta,
size_t opcodeOffset, ResultType subType,
ResultType superType) {
if (subType.length() != superType.length()) {
UniqueChars error(
JS_smprintf(
"type mismatch: expected %zu values, got %zu values",
superType.length(), subType.length()));
if (!error) {
return false;
}
MOZ_ASSERT(!ResultType::isSubTypeOf(subType, superType));
return d.fail(opcodeOffset, error.get());
}
for (uint32_t i = 0; i < subType.length(); i++) {
StorageType sub = subType[i].storageType();
StorageType super = superType[i].storageType();
if (!CheckIsSubtypeOf(d, codeMeta, opcodeOffset, sub, super)) {
MOZ_ASSERT(!ResultType::isSubTypeOf(subType, superType));
return false;
}
}
MOZ_ASSERT(ResultType::isSubTypeOf(subType, superType));
return true;
}
bool wasm::CheckIsSubtypeOf(Decoder& d,
const CodeMetadata& codeMeta,
size_t opcodeOffset, StorageType subType,
StorageType superType) {
if (StorageType::isSubTypeOf(subType, superType)) {
return true;
}
UniqueChars subText = ToString(subType, codeMeta.types);
if (!subText) {
return false;
}
UniqueChars superText = ToString(superType, codeMeta.types);
if (!superText) {
return false;
}
UniqueChars error(
JS_smprintf(
"type mismatch: expression has type %s but expected %s",
subText.get(), superText.get()));
if (!error) {
return false;
}
return d.fail(opcodeOffset, error.get());
}
// Function body validation.
struct NopOpDumper {
void dumpOpBegin(OpBytes op) {}
void dumpOpEnd() {}
void dumpTypeIndex(uint32_t typeIndex) {}
void dumpFuncIndex(uint32_t funcIndex) {}
void dumpTableIndex(uint32_t tableIndex) {}
void dumpGlobalIndex(uint32_t globalIndex) {}
void dumpMemoryIndex(uint32_t memoryIndex) {}
void dumpElemIndex(uint32_t elemIndex) {}
void dumpDataIndex(uint32_t dataIndex) {}
void dumpTagIndex(uint32_t tagIndex) {}
void dumpLocalIndex(uint32_t localIndex) {}
void dumpResultType(ResultType type) {}
void dumpI32Const(int32_t constant) {}
void dumpI64Const(int64_t constant) {}
void dumpF32Const(
float constant) {}
void dumpF64Const(
double constant) {}
void dumpV128Const(V128 constant) {}
void dumpVectorMask(V128 mask) {}
void dumpRefType(RefType type) {}
void dumpValType(ValType type) {}
void dumpTryTableCatches(
const TryTableCatchVector& catches) {}
void dumpLinearMemoryAddress(LinearMemoryAddress<Nothing> addr) {}
void dumpBlockDepth(uint32_t relativeDepth) {}
void dumpBlockDepths(
const Uint32Vector& relativeDepths) {}
void dumpFieldIndex(uint32_t fieldIndex) {}
void dumpNumElements(uint32_t numElements) {}
void dumpLaneIndex(uint32_t laneIndex) {}
};
#ifdef DEBUG
struct OpDumper {
IndentedPrinter& out;
explicit OpDumper(IndentedPrinter& out) : out(out) {}
void dumpOpBegin(OpBytes op) { out.put(op.toString()); }
void dumpOpEnd() { out.put(
"\n"); }
void dumpTypeIndex(uint32_t typeIndex) { out.printf(
" %" PRIu32, typeIndex); }
void dumpFuncIndex(uint32_t funcIndex) { out.printf(
" %" PRIu32, funcIndex); }
void dumpTableIndex(uint32_t tableIndex) {
out.printf(
" %" PRIu32, tableIndex);
}
void dumpGlobalIndex(uint32_t globalIndex) {
out.printf(
" %" PRIu32, globalIndex);
}
void dumpMemoryIndex(uint32_t memoryIndex) {
out.printf(
" %" PRIu32, memoryIndex);
}
void dumpElemIndex(uint32_t elemIndex) { out.printf(
" %" PRIu32, elemIndex); }
void dumpDataIndex(uint32_t dataIndex) { out.printf(
" %" PRIu32, dataIndex); }
void dumpTagIndex(uint32_t tagIndex) { out.printf(
" %" PRIu32, tagIndex); }
void dumpLocalIndex(uint32_t localIndex) {
out.printf(
" %" PRIu32, localIndex);
}
void dumpResultType(ResultType type) {
for (uint32_t i = 0; i < type.length(); i++) {
dumpValType(type[i]);
}
}
void dumpI32Const(int32_t constant) { out.printf(
" %" PRId32, constant); }
void dumpI64Const(int64_t constant) { out.printf(
" %" PRId64, constant); }
void dumpF32Const(
float constant) { out.printf(
" %f", constant); }
void dumpF64Const(
double constant) { out.printf(
" %lf", constant); }
void dumpV128Const(V128 constant) {
out.printf(
"i8x16 %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
constant.bytes[0], constant.bytes[1], constant.bytes[2],
constant.bytes[3], constant.bytes[4], constant.bytes[5],
constant.bytes[6], constant.bytes[7], constant.bytes[8],
constant.bytes[9], constant.bytes[10], constant.bytes[11],
constant.bytes[12], constant.bytes[13], constant.bytes[14],
constant.bytes[15]);
}
void dumpVectorMask(V128 mask) {
out.printf(
"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", mask.bytes[0],
mask.bytes[1], mask.bytes[2], mask.bytes[3], mask.bytes[4],
mask.bytes[5], mask.bytes[6], mask.bytes[7], mask.bytes[8],
mask.bytes[9], mask.bytes[10], mask.bytes[11], mask.bytes[12],
mask.bytes[13], mask.bytes[14], mask.bytes[15]);
}
void dumpRefType(RefType type) {
out.put(
" ");
wasm::Dump(type, out);
}
void dumpValType(ValType type) {
out.put(
" ");
wasm::Dump(type, out);
}
void dumpTryTableCatches(
const TryTableCatchVector& catches) {
for (uint32_t i = 0; i < catches.length(); i++) {
const TryTableCatch& tryCatch = catches[i];
if (tryCatch.tagIndex == CatchAllIndex) {
if (tryCatch.captureExnRef) {
out.put(
" (catch_all_ref ");
}
else {
out.put(
" (catch_all ");
}
}
else {
if (tryCatch.captureExnRef) {
out.printf(
" (catch_ref %d ", tryCatch.tagIndex);
}
else {
out.printf(
" (catch %d ", tryCatch.tagIndex);
}
}
dumpBlockDepth(tryCatch.labelRelativeDepth);
out.put(
")");
}
}
void dumpLinearMemoryAddress(LinearMemoryAddress<Nothing> addr) {
if (addr.memoryIndex != 0) {
out.printf(
" (memory %d)", addr.memoryIndex);
}
if (addr.offset != 0) {
out.printf(
" offset=%" PRIu64, addr.offset);
}
if (addr.align != 0) {
out.printf(
" align=%d", addr.align);
}
}
void dumpBlockDepth(uint32_t relativeDepth) {
out.printf(
" %d", relativeDepth);
}
void dumpBlockDepths(
const Uint32Vector& relativeDepths) {
for (uint32_t i = 0; i < relativeDepths.length(); i++) {
out.printf(
" %d", relativeDepths[i]);
}
}
void dumpFieldIndex(uint32_t fieldIndex) { out.printf(
" %d", fieldIndex); }
void dumpNumElements(uint32_t numElements) { out.printf(
" %d", numElements); }
void dumpLaneIndex(uint32_t laneIndex) { out.printf(
" %d", laneIndex); }
};
#endif
template <
typename DumpT>
static bool ValidateOps(ValidatingOpIter& iter, DumpT& dumper,
const CodeMetadata& codeMeta,
const uint8_t* bodyEnd) {
while (
true) {
OpBytes op;
if (!iter.readOp(&op)) {
return false;
}
dumper.dumpOpBegin(op);
Nothing nothing;
NothingVector nothings{};
ResultType unusedType;
switch (op.b0) {
case uint16_t(Op::End): {
LabelKind unusedKind;
if (!iter.readEnd(&unusedKind, &unusedType, ¬hings, ¬hings)) {
return false;
}
iter.popEnd();
if (iter.controlStackEmpty()) {
return true;
}
break;
}
case uint16_t(Op::Nop): {
if (!iter.readNop()) {
return false;
}
break;
}
case uint16_t(Op::Drop): {
if (!iter.readDrop()) {
return false;
}
break;
}
case uint16_t(Op::Call): {
uint32_t funcIndex;
NothingVector unusedArgs{};
if (!iter.readCall(&funcIndex, &unusedArgs)) {
return false;
}
dumper.dumpFuncIndex(funcIndex);
break;
}
case uint16_t(Op::CallIndirect): {
uint32_t funcTypeIndex, tableIndex;
NothingVector unusedArgs{};
if (!iter.readCallIndirect(&funcTypeIndex, &tableIndex, ¬hing,
&unusedArgs)) {
return false;
}
dumper.dumpTypeIndex(funcTypeIndex);
dumper.dumpTableIndex(tableIndex);
break;
}
case uint16_t(Op::ReturnCall): {
uint32_t funcIndex;
NothingVector unusedArgs{};
if (!iter.readReturnCall(&funcIndex, &unusedArgs)) {
return false;
}
dumper.dumpFuncIndex(funcIndex);
break;
}
case uint16_t(Op::ReturnCallIndirect): {
uint32_t funcTypeIndex, tableIndex;
NothingVector unusedArgs{};
if (!iter.readReturnCallIndirect(&funcTypeIndex, &tableIndex, ¬hing,
&unusedArgs)) {
return false;
}
dumper.dumpTypeIndex(funcTypeIndex);
dumper.dumpTableIndex(tableIndex);
break;
}
case uint16_t(Op::CallRef): {
uint32_t funcTypeIndex;
NothingVector unusedArgs{};
if (!iter.readCallRef(&funcTypeIndex, ¬hing, &unusedArgs)) {
return false;
}
dumper.dumpTypeIndex(funcTypeIndex);
break;
}
case uint16_t(Op::ReturnCallRef): {
uint32_t funcTypeIndex;
NothingVector unusedArgs{};
if (!iter.readReturnCallRef(&funcTypeIndex, ¬hing, &unusedArgs)) {
return false;
}
dumper.dumpTypeIndex(funcTypeIndex);
break;
}
case uint16_t(Op::I32Const): {
int32_t constant;
if (!iter.readI32Const(&constant)) {
return false;
}
dumper.dumpI32Const(constant);
break;
}
case uint16_t(Op::I64Const): {
int64_t constant;
if (!iter.readI64Const(&constant)) {
return false;
}
dumper.dumpI64Const(constant);
break;
}
case uint16_t(Op::F32Const): {
float constant;
if (!iter.readF32Const(&constant)) {
return false;
}
dumper.dumpF32Const(constant);
break;
}
case uint16_t(Op::F64Const): {
double constant;
if (!iter.readF64Const(&constant)) {
return false;
}
dumper.dumpF64Const(constant);
break;
}
case uint16_t(Op::LocalGet): {
uint32_t localIndex;
if (!iter.readGetLocal(&localIndex)) {
return false;
}
dumper.dumpLocalIndex(localIndex);
break;
}
case uint16_t(Op::LocalSet): {
uint32_t localIndex;
if (!iter.readSetLocal(&localIndex, ¬hing)) {
return false;
}
dumper.dumpLocalIndex(localIndex);
break;
}
case uint16_t(Op::LocalTee): {
uint32_t localIndex;
if (!iter.readTeeLocal(&localIndex, ¬hing)) {
return false;
}
dumper.dumpLocalIndex(localIndex);
break;
}
case uint16_t(Op::GlobalGet): {
uint32_t globalIndex;
if (!iter.readGetGlobal(&globalIndex)) {
return false;
}
dumper.dumpGlobalIndex(globalIndex);
break;
}
case uint16_t(Op::GlobalSet): {
uint32_t globalIndex;
if (!iter.readSetGlobal(&globalIndex, ¬hing)) {
return false;
}
dumper.dumpGlobalIndex(globalIndex);
break;
}
case uint16_t(Op::TableGet): {
uint32_t tableIndex;
if (!iter.readTableGet(&tableIndex, ¬hing)) {
return false;
}
dumper.dumpTableIndex(tableIndex);
break;
}
case uint16_t(Op::TableSet): {
uint32_t tableIndex;
if (!iter.readTableSet(&tableIndex, ¬hing, ¬hing)) {
return false;
}
dumper.dumpTableIndex(tableIndex);
break;
}
case uint16_t(Op::SelectNumeric): {
StackType unused;
if (!iter.readSelect(
/*typed*/ false, &unused, ¬hing, ¬hing,
¬hing)) {
return false;
}
break;
}
case uint16_t(Op::SelectTyped): {
StackType type;
if (!iter.readSelect(
/*typed*/ true, &type, ¬hing, ¬hing,
¬hing)) {
return false;
}
dumper.dumpValType(type.valType());
break;
}
case uint16_t(Op::Block): {
if (!iter.readBlock(&unusedType)) {
return false;
}
dumper.dumpResultType(unusedType);
break;
}
case uint16_t(Op::Loop): {
if (!iter.readLoop(&unusedType)) {
return false;
}
dumper.dumpResultType(unusedType);
break;
}
case uint16_t(Op::
If): {
if (!iter.readIf(&unusedType, ¬hing)) {
return false;
}
dumper.dumpResultType(unusedType);
break;
}
case uint16_t(Op::
Else): {
if (!iter.readElse(&unusedType, &unusedType, ¬hings)) {
return false;
}
break;
}
case uint16_t(Op::I32Clz):
case uint16_t(Op::I32Ctz):
case uint16_t(Op::I32Popcnt): {
if (!iter.readUnary(ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64Clz):
case uint16_t(Op::I64Ctz):
case uint16_t(Op::I64Popcnt): {
if (!iter.readUnary(ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F32Abs):
case uint16_t(Op::F32Neg):
case uint16_t(Op::F32Ceil):
case uint16_t(Op::F32Floor):
case uint16_t(Op::F32Sqrt):
case uint16_t(Op::F32Trunc):
case uint16_t(Op::F32Nearest): {
if (!iter.readUnary(ValType::F32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F64Abs):
case uint16_t(Op::F64Neg):
case uint16_t(Op::F64Ceil):
case uint16_t(Op::F64Floor):
case uint16_t(Op::F64Sqrt):
case uint16_t(Op::F64Trunc):
case uint16_t(Op::F64Nearest): {
if (!iter.readUnary(ValType::F64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32Add):
case uint16_t(Op::I32Sub):
case uint16_t(Op::I32Mul):
case uint16_t(Op::I32DivS):
case uint16_t(Op::I32DivU):
case uint16_t(Op::I32RemS):
case uint16_t(Op::I32RemU):
case uint16_t(Op::I32And):
case uint16_t(Op::I32Or):
case uint16_t(Op::I32Xor):
case uint16_t(Op::I32Shl):
case uint16_t(Op::I32ShrS):
case uint16_t(Op::I32ShrU):
case uint16_t(Op::I32Rotl):
case uint16_t(Op::I32Rotr): {
if (!iter.readBinary(ValType::I32, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64Add):
case uint16_t(Op::I64Sub):
case uint16_t(Op::I64Mul):
case uint16_t(Op::I64DivS):
case uint16_t(Op::I64DivU):
case uint16_t(Op::I64RemS):
case uint16_t(Op::I64RemU):
case uint16_t(Op::I64And):
case uint16_t(Op::I64Or):
case uint16_t(Op::I64Xor):
case uint16_t(Op::I64Shl):
case uint16_t(Op::I64ShrS):
case uint16_t(Op::I64ShrU):
case uint16_t(Op::I64Rotl):
case uint16_t(Op::I64Rotr): {
if (!iter.readBinary(ValType::I64, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F32Add):
case uint16_t(Op::F32Sub):
case uint16_t(Op::F32Mul):
case uint16_t(Op::F32Div):
case uint16_t(Op::F32Min):
case uint16_t(Op::F32Max):
case uint16_t(Op::F32CopySign): {
if (!iter.readBinary(ValType::F32, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F64Add):
case uint16_t(Op::F64Sub):
case uint16_t(Op::F64Mul):
case uint16_t(Op::F64Div):
case uint16_t(Op::F64Min):
case uint16_t(Op::F64Max):
case uint16_t(Op::F64CopySign): {
if (!iter.readBinary(ValType::F64, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32Eq):
case uint16_t(Op::I32Ne):
case uint16_t(Op::I32LtS):
case uint16_t(Op::I32LtU):
case uint16_t(Op::I32LeS):
case uint16_t(Op::I32LeU):
case uint16_t(Op::I32GtS):
case uint16_t(Op::I32GtU):
case uint16_t(Op::I32GeS):
case uint16_t(Op::I32GeU): {
if (!iter.readComparison(ValType::I32, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64Eq):
case uint16_t(Op::I64Ne):
case uint16_t(Op::I64LtS):
case uint16_t(Op::I64LtU):
case uint16_t(Op::I64LeS):
case uint16_t(Op::I64LeU):
case uint16_t(Op::I64GtS):
case uint16_t(Op::I64GtU):
case uint16_t(Op::I64GeS):
case uint16_t(Op::I64GeU): {
if (!iter.readComparison(ValType::I64, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F32Eq):
case uint16_t(Op::F32Ne):
case uint16_t(Op::F32Lt):
case uint16_t(Op::F32Le):
case uint16_t(Op::F32Gt):
case uint16_t(Op::F32Ge): {
if (!iter.readComparison(ValType::F32, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F64Eq):
case uint16_t(Op::F64Ne):
case uint16_t(Op::F64Lt):
case uint16_t(Op::F64Le):
case uint16_t(Op::F64Gt):
case uint16_t(Op::F64Ge): {
if (!iter.readComparison(ValType::F64, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32Eqz): {
if (!iter.readConversion(ValType::I32, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64Eqz):
case uint16_t(Op::I32WrapI64): {
if (!iter.readConversion(ValType::I64, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32TruncF32S):
case uint16_t(Op::I32TruncF32U):
case uint16_t(Op::I32ReinterpretF32): {
if (!iter.readConversion(ValType::F32, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32TruncF64S):
case uint16_t(Op::I32TruncF64U): {
if (!iter.readConversion(ValType::F64, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64ExtendI32S):
case uint16_t(Op::I64ExtendI32U): {
if (!iter.readConversion(ValType::I32, ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64TruncF32S):
case uint16_t(Op::I64TruncF32U): {
if (!iter.readConversion(ValType::F32, ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64TruncF64S):
case uint16_t(Op::I64TruncF64U):
case uint16_t(Op::I64ReinterpretF64): {
if (!iter.readConversion(ValType::F64, ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F32ConvertI32S):
case uint16_t(Op::F32ConvertI32U):
case uint16_t(Op::F32ReinterpretI32): {
if (!iter.readConversion(ValType::I32, ValType::F32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F32ConvertI64S):
case uint16_t(Op::F32ConvertI64U): {
if (!iter.readConversion(ValType::I64, ValType::F32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F32DemoteF64): {
if (!iter.readConversion(ValType::F64, ValType::F32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F64ConvertI32S):
case uint16_t(Op::F64ConvertI32U): {
if (!iter.readConversion(ValType::I32, ValType::F64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F64ConvertI64S):
case uint16_t(Op::F64ConvertI64U):
case uint16_t(Op::F64ReinterpretI64): {
if (!iter.readConversion(ValType::I64, ValType::F64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::F64PromoteF32): {
if (!iter.readConversion(ValType::F32, ValType::F64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32Extend8S):
case uint16_t(Op::I32Extend16S): {
if (!iter.readConversion(ValType::I32, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I64Extend8S):
case uint16_t(Op::I64Extend16S):
case uint16_t(Op::I64Extend32S): {
if (!iter.readConversion(ValType::I64, ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint16_t(Op::I32Load8S):
case uint16_t(Op::I32Load8U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I32, 1, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I32Load16S):
case uint16_t(Op::I32Load16U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I32, 2, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I32Load): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I32, 4, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Load8S):
case uint16_t(Op::I64Load8U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I64, 1, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Load16S):
case uint16_t(Op::I64Load16U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I64, 2, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Load32S):
case uint16_t(Op::I64Load32U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I64, 4, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Load): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::I64, 8, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::F32Load): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::F32, 4, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::F64Load): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::F64, 8, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I32Store8): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I32, 1, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I32Store16): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I32, 2, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I32Store): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I32, 4, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Store8): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I64, 1, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Store16): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I64, 2, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Store32): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I64, 4, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::I64Store): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::I64, 8, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::F32Store): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::F32, 4, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::F64Store): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::F64, 8, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint16_t(Op::MemoryGrow): {
uint32_t memoryIndex;
if (!iter.readMemoryGrow(&memoryIndex, ¬hing)) {
return false;
}
dumper.dumpMemoryIndex(memoryIndex);
break;
}
case uint16_t(Op::MemorySize): {
uint32_t memoryIndex;
if (!iter.readMemorySize(&memoryIndex)) {
return false;
}
dumper.dumpMemoryIndex(memoryIndex);
break;
}
case uint16_t(Op::Br): {
uint32_t depth;
if (!iter.readBr(&depth, &unusedType, ¬hings)) {
return false;
}
dumper.dumpBlockDepth(depth);
break;
}
case uint16_t(Op::BrIf): {
uint32_t depth;
if (!iter.readBrIf(&depth, &unusedType, ¬hings, ¬hing)) {
return false;
}
dumper.dumpBlockDepth(depth);
break;
}
case uint16_t(Op::BrTable): {
Uint32Vector depths;
uint32_t defaultDepth;
if (!iter.readBrTable(&depths, &defaultDepth, &unusedType, ¬hings,
¬hing)) {
return false;
}
dumper.dumpBlockDepths(depths);
dumper.dumpBlockDepth(defaultDepth);
break;
}
case uint16_t(Op::
Return): {
if (!iter.readReturn(¬hings)) {
return false;
}
break;
}
case uint16_t(Op::Unreachable): {
if (!iter.readUnreachable()) {
return false;
}
break;
}
case uint16_t(Op::GcPrefix): {
switch (op.b1) {
case uint32_t(GcOp::StructNew): {
uint32_t typeIndex;
NothingVector unusedArgs{};
if (!iter.readStructNew(&typeIndex, &unusedArgs)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::StructNewDefault): {
uint32_t typeIndex;
if (!iter.readStructNewDefault(&typeIndex)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::StructGet): {
uint32_t typeIndex, fieldIndex;
if (!iter.readStructGet(&typeIndex, &fieldIndex,
FieldWideningOp::None, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpFieldIndex(fieldIndex);
break;
}
case uint32_t(GcOp::StructGetS): {
uint32_t typeIndex, fieldIndex;
if (!iter.readStructGet(&typeIndex, &fieldIndex,
FieldWideningOp::
Signed, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpFieldIndex(fieldIndex);
break;
}
case uint32_t(GcOp::StructGetU): {
uint32_t typeIndex, fieldIndex;
if (!iter.readStructGet(&typeIndex, &fieldIndex,
FieldWideningOp::
Unsigned, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpFieldIndex(fieldIndex);
break;
}
case uint32_t(GcOp::StructSet): {
uint32_t typeIndex, fieldIndex;
if (!iter.readStructSet(&typeIndex, &fieldIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpFieldIndex(fieldIndex);
break;
}
case uint32_t(GcOp::ArrayNew): {
uint32_t typeIndex;
if (!iter.readArrayNew(&typeIndex, ¬hing, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::ArrayNewFixed): {
uint32_t typeIndex, numElements;
if (!iter.readArrayNewFixed(&typeIndex, &numElements, ¬hings)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpNumElements(numElements);
break;
}
case uint32_t(GcOp::ArrayNewDefault): {
uint32_t typeIndex;
if (!iter.readArrayNewDefault(&typeIndex, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::ArrayNewData): {
uint32_t typeIndex, dataIndex;
if (!iter.readArrayNewData(&typeIndex, &dataIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpDataIndex(dataIndex);
break;
}
case uint32_t(GcOp::ArrayNewElem): {
uint32_t typeIndex, elemIndex;
if (!iter.readArrayNewElem(&typeIndex, &elemIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpElemIndex(elemIndex);
break;
}
case uint32_t(GcOp::ArrayInitData): {
uint32_t typeIndex, dataIndex;
if (!iter.readArrayInitData(&typeIndex, &dataIndex, ¬hing,
¬hing, ¬hing, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpDataIndex(dataIndex);
break;
}
case uint32_t(GcOp::ArrayInitElem): {
uint32_t typeIndex, elemIndex;
if (!iter.readArrayInitElem(&typeIndex, &elemIndex, ¬hing,
¬hing, ¬hing, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
dumper.dumpElemIndex(elemIndex);
break;
}
case uint32_t(GcOp::ArrayGet): {
uint32_t typeIndex;
if (!iter.readArrayGet(&typeIndex, FieldWideningOp::None, ¬hing,
¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::ArrayGetS): {
uint32_t typeIndex;
if (!iter.readArrayGet(&typeIndex, FieldWideningOp::
Signed,
¬hing, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::ArrayGetU): {
uint32_t typeIndex;
if (!iter.readArrayGet(&typeIndex, FieldWideningOp::
Unsigned,
¬hing, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::ArraySet): {
uint32_t typeIndex;
if (!iter.readArraySet(&typeIndex, ¬hing, ¬hing, ¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::ArrayLen): {
if (!iter.readArrayLen(¬hing)) {
return false;
}
break;
}
case uint32_t(GcOp::ArrayCopy): {
uint32_t dstArrayTypeIndex;
uint32_t srcArrayTypeIndex;
if (!iter.readArrayCopy(&dstArrayTypeIndex, &srcArrayTypeIndex,
¬hing, ¬hing, ¬hing, ¬hing,
¬hing)) {
return false;
}
dumper.dumpTypeIndex(dstArrayTypeIndex);
dumper.dumpTypeIndex(srcArrayTypeIndex);
break;
}
case uint32_t(GcOp::ArrayFill): {
uint32_t typeIndex;
if (!iter.readArrayFill(&typeIndex, ¬hing, ¬hing, ¬hing,
¬hing)) {
return false;
}
dumper.dumpTypeIndex(typeIndex);
break;
}
case uint32_t(GcOp::RefI31): {
if (!iter.readConversion(ValType::I32,
ValType(RefType::i31().asNonNullable()),
¬hing)) {
return false;
}
break;
}
case uint32_t(GcOp::I31GetS): {
if (!iter.readConversion(ValType(RefType::i31()), ValType::I32,
¬hing)) {
return false;
}
break;
}
case uint32_t(GcOp::I31GetU): {
if (!iter.readConversion(ValType(RefType::i31()), ValType::I32,
¬hing)) {
return false;
}
break;
}
case uint16_t(GcOp::RefTest): {
RefType srcType;
RefType destType;
if (!iter.readRefTest(
false, &srcType, &destType, ¬hing)) {
return false;
}
dumper.dumpRefType(destType);
break;
}
case uint16_t(GcOp::RefTestNull): {
RefType srcType;
RefType destType;
if (!iter.readRefTest(
true, &srcType, &destType, ¬hing)) {
return false;
}
dumper.dumpRefType(srcType);
dumper.dumpRefType(destType);
break;
}
case uint16_t(GcOp::RefCast): {
RefType srcType;
RefType destType;
if (!iter.readRefCast(
false, &srcType, &destType, ¬hing)) {
return false;
}
dumper.dumpRefType(srcType);
dumper.dumpRefType(destType);
break;
}
case uint16_t(GcOp::RefCastNull): {
RefType srcType;
RefType destType;
if (!iter.readRefCast(
true, &srcType, &destType, ¬hing)) {
return false;
}
dumper.dumpRefType(srcType);
dumper.dumpRefType(destType);
break;
}
case uint16_t(GcOp::BrOnCast): {
uint32_t relativeDepth;
RefType srcType;
RefType destType;
if (!iter.readBrOnCast(
true, &relativeDepth, &srcType, &destType,
&unusedType, ¬hings)) {
return false;
}
dumper.dumpBlockDepth(relativeDepth);
dumper.dumpRefType(srcType);
dumper.dumpRefType(destType);
break;
}
case uint16_t(GcOp::BrOnCastFail): {
uint32_t relativeDepth;
RefType srcType;
RefType destType;
if (!iter.readBrOnCast(
false, &relativeDepth, &srcType, &destType,
&unusedType, ¬hings)) {
return false;
}
dumper.dumpBlockDepth(relativeDepth);
dumper.dumpRefType(srcType);
dumper.dumpRefType(destType);
break;
}
case uint16_t(GcOp::AnyConvertExtern): {
if (!iter.readRefConversion(RefType::extern_(), RefType::any(),
¬hing)) {
return false;
}
break;
}
case uint16_t(GcOp::ExternConvertAny): {
if (!iter.readRefConversion(RefType::any(), RefType::extern_(),
¬hing)) {
return false;
}
break;
}
default:
return iter.unrecognizedOpcode(&op);
}
break;
}
#ifdef ENABLE_WASM_SIMD
case uint16_t(Op::SimdPrefix): {
if (!codeMeta.simdAvailable()) {
return iter.unrecognizedOpcode(&op);
}
uint32_t laneIndex;
switch (op.b1) {
case uint32_t(SimdOp::I8x16ExtractLaneS):
case uint32_t(SimdOp::I8x16ExtractLaneU): {
if (!iter.readExtractLane(ValType::I32, 16, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I16x8ExtractLaneS):
case uint32_t(SimdOp::I16x8ExtractLaneU): {
if (!iter.readExtractLane(ValType::I32, 8, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I32x4ExtractLane): {
if (!iter.readExtractLane(ValType::I32, 4, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I64x2ExtractLane): {
if (!iter.readExtractLane(ValType::I64, 2, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::F32x4ExtractLane): {
if (!iter.readExtractLane(ValType::F32, 4, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::F64x2ExtractLane): {
if (!iter.readExtractLane(ValType::F64, 2, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I8x16Splat):
case uint32_t(SimdOp::I16x8Splat):
case uint32_t(SimdOp::I32x4Splat): {
if (!iter.readConversion(ValType::I32, ValType::V128, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I64x2Splat): {
if (!iter.readConversion(ValType::I64, ValType::V128, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::F32x4Splat): {
if (!iter.readConversion(ValType::F32, ValType::V128, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::F64x2Splat): {
if (!iter.readConversion(ValType::F64, ValType::V128, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::V128AnyTrue):
case uint32_t(SimdOp::I8x16AllTrue):
case uint32_t(SimdOp::I16x8AllTrue):
case uint32_t(SimdOp::I32x4AllTrue):
case uint32_t(SimdOp::I64x2AllTrue):
case uint32_t(SimdOp::I8x16Bitmask):
case uint32_t(SimdOp::I16x8Bitmask):
case uint32_t(SimdOp::I32x4Bitmask):
case uint32_t(SimdOp::I64x2Bitmask): {
if (!iter.readConversion(ValType::V128, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I8x16ReplaceLane): {
if (!iter.readReplaceLane(ValType::I32, 16, &laneIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I16x8ReplaceLane): {
if (!iter.readReplaceLane(ValType::I32, 8, &laneIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I32x4ReplaceLane): {
if (!iter.readReplaceLane(ValType::I32, 4, &laneIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I64x2ReplaceLane): {
if (!iter.readReplaceLane(ValType::I64, 2, &laneIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::F32x4ReplaceLane): {
if (!iter.readReplaceLane(ValType::F32, 4, &laneIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::F64x2ReplaceLane): {
if (!iter.readReplaceLane(ValType::F64, 2, &laneIndex, ¬hing,
¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
break;
}
case uint32_t(SimdOp::I8x16Eq):
case uint32_t(SimdOp::I8x16Ne):
case uint32_t(SimdOp::I8x16LtS):
case uint32_t(SimdOp::I8x16LtU):
case uint32_t(SimdOp::I8x16GtS):
case uint32_t(SimdOp::I8x16GtU):
case uint32_t(SimdOp::I8x16LeS):
case uint32_t(SimdOp::I8x16LeU):
case uint32_t(SimdOp::I8x16GeS):
case uint32_t(SimdOp::I8x16GeU):
case uint32_t(SimdOp::I16x8Eq):
case uint32_t(SimdOp::I16x8Ne):
case uint32_t(SimdOp::I16x8LtS):
case uint32_t(SimdOp::I16x8LtU):
case uint32_t(SimdOp::I16x8GtS):
case uint32_t(SimdOp::I16x8GtU):
case uint32_t(SimdOp::I16x8LeS):
case uint32_t(SimdOp::I16x8LeU):
case uint32_t(SimdOp::I16x8GeS):
case uint32_t(SimdOp::I16x8GeU):
case uint32_t(SimdOp::I32x4Eq):
case uint32_t(SimdOp::I32x4Ne):
case uint32_t(SimdOp::I32x4LtS):
case uint32_t(SimdOp::I32x4LtU):
case uint32_t(SimdOp::I32x4GtS):
case uint32_t(SimdOp::I32x4GtU):
case uint32_t(SimdOp::I32x4LeS):
case uint32_t(SimdOp::I32x4LeU):
case uint32_t(SimdOp::I32x4GeS):
case uint32_t(SimdOp::I32x4GeU):
case uint32_t(SimdOp::I64x2Eq):
case uint32_t(SimdOp::I64x2Ne):
case uint32_t(SimdOp::I64x2LtS):
case uint32_t(SimdOp::I64x2GtS):
case uint32_t(SimdOp::I64x2LeS):
case uint32_t(SimdOp::I64x2GeS):
case uint32_t(SimdOp::F32x4Eq):
case uint32_t(SimdOp::F32x4Ne):
case uint32_t(SimdOp::F32x4Lt):
case uint32_t(SimdOp::F32x4Gt):
case uint32_t(SimdOp::F32x4Le):
case uint32_t(SimdOp::F32x4Ge):
case uint32_t(SimdOp::F64x2Eq):
case uint32_t(SimdOp::F64x2Ne):
case uint32_t(SimdOp::F64x2Lt):
case uint32_t(SimdOp::F64x2Gt):
case uint32_t(SimdOp::F64x2Le):
case uint32_t(SimdOp::F64x2Ge):
case uint32_t(SimdOp::V128And):
case uint32_t(SimdOp::V128Or):
case uint32_t(SimdOp::V128Xor):
case uint32_t(SimdOp::V128AndNot):
case uint32_t(SimdOp::I8x16AvgrU):
case uint32_t(SimdOp::I16x8AvgrU):
case uint32_t(SimdOp::I8x16Add):
case uint32_t(SimdOp::I8x16AddSatS):
case uint32_t(SimdOp::I8x16AddSatU):
case uint32_t(SimdOp::I8x16Sub):
case uint32_t(SimdOp::I8x16SubSatS):
case uint32_t(SimdOp::I8x16SubSatU):
case uint32_t(SimdOp::I8x16MinS):
case uint32_t(SimdOp::I8x16MinU):
case uint32_t(SimdOp::I8x16MaxS):
case uint32_t(SimdOp::I8x16MaxU):
case uint32_t(SimdOp::I16x8Add):
case uint32_t(SimdOp::I16x8AddSatS):
case uint32_t(SimdOp::I16x8AddSatU):
case uint32_t(SimdOp::I16x8Sub):
case uint32_t(SimdOp::I16x8SubSatS):
case uint32_t(SimdOp::I16x8SubSatU):
case uint32_t(SimdOp::I16x8Mul):
case uint32_t(SimdOp::I16x8MinS):
case uint32_t(SimdOp::I16x8MinU):
case uint32_t(SimdOp::I16x8MaxS):
case uint32_t(SimdOp::I16x8MaxU):
case uint32_t(SimdOp::I32x4Add):
case uint32_t(SimdOp::I32x4Sub):
case uint32_t(SimdOp::I32x4Mul):
case uint32_t(SimdOp::I32x4MinS):
case uint32_t(SimdOp::I32x4MinU):
case uint32_t(SimdOp::I32x4MaxS):
case uint32_t(SimdOp::I32x4MaxU):
case uint32_t(SimdOp::I64x2Add):
case uint32_t(SimdOp::I64x2Sub):
case uint32_t(SimdOp::I64x2Mul):
case uint32_t(SimdOp::F32x4Add):
case uint32_t(SimdOp::F32x4Sub):
case uint32_t(SimdOp::F32x4Mul):
case uint32_t(SimdOp::F32x4Div):
case uint32_t(SimdOp::F32x4Min):
case uint32_t(SimdOp::F32x4Max):
case uint32_t(SimdOp::F64x2Add):
case uint32_t(SimdOp::F64x2Sub):
case uint32_t(SimdOp::F64x2Mul):
case uint32_t(SimdOp::F64x2Div):
case uint32_t(SimdOp::F64x2Min):
case uint32_t(SimdOp::F64x2Max):
case uint32_t(SimdOp::I8x16NarrowI16x8S):
case uint32_t(SimdOp::I8x16NarrowI16x8U):
case uint32_t(SimdOp::I16x8NarrowI32x4S):
case uint32_t(SimdOp::I16x8NarrowI32x4U):
case uint32_t(SimdOp::I8x16Swizzle):
case uint32_t(SimdOp::F32x4PMax):
case uint32_t(SimdOp::F32x4PMin):
case uint32_t(SimdOp::F64x2PMax):
case uint32_t(SimdOp::F64x2PMin):
case uint32_t(SimdOp::I32x4DotI16x8S):
case uint32_t(SimdOp::I16x8ExtmulLowI8x16S):
case uint32_t(SimdOp::I16x8ExtmulHighI8x16S):
case uint32_t(SimdOp::I16x8ExtmulLowI8x16U):
case uint32_t(SimdOp::I16x8ExtmulHighI8x16U):
case uint32_t(SimdOp::I32x4ExtmulLowI16x8S):
case uint32_t(SimdOp::I32x4ExtmulHighI16x8S):
case uint32_t(SimdOp::I32x4ExtmulLowI16x8U):
case uint32_t(SimdOp::I32x4ExtmulHighI16x8U):
case uint32_t(SimdOp::I64x2ExtmulLowI32x4S):
case uint32_t(SimdOp::I64x2ExtmulHighI32x4S):
case uint32_t(SimdOp::I64x2ExtmulLowI32x4U):
case uint32_t(SimdOp::I64x2ExtmulHighI32x4U):
case uint32_t(SimdOp::I16x8Q15MulrSatS): {
if (!iter.readBinary(ValType::V128, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I8x16Neg):
case uint32_t(SimdOp::I16x8Neg):
case uint32_t(SimdOp::I16x8ExtendLowI8x16S):
case uint32_t(SimdOp::I16x8ExtendHighI8x16S):
case uint32_t(SimdOp::I16x8ExtendLowI8x16U):
case uint32_t(SimdOp::I16x8ExtendHighI8x16U):
case uint32_t(SimdOp::I32x4Neg):
case uint32_t(SimdOp::I32x4ExtendLowI16x8S):
case uint32_t(SimdOp::I32x4ExtendHighI16x8S):
case uint32_t(SimdOp::I32x4ExtendLowI16x8U):
case uint32_t(SimdOp::I32x4ExtendHighI16x8U):
case uint32_t(SimdOp::I32x4TruncSatF32x4S):
case uint32_t(SimdOp::I32x4TruncSatF32x4U):
case uint32_t(SimdOp::I64x2Neg):
case uint32_t(SimdOp::I64x2ExtendLowI32x4S):
case uint32_t(SimdOp::I64x2ExtendHighI32x4S):
case uint32_t(SimdOp::I64x2ExtendLowI32x4U):
case uint32_t(SimdOp::I64x2ExtendHighI32x4U):
case uint32_t(SimdOp::F32x4Abs):
case uint32_t(SimdOp::F32x4Neg):
case uint32_t(SimdOp::F32x4Sqrt):
case uint32_t(SimdOp::F32x4ConvertI32x4S):
case uint32_t(SimdOp::F32x4ConvertI32x4U):
case uint32_t(SimdOp::F64x2Abs):
case uint32_t(SimdOp::F64x2Neg):
case uint32_t(SimdOp::F64x2Sqrt):
case uint32_t(SimdOp::V128Not):
case uint32_t(SimdOp::I8x16Popcnt):
case uint32_t(SimdOp::I8x16Abs):
case uint32_t(SimdOp::I16x8Abs):
case uint32_t(SimdOp::I32x4Abs):
case uint32_t(SimdOp::I64x2Abs):
case uint32_t(SimdOp::F32x4Ceil):
case uint32_t(SimdOp::F32x4Floor):
case uint32_t(SimdOp::F32x4Trunc):
case uint32_t(SimdOp::F32x4Nearest):
case uint32_t(SimdOp::F64x2Ceil):
case uint32_t(SimdOp::F64x2Floor):
case uint32_t(SimdOp::F64x2Trunc):
case uint32_t(SimdOp::F64x2Nearest):
case uint32_t(SimdOp::F32x4DemoteF64x2Zero):
case uint32_t(SimdOp::F64x2PromoteLowF32x4):
case uint32_t(SimdOp::F64x2ConvertLowI32x4S):
case uint32_t(SimdOp::F64x2ConvertLowI32x4U):
case uint32_t(SimdOp::I32x4TruncSatF64x2SZero):
case uint32_t(SimdOp::I32x4TruncSatF64x2UZero):
case uint32_t(SimdOp::I16x8ExtaddPairwiseI8x16S):
case uint32_t(SimdOp::I16x8ExtaddPairwiseI8x16U):
case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8S):
case uint32_t(SimdOp::I32x4ExtaddPairwiseI16x8U): {
if (!iter.readUnary(ValType::V128, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I8x16Shl):
case uint32_t(SimdOp::I8x16ShrS):
case uint32_t(SimdOp::I8x16ShrU):
case uint32_t(SimdOp::I16x8Shl):
case uint32_t(SimdOp::I16x8ShrS):
case uint32_t(SimdOp::I16x8ShrU):
case uint32_t(SimdOp::I32x4Shl):
case uint32_t(SimdOp::I32x4ShrS):
case uint32_t(SimdOp::I32x4ShrU):
case uint32_t(SimdOp::I64x2Shl):
case uint32_t(SimdOp::I64x2ShrS):
case uint32_t(SimdOp::I64x2ShrU): {
if (!iter.readVectorShift(¬hing, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::V128Bitselect): {
if (!iter.readTernary(ValType::V128, ¬hing, ¬hing,
¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I8x16Shuffle): {
V128 mask;
if (!iter.readVectorShuffle(¬hing, ¬hing, &mask)) {
return false;
}
dumper.dumpVectorMask(mask);
break;
}
case uint32_t(SimdOp::V128Const): {
V128 constant;
if (!iter.readV128Const(&constant)) {
return false;
}
dumper.dumpV128Const(constant);
break;
}
case uint32_t(SimdOp::V128Load): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoad(ValType::V128, 16, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load8Splat): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadSplat(1, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load16Splat): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadSplat(2, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load32Splat): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadSplat(4, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load64Splat): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadSplat(8, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load8x8S):
case uint32_t(SimdOp::V128Load8x8U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadExtend(&addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load16x4S):
case uint32_t(SimdOp::V128Load16x4U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadExtend(&addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load32x2S):
case uint32_t(SimdOp::V128Load32x2U): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadExtend(&addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Store): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStore(ValType::V128, 16, &addr, ¬hing)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load32Zero): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadSplat(4, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load64Zero): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadSplat(8, &addr)) {
return false;
}
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load8Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadLane(1, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load16Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadLane(2, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load32Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadLane(4, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Load64Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readLoadLane(8, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Store8Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStoreLane(1, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Store16Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStoreLane(2, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Store32Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStoreLane(4, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
case uint32_t(SimdOp::V128Store64Lane): {
LinearMemoryAddress<Nothing> addr;
if (!iter.readStoreLane(8, &addr, &laneIndex, ¬hing)) {
return false;
}
dumper.dumpLaneIndex(laneIndex);
dumper.dumpLinearMemoryAddress(addr);
break;
}
# ifdef ENABLE_WASM_RELAXED_SIMD
case uint32_t(SimdOp::F32x4RelaxedMadd):
case uint32_t(SimdOp::F32x4RelaxedNmadd):
case uint32_t(SimdOp::F64x2RelaxedMadd):
case uint32_t(SimdOp::F64x2RelaxedNmadd):
case uint32_t(SimdOp::I8x16RelaxedLaneSelect):
case uint32_t(SimdOp::I16x8RelaxedLaneSelect):
case uint32_t(SimdOp::I32x4RelaxedLaneSelect):
case uint32_t(SimdOp::I64x2RelaxedLaneSelect):
case uint32_t(SimdOp::I32x4DotI8x16I7x16AddS): {
if (!codeMeta.v128RelaxedEnabled()) {
return iter.unrecognizedOpcode(&op);
}
if (!iter.readTernary(ValType::V128, ¬hing, ¬hing,
¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::F32x4RelaxedMin):
case uint32_t(SimdOp::F32x4RelaxedMax):
case uint32_t(SimdOp::F64x2RelaxedMin):
case uint32_t(SimdOp::F64x2RelaxedMax):
case uint32_t(SimdOp::I16x8RelaxedQ15MulrS):
case uint32_t(SimdOp::I16x8DotI8x16I7x16S): {
if (!codeMeta.v128RelaxedEnabled()) {
return iter.unrecognizedOpcode(&op);
}
if (!iter.readBinary(ValType::V128, ¬hing, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I32x4RelaxedTruncF32x4S):
case uint32_t(SimdOp::I32x4RelaxedTruncF32x4U):
case uint32_t(SimdOp::I32x4RelaxedTruncF64x2SZero):
case uint32_t(SimdOp::I32x4RelaxedTruncF64x2UZero): {
if (!codeMeta.v128RelaxedEnabled()) {
return iter.unrecognizedOpcode(&op);
}
if (!iter.readUnary(ValType::V128, ¬hing)) {
return false;
}
break;
}
case uint32_t(SimdOp::I8x16RelaxedSwizzle): {
if (!codeMeta.v128RelaxedEnabled()) {
return iter.unrecognizedOpcode(&op);
}
if (!iter.readBinary(ValType::V128, ¬hing, ¬hing)) {
return false;
}
break;
}
# endif
default:
return iter.unrecognizedOpcode(&op);
}
break;
}
#endif // ENABLE_WASM_SIMD
case uint16_t(Op::MiscPrefix): {
switch (op.b1) {
case uint32_t(MiscOp::I32TruncSatF32S):
case uint32_t(MiscOp::I32TruncSatF32U): {
if (!iter.readConversion(ValType::F32, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint32_t(MiscOp::I32TruncSatF64S):
case uint32_t(MiscOp::I32TruncSatF64U): {
if (!iter.readConversion(ValType::F64, ValType::I32, ¬hing)) {
return false;
}
break;
}
case uint32_t(MiscOp::I64TruncSatF32S):
case uint32_t(MiscOp::I64TruncSatF32U): {
if (!iter.readConversion(ValType::F32, ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint32_t(MiscOp::I64TruncSatF64S):
case uint32_t(MiscOp::I64TruncSatF64U): {
if (!iter.readConversion(ValType::F64, ValType::I64, ¬hing)) {
return false;
}
break;
}
case uint32_t(MiscOp::MemoryCopy): {
uint32_t destMemIndex;
uint32_t srcMemIndex;
--> --------------------
--> maximum size reached
--> --------------------