| /* |
| * Copyright 2018 WebAssembly Community Group participants |
| * |
| * 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 "src/interp/interp.h" |
| |
| #include <cinttypes> |
| |
| #include "src/cast.h" |
| #include "src/interp/interp-internal.h" |
| |
| namespace wabt { |
| namespace interp { |
| |
| void Environment::Disassemble(Stream* stream, |
| IstreamOffset from, |
| IstreamOffset to) { |
| /* TODO(binji): mark function entries */ |
| /* TODO(binji): track value stack size */ |
| if (from >= istream_->data.size()) { |
| return; |
| } |
| to = std::min<IstreamOffset>(to, istream_->data.size()); |
| const uint8_t* istream = istream_->data.data(); |
| const uint8_t* pc = &istream[from]; |
| |
| while (static_cast<IstreamOffset>(pc - istream) < to) { |
| stream->Writef("%4" PRIzd "| ", pc - istream); |
| |
| Opcode opcode = ReadOpcode(&pc); |
| assert(!opcode.IsInvalid()); |
| switch (opcode) { |
| case Opcode::Select: |
| case Opcode::V128BitSelect: |
| stream->Writef("%s %%[-3], %%[-2], %%[-1]\n", opcode.GetName()); |
| break; |
| |
| case Opcode::Br: |
| stream->Writef("%s @%u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::BrIf: |
| stream->Writef("%s @%u, %%[-1]\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::BrTable: { |
| const Index num_targets = ReadU32(&pc); |
| const IstreamOffset table_offset = ReadU32(&pc); |
| stream->Writef("%s %%[-1], $#%" PRIindex ", table:$%u\n", |
| opcode.GetName(), num_targets, table_offset); |
| break; |
| } |
| |
| case Opcode::Nop: |
| case Opcode::Return: |
| case Opcode::Unreachable: |
| case Opcode::Drop: |
| stream->Writef("%s\n", opcode.GetName()); |
| break; |
| |
| case Opcode::MemorySize: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex "\n", opcode.GetName(), memory_index); |
| break; |
| } |
| |
| case Opcode::I32Const: |
| stream->Writef("%s %u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::I64Const: |
| stream->Writef("%s %" PRIu64 "\n", opcode.GetName(), ReadU64(&pc)); |
| break; |
| |
| case Opcode::F32Const: |
| stream->Writef("%s %g\n", opcode.GetName(), |
| Bitcast<float>(ReadU32(&pc))); |
| break; |
| |
| case Opcode::F64Const: |
| stream->Writef("%s %g\n", opcode.GetName(), |
| Bitcast<double>(ReadU64(&pc))); |
| break; |
| |
| case Opcode::LocalGet: |
| case Opcode::GlobalGet: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::LocalSet: |
| case Opcode::GlobalSet: |
| case Opcode::LocalTee: |
| stream->Writef("%s $%u, %%[-1]\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::Call: |
| case Opcode::ReturnCall: |
| stream->Writef("%s @%u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::CallIndirect: |
| case Opcode::ReturnCallIndirect: { |
| const Index table_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u, %%[-1]\n", opcode.GetName(), |
| table_index, ReadU32(&pc)); |
| break; |
| } |
| |
| case Opcode::InterpCallHost: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::I32AtomicLoad: |
| case Opcode::I64AtomicLoad: |
| case Opcode::I32AtomicLoad8U: |
| case Opcode::I32AtomicLoad16U: |
| case Opcode::I64AtomicLoad8U: |
| case Opcode::I64AtomicLoad16U: |
| case Opcode::I64AtomicLoad32U: |
| case Opcode::I32Load8S: |
| case Opcode::I32Load8U: |
| case Opcode::I32Load16S: |
| case Opcode::I32Load16U: |
| case Opcode::I64Load8S: |
| case Opcode::I64Load8U: |
| case Opcode::I64Load16S: |
| case Opcode::I64Load16U: |
| case Opcode::I64Load32S: |
| case Opcode::I64Load32U: |
| case Opcode::I32Load: |
| case Opcode::I64Load: |
| case Opcode::F32Load: |
| case Opcode::F64Load: |
| case Opcode::V128Load: |
| case Opcode::I8X16LoadSplat: |
| case Opcode::I16X8LoadSplat: |
| case Opcode::I32X4LoadSplat: |
| case Opcode::I64X2LoadSplat: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%%[-1]+$%u\n", opcode.GetName(), |
| memory_index, ReadU32(&pc)); |
| break; |
| } |
| |
| case Opcode::AtomicNotify: |
| case Opcode::I32AtomicStore: |
| case Opcode::I64AtomicStore: |
| case Opcode::I32AtomicStore8: |
| case Opcode::I32AtomicStore16: |
| case Opcode::I64AtomicStore8: |
| case Opcode::I64AtomicStore16: |
| case Opcode::I64AtomicStore32: |
| case Opcode::I32AtomicRmwAdd: |
| case Opcode::I64AtomicRmwAdd: |
| case Opcode::I32AtomicRmw8AddU: |
| case Opcode::I32AtomicRmw16AddU: |
| case Opcode::I64AtomicRmw8AddU: |
| case Opcode::I64AtomicRmw16AddU: |
| case Opcode::I64AtomicRmw32AddU: |
| case Opcode::I32AtomicRmwSub: |
| case Opcode::I64AtomicRmwSub: |
| case Opcode::I32AtomicRmw8SubU: |
| case Opcode::I32AtomicRmw16SubU: |
| case Opcode::I64AtomicRmw8SubU: |
| case Opcode::I64AtomicRmw16SubU: |
| case Opcode::I64AtomicRmw32SubU: |
| case Opcode::I32AtomicRmwAnd: |
| case Opcode::I64AtomicRmwAnd: |
| case Opcode::I32AtomicRmw8AndU: |
| case Opcode::I32AtomicRmw16AndU: |
| case Opcode::I64AtomicRmw8AndU: |
| case Opcode::I64AtomicRmw16AndU: |
| case Opcode::I64AtomicRmw32AndU: |
| case Opcode::I32AtomicRmwOr: |
| case Opcode::I64AtomicRmwOr: |
| case Opcode::I32AtomicRmw8OrU: |
| case Opcode::I32AtomicRmw16OrU: |
| case Opcode::I64AtomicRmw8OrU: |
| case Opcode::I64AtomicRmw16OrU: |
| case Opcode::I64AtomicRmw32OrU: |
| case Opcode::I32AtomicRmwXor: |
| case Opcode::I64AtomicRmwXor: |
| case Opcode::I32AtomicRmw8XorU: |
| case Opcode::I32AtomicRmw16XorU: |
| case Opcode::I64AtomicRmw8XorU: |
| case Opcode::I64AtomicRmw16XorU: |
| case Opcode::I64AtomicRmw32XorU: |
| case Opcode::I32AtomicRmwXchg: |
| case Opcode::I64AtomicRmwXchg: |
| case Opcode::I32AtomicRmw8XchgU: |
| case Opcode::I32AtomicRmw16XchgU: |
| case Opcode::I64AtomicRmw8XchgU: |
| case Opcode::I64AtomicRmw16XchgU: |
| case Opcode::I64AtomicRmw32XchgU: |
| case Opcode::I32Store8: |
| case Opcode::I32Store16: |
| case Opcode::I32Store: |
| case Opcode::I64Store8: |
| case Opcode::I64Store16: |
| case Opcode::I64Store32: |
| case Opcode::I64Store: |
| case Opcode::F32Store: |
| case Opcode::F64Store: |
| case Opcode::V128Store: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%%[-2]+$%u, %%[-1]\n", |
| opcode.GetName(), memory_index, ReadU32(&pc)); |
| break; |
| } |
| |
| case Opcode::I32AtomicWait: |
| case Opcode::I64AtomicWait: |
| case Opcode::I32AtomicRmwCmpxchg: |
| case Opcode::I64AtomicRmwCmpxchg: |
| case Opcode::I32AtomicRmw8CmpxchgU: |
| case Opcode::I32AtomicRmw16CmpxchgU: |
| case Opcode::I64AtomicRmw8CmpxchgU: |
| case Opcode::I64AtomicRmw16CmpxchgU: |
| case Opcode::I64AtomicRmw32CmpxchgU: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%%[-3]+$%u, %%[-2], %%[-1]\n", |
| opcode.GetName(), memory_index, ReadU32(&pc)); |
| break; |
| } |
| |
| case Opcode::I32Add: |
| case Opcode::I32Sub: |
| case Opcode::I32Mul: |
| case Opcode::I32DivS: |
| case Opcode::I32DivU: |
| case Opcode::I32RemS: |
| case Opcode::I32RemU: |
| case Opcode::I32And: |
| case Opcode::I32Or: |
| case Opcode::I32Xor: |
| case Opcode::I32Shl: |
| case Opcode::I32ShrU: |
| case Opcode::I32ShrS: |
| case Opcode::I32Eq: |
| case Opcode::I32Ne: |
| case Opcode::I32LtS: |
| case Opcode::I32LeS: |
| case Opcode::I32LtU: |
| case Opcode::I32LeU: |
| case Opcode::I32GtS: |
| case Opcode::I32GeS: |
| case Opcode::I32GtU: |
| case Opcode::I32GeU: |
| case Opcode::I32Rotr: |
| case Opcode::I32Rotl: |
| case Opcode::F32Add: |
| case Opcode::F32Sub: |
| case Opcode::F32Mul: |
| case Opcode::F32Div: |
| case Opcode::F32Min: |
| case Opcode::F32Max: |
| case Opcode::F32Copysign: |
| case Opcode::F32Eq: |
| case Opcode::F32Ne: |
| case Opcode::F32Lt: |
| case Opcode::F32Le: |
| case Opcode::F32Gt: |
| case Opcode::F32Ge: |
| case Opcode::I64Add: |
| case Opcode::I64Sub: |
| case Opcode::I64Mul: |
| case Opcode::I64DivS: |
| case Opcode::I64DivU: |
| case Opcode::I64RemS: |
| case Opcode::I64RemU: |
| case Opcode::I64And: |
| case Opcode::I64Or: |
| case Opcode::I64Xor: |
| case Opcode::I64Shl: |
| case Opcode::I64ShrU: |
| case Opcode::I64ShrS: |
| case Opcode::I64Eq: |
| case Opcode::I64Ne: |
| case Opcode::I64LtS: |
| case Opcode::I64LeS: |
| case Opcode::I64LtU: |
| case Opcode::I64LeU: |
| case Opcode::I64GtS: |
| case Opcode::I64GeS: |
| case Opcode::I64GtU: |
| case Opcode::I64GeU: |
| case Opcode::I64Rotr: |
| case Opcode::I64Rotl: |
| case Opcode::F64Add: |
| case Opcode::F64Sub: |
| case Opcode::F64Mul: |
| case Opcode::F64Div: |
| case Opcode::F64Min: |
| case Opcode::F64Max: |
| case Opcode::F64Copysign: |
| case Opcode::F64Eq: |
| case Opcode::F64Ne: |
| case Opcode::F64Lt: |
| case Opcode::F64Le: |
| case Opcode::F64Gt: |
| case Opcode::F64Ge: |
| case Opcode::I8X16Add: |
| case Opcode::I16X8Add: |
| case Opcode::I32X4Add: |
| case Opcode::I64X2Add: |
| case Opcode::I8X16Sub: |
| case Opcode::I16X8Sub: |
| case Opcode::I32X4Sub: |
| case Opcode::I64X2Sub: |
| case Opcode::I8X16Mul: |
| case Opcode::I16X8Mul: |
| case Opcode::I32X4Mul: |
| case Opcode::I8X16AddSaturateS: |
| case Opcode::I8X16AddSaturateU: |
| case Opcode::I16X8AddSaturateS: |
| case Opcode::I16X8AddSaturateU: |
| case Opcode::I8X16SubSaturateS: |
| case Opcode::I8X16SubSaturateU: |
| case Opcode::I16X8SubSaturateS: |
| case Opcode::I16X8SubSaturateU: |
| case Opcode::I8X16Shl: |
| case Opcode::I16X8Shl: |
| case Opcode::I32X4Shl: |
| case Opcode::I64X2Shl: |
| case Opcode::I8X16ShrS: |
| case Opcode::I8X16ShrU: |
| case Opcode::I16X8ShrS: |
| case Opcode::I16X8ShrU: |
| case Opcode::I32X4ShrS: |
| case Opcode::I32X4ShrU: |
| case Opcode::I64X2ShrS: |
| case Opcode::I64X2ShrU: |
| case Opcode::V128And: |
| case Opcode::V128Or: |
| case Opcode::V128Xor: |
| case Opcode::I8X16Eq: |
| case Opcode::I16X8Eq: |
| case Opcode::I32X4Eq: |
| case Opcode::F32X4Eq: |
| case Opcode::F64X2Eq: |
| case Opcode::I8X16Ne: |
| case Opcode::I16X8Ne: |
| case Opcode::I32X4Ne: |
| case Opcode::F32X4Ne: |
| case Opcode::F64X2Ne: |
| case Opcode::I8X16LtS: |
| case Opcode::I8X16LtU: |
| case Opcode::I16X8LtS: |
| case Opcode::I16X8LtU: |
| case Opcode::I32X4LtS: |
| case Opcode::I32X4LtU: |
| case Opcode::F32X4Lt: |
| case Opcode::F64X2Lt: |
| case Opcode::I8X16LeS: |
| case Opcode::I8X16LeU: |
| case Opcode::I16X8LeS: |
| case Opcode::I16X8LeU: |
| case Opcode::I32X4LeS: |
| case Opcode::I32X4LeU: |
| case Opcode::F32X4Le: |
| case Opcode::F64X2Le: |
| case Opcode::I8X16GtS: |
| case Opcode::I8X16GtU: |
| case Opcode::I16X8GtS: |
| case Opcode::I16X8GtU: |
| case Opcode::I32X4GtS: |
| case Opcode::I32X4GtU: |
| case Opcode::F32X4Gt: |
| case Opcode::F64X2Gt: |
| case Opcode::I8X16GeS: |
| case Opcode::I8X16GeU: |
| case Opcode::I16X8GeS: |
| case Opcode::I16X8GeU: |
| case Opcode::I32X4GeS: |
| case Opcode::I32X4GeU: |
| case Opcode::F32X4Ge: |
| case Opcode::F64X2Ge: |
| case Opcode::F32X4Min: |
| case Opcode::F64X2Min: |
| case Opcode::F32X4Max: |
| case Opcode::F64X2Max: |
| case Opcode::F32X4Add: |
| case Opcode::F64X2Add: |
| case Opcode::F32X4Sub: |
| case Opcode::F64X2Sub: |
| case Opcode::F32X4Div: |
| case Opcode::F64X2Div: |
| case Opcode::F32X4Mul: |
| case Opcode::F64X2Mul: |
| case Opcode::V8X16Swizzle: |
| stream->Writef("%s %%[-2], %%[-1]\n", opcode.GetName()); |
| break; |
| |
| case Opcode::I32Clz: |
| case Opcode::I32Ctz: |
| case Opcode::I32Popcnt: |
| case Opcode::I32Eqz: |
| case Opcode::I64Clz: |
| case Opcode::I64Ctz: |
| case Opcode::I64Popcnt: |
| case Opcode::I64Eqz: |
| case Opcode::F32Abs: |
| case Opcode::F32Neg: |
| case Opcode::F32Ceil: |
| case Opcode::F32Floor: |
| case Opcode::F32Trunc: |
| case Opcode::F32Nearest: |
| case Opcode::F32Sqrt: |
| case Opcode::F64Abs: |
| case Opcode::F64Neg: |
| case Opcode::F64Ceil: |
| case Opcode::F64Floor: |
| case Opcode::F64Trunc: |
| case Opcode::F64Nearest: |
| case Opcode::F64Sqrt: |
| case Opcode::I32TruncF32S: |
| case Opcode::I32TruncF32U: |
| case Opcode::I64TruncF32S: |
| case Opcode::I64TruncF32U: |
| case Opcode::F64PromoteF32: |
| case Opcode::I32ReinterpretF32: |
| case Opcode::I32TruncF64S: |
| case Opcode::I32TruncF64U: |
| case Opcode::I64TruncF64S: |
| case Opcode::I64TruncF64U: |
| case Opcode::F32DemoteF64: |
| case Opcode::I64ReinterpretF64: |
| case Opcode::I32WrapI64: |
| case Opcode::F32ConvertI64S: |
| case Opcode::F32ConvertI64U: |
| case Opcode::F64ConvertI64S: |
| case Opcode::F64ConvertI64U: |
| case Opcode::F64ReinterpretI64: |
| case Opcode::I64ExtendI32S: |
| case Opcode::I64ExtendI32U: |
| case Opcode::F32ConvertI32S: |
| case Opcode::F32ConvertI32U: |
| case Opcode::F32ReinterpretI32: |
| case Opcode::F64ConvertI32S: |
| case Opcode::F64ConvertI32U: |
| case Opcode::I32TruncSatF32S: |
| case Opcode::I32TruncSatF32U: |
| case Opcode::I64TruncSatF32S: |
| case Opcode::I64TruncSatF32U: |
| case Opcode::I32TruncSatF64S: |
| case Opcode::I32TruncSatF64U: |
| case Opcode::I64TruncSatF64S: |
| case Opcode::I64TruncSatF64U: |
| case Opcode::I32Extend16S: |
| case Opcode::I32Extend8S: |
| case Opcode::I64Extend16S: |
| case Opcode::I64Extend32S: |
| case Opcode::I64Extend8S: |
| case Opcode::I8X16Splat: |
| case Opcode::I16X8Splat: |
| case Opcode::I32X4Splat: |
| case Opcode::I64X2Splat: |
| case Opcode::F32X4Splat: |
| case Opcode::F64X2Splat: |
| case Opcode::I8X16Neg: |
| case Opcode::I16X8Neg: |
| case Opcode::I32X4Neg: |
| case Opcode::I64X2Neg: |
| case Opcode::V128Not: |
| case Opcode::I8X16AnyTrue: |
| case Opcode::I16X8AnyTrue: |
| case Opcode::I32X4AnyTrue: |
| case Opcode::I64X2AnyTrue: |
| case Opcode::I8X16AllTrue: |
| case Opcode::I16X8AllTrue: |
| case Opcode::I32X4AllTrue: |
| case Opcode::I64X2AllTrue: |
| case Opcode::F32X4Neg: |
| case Opcode::F64X2Neg: |
| case Opcode::F32X4Abs: |
| case Opcode::F64X2Abs: |
| case Opcode::F32X4Sqrt: |
| case Opcode::F64X2Sqrt: |
| case Opcode::F32X4ConvertI32X4S: |
| case Opcode::F32X4ConvertI32X4U: |
| case Opcode::F64X2ConvertI64X2S: |
| case Opcode::F64X2ConvertI64X2U: |
| case Opcode::I32X4TruncSatF32X4S: |
| case Opcode::I32X4TruncSatF32X4U: |
| case Opcode::I64X2TruncSatF64X2S: |
| case Opcode::I64X2TruncSatF64X2U: |
| stream->Writef("%s %%[-1]\n", opcode.GetName()); |
| break; |
| |
| case Opcode::I8X16ExtractLaneS: |
| case Opcode::I8X16ExtractLaneU: |
| case Opcode::I16X8ExtractLaneS: |
| case Opcode::I16X8ExtractLaneU: |
| case Opcode::I32X4ExtractLane: |
| case Opcode::I64X2ExtractLane: |
| case Opcode::F32X4ExtractLane: |
| case Opcode::F64X2ExtractLane: { |
| stream->Writef("%s %%[-1] : (Lane imm: %d)\n", opcode.GetName(), |
| ReadU8(&pc)); |
| break; |
| } |
| |
| case Opcode::I8X16ReplaceLane: |
| case Opcode::I16X8ReplaceLane: |
| case Opcode::I32X4ReplaceLane: |
| case Opcode::I64X2ReplaceLane: |
| case Opcode::F32X4ReplaceLane: |
| case Opcode::F64X2ReplaceLane: { |
| stream->Writef("%s %%[-1], %%[-2] : (Lane imm: %d)\n", |
| opcode.GetName(), ReadU8(&pc)); |
| break; |
| } |
| |
| case Opcode::V8X16Shuffle: |
| stream->Writef( |
| "%s %%[-2], %%[-1] : (Lane imm: $0x%08x 0x%08x 0x%08x 0x%08x )\n", |
| opcode.GetName(), ReadU32(&pc), ReadU32(&pc), ReadU32(&pc), |
| ReadU32(&pc)); |
| break; |
| |
| case Opcode::MemoryGrow: { |
| Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%%[-1]\n", opcode.GetName(), |
| memory_index); |
| break; |
| } |
| |
| case Opcode::InterpAlloca: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::InterpBrUnless: |
| stream->Writef("%s @%u, %%[-1]\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::InterpDropKeep: { |
| const uint32_t drop = ReadU32(&pc); |
| const uint32_t keep = ReadU32(&pc); |
| stream->Writef("%s $%u $%u\n", opcode.GetName(), drop, keep); |
| break; |
| } |
| |
| case Opcode::InterpData: { |
| const uint32_t num_bytes = ReadU32(&pc); |
| stream->Writef("%s $%u\n", opcode.GetName(), num_bytes); |
| /* for now, the only reason this is emitted is for br_table, so display |
| * it as a list of table entries */ |
| if (num_bytes % WABT_TABLE_ENTRY_SIZE == 0) { |
| Index num_entries = num_bytes / WABT_TABLE_ENTRY_SIZE; |
| for (Index i = 0; i < num_entries; ++i) { |
| stream->Writef("%4" PRIzd "| ", pc - istream); |
| IstreamOffset offset; |
| uint32_t drop; |
| uint32_t keep; |
| ReadTableEntryAt(pc, &offset, &drop, &keep); |
| stream->Writef(" entry %" PRIindex |
| ": offset: %u drop: %u keep: %u\n", |
| i, offset, drop, keep); |
| pc += WABT_TABLE_ENTRY_SIZE; |
| } |
| } else { |
| /* just skip those data bytes */ |
| pc += num_bytes; |
| } |
| |
| break; |
| } |
| |
| case Opcode::V128Const: { |
| stream->Writef("%s i32x4 0x%08x 0x%08x 0x%08x 0x%08x\n", opcode.GetName(), |
| ReadU32(&pc), ReadU32(&pc), ReadU32(&pc), ReadU32(&pc)); |
| |
| break; |
| } |
| |
| case Opcode::TableGet: |
| case Opcode::TableSet: |
| case Opcode::TableGrow: |
| case Opcode::TableSize: |
| case Opcode::RefNull: |
| case Opcode::RefIsNull: |
| case Opcode::RefFunc: |
| WABT_UNREACHABLE; |
| break; |
| |
| case Opcode::MemoryInit: |
| case Opcode::TableInit: { |
| Index index = ReadU32(&pc); |
| Index segment_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ", $%" PRIindex |
| ", %%[-3], %%[-2], %%[-1]\n", |
| opcode.GetName(), index, segment_index); |
| break; |
| } |
| |
| case Opcode::DataDrop: |
| case Opcode::ElemDrop: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32(&pc)); |
| break; |
| |
| case Opcode::MemoryCopy: |
| case Opcode::MemoryFill: |
| stream->Writef("%s $%u, %%[-3], %%[-2], %%[-1]\n", opcode.GetName(), |
| ReadU32(&pc)); |
| break; |
| |
| case Opcode::TableCopy: |
| stream->Writef("%s $%u, $%u, %%[-3], %%[-2], %%[-1]\n", |
| opcode.GetName(), ReadU32(&pc), ReadU32(&pc)); |
| break; |
| |
| // The following opcodes are either never generated or should never be |
| // executed. |
| case Opcode::Block: |
| case Opcode::BrOnExn: |
| case Opcode::Catch: |
| case Opcode::Else: |
| case Opcode::End: |
| case Opcode::If: |
| case Opcode::Invalid: |
| case Opcode::Loop: |
| case Opcode::Rethrow: |
| case Opcode::Throw: |
| case Opcode::Try: |
| WABT_UNREACHABLE; |
| break; |
| } |
| } |
| } |
| |
| void Environment::DisassembleModule(Stream* stream, Module* module) { |
| assert(!module->is_host); |
| auto* defined_module = cast<DefinedModule>(module); |
| Disassemble(stream, defined_module->istream_start, |
| defined_module->istream_end); |
| } |
| |
| } // namespace interp |
| } // namespace wabt |