bool wasm::ValidateOps()

in js/src/wasm/WasmValidate.cpp [232:2437]


bool wasm::ValidateOps(ValidatingOpIter& iter, BaseOpDumper& dumper,
                       const CodeMetadata& codeMeta) {
  while (true) {
    OpBytes op;
    if (!iter.readOp(&op)) {
      return false;
    }

    // End instructions get handled differently since we don't actually want to
    // dump the final `end`. Also, Else instructions need to have their
    // indentation managed when dumping.
    if (op.b0 != uint16_t(Op::End)) {
      if (op.b0 == uint64_t(Op::Else)) {
        dumper.endScope();
      }
      dumper.dumpOpBegin(op);
      if (op.b0 == uint64_t(Op::Else)) {
        dumper.startScope();
      }
    }

    Nothing nothing;
    NothingVector nothings{};
    BlockType blockType;
    ResultType resultType;

    switch (op.b0) {
      case uint16_t(Op::End): {
        LabelKind unusedKind;
        if (!iter.readEnd(&unusedKind, &resultType, &nothings, &nothings)) {
          return false;
        }
        iter.popEnd();
        if (iter.controlStackEmpty()) {
          return true;
        }

        // Only dump `end` if it was not the final `end` of the expression.
        dumper.endScope();
        dumper.dumpOpBegin(op);

        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, &nothing,
                                   &unusedArgs)) {
          return false;
        }
        dumper.dumpTableIndex(tableIndex);
        dumper.dumpTypeIndex(funcTypeIndex, /*asTypeUse=*/true);
        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, &nothing,
                                         &unusedArgs)) {
          return false;
        }
        dumper.dumpTableIndex(tableIndex);
        dumper.dumpTypeIndex(funcTypeIndex, /*asTypeUse=*/true);
        break;
      }
      case uint16_t(Op::CallRef): {
        uint32_t funcTypeIndex;
        NothingVector unusedArgs{};
        if (!iter.readCallRef(&funcTypeIndex, &nothing, &unusedArgs)) {
          return false;
        }
        dumper.dumpTypeIndex(funcTypeIndex);
        break;
      }
      case uint16_t(Op::ReturnCallRef): {
        uint32_t funcTypeIndex;
        NothingVector unusedArgs{};
        if (!iter.readReturnCallRef(&funcTypeIndex, &nothing, &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, &nothing)) {
          return false;
        }
        dumper.dumpLocalIndex(localIndex);
        break;
      }
      case uint16_t(Op::LocalTee): {
        uint32_t localIndex;
        if (!iter.readTeeLocal(&localIndex, &nothing)) {
          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, &nothing)) {
          return false;
        }
        dumper.dumpGlobalIndex(globalIndex);
        break;
      }
      case uint16_t(Op::TableGet): {
        uint32_t tableIndex;
        if (!iter.readTableGet(&tableIndex, &nothing)) {
          return false;
        }
        dumper.dumpTableIndex(tableIndex);
        break;
      }
      case uint16_t(Op::TableSet): {
        uint32_t tableIndex;
        if (!iter.readTableSet(&tableIndex, &nothing, &nothing)) {
          return false;
        }
        dumper.dumpTableIndex(tableIndex);
        break;
      }
      case uint16_t(Op::SelectNumeric): {
        StackType unused;
        if (!iter.readSelect(/*typed*/ false, &unused, &nothing, &nothing,
                             &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::SelectTyped): {
        StackType type;
        if (!iter.readSelect(/*typed*/ true, &type, &nothing, &nothing,
                             &nothing)) {
          return false;
        }
        dumper.dumpValType(type.valType());
        break;
      }
      case uint16_t(Op::Block): {
        if (!iter.readBlock(&blockType)) {
          return false;
        }
        dumper.dumpBlockType(blockType);
        dumper.startScope();
        break;
      }
      case uint16_t(Op::Loop): {
        if (!iter.readLoop(&blockType)) {
          return false;
        }
        dumper.dumpBlockType(blockType);
        dumper.startScope();
        break;
      }
      case uint16_t(Op::If): {
        if (!iter.readIf(&blockType, &nothing)) {
          return false;
        }
        dumper.dumpBlockType(blockType);
        dumper.startScope();
        break;
      }
      case uint16_t(Op::Else): {
        if (!iter.readElse(&resultType, &resultType, &nothings)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I32Clz):
      case uint16_t(Op::I32Ctz):
      case uint16_t(Op::I32Popcnt): {
        if (!iter.readUnary(ValType::I32, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I64Clz):
      case uint16_t(Op::I64Ctz):
      case uint16_t(Op::I64Popcnt): {
        if (!iter.readUnary(ValType::I64, &nothing)) {
          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, &nothing)) {
          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, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          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, &nothing, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I32Eqz): {
        if (!iter.readConversion(ValType::I32, ValType::I32, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I64Eqz):
      case uint16_t(Op::I32WrapI64): {
        if (!iter.readConversion(ValType::I64, ValType::I32, &nothing)) {
          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, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I32TruncF64S):
      case uint16_t(Op::I32TruncF64U): {
        if (!iter.readConversion(ValType::F64, ValType::I32, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I64ExtendI32S):
      case uint16_t(Op::I64ExtendI32U): {
        if (!iter.readConversion(ValType::I32, ValType::I64, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I64TruncF32S):
      case uint16_t(Op::I64TruncF32U): {
        if (!iter.readConversion(ValType::F32, ValType::I64, &nothing)) {
          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, &nothing)) {
          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, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::F32ConvertI64S):
      case uint16_t(Op::F32ConvertI64U): {
        if (!iter.readConversion(ValType::I64, ValType::F32, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::F32DemoteF64): {
        if (!iter.readConversion(ValType::F64, ValType::F32, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::F64ConvertI32S):
      case uint16_t(Op::F64ConvertI32U): {
        if (!iter.readConversion(ValType::I32, ValType::F64, &nothing)) {
          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, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::F64PromoteF32): {
        if (!iter.readConversion(ValType::F32, ValType::F64, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::I32Extend8S):
      case uint16_t(Op::I32Extend16S): {
        if (!iter.readConversion(ValType::I32, ValType::I32, &nothing)) {
          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, &nothing)) {
          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, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::I32Store16): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::I32, 2, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::I32Store): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::I32, 4, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::I64Store8): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::I64, 1, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::I64Store16): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::I64, 2, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::I64Store32): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::I64, 4, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::I64Store): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::I64, 8, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::F32Store): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::F32, 4, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::F64Store): {
        LinearMemoryAddress<Nothing> addr;
        if (!iter.readStore(ValType::F64, 8, &addr, &nothing)) {
          return false;
        }
        dumper.dumpLinearMemoryAddress(addr);
        break;
      }
      case uint16_t(Op::MemoryGrow): {
        uint32_t memoryIndex;
        if (!iter.readMemoryGrow(&memoryIndex, &nothing)) {
          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, &resultType, &nothings)) {
          return false;
        }
        dumper.dumpBlockDepth(depth);
        break;
      }
      case uint16_t(Op::BrIf): {
        uint32_t depth;
        if (!iter.readBrIf(&depth, &resultType, &nothings, &nothing)) {
          return false;
        }
        dumper.dumpBlockDepth(depth);
        break;
      }
      case uint16_t(Op::BrTable): {
        Uint32Vector depths;
        uint32_t defaultDepth;
        if (!iter.readBrTable(&depths, &defaultDepth, &resultType, &nothings,
                              &nothing)) {
          return false;
        }
        dumper.dumpBlockDepths(depths);
        dumper.dumpBlockDepth(defaultDepth);
        break;
      }
      case uint16_t(Op::Return): {
        if (!iter.readReturn(&nothings)) {
          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, &nothing)) {
              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, &nothing)) {
              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, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpFieldIndex(fieldIndex);
            break;
          }
          case uint32_t(GcOp::StructSet): {
            uint32_t typeIndex, fieldIndex;
            if (!iter.readStructSet(&typeIndex, &fieldIndex, &nothing,
                                    &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpFieldIndex(fieldIndex);
            break;
          }
          case uint32_t(GcOp::ArrayNew): {
            uint32_t typeIndex;
            if (!iter.readArrayNew(&typeIndex, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::ArrayNewFixed): {
            uint32_t typeIndex, numElements;
            if (!iter.readArrayNewFixed(&typeIndex, &numElements, &nothings)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpNumElements(numElements);
            break;
          }
          case uint32_t(GcOp::ArrayNewDefault): {
            uint32_t typeIndex;
            if (!iter.readArrayNewDefault(&typeIndex, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::ArrayNewData): {
            uint32_t typeIndex, dataIndex;
            if (!iter.readArrayNewData(&typeIndex, &dataIndex, &nothing,
                                       &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpDataIndex(dataIndex);
            break;
          }
          case uint32_t(GcOp::ArrayNewElem): {
            uint32_t typeIndex, elemIndex;
            if (!iter.readArrayNewElem(&typeIndex, &elemIndex, &nothing,
                                       &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpElemIndex(elemIndex);
            break;
          }
          case uint32_t(GcOp::ArrayInitData): {
            uint32_t typeIndex, dataIndex;
            if (!iter.readArrayInitData(&typeIndex, &dataIndex, &nothing,
                                        &nothing, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpDataIndex(dataIndex);
            break;
          }
          case uint32_t(GcOp::ArrayInitElem): {
            uint32_t typeIndex, elemIndex;
            if (!iter.readArrayInitElem(&typeIndex, &elemIndex, &nothing,
                                        &nothing, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            dumper.dumpElemIndex(elemIndex);
            break;
          }
          case uint32_t(GcOp::ArrayGet): {
            uint32_t typeIndex;
            if (!iter.readArrayGet(&typeIndex, FieldWideningOp::None, &nothing,
                                   &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::ArrayGetS): {
            uint32_t typeIndex;
            if (!iter.readArrayGet(&typeIndex, FieldWideningOp::Signed,
                                   &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::ArrayGetU): {
            uint32_t typeIndex;
            if (!iter.readArrayGet(&typeIndex, FieldWideningOp::Unsigned,
                                   &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::ArraySet): {
            uint32_t typeIndex;
            if (!iter.readArraySet(&typeIndex, &nothing, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::ArrayLen): {
            if (!iter.readArrayLen(&nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(GcOp::ArrayCopy): {
            uint32_t dstArrayTypeIndex;
            uint32_t srcArrayTypeIndex;
            if (!iter.readArrayCopy(&dstArrayTypeIndex, &srcArrayTypeIndex,
                                    &nothing, &nothing, &nothing, &nothing,
                                    &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(dstArrayTypeIndex);
            dumper.dumpTypeIndex(srcArrayTypeIndex);
            break;
          }
          case uint32_t(GcOp::ArrayFill): {
            uint32_t typeIndex;
            if (!iter.readArrayFill(&typeIndex, &nothing, &nothing, &nothing,
                                    &nothing)) {
              return false;
            }
            dumper.dumpTypeIndex(typeIndex);
            break;
          }
          case uint32_t(GcOp::RefI31): {
            if (!iter.readConversion(ValType::I32,
                                     ValType(RefType::i31().asNonNullable()),
                                     &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(GcOp::I31GetS): {
            if (!iter.readConversion(ValType(RefType::i31()), ValType::I32,
                                     &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(GcOp::I31GetU): {
            if (!iter.readConversion(ValType(RefType::i31()), ValType::I32,
                                     &nothing)) {
              return false;
            }
            break;
          }
          case uint16_t(GcOp::RefTest): {
            RefType srcType;
            RefType destType;
            if (!iter.readRefTest(false, &srcType, &destType, &nothing)) {
              return false;
            }
            dumper.dumpRefType(destType);
            break;
          }
          case uint16_t(GcOp::RefTestNull): {
            RefType srcType;
            RefType destType;
            if (!iter.readRefTest(true, &srcType, &destType, &nothing)) {
              return false;
            }
            dumper.dumpRefType(srcType);
            dumper.dumpRefType(destType);
            break;
          }
          case uint16_t(GcOp::RefCast): {
            RefType srcType;
            RefType destType;
            if (!iter.readRefCast(false, &srcType, &destType, &nothing)) {
              return false;
            }
            dumper.dumpRefType(destType);
            break;
          }
          case uint16_t(GcOp::RefCastNull): {
            RefType srcType;
            RefType destType;
            if (!iter.readRefCast(true, &srcType, &destType, &nothing)) {
              return false;
            }
            dumper.dumpRefType(destType);
            break;
          }
          case uint16_t(GcOp::BrOnCast): {
            uint32_t relativeDepth;
            RefType srcType;
            RefType destType;
            if (!iter.readBrOnCast(true, &relativeDepth, &srcType, &destType,
                                   &resultType, &nothings)) {
              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,
                                   &resultType, &nothings)) {
              return false;
            }
            dumper.dumpBlockDepth(relativeDepth);
            dumper.dumpRefType(srcType);
            dumper.dumpRefType(destType);
            break;
          }
          case uint16_t(GcOp::AnyConvertExtern): {
            if (!iter.readRefConversion(RefType::extern_(), RefType::any(),
                                        &nothing)) {
              return false;
            }
            break;
          }
          case uint16_t(GcOp::ExternConvertAny): {
            if (!iter.readRefConversion(RefType::any(), RefType::extern_(),
                                        &nothing)) {
              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, &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::I16x8ExtractLaneS):
          case uint32_t(SimdOp::I16x8ExtractLaneU): {
            if (!iter.readExtractLane(ValType::I32, 8, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::I32x4ExtractLane): {
            if (!iter.readExtractLane(ValType::I32, 4, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::I64x2ExtractLane): {
            if (!iter.readExtractLane(ValType::I64, 2, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::F32x4ExtractLane): {
            if (!iter.readExtractLane(ValType::F32, 4, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::F64x2ExtractLane): {
            if (!iter.readExtractLane(ValType::F64, 2, &laneIndex, &nothing)) {
              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, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(SimdOp::I64x2Splat): {
            if (!iter.readConversion(ValType::I64, ValType::V128, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(SimdOp::F32x4Splat): {
            if (!iter.readConversion(ValType::F32, ValType::V128, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(SimdOp::F64x2Splat): {
            if (!iter.readConversion(ValType::F64, ValType::V128, &nothing)) {
              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, &nothing)) {
              return false;
            }
            break;
          }

          case uint32_t(SimdOp::I8x16ReplaceLane): {
            if (!iter.readReplaceLane(ValType::I32, 16, &laneIndex, &nothing,
                                      &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::I16x8ReplaceLane): {
            if (!iter.readReplaceLane(ValType::I32, 8, &laneIndex, &nothing,
                                      &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::I32x4ReplaceLane): {
            if (!iter.readReplaceLane(ValType::I32, 4, &laneIndex, &nothing,
                                      &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::I64x2ReplaceLane): {
            if (!iter.readReplaceLane(ValType::I64, 2, &laneIndex, &nothing,
                                      &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::F32x4ReplaceLane): {
            if (!iter.readReplaceLane(ValType::F32, 4, &laneIndex, &nothing,
                                      &nothing)) {
              return false;
            }
            dumper.dumpLaneIndex(laneIndex);
            break;
          }
          case uint32_t(SimdOp::F64x2ReplaceLane): {
            if (!iter.readReplaceLane(ValType::F64, 2, &laneIndex, &nothing,
                                      &nothing)) {
              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, &nothing, &nothing)) {
              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, &nothing)) {
              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(&nothing, &nothing)) {
              return false;
            }
            break;
          }

          case uint32_t(SimdOp::V128Bitselect): {
            if (!iter.readTernary(ValType::V128, &nothing, &nothing,
                                  &nothing)) {
              return false;
            }
            break;
          }

          case uint32_t(SimdOp::I8x16Shuffle): {
            V128 mask;
            if (!iter.readVectorShuffle(&nothing, &nothing, &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, &nothing)) {
              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, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Load16Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readLoadLane(2, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Load32Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readLoadLane(4, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Load64Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readLoadLane(8, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Store8Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readStoreLane(1, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Store16Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readStoreLane(2, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Store32Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readStoreLane(4, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            break;
          }

          case uint32_t(SimdOp::V128Store64Lane): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readStoreLane(8, &addr, &laneIndex, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            dumper.dumpLaneIndex(laneIndex);
            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::I32x4RelaxedDotI8x16I7x16AddS): {
            if (!codeMeta.v128RelaxedEnabled()) {
              return iter.unrecognizedOpcode(&op);
            }
            if (!iter.readTernary(ValType::V128, &nothing, &nothing,
                                  &nothing)) {
              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::I16x8RelaxedDotI8x16I7x16S): {
            if (!codeMeta.v128RelaxedEnabled()) {
              return iter.unrecognizedOpcode(&op);
            }
            if (!iter.readBinary(ValType::V128, &nothing, &nothing)) {
              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, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(SimdOp::I8x16RelaxedSwizzle): {
            if (!codeMeta.v128RelaxedEnabled()) {
              return iter.unrecognizedOpcode(&op);
            }
            if (!iter.readBinary(ValType::V128, &nothing, &nothing)) {
              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, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(MiscOp::I32TruncSatF64S):
          case uint32_t(MiscOp::I32TruncSatF64U): {
            if (!iter.readConversion(ValType::F64, ValType::I32, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(MiscOp::I64TruncSatF32S):
          case uint32_t(MiscOp::I64TruncSatF32U): {
            if (!iter.readConversion(ValType::F32, ValType::I64, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(MiscOp::I64TruncSatF64S):
          case uint32_t(MiscOp::I64TruncSatF64U): {
            if (!iter.readConversion(ValType::F64, ValType::I64, &nothing)) {
              return false;
            }
            break;
          }
          case uint32_t(MiscOp::MemoryCopy): {
            uint32_t destMemIndex;
            uint32_t srcMemIndex;
            if (!iter.readMemOrTableCopy(/*isMem=*/true, &destMemIndex,
                                         &nothing, &srcMemIndex, &nothing,
                                         &nothing)) {
              return false;
            }
            dumper.dumpMemoryIndex(destMemIndex);
            dumper.dumpMemoryIndex(srcMemIndex);
            break;
          }
          case uint32_t(MiscOp::DataDrop): {
            uint32_t dataIndex;
            if (!iter.readDataOrElemDrop(/*isData=*/true, &dataIndex)) {
              return false;
            }
            dumper.dumpDataIndex(dataIndex);
            break;
          }
          case uint32_t(MiscOp::MemoryFill): {
            uint32_t memoryIndex;
            if (!iter.readMemFill(&memoryIndex, &nothing, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpMemoryIndex(memoryIndex);
            break;
          }
          case uint32_t(MiscOp::MemoryInit): {
            uint32_t dataIndex;
            uint32_t memoryIndex;
            if (!iter.readMemOrTableInit(/*isMem=*/true, &dataIndex,
                                         &memoryIndex, &nothing, &nothing,
                                         &nothing)) {
              return false;
            }
            dumper.dumpMemoryIndex(memoryIndex);
            dumper.dumpDataIndex(dataIndex);
            break;
          }
          case uint32_t(MiscOp::TableCopy): {
            uint32_t destTableIndex;
            uint32_t srcTableIndex;
            if (!iter.readMemOrTableCopy(
                    /*isMem=*/false, &destTableIndex, &nothing, &srcTableIndex,
                    &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTableIndex(destTableIndex);
            dumper.dumpTableIndex(srcTableIndex);
            break;
          }
          case uint32_t(MiscOp::ElemDrop): {
            uint32_t elemIndex;
            if (!iter.readDataOrElemDrop(/*isData=*/false, &elemIndex)) {
              return false;
            }
            dumper.dumpElemIndex(elemIndex);
            break;
          }
          case uint32_t(MiscOp::TableInit): {
            uint32_t elemIndex;
            uint32_t tableIndex;
            if (!iter.readMemOrTableInit(/*isMem=*/false, &elemIndex,
                                         &tableIndex, &nothing, &nothing,
                                         &nothing)) {
              return false;
            }
            dumper.dumpTableIndex(tableIndex);
            dumper.dumpElemIndex(elemIndex);
            break;
          }
          case uint32_t(MiscOp::TableFill): {
            uint32_t tableIndex;
            if (!iter.readTableFill(&tableIndex, &nothing, &nothing,
                                    &nothing)) {
              return false;
            }
            dumper.dumpTableIndex(tableIndex);
            break;
          }
#ifdef ENABLE_WASM_MEMORY_CONTROL
          case uint32_t(MiscOp::MemoryDiscard): {
            if (!codeMeta.memoryControlEnabled()) {
              return iter.unrecognizedOpcode(&op);
            }
            uint32_t memoryIndex;
            if (!iter.readMemDiscard(&memoryIndex, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpMemoryIndex(memoryIndex);
            break;
          }
#endif
          case uint32_t(MiscOp::TableGrow): {
            uint32_t tableIndex;
            if (!iter.readTableGrow(&tableIndex, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpTableIndex(tableIndex);
            break;
          }
          case uint32_t(MiscOp::TableSize): {
            uint32_t tableIndex;
            if (!iter.readTableSize(&tableIndex)) {
              return false;
            }
            dumper.dumpTableIndex(tableIndex);
            break;
          }
          default:
            return iter.unrecognizedOpcode(&op);
        }
        break;
      }
      case uint16_t(Op::RefAsNonNull): {
        if (!iter.readRefAsNonNull(&nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::BrOnNull): {
        uint32_t depth;
        if (!iter.readBrOnNull(&depth, &resultType, &nothings, &nothing)) {
          return false;
        }
        dumper.dumpBlockDepth(depth);
        break;
      }
      case uint16_t(Op::BrOnNonNull): {
        uint32_t depth;
        if (!iter.readBrOnNonNull(&depth, &resultType, &nothings, &nothing)) {
          return false;
        }
        dumper.dumpBlockDepth(depth);
        break;
      }
      case uint16_t(Op::RefEq): {
        if (!iter.readComparison(RefType::eq(), &nothing, &nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::RefFunc): {
        uint32_t funcIndex;
        if (!iter.readRefFunc(&funcIndex)) {
          return false;
        }
        dumper.dumpFuncIndex(funcIndex);
        break;
      }
      case uint16_t(Op::RefNull): {
        RefType type;
        if (!iter.readRefNull(&type)) {
          return false;
        }
        dumper.dumpHeapType(type);
        break;
      }
      case uint16_t(Op::RefIsNull): {
        Nothing nothing;
        if (!iter.readRefIsNull(&nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::Try): {
        if (!iter.readTry(&blockType)) {
          return false;
        }
        dumper.dumpBlockType(blockType);
        break;
      }
      case uint16_t(Op::Catch): {
        LabelKind unusedKind;
        uint32_t tagIndex;
        if (!iter.readCatch(&unusedKind, &tagIndex, &resultType, &resultType,
                            &nothings)) {
          return false;
        }
        dumper.dumpTagIndex(tagIndex);
        break;
      }
      case uint16_t(Op::CatchAll): {
        LabelKind unusedKind;
        if (!iter.readCatchAll(&unusedKind, &resultType, &resultType,
                               &nothings)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::Delegate): {
        uint32_t depth;
        if (!iter.readDelegate(&depth, &resultType, &nothings)) {
          return false;
        }
        iter.popDelegate();
        dumper.dumpBlockDepth(depth);
        break;
      }
      case uint16_t(Op::Throw): {
        uint32_t tagIndex;
        if (!iter.readThrow(&tagIndex, &nothings)) {
          return false;
        }
        dumper.dumpTagIndex(tagIndex);
        break;
      }
      case uint16_t(Op::Rethrow): {
        uint32_t depth;
        if (!iter.readRethrow(&depth)) {
          return false;
        }
        dumper.dumpBlockDepth(depth);
        break;
      }
      case uint16_t(Op::ThrowRef): {
        if (!codeMeta.exnrefEnabled()) {
          return iter.unrecognizedOpcode(&op);
        }
        if (!iter.readThrowRef(&nothing)) {
          return false;
        }
        break;
      }
      case uint16_t(Op::TryTable): {
        if (!codeMeta.exnrefEnabled()) {
          return iter.unrecognizedOpcode(&op);
        }
        TryTableCatchVector catches;
        if (!iter.readTryTable(&blockType, &catches)) {
          return false;
        }
        dumper.dumpTryTableCatches(catches);
        break;
      }
      case uint16_t(Op::ThreadPrefix): {
        // Though thread ops can be used on nonshared memories, we make them
        // unavailable if shared memory has been disabled in the prefs, for
        // maximum predictability and safety and consistency with JS.
        if (codeMeta.sharedMemoryEnabled() == Shareable::False) {
          return iter.unrecognizedOpcode(&op);
        }
        switch (op.b1) {
          case uint32_t(ThreadOp::Notify): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readNotify(&addr, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32Wait): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readWait(&addr, ValType::I32, 4, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64Wait): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readWait(&addr, ValType::I64, 8, &nothing, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::Fence): {
            if (!iter.readFence()) {
              return false;
            }
            break;
          }
          case uint32_t(ThreadOp::I32AtomicLoad): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I32, 4)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicLoad): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I64, 8)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicLoad8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I32, 1)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicLoad16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I32, 2)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicLoad8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I64, 1)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicLoad16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I64, 2)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicLoad32U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicLoad(&addr, ValType::I64, 4)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicStore): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I32, 4, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicStore): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I64, 8, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicStore8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I32, 1, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicStore16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I32, 2, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicStore8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I64, 1, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicStore16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I64, 2, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicStore32U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicStore(&addr, ValType::I64, 4, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicAdd):
          case uint32_t(ThreadOp::I32AtomicSub):
          case uint32_t(ThreadOp::I32AtomicAnd):
          case uint32_t(ThreadOp::I32AtomicOr):
          case uint32_t(ThreadOp::I32AtomicXor):
          case uint32_t(ThreadOp::I32AtomicXchg): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I32, 4, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicAdd):
          case uint32_t(ThreadOp::I64AtomicSub):
          case uint32_t(ThreadOp::I64AtomicAnd):
          case uint32_t(ThreadOp::I64AtomicOr):
          case uint32_t(ThreadOp::I64AtomicXor):
          case uint32_t(ThreadOp::I64AtomicXchg): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I64, 8, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicAdd8U):
          case uint32_t(ThreadOp::I32AtomicSub8U):
          case uint32_t(ThreadOp::I32AtomicAnd8U):
          case uint32_t(ThreadOp::I32AtomicOr8U):
          case uint32_t(ThreadOp::I32AtomicXor8U):
          case uint32_t(ThreadOp::I32AtomicXchg8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I32, 1, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicAdd16U):
          case uint32_t(ThreadOp::I32AtomicSub16U):
          case uint32_t(ThreadOp::I32AtomicAnd16U):
          case uint32_t(ThreadOp::I32AtomicOr16U):
          case uint32_t(ThreadOp::I32AtomicXor16U):
          case uint32_t(ThreadOp::I32AtomicXchg16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I32, 2, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicAdd8U):
          case uint32_t(ThreadOp::I64AtomicSub8U):
          case uint32_t(ThreadOp::I64AtomicAnd8U):
          case uint32_t(ThreadOp::I64AtomicOr8U):
          case uint32_t(ThreadOp::I64AtomicXor8U):
          case uint32_t(ThreadOp::I64AtomicXchg8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I64, 1, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicAdd16U):
          case uint32_t(ThreadOp::I64AtomicSub16U):
          case uint32_t(ThreadOp::I64AtomicAnd16U):
          case uint32_t(ThreadOp::I64AtomicOr16U):
          case uint32_t(ThreadOp::I64AtomicXor16U):
          case uint32_t(ThreadOp::I64AtomicXchg16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I64, 2, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicAdd32U):
          case uint32_t(ThreadOp::I64AtomicSub32U):
          case uint32_t(ThreadOp::I64AtomicAnd32U):
          case uint32_t(ThreadOp::I64AtomicOr32U):
          case uint32_t(ThreadOp::I64AtomicXor32U):
          case uint32_t(ThreadOp::I64AtomicXchg32U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicRMW(&addr, ValType::I64, 4, &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicCmpXchg): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I32, 4, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicCmpXchg): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 8, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicCmpXchg8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I32, 1, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I32AtomicCmpXchg16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I32, 2, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicCmpXchg8U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 1, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicCmpXchg16U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 2, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          case uint32_t(ThreadOp::I64AtomicCmpXchg32U): {
            LinearMemoryAddress<Nothing> addr;
            if (!iter.readAtomicCmpXchg(&addr, ValType::I64, 4, &nothing,
                                        &nothing)) {
              return false;
            }
            dumper.dumpLinearMemoryAddress(addr);
            break;
          }
          default:
            return iter.unrecognizedOpcode(&op);
        }
        break;
      }
      case uint16_t(Op::MozPrefix):
        return iter.unrecognizedOpcode(&op);
      default:
        return iter.unrecognizedOpcode(&op);
    }

    dumper.dumpOpEnd();
  }

  MOZ_CRASH("unreachable");
}