diff --git a/Sources/WAT/Encoder.swift b/Sources/WAT/Encoder.swift index ec76b9a5..9789d7ed 100644 --- a/Sources/WAT/Encoder.swift +++ b/Sources/WAT/Encoder.swift @@ -499,7 +499,7 @@ struct ExpressionEncoder: InstructionEncoder { mutating func encodeImmediates(globalIndex: UInt32) throws { encodeUnsigned(globalIndex) } mutating func encodeImmediates(localIndex: UInt32) throws { encodeUnsigned(localIndex) } mutating func encodeImmediates(memarg: WasmParser.MemArg) throws { - encodeUnsigned(UInt(memarg.align.trailingZeroBitCount)) + encodeUnsigned(UInt(memarg.align)) encodeUnsigned(memarg.offset) } mutating func encodeImmediates(memory: UInt32) throws { encodeUnsigned(memory) } diff --git a/Sources/WAT/InstructionEncoder.swift b/Sources/WAT/InstructionEncoder.swift index 05217cae..14a2b8ba 100644 --- a/Sources/WAT/InstructionEncoder.swift +++ b/Sources/WAT/InstructionEncoder.swift @@ -99,96 +99,43 @@ extension InstructionEncoder { try encodeInstruction(0x24, nil) try encodeImmediates(globalIndex: globalIndex) } - mutating func visitI32Load(memarg: MemArg) throws { - try encodeInstruction(0x28, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load(memarg: MemArg) throws { - try encodeInstruction(0x29, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitF32Load(memarg: MemArg) throws { - try encodeInstruction(0x2A, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitF64Load(memarg: MemArg) throws { - try encodeInstruction(0x2B, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Load8S(memarg: MemArg) throws { - try encodeInstruction(0x2C, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Load8U(memarg: MemArg) throws { - try encodeInstruction(0x2D, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Load16S(memarg: MemArg) throws { - try encodeInstruction(0x2E, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Load16U(memarg: MemArg) throws { - try encodeInstruction(0x2F, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load8S(memarg: MemArg) throws { - try encodeInstruction(0x30, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load8U(memarg: MemArg) throws { - try encodeInstruction(0x31, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load16S(memarg: MemArg) throws { - try encodeInstruction(0x32, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load16U(memarg: MemArg) throws { - try encodeInstruction(0x33, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load32S(memarg: MemArg) throws { - try encodeInstruction(0x34, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Load32U(memarg: MemArg) throws { - try encodeInstruction(0x35, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Store(memarg: MemArg) throws { - try encodeInstruction(0x36, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Store(memarg: MemArg) throws { - try encodeInstruction(0x37, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitF32Store(memarg: MemArg) throws { - try encodeInstruction(0x38, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitF64Store(memarg: MemArg) throws { - try encodeInstruction(0x39, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Store8(memarg: MemArg) throws { - try encodeInstruction(0x3A, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI32Store16(memarg: MemArg) throws { - try encodeInstruction(0x3B, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Store8(memarg: MemArg) throws { - try encodeInstruction(0x3C, nil) - try encodeImmediates(memarg: memarg) - } - mutating func visitI64Store16(memarg: MemArg) throws { - try encodeInstruction(0x3D, nil) + mutating func visitLoad(_ load: Instruction.Load, memarg: MemArg) throws { + let (prefix, opcode): (UInt8?, UInt8) + switch load { + case .i32Load: (prefix, opcode) = (nil, 0x28) + case .i64Load: (prefix, opcode) = (nil, 0x29) + case .f32Load: (prefix, opcode) = (nil, 0x2A) + case .f64Load: (prefix, opcode) = (nil, 0x2B) + case .i32Load8S: (prefix, opcode) = (nil, 0x2C) + case .i32Load8U: (prefix, opcode) = (nil, 0x2D) + case .i32Load16S: (prefix, opcode) = (nil, 0x2E) + case .i32Load16U: (prefix, opcode) = (nil, 0x2F) + case .i64Load8S: (prefix, opcode) = (nil, 0x30) + case .i64Load8U: (prefix, opcode) = (nil, 0x31) + case .i64Load16S: (prefix, opcode) = (nil, 0x32) + case .i64Load16U: (prefix, opcode) = (nil, 0x33) + case .i64Load32S: (prefix, opcode) = (nil, 0x34) + case .i64Load32U: (prefix, opcode) = (nil, 0x35) + } + + try encodeInstruction(opcode, prefix) try encodeImmediates(memarg: memarg) } - mutating func visitI64Store32(memarg: MemArg) throws { - try encodeInstruction(0x3E, nil) + mutating func visitStore(_ store: Instruction.Store, memarg: MemArg) throws { + let (prefix, opcode): (UInt8?, UInt8) + switch store { + case .i32Store: (prefix, opcode) = (nil, 0x36) + case .i64Store: (prefix, opcode) = (nil, 0x37) + case .f32Store: (prefix, opcode) = (nil, 0x38) + case .f64Store: (prefix, opcode) = (nil, 0x39) + case .i32Store8: (prefix, opcode) = (nil, 0x3A) + case .i32Store16: (prefix, opcode) = (nil, 0x3B) + case .i64Store8: (prefix, opcode) = (nil, 0x3C) + case .i64Store16: (prefix, opcode) = (nil, 0x3D) + case .i64Store32: (prefix, opcode) = (nil, 0x3E) + } + + try encodeInstruction(opcode, prefix) try encodeImmediates(memarg: memarg) } mutating func visitMemorySize(memory: UInt32) throws { @@ -225,133 +172,169 @@ extension InstructionEncoder { try encodeImmediates(functionIndex: functionIndex) } mutating func visitI32Eqz() throws { try encodeInstruction(0x45, nil) } - mutating func visitI32Eq() throws { try encodeInstruction(0x46, nil) } - mutating func visitI32Ne() throws { try encodeInstruction(0x47, nil) } - mutating func visitI32LtS() throws { try encodeInstruction(0x48, nil) } - mutating func visitI32LtU() throws { try encodeInstruction(0x49, nil) } - mutating func visitI32GtS() throws { try encodeInstruction(0x4A, nil) } - mutating func visitI32GtU() throws { try encodeInstruction(0x4B, nil) } - mutating func visitI32LeS() throws { try encodeInstruction(0x4C, nil) } - mutating func visitI32LeU() throws { try encodeInstruction(0x4D, nil) } - mutating func visitI32GeS() throws { try encodeInstruction(0x4E, nil) } - mutating func visitI32GeU() throws { try encodeInstruction(0x4F, nil) } + mutating func visitCmp(_ cmp: Instruction.Cmp) throws { + let (prefix, opcode): (UInt8?, UInt8) + switch cmp { + case .i32Eq: (prefix, opcode) = (nil, 0x46) + case .i32Ne: (prefix, opcode) = (nil, 0x47) + case .i32LtS: (prefix, opcode) = (nil, 0x48) + case .i32LtU: (prefix, opcode) = (nil, 0x49) + case .i32GtS: (prefix, opcode) = (nil, 0x4A) + case .i32GtU: (prefix, opcode) = (nil, 0x4B) + case .i32LeS: (prefix, opcode) = (nil, 0x4C) + case .i32LeU: (prefix, opcode) = (nil, 0x4D) + case .i32GeS: (prefix, opcode) = (nil, 0x4E) + case .i32GeU: (prefix, opcode) = (nil, 0x4F) + case .i64Eq: (prefix, opcode) = (nil, 0x51) + case .i64Ne: (prefix, opcode) = (nil, 0x52) + case .i64LtS: (prefix, opcode) = (nil, 0x53) + case .i64LtU: (prefix, opcode) = (nil, 0x54) + case .i64GtS: (prefix, opcode) = (nil, 0x55) + case .i64GtU: (prefix, opcode) = (nil, 0x56) + case .i64LeS: (prefix, opcode) = (nil, 0x57) + case .i64LeU: (prefix, opcode) = (nil, 0x58) + case .i64GeS: (prefix, opcode) = (nil, 0x59) + case .i64GeU: (prefix, opcode) = (nil, 0x5A) + case .f32Eq: (prefix, opcode) = (nil, 0x5B) + case .f32Ne: (prefix, opcode) = (nil, 0x5C) + case .f32Lt: (prefix, opcode) = (nil, 0x5D) + case .f32Gt: (prefix, opcode) = (nil, 0x5E) + case .f32Le: (prefix, opcode) = (nil, 0x5F) + case .f32Ge: (prefix, opcode) = (nil, 0x60) + case .f64Eq: (prefix, opcode) = (nil, 0x61) + case .f64Ne: (prefix, opcode) = (nil, 0x62) + case .f64Lt: (prefix, opcode) = (nil, 0x63) + case .f64Gt: (prefix, opcode) = (nil, 0x64) + case .f64Le: (prefix, opcode) = (nil, 0x65) + case .f64Ge: (prefix, opcode) = (nil, 0x66) + } + + try encodeInstruction(opcode, prefix) + } mutating func visitI64Eqz() throws { try encodeInstruction(0x50, nil) } - mutating func visitI64Eq() throws { try encodeInstruction(0x51, nil) } - mutating func visitI64Ne() throws { try encodeInstruction(0x52, nil) } - mutating func visitI64LtS() throws { try encodeInstruction(0x53, nil) } - mutating func visitI64LtU() throws { try encodeInstruction(0x54, nil) } - mutating func visitI64GtS() throws { try encodeInstruction(0x55, nil) } - mutating func visitI64GtU() throws { try encodeInstruction(0x56, nil) } - mutating func visitI64LeS() throws { try encodeInstruction(0x57, nil) } - mutating func visitI64LeU() throws { try encodeInstruction(0x58, nil) } - mutating func visitI64GeS() throws { try encodeInstruction(0x59, nil) } - mutating func visitI64GeU() throws { try encodeInstruction(0x5A, nil) } - mutating func visitF32Eq() throws { try encodeInstruction(0x5B, nil) } - mutating func visitF32Ne() throws { try encodeInstruction(0x5C, nil) } - mutating func visitF32Lt() throws { try encodeInstruction(0x5D, nil) } - mutating func visitF32Gt() throws { try encodeInstruction(0x5E, nil) } - mutating func visitF32Le() throws { try encodeInstruction(0x5F, nil) } - mutating func visitF32Ge() throws { try encodeInstruction(0x60, nil) } - mutating func visitF64Eq() throws { try encodeInstruction(0x61, nil) } - mutating func visitF64Ne() throws { try encodeInstruction(0x62, nil) } - mutating func visitF64Lt() throws { try encodeInstruction(0x63, nil) } - mutating func visitF64Gt() throws { try encodeInstruction(0x64, nil) } - mutating func visitF64Le() throws { try encodeInstruction(0x65, nil) } - mutating func visitF64Ge() throws { try encodeInstruction(0x66, nil) } - mutating func visitI32Clz() throws { try encodeInstruction(0x67, nil) } - mutating func visitI32Ctz() throws { try encodeInstruction(0x68, nil) } - mutating func visitI32Popcnt() throws { try encodeInstruction(0x69, nil) } - mutating func visitI32Add() throws { try encodeInstruction(0x6A, nil) } - mutating func visitI32Sub() throws { try encodeInstruction(0x6B, nil) } - mutating func visitI32Mul() throws { try encodeInstruction(0x6C, nil) } - mutating func visitI32DivS() throws { try encodeInstruction(0x6D, nil) } - mutating func visitI32DivU() throws { try encodeInstruction(0x6E, nil) } - mutating func visitI32RemS() throws { try encodeInstruction(0x6F, nil) } - mutating func visitI32RemU() throws { try encodeInstruction(0x70, nil) } - mutating func visitI32And() throws { try encodeInstruction(0x71, nil) } - mutating func visitI32Or() throws { try encodeInstruction(0x72, nil) } - mutating func visitI32Xor() throws { try encodeInstruction(0x73, nil) } - mutating func visitI32Shl() throws { try encodeInstruction(0x74, nil) } - mutating func visitI32ShrS() throws { try encodeInstruction(0x75, nil) } - mutating func visitI32ShrU() throws { try encodeInstruction(0x76, nil) } - mutating func visitI32Rotl() throws { try encodeInstruction(0x77, nil) } - mutating func visitI32Rotr() throws { try encodeInstruction(0x78, nil) } - mutating func visitI64Clz() throws { try encodeInstruction(0x79, nil) } - mutating func visitI64Ctz() throws { try encodeInstruction(0x7A, nil) } - mutating func visitI64Popcnt() throws { try encodeInstruction(0x7B, nil) } - mutating func visitI64Add() throws { try encodeInstruction(0x7C, nil) } - mutating func visitI64Sub() throws { try encodeInstruction(0x7D, nil) } - mutating func visitI64Mul() throws { try encodeInstruction(0x7E, nil) } - mutating func visitI64DivS() throws { try encodeInstruction(0x7F, nil) } - mutating func visitI64DivU() throws { try encodeInstruction(0x80, nil) } - mutating func visitI64RemS() throws { try encodeInstruction(0x81, nil) } - mutating func visitI64RemU() throws { try encodeInstruction(0x82, nil) } - mutating func visitI64And() throws { try encodeInstruction(0x83, nil) } - mutating func visitI64Or() throws { try encodeInstruction(0x84, nil) } - mutating func visitI64Xor() throws { try encodeInstruction(0x85, nil) } - mutating func visitI64Shl() throws { try encodeInstruction(0x86, nil) } - mutating func visitI64ShrS() throws { try encodeInstruction(0x87, nil) } - mutating func visitI64ShrU() throws { try encodeInstruction(0x88, nil) } - mutating func visitI64Rotl() throws { try encodeInstruction(0x89, nil) } - mutating func visitI64Rotr() throws { try encodeInstruction(0x8A, nil) } - mutating func visitF32Abs() throws { try encodeInstruction(0x8B, nil) } - mutating func visitF32Neg() throws { try encodeInstruction(0x8C, nil) } - mutating func visitF32Ceil() throws { try encodeInstruction(0x8D, nil) } - mutating func visitF32Floor() throws { try encodeInstruction(0x8E, nil) } - mutating func visitF32Trunc() throws { try encodeInstruction(0x8F, nil) } - mutating func visitF32Nearest() throws { try encodeInstruction(0x90, nil) } - mutating func visitF32Sqrt() throws { try encodeInstruction(0x91, nil) } - mutating func visitF32Add() throws { try encodeInstruction(0x92, nil) } - mutating func visitF32Sub() throws { try encodeInstruction(0x93, nil) } - mutating func visitF32Mul() throws { try encodeInstruction(0x94, nil) } - mutating func visitF32Div() throws { try encodeInstruction(0x95, nil) } - mutating func visitF32Min() throws { try encodeInstruction(0x96, nil) } - mutating func visitF32Max() throws { try encodeInstruction(0x97, nil) } - mutating func visitF32Copysign() throws { try encodeInstruction(0x98, nil) } - mutating func visitF64Abs() throws { try encodeInstruction(0x99, nil) } - mutating func visitF64Neg() throws { try encodeInstruction(0x9A, nil) } - mutating func visitF64Ceil() throws { try encodeInstruction(0x9B, nil) } - mutating func visitF64Floor() throws { try encodeInstruction(0x9C, nil) } - mutating func visitF64Trunc() throws { try encodeInstruction(0x9D, nil) } - mutating func visitF64Nearest() throws { try encodeInstruction(0x9E, nil) } - mutating func visitF64Sqrt() throws { try encodeInstruction(0x9F, nil) } - mutating func visitF64Add() throws { try encodeInstruction(0xA0, nil) } - mutating func visitF64Sub() throws { try encodeInstruction(0xA1, nil) } - mutating func visitF64Mul() throws { try encodeInstruction(0xA2, nil) } - mutating func visitF64Div() throws { try encodeInstruction(0xA3, nil) } - mutating func visitF64Min() throws { try encodeInstruction(0xA4, nil) } - mutating func visitF64Max() throws { try encodeInstruction(0xA5, nil) } - mutating func visitF64Copysign() throws { try encodeInstruction(0xA6, nil) } - mutating func visitI32WrapI64() throws { try encodeInstruction(0xA7, nil) } - mutating func visitI32TruncF32S() throws { try encodeInstruction(0xA8, nil) } - mutating func visitI32TruncF32U() throws { try encodeInstruction(0xA9, nil) } - mutating func visitI32TruncF64S() throws { try encodeInstruction(0xAA, nil) } - mutating func visitI32TruncF64U() throws { try encodeInstruction(0xAB, nil) } - mutating func visitI64ExtendI32S() throws { try encodeInstruction(0xAC, nil) } - mutating func visitI64ExtendI32U() throws { try encodeInstruction(0xAD, nil) } - mutating func visitI64TruncF32S() throws { try encodeInstruction(0xAE, nil) } - mutating func visitI64TruncF32U() throws { try encodeInstruction(0xAF, nil) } - mutating func visitI64TruncF64S() throws { try encodeInstruction(0xB0, nil) } - mutating func visitI64TruncF64U() throws { try encodeInstruction(0xB1, nil) } - mutating func visitF32ConvertI32S() throws { try encodeInstruction(0xB2, nil) } - mutating func visitF32ConvertI32U() throws { try encodeInstruction(0xB3, nil) } - mutating func visitF32ConvertI64S() throws { try encodeInstruction(0xB4, nil) } - mutating func visitF32ConvertI64U() throws { try encodeInstruction(0xB5, nil) } - mutating func visitF32DemoteF64() throws { try encodeInstruction(0xB6, nil) } - mutating func visitF64ConvertI32S() throws { try encodeInstruction(0xB7, nil) } - mutating func visitF64ConvertI32U() throws { try encodeInstruction(0xB8, nil) } - mutating func visitF64ConvertI64S() throws { try encodeInstruction(0xB9, nil) } - mutating func visitF64ConvertI64U() throws { try encodeInstruction(0xBA, nil) } - mutating func visitF64PromoteF32() throws { try encodeInstruction(0xBB, nil) } - mutating func visitI32ReinterpretF32() throws { try encodeInstruction(0xBC, nil) } - mutating func visitI64ReinterpretF64() throws { try encodeInstruction(0xBD, nil) } - mutating func visitF32ReinterpretI32() throws { try encodeInstruction(0xBE, nil) } - mutating func visitF64ReinterpretI64() throws { try encodeInstruction(0xBF, nil) } - mutating func visitI32Extend8S() throws { try encodeInstruction(0xC0, nil) } - mutating func visitI32Extend16S() throws { try encodeInstruction(0xC1, nil) } - mutating func visitI64Extend8S() throws { try encodeInstruction(0xC2, nil) } - mutating func visitI64Extend16S() throws { try encodeInstruction(0xC3, nil) } - mutating func visitI64Extend32S() throws { try encodeInstruction(0xC4, nil) } + mutating func visitUnary(_ unary: Instruction.Unary) throws { + let (prefix, opcode): (UInt8?, UInt8) + switch unary { + case .i32Clz: (prefix, opcode) = (nil, 0x67) + case .i32Ctz: (prefix, opcode) = (nil, 0x68) + case .i32Popcnt: (prefix, opcode) = (nil, 0x69) + case .i64Clz: (prefix, opcode) = (nil, 0x79) + case .i64Ctz: (prefix, opcode) = (nil, 0x7A) + case .i64Popcnt: (prefix, opcode) = (nil, 0x7B) + case .f32Abs: (prefix, opcode) = (nil, 0x8B) + case .f32Neg: (prefix, opcode) = (nil, 0x8C) + case .f32Ceil: (prefix, opcode) = (nil, 0x8D) + case .f32Floor: (prefix, opcode) = (nil, 0x8E) + case .f32Trunc: (prefix, opcode) = (nil, 0x8F) + case .f32Nearest: (prefix, opcode) = (nil, 0x90) + case .f32Sqrt: (prefix, opcode) = (nil, 0x91) + case .f64Abs: (prefix, opcode) = (nil, 0x99) + case .f64Neg: (prefix, opcode) = (nil, 0x9A) + case .f64Ceil: (prefix, opcode) = (nil, 0x9B) + case .f64Floor: (prefix, opcode) = (nil, 0x9C) + case .f64Trunc: (prefix, opcode) = (nil, 0x9D) + case .f64Nearest: (prefix, opcode) = (nil, 0x9E) + case .f64Sqrt: (prefix, opcode) = (nil, 0x9F) + case .i32Extend8S: (prefix, opcode) = (nil, 0xC0) + case .i32Extend16S: (prefix, opcode) = (nil, 0xC1) + case .i64Extend8S: (prefix, opcode) = (nil, 0xC2) + case .i64Extend16S: (prefix, opcode) = (nil, 0xC3) + case .i64Extend32S: (prefix, opcode) = (nil, 0xC4) + } + + try encodeInstruction(opcode, prefix) + } + mutating func visitBinary(_ binary: Instruction.Binary) throws { + let (prefix, opcode): (UInt8?, UInt8) + switch binary { + case .i32Add: (prefix, opcode) = (nil, 0x6A) + case .i32Sub: (prefix, opcode) = (nil, 0x6B) + case .i32Mul: (prefix, opcode) = (nil, 0x6C) + case .i32DivS: (prefix, opcode) = (nil, 0x6D) + case .i32DivU: (prefix, opcode) = (nil, 0x6E) + case .i32RemS: (prefix, opcode) = (nil, 0x6F) + case .i32RemU: (prefix, opcode) = (nil, 0x70) + case .i32And: (prefix, opcode) = (nil, 0x71) + case .i32Or: (prefix, opcode) = (nil, 0x72) + case .i32Xor: (prefix, opcode) = (nil, 0x73) + case .i32Shl: (prefix, opcode) = (nil, 0x74) + case .i32ShrS: (prefix, opcode) = (nil, 0x75) + case .i32ShrU: (prefix, opcode) = (nil, 0x76) + case .i32Rotl: (prefix, opcode) = (nil, 0x77) + case .i32Rotr: (prefix, opcode) = (nil, 0x78) + case .i64Add: (prefix, opcode) = (nil, 0x7C) + case .i64Sub: (prefix, opcode) = (nil, 0x7D) + case .i64Mul: (prefix, opcode) = (nil, 0x7E) + case .i64DivS: (prefix, opcode) = (nil, 0x7F) + case .i64DivU: (prefix, opcode) = (nil, 0x80) + case .i64RemS: (prefix, opcode) = (nil, 0x81) + case .i64RemU: (prefix, opcode) = (nil, 0x82) + case .i64And: (prefix, opcode) = (nil, 0x83) + case .i64Or: (prefix, opcode) = (nil, 0x84) + case .i64Xor: (prefix, opcode) = (nil, 0x85) + case .i64Shl: (prefix, opcode) = (nil, 0x86) + case .i64ShrS: (prefix, opcode) = (nil, 0x87) + case .i64ShrU: (prefix, opcode) = (nil, 0x88) + case .i64Rotl: (prefix, opcode) = (nil, 0x89) + case .i64Rotr: (prefix, opcode) = (nil, 0x8A) + case .f32Add: (prefix, opcode) = (nil, 0x92) + case .f32Sub: (prefix, opcode) = (nil, 0x93) + case .f32Mul: (prefix, opcode) = (nil, 0x94) + case .f32Div: (prefix, opcode) = (nil, 0x95) + case .f32Min: (prefix, opcode) = (nil, 0x96) + case .f32Max: (prefix, opcode) = (nil, 0x97) + case .f32Copysign: (prefix, opcode) = (nil, 0x98) + case .f64Add: (prefix, opcode) = (nil, 0xA0) + case .f64Sub: (prefix, opcode) = (nil, 0xA1) + case .f64Mul: (prefix, opcode) = (nil, 0xA2) + case .f64Div: (prefix, opcode) = (nil, 0xA3) + case .f64Min: (prefix, opcode) = (nil, 0xA4) + case .f64Max: (prefix, opcode) = (nil, 0xA5) + case .f64Copysign: (prefix, opcode) = (nil, 0xA6) + } + + try encodeInstruction(opcode, prefix) + } + mutating func visitConversion(_ conversion: Instruction.Conversion) throws { + let (prefix, opcode): (UInt8?, UInt8) + switch conversion { + case .i32WrapI64: (prefix, opcode) = (nil, 0xA7) + case .i32TruncF32S: (prefix, opcode) = (nil, 0xA8) + case .i32TruncF32U: (prefix, opcode) = (nil, 0xA9) + case .i32TruncF64S: (prefix, opcode) = (nil, 0xAA) + case .i32TruncF64U: (prefix, opcode) = (nil, 0xAB) + case .i64ExtendI32S: (prefix, opcode) = (nil, 0xAC) + case .i64ExtendI32U: (prefix, opcode) = (nil, 0xAD) + case .i64TruncF32S: (prefix, opcode) = (nil, 0xAE) + case .i64TruncF32U: (prefix, opcode) = (nil, 0xAF) + case .i64TruncF64S: (prefix, opcode) = (nil, 0xB0) + case .i64TruncF64U: (prefix, opcode) = (nil, 0xB1) + case .f32ConvertI32S: (prefix, opcode) = (nil, 0xB2) + case .f32ConvertI32U: (prefix, opcode) = (nil, 0xB3) + case .f32ConvertI64S: (prefix, opcode) = (nil, 0xB4) + case .f32ConvertI64U: (prefix, opcode) = (nil, 0xB5) + case .f32DemoteF64: (prefix, opcode) = (nil, 0xB6) + case .f64ConvertI32S: (prefix, opcode) = (nil, 0xB7) + case .f64ConvertI32U: (prefix, opcode) = (nil, 0xB8) + case .f64ConvertI64S: (prefix, opcode) = (nil, 0xB9) + case .f64ConvertI64U: (prefix, opcode) = (nil, 0xBA) + case .f64PromoteF32: (prefix, opcode) = (nil, 0xBB) + case .i32ReinterpretF32: (prefix, opcode) = (nil, 0xBC) + case .i64ReinterpretF64: (prefix, opcode) = (nil, 0xBD) + case .f32ReinterpretI32: (prefix, opcode) = (nil, 0xBE) + case .f64ReinterpretI64: (prefix, opcode) = (nil, 0xBF) + case .i32TruncSatF32S: (prefix, opcode) = (0xFC, 0x00) + case .i32TruncSatF32U: (prefix, opcode) = (0xFC, 0x01) + case .i32TruncSatF64S: (prefix, opcode) = (0xFC, 0x02) + case .i32TruncSatF64U: (prefix, opcode) = (0xFC, 0x03) + case .i64TruncSatF32S: (prefix, opcode) = (0xFC, 0x04) + case .i64TruncSatF32U: (prefix, opcode) = (0xFC, 0x05) + case .i64TruncSatF64S: (prefix, opcode) = (0xFC, 0x06) + case .i64TruncSatF64U: (prefix, opcode) = (0xFC, 0x07) + } + + try encodeInstruction(opcode, prefix) + } mutating func visitMemoryInit(dataIndex: UInt32) throws { try encodeInstruction(0x08, 0xFC) try encodeImmediates(dataIndex: dataIndex) @@ -400,12 +383,4 @@ extension InstructionEncoder { try encodeInstruction(0x10, 0xFC) try encodeImmediates(table: table) } - mutating func visitI32TruncSatF32S() throws { try encodeInstruction(0x00, 0xFC) } - mutating func visitI32TruncSatF32U() throws { try encodeInstruction(0x01, 0xFC) } - mutating func visitI32TruncSatF64S() throws { try encodeInstruction(0x02, 0xFC) } - mutating func visitI32TruncSatF64U() throws { try encodeInstruction(0x03, 0xFC) } - mutating func visitI64TruncSatF32S() throws { try encodeInstruction(0x04, 0xFC) } - mutating func visitI64TruncSatF32U() throws { try encodeInstruction(0x05, 0xFC) } - mutating func visitI64TruncSatF64S() throws { try encodeInstruction(0x06, 0xFC) } - mutating func visitI64TruncSatF64U() throws { try encodeInstruction(0x07, 0xFC) } } diff --git a/Sources/WAT/ParseInstruction.swift b/Sources/WAT/ParseInstruction.swift index 4cb90805..8494bd15 100644 --- a/Sources/WAT/ParseInstruction.swift +++ b/Sources/WAT/ParseInstruction.swift @@ -61,74 +61,74 @@ func parseTextInstruction(keyword: String, expressionPars let (globalIndex) = try expressionParser.visitGlobalSet(wat: &wat) return { return try $0.visitGlobalSet(globalIndex: globalIndex) } case "i32.load": - let (memarg) = try expressionParser.visitI32Load(wat: &wat) - return { return try $0.visitI32Load(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i32Load, wat: &wat) + return { return try $0.visitLoad(.i32Load, memarg: memarg) } case "i64.load": - let (memarg) = try expressionParser.visitI64Load(wat: &wat) - return { return try $0.visitI64Load(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load, wat: &wat) + return { return try $0.visitLoad(.i64Load, memarg: memarg) } case "f32.load": - let (memarg) = try expressionParser.visitF32Load(wat: &wat) - return { return try $0.visitF32Load(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.f32Load, wat: &wat) + return { return try $0.visitLoad(.f32Load, memarg: memarg) } case "f64.load": - let (memarg) = try expressionParser.visitF64Load(wat: &wat) - return { return try $0.visitF64Load(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.f64Load, wat: &wat) + return { return try $0.visitLoad(.f64Load, memarg: memarg) } case "i32.load8_s": - let (memarg) = try expressionParser.visitI32Load8S(wat: &wat) - return { return try $0.visitI32Load8S(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i32Load8S, wat: &wat) + return { return try $0.visitLoad(.i32Load8S, memarg: memarg) } case "i32.load8_u": - let (memarg) = try expressionParser.visitI32Load8U(wat: &wat) - return { return try $0.visitI32Load8U(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i32Load8U, wat: &wat) + return { return try $0.visitLoad(.i32Load8U, memarg: memarg) } case "i32.load16_s": - let (memarg) = try expressionParser.visitI32Load16S(wat: &wat) - return { return try $0.visitI32Load16S(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i32Load16S, wat: &wat) + return { return try $0.visitLoad(.i32Load16S, memarg: memarg) } case "i32.load16_u": - let (memarg) = try expressionParser.visitI32Load16U(wat: &wat) - return { return try $0.visitI32Load16U(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i32Load16U, wat: &wat) + return { return try $0.visitLoad(.i32Load16U, memarg: memarg) } case "i64.load8_s": - let (memarg) = try expressionParser.visitI64Load8S(wat: &wat) - return { return try $0.visitI64Load8S(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load8S, wat: &wat) + return { return try $0.visitLoad(.i64Load8S, memarg: memarg) } case "i64.load8_u": - let (memarg) = try expressionParser.visitI64Load8U(wat: &wat) - return { return try $0.visitI64Load8U(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load8U, wat: &wat) + return { return try $0.visitLoad(.i64Load8U, memarg: memarg) } case "i64.load16_s": - let (memarg) = try expressionParser.visitI64Load16S(wat: &wat) - return { return try $0.visitI64Load16S(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load16S, wat: &wat) + return { return try $0.visitLoad(.i64Load16S, memarg: memarg) } case "i64.load16_u": - let (memarg) = try expressionParser.visitI64Load16U(wat: &wat) - return { return try $0.visitI64Load16U(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load16U, wat: &wat) + return { return try $0.visitLoad(.i64Load16U, memarg: memarg) } case "i64.load32_s": - let (memarg) = try expressionParser.visitI64Load32S(wat: &wat) - return { return try $0.visitI64Load32S(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load32S, wat: &wat) + return { return try $0.visitLoad(.i64Load32S, memarg: memarg) } case "i64.load32_u": - let (memarg) = try expressionParser.visitI64Load32U(wat: &wat) - return { return try $0.visitI64Load32U(memarg: memarg) } + let (memarg) = try expressionParser.visitLoad(.i64Load32U, wat: &wat) + return { return try $0.visitLoad(.i64Load32U, memarg: memarg) } case "i32.store": - let (memarg) = try expressionParser.visitI32Store(wat: &wat) - return { return try $0.visitI32Store(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i32Store, wat: &wat) + return { return try $0.visitStore(.i32Store, memarg: memarg) } case "i64.store": - let (memarg) = try expressionParser.visitI64Store(wat: &wat) - return { return try $0.visitI64Store(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i64Store, wat: &wat) + return { return try $0.visitStore(.i64Store, memarg: memarg) } case "f32.store": - let (memarg) = try expressionParser.visitF32Store(wat: &wat) - return { return try $0.visitF32Store(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.f32Store, wat: &wat) + return { return try $0.visitStore(.f32Store, memarg: memarg) } case "f64.store": - let (memarg) = try expressionParser.visitF64Store(wat: &wat) - return { return try $0.visitF64Store(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.f64Store, wat: &wat) + return { return try $0.visitStore(.f64Store, memarg: memarg) } case "i32.store8": - let (memarg) = try expressionParser.visitI32Store8(wat: &wat) - return { return try $0.visitI32Store8(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i32Store8, wat: &wat) + return { return try $0.visitStore(.i32Store8, memarg: memarg) } case "i32.store16": - let (memarg) = try expressionParser.visitI32Store16(wat: &wat) - return { return try $0.visitI32Store16(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i32Store16, wat: &wat) + return { return try $0.visitStore(.i32Store16, memarg: memarg) } case "i64.store8": - let (memarg) = try expressionParser.visitI64Store8(wat: &wat) - return { return try $0.visitI64Store8(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i64Store8, wat: &wat) + return { return try $0.visitStore(.i64Store8, memarg: memarg) } case "i64.store16": - let (memarg) = try expressionParser.visitI64Store16(wat: &wat) - return { return try $0.visitI64Store16(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i64Store16, wat: &wat) + return { return try $0.visitStore(.i64Store16, memarg: memarg) } case "i64.store32": - let (memarg) = try expressionParser.visitI64Store32(wat: &wat) - return { return try $0.visitI64Store32(memarg: memarg) } + let (memarg) = try expressionParser.visitStore(.i64Store32, wat: &wat) + return { return try $0.visitStore(.i64Store32, memarg: memarg) } case "memory.size": let (memory) = try expressionParser.visitMemorySize(wat: &wat) return { return try $0.visitMemorySize(memory: memory) } @@ -155,133 +155,133 @@ func parseTextInstruction(keyword: String, expressionPars let (functionIndex) = try expressionParser.visitRefFunc(wat: &wat) return { return try $0.visitRefFunc(functionIndex: functionIndex) } case "i32.eqz": return { return try $0.visitI32Eqz() } - case "i32.eq": return { return try $0.visitI32Eq() } - case "i32.ne": return { return try $0.visitI32Ne() } - case "i32.lt_s": return { return try $0.visitI32LtS() } - case "i32.lt_u": return { return try $0.visitI32LtU() } - case "i32.gt_s": return { return try $0.visitI32GtS() } - case "i32.gt_u": return { return try $0.visitI32GtU() } - case "i32.le_s": return { return try $0.visitI32LeS() } - case "i32.le_u": return { return try $0.visitI32LeU() } - case "i32.ge_s": return { return try $0.visitI32GeS() } - case "i32.ge_u": return { return try $0.visitI32GeU() } + case "i32.eq": return { return try $0.visitCmp(.i32Eq) } + case "i32.ne": return { return try $0.visitCmp(.i32Ne) } + case "i32.lt_s": return { return try $0.visitCmp(.i32LtS) } + case "i32.lt_u": return { return try $0.visitCmp(.i32LtU) } + case "i32.gt_s": return { return try $0.visitCmp(.i32GtS) } + case "i32.gt_u": return { return try $0.visitCmp(.i32GtU) } + case "i32.le_s": return { return try $0.visitCmp(.i32LeS) } + case "i32.le_u": return { return try $0.visitCmp(.i32LeU) } + case "i32.ge_s": return { return try $0.visitCmp(.i32GeS) } + case "i32.ge_u": return { return try $0.visitCmp(.i32GeU) } case "i64.eqz": return { return try $0.visitI64Eqz() } - case "i64.eq": return { return try $0.visitI64Eq() } - case "i64.ne": return { return try $0.visitI64Ne() } - case "i64.lt_s": return { return try $0.visitI64LtS() } - case "i64.lt_u": return { return try $0.visitI64LtU() } - case "i64.gt_s": return { return try $0.visitI64GtS() } - case "i64.gt_u": return { return try $0.visitI64GtU() } - case "i64.le_s": return { return try $0.visitI64LeS() } - case "i64.le_u": return { return try $0.visitI64LeU() } - case "i64.ge_s": return { return try $0.visitI64GeS() } - case "i64.ge_u": return { return try $0.visitI64GeU() } - case "f32.eq": return { return try $0.visitF32Eq() } - case "f32.ne": return { return try $0.visitF32Ne() } - case "f32.lt": return { return try $0.visitF32Lt() } - case "f32.gt": return { return try $0.visitF32Gt() } - case "f32.le": return { return try $0.visitF32Le() } - case "f32.ge": return { return try $0.visitF32Ge() } - case "f64.eq": return { return try $0.visitF64Eq() } - case "f64.ne": return { return try $0.visitF64Ne() } - case "f64.lt": return { return try $0.visitF64Lt() } - case "f64.gt": return { return try $0.visitF64Gt() } - case "f64.le": return { return try $0.visitF64Le() } - case "f64.ge": return { return try $0.visitF64Ge() } - case "i32.clz": return { return try $0.visitI32Clz() } - case "i32.ctz": return { return try $0.visitI32Ctz() } - case "i32.popcnt": return { return try $0.visitI32Popcnt() } - case "i32.add": return { return try $0.visitI32Add() } - case "i32.sub": return { return try $0.visitI32Sub() } - case "i32.mul": return { return try $0.visitI32Mul() } - case "i32.div_s": return { return try $0.visitI32DivS() } - case "i32.div_u": return { return try $0.visitI32DivU() } - case "i32.rem_s": return { return try $0.visitI32RemS() } - case "i32.rem_u": return { return try $0.visitI32RemU() } - case "i32.and": return { return try $0.visitI32And() } - case "i32.or": return { return try $0.visitI32Or() } - case "i32.xor": return { return try $0.visitI32Xor() } - case "i32.shl": return { return try $0.visitI32Shl() } - case "i32.shr_s": return { return try $0.visitI32ShrS() } - case "i32.shr_u": return { return try $0.visitI32ShrU() } - case "i32.rotl": return { return try $0.visitI32Rotl() } - case "i32.rotr": return { return try $0.visitI32Rotr() } - case "i64.clz": return { return try $0.visitI64Clz() } - case "i64.ctz": return { return try $0.visitI64Ctz() } - case "i64.popcnt": return { return try $0.visitI64Popcnt() } - case "i64.add": return { return try $0.visitI64Add() } - case "i64.sub": return { return try $0.visitI64Sub() } - case "i64.mul": return { return try $0.visitI64Mul() } - case "i64.div_s": return { return try $0.visitI64DivS() } - case "i64.div_u": return { return try $0.visitI64DivU() } - case "i64.rem_s": return { return try $0.visitI64RemS() } - case "i64.rem_u": return { return try $0.visitI64RemU() } - case "i64.and": return { return try $0.visitI64And() } - case "i64.or": return { return try $0.visitI64Or() } - case "i64.xor": return { return try $0.visitI64Xor() } - case "i64.shl": return { return try $0.visitI64Shl() } - case "i64.shr_s": return { return try $0.visitI64ShrS() } - case "i64.shr_u": return { return try $0.visitI64ShrU() } - case "i64.rotl": return { return try $0.visitI64Rotl() } - case "i64.rotr": return { return try $0.visitI64Rotr() } - case "f32.abs": return { return try $0.visitF32Abs() } - case "f32.neg": return { return try $0.visitF32Neg() } - case "f32.ceil": return { return try $0.visitF32Ceil() } - case "f32.floor": return { return try $0.visitF32Floor() } - case "f32.trunc": return { return try $0.visitF32Trunc() } - case "f32.nearest": return { return try $0.visitF32Nearest() } - case "f32.sqrt": return { return try $0.visitF32Sqrt() } - case "f32.add": return { return try $0.visitF32Add() } - case "f32.sub": return { return try $0.visitF32Sub() } - case "f32.mul": return { return try $0.visitF32Mul() } - case "f32.div": return { return try $0.visitF32Div() } - case "f32.min": return { return try $0.visitF32Min() } - case "f32.max": return { return try $0.visitF32Max() } - case "f32.copysign": return { return try $0.visitF32Copysign() } - case "f64.abs": return { return try $0.visitF64Abs() } - case "f64.neg": return { return try $0.visitF64Neg() } - case "f64.ceil": return { return try $0.visitF64Ceil() } - case "f64.floor": return { return try $0.visitF64Floor() } - case "f64.trunc": return { return try $0.visitF64Trunc() } - case "f64.nearest": return { return try $0.visitF64Nearest() } - case "f64.sqrt": return { return try $0.visitF64Sqrt() } - case "f64.add": return { return try $0.visitF64Add() } - case "f64.sub": return { return try $0.visitF64Sub() } - case "f64.mul": return { return try $0.visitF64Mul() } - case "f64.div": return { return try $0.visitF64Div() } - case "f64.min": return { return try $0.visitF64Min() } - case "f64.max": return { return try $0.visitF64Max() } - case "f64.copysign": return { return try $0.visitF64Copysign() } - case "i32.wrap_i64": return { return try $0.visitI32WrapI64() } - case "i32.trunc_f32_s": return { return try $0.visitI32TruncF32S() } - case "i32.trunc_f32_u": return { return try $0.visitI32TruncF32U() } - case "i32.trunc_f64_s": return { return try $0.visitI32TruncF64S() } - case "i32.trunc_f64_u": return { return try $0.visitI32TruncF64U() } - case "i64.extend_i32_s": return { return try $0.visitI64ExtendI32S() } - case "i64.extend_i32_u": return { return try $0.visitI64ExtendI32U() } - case "i64.trunc_f32_s": return { return try $0.visitI64TruncF32S() } - case "i64.trunc_f32_u": return { return try $0.visitI64TruncF32U() } - case "i64.trunc_f64_s": return { return try $0.visitI64TruncF64S() } - case "i64.trunc_f64_u": return { return try $0.visitI64TruncF64U() } - case "f32.convert_i32_s": return { return try $0.visitF32ConvertI32S() } - case "f32.convert_i32_u": return { return try $0.visitF32ConvertI32U() } - case "f32.convert_i64_s": return { return try $0.visitF32ConvertI64S() } - case "f32.convert_i64_u": return { return try $0.visitF32ConvertI64U() } - case "f32.demote_f64": return { return try $0.visitF32DemoteF64() } - case "f64.convert_i32_s": return { return try $0.visitF64ConvertI32S() } - case "f64.convert_i32_u": return { return try $0.visitF64ConvertI32U() } - case "f64.convert_i64_s": return { return try $0.visitF64ConvertI64S() } - case "f64.convert_i64_u": return { return try $0.visitF64ConvertI64U() } - case "f64.promote_f32": return { return try $0.visitF64PromoteF32() } - case "i32.reinterpret_f32": return { return try $0.visitI32ReinterpretF32() } - case "i64.reinterpret_f64": return { return try $0.visitI64ReinterpretF64() } - case "f32.reinterpret_i32": return { return try $0.visitF32ReinterpretI32() } - case "f64.reinterpret_i64": return { return try $0.visitF64ReinterpretI64() } - case "i32.extend8_s": return { return try $0.visitI32Extend8S() } - case "i32.extend16_s": return { return try $0.visitI32Extend16S() } - case "i64.extend8_s": return { return try $0.visitI64Extend8S() } - case "i64.extend16_s": return { return try $0.visitI64Extend16S() } - case "i64.extend32_s": return { return try $0.visitI64Extend32S() } + case "i64.eq": return { return try $0.visitCmp(.i64Eq) } + case "i64.ne": return { return try $0.visitCmp(.i64Ne) } + case "i64.lt_s": return { return try $0.visitCmp(.i64LtS) } + case "i64.lt_u": return { return try $0.visitCmp(.i64LtU) } + case "i64.gt_s": return { return try $0.visitCmp(.i64GtS) } + case "i64.gt_u": return { return try $0.visitCmp(.i64GtU) } + case "i64.le_s": return { return try $0.visitCmp(.i64LeS) } + case "i64.le_u": return { return try $0.visitCmp(.i64LeU) } + case "i64.ge_s": return { return try $0.visitCmp(.i64GeS) } + case "i64.ge_u": return { return try $0.visitCmp(.i64GeU) } + case "f32.eq": return { return try $0.visitCmp(.f32Eq) } + case "f32.ne": return { return try $0.visitCmp(.f32Ne) } + case "f32.lt": return { return try $0.visitCmp(.f32Lt) } + case "f32.gt": return { return try $0.visitCmp(.f32Gt) } + case "f32.le": return { return try $0.visitCmp(.f32Le) } + case "f32.ge": return { return try $0.visitCmp(.f32Ge) } + case "f64.eq": return { return try $0.visitCmp(.f64Eq) } + case "f64.ne": return { return try $0.visitCmp(.f64Ne) } + case "f64.lt": return { return try $0.visitCmp(.f64Lt) } + case "f64.gt": return { return try $0.visitCmp(.f64Gt) } + case "f64.le": return { return try $0.visitCmp(.f64Le) } + case "f64.ge": return { return try $0.visitCmp(.f64Ge) } + case "i32.clz": return { return try $0.visitUnary(.i32Clz) } + case "i32.ctz": return { return try $0.visitUnary(.i32Ctz) } + case "i32.popcnt": return { return try $0.visitUnary(.i32Popcnt) } + case "i32.add": return { return try $0.visitBinary(.i32Add) } + case "i32.sub": return { return try $0.visitBinary(.i32Sub) } + case "i32.mul": return { return try $0.visitBinary(.i32Mul) } + case "i32.div_s": return { return try $0.visitBinary(.i32DivS) } + case "i32.div_u": return { return try $0.visitBinary(.i32DivU) } + case "i32.rem_s": return { return try $0.visitBinary(.i32RemS) } + case "i32.rem_u": return { return try $0.visitBinary(.i32RemU) } + case "i32.and": return { return try $0.visitBinary(.i32And) } + case "i32.or": return { return try $0.visitBinary(.i32Or) } + case "i32.xor": return { return try $0.visitBinary(.i32Xor) } + case "i32.shl": return { return try $0.visitBinary(.i32Shl) } + case "i32.shr_s": return { return try $0.visitBinary(.i32ShrS) } + case "i32.shr_u": return { return try $0.visitBinary(.i32ShrU) } + case "i32.rotl": return { return try $0.visitBinary(.i32Rotl) } + case "i32.rotr": return { return try $0.visitBinary(.i32Rotr) } + case "i64.clz": return { return try $0.visitUnary(.i64Clz) } + case "i64.ctz": return { return try $0.visitUnary(.i64Ctz) } + case "i64.popcnt": return { return try $0.visitUnary(.i64Popcnt) } + case "i64.add": return { return try $0.visitBinary(.i64Add) } + case "i64.sub": return { return try $0.visitBinary(.i64Sub) } + case "i64.mul": return { return try $0.visitBinary(.i64Mul) } + case "i64.div_s": return { return try $0.visitBinary(.i64DivS) } + case "i64.div_u": return { return try $0.visitBinary(.i64DivU) } + case "i64.rem_s": return { return try $0.visitBinary(.i64RemS) } + case "i64.rem_u": return { return try $0.visitBinary(.i64RemU) } + case "i64.and": return { return try $0.visitBinary(.i64And) } + case "i64.or": return { return try $0.visitBinary(.i64Or) } + case "i64.xor": return { return try $0.visitBinary(.i64Xor) } + case "i64.shl": return { return try $0.visitBinary(.i64Shl) } + case "i64.shr_s": return { return try $0.visitBinary(.i64ShrS) } + case "i64.shr_u": return { return try $0.visitBinary(.i64ShrU) } + case "i64.rotl": return { return try $0.visitBinary(.i64Rotl) } + case "i64.rotr": return { return try $0.visitBinary(.i64Rotr) } + case "f32.abs": return { return try $0.visitUnary(.f32Abs) } + case "f32.neg": return { return try $0.visitUnary(.f32Neg) } + case "f32.ceil": return { return try $0.visitUnary(.f32Ceil) } + case "f32.floor": return { return try $0.visitUnary(.f32Floor) } + case "f32.trunc": return { return try $0.visitUnary(.f32Trunc) } + case "f32.nearest": return { return try $0.visitUnary(.f32Nearest) } + case "f32.sqrt": return { return try $0.visitUnary(.f32Sqrt) } + case "f32.add": return { return try $0.visitBinary(.f32Add) } + case "f32.sub": return { return try $0.visitBinary(.f32Sub) } + case "f32.mul": return { return try $0.visitBinary(.f32Mul) } + case "f32.div": return { return try $0.visitBinary(.f32Div) } + case "f32.min": return { return try $0.visitBinary(.f32Min) } + case "f32.max": return { return try $0.visitBinary(.f32Max) } + case "f32.copysign": return { return try $0.visitBinary(.f32Copysign) } + case "f64.abs": return { return try $0.visitUnary(.f64Abs) } + case "f64.neg": return { return try $0.visitUnary(.f64Neg) } + case "f64.ceil": return { return try $0.visitUnary(.f64Ceil) } + case "f64.floor": return { return try $0.visitUnary(.f64Floor) } + case "f64.trunc": return { return try $0.visitUnary(.f64Trunc) } + case "f64.nearest": return { return try $0.visitUnary(.f64Nearest) } + case "f64.sqrt": return { return try $0.visitUnary(.f64Sqrt) } + case "f64.add": return { return try $0.visitBinary(.f64Add) } + case "f64.sub": return { return try $0.visitBinary(.f64Sub) } + case "f64.mul": return { return try $0.visitBinary(.f64Mul) } + case "f64.div": return { return try $0.visitBinary(.f64Div) } + case "f64.min": return { return try $0.visitBinary(.f64Min) } + case "f64.max": return { return try $0.visitBinary(.f64Max) } + case "f64.copysign": return { return try $0.visitBinary(.f64Copysign) } + case "i32.wrap_i64": return { return try $0.visitConversion(.i32WrapI64) } + case "i32.trunc_f32_s": return { return try $0.visitConversion(.i32TruncF32S) } + case "i32.trunc_f32_u": return { return try $0.visitConversion(.i32TruncF32U) } + case "i32.trunc_f64_s": return { return try $0.visitConversion(.i32TruncF64S) } + case "i32.trunc_f64_u": return { return try $0.visitConversion(.i32TruncF64U) } + case "i64.extend_i32_s": return { return try $0.visitConversion(.i64ExtendI32S) } + case "i64.extend_i32_u": return { return try $0.visitConversion(.i64ExtendI32U) } + case "i64.trunc_f32_s": return { return try $0.visitConversion(.i64TruncF32S) } + case "i64.trunc_f32_u": return { return try $0.visitConversion(.i64TruncF32U) } + case "i64.trunc_f64_s": return { return try $0.visitConversion(.i64TruncF64S) } + case "i64.trunc_f64_u": return { return try $0.visitConversion(.i64TruncF64U) } + case "f32.convert_i32_s": return { return try $0.visitConversion(.f32ConvertI32S) } + case "f32.convert_i32_u": return { return try $0.visitConversion(.f32ConvertI32U) } + case "f32.convert_i64_s": return { return try $0.visitConversion(.f32ConvertI64S) } + case "f32.convert_i64_u": return { return try $0.visitConversion(.f32ConvertI64U) } + case "f32.demote_f64": return { return try $0.visitConversion(.f32DemoteF64) } + case "f64.convert_i32_s": return { return try $0.visitConversion(.f64ConvertI32S) } + case "f64.convert_i32_u": return { return try $0.visitConversion(.f64ConvertI32U) } + case "f64.convert_i64_s": return { return try $0.visitConversion(.f64ConvertI64S) } + case "f64.convert_i64_u": return { return try $0.visitConversion(.f64ConvertI64U) } + case "f64.promote_f32": return { return try $0.visitConversion(.f64PromoteF32) } + case "i32.reinterpret_f32": return { return try $0.visitConversion(.i32ReinterpretF32) } + case "i64.reinterpret_f64": return { return try $0.visitConversion(.i64ReinterpretF64) } + case "f32.reinterpret_i32": return { return try $0.visitConversion(.f32ReinterpretI32) } + case "f64.reinterpret_i64": return { return try $0.visitConversion(.f64ReinterpretI64) } + case "i32.extend8_s": return { return try $0.visitUnary(.i32Extend8S) } + case "i32.extend16_s": return { return try $0.visitUnary(.i32Extend16S) } + case "i64.extend8_s": return { return try $0.visitUnary(.i64Extend8S) } + case "i64.extend16_s": return { return try $0.visitUnary(.i64Extend16S) } + case "i64.extend32_s": return { return try $0.visitUnary(.i64Extend32S) } case "memory.init": let (dataIndex) = try expressionParser.visitMemoryInit(wat: &wat) return { return try $0.visitMemoryInit(dataIndex: dataIndex) } @@ -318,14 +318,14 @@ func parseTextInstruction(keyword: String, expressionPars case "table.size": let (table) = try expressionParser.visitTableSize(wat: &wat) return { return try $0.visitTableSize(table: table) } - case "i32.trunc_sat_f32_s": return { return try $0.visitI32TruncSatF32S() } - case "i32.trunc_sat_f32_u": return { return try $0.visitI32TruncSatF32U() } - case "i32.trunc_sat_f64_s": return { return try $0.visitI32TruncSatF64S() } - case "i32.trunc_sat_f64_u": return { return try $0.visitI32TruncSatF64U() } - case "i64.trunc_sat_f32_s": return { return try $0.visitI64TruncSatF32S() } - case "i64.trunc_sat_f32_u": return { return try $0.visitI64TruncSatF32U() } - case "i64.trunc_sat_f64_s": return { return try $0.visitI64TruncSatF64S() } - case "i64.trunc_sat_f64_u": return { return try $0.visitI64TruncSatF64U() } + case "i32.trunc_sat_f32_s": return { return try $0.visitConversion(.i32TruncSatF32S) } + case "i32.trunc_sat_f32_u": return { return try $0.visitConversion(.i32TruncSatF32U) } + case "i32.trunc_sat_f64_s": return { return try $0.visitConversion(.i32TruncSatF64S) } + case "i32.trunc_sat_f64_u": return { return try $0.visitConversion(.i32TruncSatF64U) } + case "i64.trunc_sat_f32_s": return { return try $0.visitConversion(.i64TruncSatF32S) } + case "i64.trunc_sat_f32_u": return { return try $0.visitConversion(.i64TruncSatF32U) } + case "i64.trunc_sat_f64_s": return { return try $0.visitConversion(.i64TruncSatF64S) } + case "i64.trunc_sat_f64_u": return { return try $0.visitConversion(.i64TruncSatF64U) } default: return nil } } diff --git a/Sources/WAT/Parser/ExpressionParser.swift b/Sources/WAT/Parser/ExpressionParser.swift index 7d7952d6..6c7f4194 100644 --- a/Sources/WAT/Parser/ExpressionParser.swift +++ b/Sources/WAT/Parser/ExpressionParser.swift @@ -387,11 +387,12 @@ struct ExpressionParser { if let maybeAlign = try parser.peekKeyword(), maybeAlign.starts(with: alignPrefix) { try parser.consume() var subParser = Parser(String(maybeAlign.dropFirst(alignPrefix.count))) - align = try subParser.expectUnsignedInt(UInt32.self) + let rawAlign = try subParser.expectUnsignedInt(UInt32.self) - if align == 0 || align & (align - 1) != 0 { + if rawAlign == 0 || rawAlign & (rawAlign - 1) != 0 { throw WatParserError("alignment must be a power of 2", location: subParser.lexer.location()) } + align = UInt32(rawAlign.trailingZeroBitCount) } return MemArg(offset: offset, align: align) } @@ -467,74 +468,11 @@ extension ExpressionParser { mutating func visitGlobalSet(wat: inout Wat) throws -> UInt32 { return try globalIndex(wat: &wat) } - mutating func visitI32Load(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 4) + mutating func visitLoad(_ load: Instruction.Load, wat: inout Wat) throws -> MemArg { + return try visitLoad(defaultAlign: UInt32(load.naturalAlignment)) } - mutating func visitI64Load(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 8) - } - mutating func visitF32Load(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 4) - } - mutating func visitF64Load(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 8) - } - mutating func visitI32Load8S(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 1) - } - mutating func visitI32Load8U(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 1) - } - mutating func visitI32Load16S(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 2) - } - mutating func visitI32Load16U(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 2) - } - mutating func visitI64Load8S(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 1) - } - mutating func visitI64Load8U(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 1) - } - mutating func visitI64Load16S(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 2) - } - mutating func visitI64Load16U(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 2) - } - mutating func visitI64Load32S(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 4) - } - mutating func visitI64Load32U(wat: inout Wat) throws -> MemArg { - return try visitLoad(defaultAlign: 4) - } - mutating func visitI32Store(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 4) - } - mutating func visitI64Store(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 8) - } - mutating func visitF32Store(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 4) - } - mutating func visitF64Store(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 8) - } - mutating func visitI32Store8(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 1) - } - mutating func visitI32Store16(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 2) - } - mutating func visitI64Store8(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 1) - } - mutating func visitI64Store16(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 2) - } - mutating func visitI64Store32(wat: inout Wat) throws -> MemArg { - return try visitStore(defaultAlign: 4) + mutating func visitStore(_ store: Instruction.Store, wat: inout Wat) throws -> MemArg { + return try visitStore(defaultAlign: UInt32(store.naturalAlignment)) } mutating func visitMemorySize(wat: inout Wat) throws -> UInt32 { return try memoryIndex(wat: &wat) diff --git a/Sources/WasmKit/Translator.swift b/Sources/WasmKit/Translator.swift index 8cc45e25..3be6788d 100644 --- a/Sources/WasmKit/Translator.swift +++ b/Sources/WasmKit/Translator.swift @@ -1737,29 +1737,43 @@ struct InstructionTranslator: InstructionVisitor { emit(instruction(storeOperand)) } } - mutating func visitI32Load(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i32, 2, Instruction.i32Load) } - mutating func visitI64Load(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 3, Instruction.i64Load) } - mutating func visitF32Load(memarg: MemArg) throws -> Output { try visitLoad(memarg, .f32, 2, Instruction.f32Load) } - mutating func visitF64Load(memarg: MemArg) throws -> Output { try visitLoad(memarg, .f64, 3, Instruction.f64Load) } - mutating func visitI32Load8S(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i32, 0, Instruction.i32Load8S) } - mutating func visitI32Load8U(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i32, 0, Instruction.i32Load8U) } - mutating func visitI32Load16S(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i32, 1, Instruction.i32Load16S) } - mutating func visitI32Load16U(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i32, 1, Instruction.i32Load16U) } - mutating func visitI64Load8S(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 0, Instruction.i64Load8S) } - mutating func visitI64Load8U(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 0, Instruction.i64Load8U) } - mutating func visitI64Load16S(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 1, Instruction.i64Load16S) } - mutating func visitI64Load16U(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 1, Instruction.i64Load16U) } - mutating func visitI64Load32S(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 2, Instruction.i64Load32S) } - mutating func visitI64Load32U(memarg: MemArg) throws -> Output { try visitLoad(memarg, .i64, 2, Instruction.i64Load32U) } - mutating func visitI32Store(memarg: MemArg) throws -> Output { try visitStore(memarg, .i32, 2, Instruction.i32Store) } - mutating func visitI64Store(memarg: MemArg) throws -> Output { try visitStore(memarg, .i64, 3, Instruction.i64Store) } - mutating func visitF32Store(memarg: MemArg) throws -> Output { try visitStore(memarg, .f32, 2, Instruction.f32Store) } - mutating func visitF64Store(memarg: MemArg) throws -> Output { try visitStore(memarg, .f64, 3, Instruction.f64Store) } - mutating func visitI32Store8(memarg: MemArg) throws -> Output { try visitStore(memarg, .i32, 0, Instruction.i32Store8) } - mutating func visitI32Store16(memarg: MemArg) throws -> Output { try visitStore(memarg, .i32, 1, Instruction.i32Store16) } - mutating func visitI64Store8(memarg: MemArg) throws -> Output { try visitStore(memarg, .i64, 0, Instruction.i64Store8) } - mutating func visitI64Store16(memarg: MemArg) throws -> Output { try visitStore(memarg, .i64, 1, Instruction.i64Store16) } - mutating func visitI64Store32(memarg: MemArg) throws -> Output { try visitStore(memarg, .i64, 2, Instruction.i64Store32) } + + mutating func visitLoad(_ load: WasmParser.Instruction.Load, memarg: MemArg) throws { + let instruction: (Instruction.LoadOperand) -> Instruction + switch load { + case .i32Load: instruction = Instruction.i32Load + case .i64Load: instruction = Instruction.i64Load + case .f32Load: instruction = Instruction.f32Load + case .f64Load: instruction = Instruction.f64Load + case .i32Load8S: instruction = Instruction.i32Load8S + case .i32Load8U: instruction = Instruction.i32Load8U + case .i32Load16S: instruction = Instruction.i32Load16S + case .i32Load16U: instruction = Instruction.i32Load16U + case .i64Load8S: instruction = Instruction.i64Load8S + case .i64Load8U: instruction = Instruction.i64Load8U + case .i64Load16S: instruction = Instruction.i64Load16S + case .i64Load16U: instruction = Instruction.i64Load16U + case .i64Load32S: instruction = Instruction.i64Load32S + case .i64Load32U: instruction = Instruction.i64Load32U + } + try visitLoad(memarg, load.type, load.naturalAlignment, instruction) + } + + mutating func visitStore(_ store: WasmParser.Instruction.Store, memarg: MemArg) throws { + let instruction: (Instruction.StoreOperand) -> Instruction + switch store { + case .i32Store: instruction = Instruction.i32Store + case .i64Store: instruction = Instruction.i64Store + case .f32Store: instruction = Instruction.f32Store + case .f64Store: instruction = Instruction.f64Store + case .i32Store8: instruction = Instruction.i32Store8 + case .i32Store16: instruction = Instruction.i32Store16 + case .i64Store8: instruction = Instruction.i64Store8 + case .i64Store16: instruction = Instruction.i64Store16 + case .i64Store32: instruction = Instruction.i64Store32 + } + try visitStore(memarg, store.type, store.naturalAlignment, instruction) + } mutating func visitMemorySize(memory: UInt32) throws -> Output { let sizeType: ValueType = try module.isMemory64(memoryIndex: memory) ? .i64 : .i32 pushEmit(sizeType, { .memorySize(Instruction.MemorySizeOperand(memoryIndex: memory, result: LVReg($0))) }) @@ -1845,137 +1859,176 @@ struct InstructionTranslator: InstructionVisitor { .i32Eqz(Instruction.UnaryOperand(result: LVReg(result), input: LVReg(value))) } } - mutating func visitI32Eq() throws -> Output { try visitCmp(.i32, Instruction.i32Eq) } - mutating func visitI32Ne() throws -> Output { try visitCmp(.i32, Instruction.i32Ne) } - mutating func visitI32LtS() throws -> Output { try visitCmp(.i32, Instruction.i32LtS) } - mutating func visitI32LtU() throws -> Output { try visitCmp(.i32, Instruction.i32LtU) } - mutating func visitI32GtS() throws -> Output { try visitCmp(.i32, Instruction.i32GtS) } - mutating func visitI32GtU() throws -> Output { try visitCmp(.i32, Instruction.i32GtU) } - mutating func visitI32LeS() throws -> Output { try visitCmp(.i32, Instruction.i32LeS) } - mutating func visitI32LeU() throws -> Output { try visitCmp(.i32, Instruction.i32LeU) } - mutating func visitI32GeS() throws -> Output { try visitCmp(.i32, Instruction.i32GeS) } - mutating func visitI32GeU() throws -> Output { try visitCmp(.i32, Instruction.i32GeU) } + mutating func visitCmp(_ cmp: WasmParser.Instruction.Cmp) throws { + let operand: ValueType + let instruction: (Instruction.BinaryOperand) -> Instruction + switch cmp { + case .i32Eq: (operand, instruction) = (.i32, Instruction.i32Eq) + case .i32Ne: (operand, instruction) = (.i32, Instruction.i32Ne) + case .i32LtS: (operand, instruction) = (.i32, Instruction.i32LtS) + case .i32LtU: (operand, instruction) = (.i32, Instruction.i32LtU) + case .i32GtS: (operand, instruction) = (.i32, Instruction.i32GtS) + case .i32GtU: (operand, instruction) = (.i32, Instruction.i32GtU) + case .i32LeS: (operand, instruction) = (.i32, Instruction.i32LeS) + case .i32LeU: (operand, instruction) = (.i32, Instruction.i32LeU) + case .i32GeS: (operand, instruction) = (.i32, Instruction.i32GeS) + case .i32GeU: (operand, instruction) = (.i32, Instruction.i32GeU) + case .i64Eq: (operand, instruction) = (.i64, Instruction.i64Eq) + case .i64Ne: (operand, instruction) = (.i64, Instruction.i64Ne) + case .i64LtS: (operand, instruction) = (.i64, Instruction.i64LtS) + case .i64LtU: (operand, instruction) = (.i64, Instruction.i64LtU) + case .i64GtS: (operand, instruction) = (.i64, Instruction.i64GtS) + case .i64GtU: (operand, instruction) = (.i64, Instruction.i64GtU) + case .i64LeS: (operand, instruction) = (.i64, Instruction.i64LeS) + case .i64LeU: (operand, instruction) = (.i64, Instruction.i64LeU) + case .i64GeS: (operand, instruction) = (.i64, Instruction.i64GeS) + case .i64GeU: (operand, instruction) = (.i64, Instruction.i64GeU) + case .f32Eq: (operand, instruction) = (.f32, Instruction.f32Eq) + case .f32Ne: (operand, instruction) = (.f32, Instruction.f32Ne) + case .f32Lt: (operand, instruction) = (.f32, Instruction.f32Lt) + case .f32Gt: (operand, instruction) = (.f32, Instruction.f32Gt) + case .f32Le: (operand, instruction) = (.f32, Instruction.f32Le) + case .f32Ge: (operand, instruction) = (.f32, Instruction.f32Ge) + case .f64Eq: (operand, instruction) = (.f64, Instruction.f64Eq) + case .f64Ne: (operand, instruction) = (.f64, Instruction.f64Ne) + case .f64Lt: (operand, instruction) = (.f64, Instruction.f64Lt) + case .f64Gt: (operand, instruction) = (.f64, Instruction.f64Gt) + case .f64Le: (operand, instruction) = (.f64, Instruction.f64Le) + case .f64Ge: (operand, instruction) = (.f64, Instruction.f64Ge) + } + try visitCmp(operand, instruction) + } + public mutating func visitBinary(_ binary: WasmParser.Instruction.Binary) throws { + let operand: ValueType + let result: ValueType + let instruction: (Instruction.BinaryOperand) -> Instruction + switch binary { + case .i32Add: (operand, result, instruction) = (.i32, .i32, Instruction.i32Add) + case .i32Sub: (operand, result, instruction) = (.i32, .i32, Instruction.i32Sub) + case .i32Mul: (operand, result, instruction) = (.i32, .i32, Instruction.i32Mul) + case .i32DivS: (operand, result, instruction) = (.i32, .i32, Instruction.i32DivS) + case .i32DivU: (operand, result, instruction) = (.i32, .i32, Instruction.i32DivU) + case .i32RemS: (operand, result, instruction) = (.i32, .i32, Instruction.i32RemS) + case .i32RemU: (operand, result, instruction) = (.i32, .i32, Instruction.i32RemU) + case .i32And: (operand, result, instruction) = (.i32, .i32, Instruction.i32And) + case .i32Or: (operand, result, instruction) = (.i32, .i32, Instruction.i32Or) + case .i32Xor: (operand, result, instruction) = (.i32, .i32, Instruction.i32Xor) + case .i32Shl: (operand, result, instruction) = (.i32, .i32, Instruction.i32Shl) + case .i32ShrS: (operand, result, instruction) = (.i32, .i32, Instruction.i32ShrS) + case .i32ShrU: (operand, result, instruction) = (.i32, .i32, Instruction.i32ShrU) + case .i32Rotl: (operand, result, instruction) = (.i32, .i32, Instruction.i32Rotl) + case .i32Rotr: (operand, result, instruction) = (.i32, .i32, Instruction.i32Rotr) + case .i64Add: (operand, result, instruction) = (.i64, .i64, Instruction.i64Add) + case .i64Sub: (operand, result, instruction) = (.i64, .i64, Instruction.i64Sub) + case .i64Mul: (operand, result, instruction) = (.i64, .i64, Instruction.i64Mul) + case .i64DivS: (operand, result, instruction) = (.i64, .i64, Instruction.i64DivS) + case .i64DivU: (operand, result, instruction) = (.i64, .i64, Instruction.i64DivU) + case .i64RemS: (operand, result, instruction) = (.i64, .i64, Instruction.i64RemS) + case .i64RemU: (operand, result, instruction) = (.i64, .i64, Instruction.i64RemU) + case .i64And: (operand, result, instruction) = (.i64, .i64, Instruction.i64And) + case .i64Or: (operand, result, instruction) = (.i64, .i64, Instruction.i64Or) + case .i64Xor: (operand, result, instruction) = (.i64, .i64, Instruction.i64Xor) + case .i64Shl: (operand, result, instruction) = (.i64, .i64, Instruction.i64Shl) + case .i64ShrS: (operand, result, instruction) = (.i64, .i64, Instruction.i64ShrS) + case .i64ShrU: (operand, result, instruction) = (.i64, .i64, Instruction.i64ShrU) + case .i64Rotl: (operand, result, instruction) = (.i64, .i64, Instruction.i64Rotl) + case .i64Rotr: (operand, result, instruction) = (.i64, .i64, Instruction.i64Rotr) + case .f32Add: (operand, result, instruction) = (.f32, .f32, Instruction.f32Add) + case .f32Sub: (operand, result, instruction) = (.f32, .f32, Instruction.f32Sub) + case .f32Mul: (operand, result, instruction) = (.f32, .f32, Instruction.f32Mul) + case .f32Div: (operand, result, instruction) = (.f32, .f32, Instruction.f32Div) + case .f32Min: (operand, result, instruction) = (.f32, .f32, Instruction.f32Min) + case .f32Max: (operand, result, instruction) = (.f32, .f32, Instruction.f32Max) + case .f32Copysign: (operand, result, instruction) = (.f32, .f32, Instruction.f32CopySign) + case .f64Add: (operand, result, instruction) = (.f64, .f64, Instruction.f64Add) + case .f64Sub: (operand, result, instruction) = (.f64, .f64, Instruction.f64Sub) + case .f64Mul: (operand, result, instruction) = (.f64, .f64, Instruction.f64Mul) + case .f64Div: (operand, result, instruction) = (.f64, .f64, Instruction.f64Div) + case .f64Min: (operand, result, instruction) = (.f64, .f64, Instruction.f64Min) + case .f64Max: (operand, result, instruction) = (.f64, .f64, Instruction.f64Max) + case .f64Copysign: (operand, result, instruction) = (.f64, .f64, Instruction.f64CopySign) + } + try visitBinary(operand, result, instruction) + } mutating func visitI64Eqz() throws -> Output { try popPushEmit(.i64, .i32) { value, result, stack in .i64Eqz(Instruction.UnaryOperand(result: LVReg(result), input: LVReg(value))) } } - mutating func visitI64Eq() throws -> Output { try visitCmp(.i64, Instruction.i64Eq) } - mutating func visitI64Ne() throws -> Output { try visitCmp(.i64, Instruction.i64Ne) } - mutating func visitI64LtS() throws -> Output { try visitCmp(.i64, Instruction.i64LtS) } - mutating func visitI64LtU() throws -> Output { try visitCmp(.i64, Instruction.i64LtU) } - mutating func visitI64GtS() throws -> Output { try visitCmp(.i64, Instruction.i64GtS) } - mutating func visitI64GtU() throws -> Output { try visitCmp(.i64, Instruction.i64GtU) } - mutating func visitI64LeS() throws -> Output { try visitCmp(.i64, Instruction.i64LeS) } - mutating func visitI64LeU() throws -> Output { try visitCmp(.i64, Instruction.i64LeU) } - mutating func visitI64GeS() throws -> Output { try visitCmp(.i64, Instruction.i64GeS) } - mutating func visitI64GeU() throws -> Output { try visitCmp(.i64, Instruction.i64GeU) } - mutating func visitF32Eq() throws -> Output { try visitCmp(.f32, Instruction.f32Eq) } - mutating func visitF32Ne() throws -> Output { try visitCmp(.f32, Instruction.f32Ne) } - mutating func visitF32Lt() throws -> Output { try visitCmp(.f32, Instruction.f32Lt) } - mutating func visitF32Gt() throws -> Output { try visitCmp(.f32, Instruction.f32Gt) } - mutating func visitF32Le() throws -> Output { try visitCmp(.f32, Instruction.f32Le) } - mutating func visitF32Ge() throws -> Output { try visitCmp(.f32, Instruction.f32Ge) } - mutating func visitF64Eq() throws -> Output { try visitCmp(.f64, Instruction.f64Eq) } - mutating func visitF64Ne() throws -> Output { try visitCmp(.f64, Instruction.f64Ne) } - mutating func visitF64Lt() throws -> Output { try visitCmp(.f64, Instruction.f64Lt) } - mutating func visitF64Gt() throws -> Output { try visitCmp(.f64, Instruction.f64Gt) } - mutating func visitF64Le() throws -> Output { try visitCmp(.f64, Instruction.f64Le) } - mutating func visitF64Ge() throws -> Output { try visitCmp(.f64, Instruction.f64Ge) } - mutating func visitI32Clz() throws -> Output { try visitUnary(.i32, Instruction.i32Clz) } - mutating func visitI32Ctz() throws -> Output { try visitUnary(.i32, Instruction.i32Ctz) } - mutating func visitI32Popcnt() throws -> Output { try visitUnary(.i32, Instruction.i32Popcnt) } - mutating func visitI32Add() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Add) } - mutating func visitI32Sub() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Sub) } - mutating func visitI32Mul() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Mul) } - mutating func visitI32DivS() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32DivS) } - mutating func visitI32DivU() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32DivU) } - mutating func visitI32RemS() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32RemS) } - mutating func visitI32RemU() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32RemU) } - mutating func visitI32And() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32And) } - mutating func visitI32Or() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Or) } - mutating func visitI32Xor() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Xor) } - mutating func visitI32Shl() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Shl) } - mutating func visitI32ShrS() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32ShrS) } - mutating func visitI32ShrU() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32ShrU) } - mutating func visitI32Rotl() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Rotl) } - mutating func visitI32Rotr() throws -> Output { try visitBinary(.i32, .i32, Instruction.i32Rotr) } - mutating func visitI64Clz() throws -> Output { try visitUnary(.i64, Instruction.i64Clz) } - mutating func visitI64Ctz() throws -> Output { try visitUnary(.i64, Instruction.i64Ctz) } - mutating func visitI64Popcnt() throws -> Output { try visitUnary(.i64, Instruction.i64Popcnt) } - mutating func visitI64Add() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Add) } - mutating func visitI64Sub() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Sub) } - mutating func visitI64Mul() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Mul) } - mutating func visitI64DivS() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64DivS) } - mutating func visitI64DivU() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64DivU) } - mutating func visitI64RemS() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64RemS) } - mutating func visitI64RemU() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64RemU) } - mutating func visitI64And() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64And) } - mutating func visitI64Or() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Or) } - mutating func visitI64Xor() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Xor) } - mutating func visitI64Shl() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Shl) } - mutating func visitI64ShrS() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64ShrS) } - mutating func visitI64ShrU() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64ShrU) } - mutating func visitI64Rotl() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Rotl) } - mutating func visitI64Rotr() throws -> Output { try visitBinary(.i64, .i64, Instruction.i64Rotr) } - mutating func visitF32Abs() throws -> Output { try visitUnary(.f32, Instruction.f32Abs) } - mutating func visitF32Neg() throws -> Output { try visitUnary(.f32, Instruction.f32Neg) } - mutating func visitF32Ceil() throws -> Output { try visitUnary(.f32, Instruction.f32Ceil) } - mutating func visitF32Floor() throws -> Output { try visitUnary(.f32, Instruction.f32Floor) } - mutating func visitF32Trunc() throws -> Output { try visitUnary(.f32, Instruction.f32Trunc) } - mutating func visitF32Nearest() throws -> Output { try visitUnary(.f32, Instruction.f32Nearest) } - mutating func visitF32Sqrt() throws -> Output { try visitUnary(.f32, Instruction.f32Sqrt) } - mutating func visitF32Add() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32Add) } - mutating func visitF32Sub() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32Sub) } - mutating func visitF32Mul() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32Mul) } - mutating func visitF32Div() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32Div) } - mutating func visitF32Min() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32Min) } - mutating func visitF32Max() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32Max) } - mutating func visitF32Copysign() throws -> Output { try visitBinary(.f32, .f32, Instruction.f32CopySign) } - mutating func visitF64Abs() throws -> Output { try visitUnary(.f64, Instruction.f64Abs) } - mutating func visitF64Neg() throws -> Output { try visitUnary(.f64, Instruction.f64Neg) } - mutating func visitF64Ceil() throws -> Output { try visitUnary(.f64, Instruction.f64Ceil) } - mutating func visitF64Floor() throws -> Output { try visitUnary(.f64, Instruction.f64Floor) } - mutating func visitF64Trunc() throws -> Output { try visitUnary(.f64, Instruction.f64Trunc) } - mutating func visitF64Nearest() throws -> Output { try visitUnary(.f64, Instruction.f64Nearest) } - mutating func visitF64Sqrt() throws -> Output { try visitUnary(.f64, Instruction.f64Sqrt) } - mutating func visitF64Add() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64Add) } - mutating func visitF64Sub() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64Sub) } - mutating func visitF64Mul() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64Mul) } - mutating func visitF64Div() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64Div) } - mutating func visitF64Min() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64Min) } - mutating func visitF64Max() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64Max) } - mutating func visitF64Copysign() throws -> Output { try visitBinary(.f64, .f64, Instruction.f64CopySign) } - mutating func visitI32WrapI64() throws -> Output { try visitConversion(.i64, .i32, Instruction.i32WrapI64) } - mutating func visitI32TruncF32S() throws -> Output { try visitConversion(.f32, .i32, Instruction.i32TruncF32S) } - mutating func visitI32TruncF32U() throws -> Output { try visitConversion(.f32, .i32, Instruction.i32TruncF32U) } - mutating func visitI32TruncF64S() throws -> Output { try visitConversion(.f64, .i32, Instruction.i32TruncF64S) } - mutating func visitI32TruncF64U() throws -> Output { try visitConversion(.f64, .i32, Instruction.i32TruncF64U) } - mutating func visitI64ExtendI32S() throws -> Output { try visitConversion(.i32, .i64, Instruction.i64ExtendI32S) } - mutating func visitI64ExtendI32U() throws -> Output { try visitConversion(.i32, .i64, Instruction.i64ExtendI32U) } - mutating func visitI64TruncF32S() throws -> Output { try visitConversion(.f32, .i64, Instruction.i64TruncF32S) } - mutating func visitI64TruncF32U() throws -> Output { try visitConversion(.f32, .i64, Instruction.i64TruncF32U) } - mutating func visitI64TruncF64S() throws -> Output { try visitConversion(.f64, .i64, Instruction.i64TruncF64S) } - mutating func visitI64TruncF64U() throws -> Output { try visitConversion(.f64, .i64, Instruction.i64TruncF64U) } - mutating func visitF32ConvertI32S() throws -> Output { try visitConversion(.i32, .f32, Instruction.f32ConvertI32S) } - mutating func visitF32ConvertI32U() throws -> Output { try visitConversion(.i32, .f32, Instruction.f32ConvertI32U) } - mutating func visitF32ConvertI64S() throws -> Output { try visitConversion(.i64, .f32, Instruction.f32ConvertI64S) } - mutating func visitF32ConvertI64U() throws -> Output { try visitConversion(.i64, .f32, Instruction.f32ConvertI64U) } - mutating func visitF32DemoteF64() throws -> Output { try visitConversion(.f64, .f32, Instruction.f32DemoteF64) } - mutating func visitF64ConvertI32S() throws -> Output { try visitConversion(.i32, .f64, Instruction.f64ConvertI32S) } - mutating func visitF64ConvertI32U() throws -> Output { try visitConversion(.i32, .f64, Instruction.f64ConvertI32U) } - mutating func visitF64ConvertI64S() throws -> Output { try visitConversion(.i64, .f64, Instruction.f64ConvertI64S) } - mutating func visitF64ConvertI64U() throws -> Output { try visitConversion(.i64, .f64, Instruction.f64ConvertI64U) } - mutating func visitF64PromoteF32() throws -> Output { try visitConversion(.f32, .f64, Instruction.f64PromoteF32) } - mutating func visitI32ReinterpretF32() throws -> Output { try visitConversion(.f32, .i32, Instruction.i32ReinterpretF32) } - mutating func visitI64ReinterpretF64() throws -> Output { try visitConversion(.f64, .i64, Instruction.i64ReinterpretF64) } - mutating func visitF32ReinterpretI32() throws -> Output { try visitConversion(.i32, .f32, Instruction.f32ReinterpretI32) } - mutating func visitF64ReinterpretI64() throws -> Output { try visitConversion(.i64, .f64, Instruction.f64ReinterpretI64) } - mutating func visitI32Extend8S() throws -> Output { try visitUnary(.i32, Instruction.i32Extend8S) } - mutating func visitI32Extend16S() throws -> Output { try visitUnary(.i32, Instruction.i32Extend16S) } - mutating func visitI64Extend8S() throws -> Output { try visitUnary(.i64, Instruction.i64Extend8S) } - mutating func visitI64Extend16S() throws -> Output { try visitUnary(.i64, Instruction.i64Extend16S) } - mutating func visitI64Extend32S() throws -> Output { try visitUnary(.i64, Instruction.i64Extend32S) } + mutating func visitUnary(_ unary: WasmParser.Instruction.Unary) throws { + let operand: ValueType + let instruction: (Instruction.UnaryOperand) -> Instruction + switch unary { + case .i32Clz: (operand, instruction) = (.i32, Instruction.i32Clz) + case .i32Ctz: (operand, instruction) = (.i32, Instruction.i32Ctz) + case .i32Popcnt: (operand, instruction) = (.i32, Instruction.i32Popcnt) + case .i64Clz: (operand, instruction) = (.i64, Instruction.i64Clz) + case .i64Ctz: (operand, instruction) = (.i64, Instruction.i64Ctz) + case .i64Popcnt: (operand, instruction) = (.i64, Instruction.i64Popcnt) + case .f32Abs: (operand, instruction) = (.f32, Instruction.f32Abs) + case .f32Neg: (operand, instruction) = (.f32, Instruction.f32Neg) + case .f32Ceil: (operand, instruction) = (.f32, Instruction.f32Ceil) + case .f32Floor: (operand, instruction) = (.f32, Instruction.f32Floor) + case .f32Trunc: (operand, instruction) = (.f32, Instruction.f32Trunc) + case .f32Nearest: (operand, instruction) = (.f32, Instruction.f32Nearest) + case .f32Sqrt: (operand, instruction) = (.f32, Instruction.f32Sqrt) + case .f64Abs: (operand, instruction) = (.f64, Instruction.f64Abs) + case .f64Neg: (operand, instruction) = (.f64, Instruction.f64Neg) + case .f64Ceil: (operand, instruction) = (.f64, Instruction.f64Ceil) + case .f64Floor: (operand, instruction) = (.f64, Instruction.f64Floor) + case .f64Trunc: (operand, instruction) = (.f64, Instruction.f64Trunc) + case .f64Nearest: (operand, instruction) = (.f64, Instruction.f64Nearest) + case .f64Sqrt: (operand, instruction) = (.f64, Instruction.f64Sqrt) + case .i32Extend8S: (operand, instruction) = (.i32, Instruction.i32Extend8S) + case .i32Extend16S: (operand, instruction) = (.i32, Instruction.i32Extend16S) + case .i64Extend8S: (operand, instruction) = (.i64, Instruction.i64Extend8S) + case .i64Extend16S: (operand, instruction) = (.i64, Instruction.i64Extend16S) + case .i64Extend32S: (operand, instruction) = (.i64, Instruction.i64Extend32S) + } + try visitUnary(operand, instruction) + } + mutating func visitConversion(_ conversion: WasmParser.Instruction.Conversion) throws { + let from: ValueType + let to: ValueType + let instruction: (Instruction.UnaryOperand) -> Instruction + switch conversion { + case .i32WrapI64: (from, to, instruction) = (.i64, .i32, Instruction.i32WrapI64) + case .i32TruncF32S: (from, to, instruction) = (.f32, .i32, Instruction.i32TruncF32S) + case .i32TruncF32U: (from, to, instruction) = (.f32, .i32, Instruction.i32TruncF32U) + case .i32TruncF64S: (from, to, instruction) = (.f64, .i32, Instruction.i32TruncF64S) + case .i32TruncF64U: (from, to, instruction) = (.f64, .i32, Instruction.i32TruncF64U) + case .i64ExtendI32S: (from, to, instruction) = (.i32, .i64, Instruction.i64ExtendI32S) + case .i64ExtendI32U: (from, to, instruction) = (.i32, .i64, Instruction.i64ExtendI32U) + case .i64TruncF32S: (from, to, instruction) = (.f32, .i64, Instruction.i64TruncF32S) + case .i64TruncF32U: (from, to, instruction) = (.f32, .i64, Instruction.i64TruncF32U) + case .i64TruncF64S: (from, to, instruction) = (.f64, .i64, Instruction.i64TruncF64S) + case .i64TruncF64U: (from, to, instruction) = (.f64, .i64, Instruction.i64TruncF64U) + case .f32ConvertI32S: (from, to, instruction) = (.i32, .f32, Instruction.f32ConvertI32S) + case .f32ConvertI32U: (from, to, instruction) = (.i32, .f32, Instruction.f32ConvertI32U) + case .f32ConvertI64S: (from, to, instruction) = (.i64, .f32, Instruction.f32ConvertI64S) + case .f32ConvertI64U: (from, to, instruction) = (.i64, .f32, Instruction.f32ConvertI64U) + case .f32DemoteF64: (from, to, instruction) = (.f64, .f32, Instruction.f32DemoteF64) + case .f64ConvertI32S: (from, to, instruction) = (.i32, .f64, Instruction.f64ConvertI32S) + case .f64ConvertI32U: (from, to, instruction) = (.i32, .f64, Instruction.f64ConvertI32U) + case .f64ConvertI64S: (from, to, instruction) = (.i64, .f64, Instruction.f64ConvertI64S) + case .f64ConvertI64U: (from, to, instruction) = (.i64, .f64, Instruction.f64ConvertI64U) + case .f64PromoteF32: (from, to, instruction) = (.f32, .f64, Instruction.f64PromoteF32) + case .i32ReinterpretF32: (from, to, instruction) = (.f32, .i32, Instruction.i32ReinterpretF32) + case .i64ReinterpretF64: (from, to, instruction) = (.f64, .i64, Instruction.i64ReinterpretF64) + case .f32ReinterpretI32: (from, to, instruction) = (.i32, .f32, Instruction.f32ReinterpretI32) + case .f64ReinterpretI64: (from, to, instruction) = (.i64, .f64, Instruction.f64ReinterpretI64) + case .i32TruncSatF32S: (from, to, instruction) = (.f32, .i32, Instruction.i32TruncSatF32S) + case .i32TruncSatF32U: (from, to, instruction) = (.f32, .i32, Instruction.i32TruncSatF32U) + case .i32TruncSatF64S: (from, to, instruction) = (.f64, .i32, Instruction.i32TruncSatF64S) + case .i32TruncSatF64U: (from, to, instruction) = (.f64, .i32, Instruction.i32TruncSatF64U) + case .i64TruncSatF32S: (from, to, instruction) = (.f32, .i64, Instruction.i64TruncSatF32S) + case .i64TruncSatF32U: (from, to, instruction) = (.f32, .i64, Instruction.i64TruncSatF32U) + case .i64TruncSatF64S: (from, to, instruction) = (.f64, .i64, Instruction.i64TruncSatF64S) + case .i64TruncSatF64U: (from, to, instruction) = (.f64, .i64, Instruction.i64TruncSatF64U) + } + try visitConversion(from, to, instruction) + } + mutating func visitMemoryInit(dataIndex: UInt32) throws -> Output { try self.module.validateDataSegment(dataIndex) let addressType = try module.addressType(memoryIndex: 0) @@ -2140,14 +2193,6 @@ struct InstructionTranslator: InstructionVisitor { return .tableSize(Instruction.TableSizeOperand(tableIndex: table, result: LVReg(result))) } } - mutating func visitI32TruncSatF32S() throws -> Output { try visitConversion(.f32, .i32, Instruction.i32TruncSatF32S) } - mutating func visitI32TruncSatF32U() throws -> Output { try visitConversion(.f32, .i32, Instruction.i32TruncSatF32U) } - mutating func visitI32TruncSatF64S() throws -> Output { try visitConversion(.f64, .i32, Instruction.i32TruncSatF64S) } - mutating func visitI32TruncSatF64U() throws -> Output { try visitConversion(.f64, .i32, Instruction.i32TruncSatF64U) } - mutating func visitI64TruncSatF32S() throws -> Output { try visitConversion(.f32, .i64, Instruction.i64TruncSatF32S) } - mutating func visitI64TruncSatF32U() throws -> Output { try visitConversion(.f32, .i64, Instruction.i64TruncSatF32U) } - mutating func visitI64TruncSatF64S() throws -> Output { try visitConversion(.f64, .i64, Instruction.i64TruncSatF64S) } - mutating func visitI64TruncSatF64U() throws -> Output { try visitConversion(.f64, .i64, Instruction.i64TruncSatF64U) } } struct TranslationError: Error, CustomStringConvertible { diff --git a/Sources/WasmParser/InstructionVisitor.swift b/Sources/WasmParser/InstructionVisitor.swift index 904a2704..7cd7f317 100644 --- a/Sources/WasmParser/InstructionVisitor.swift +++ b/Sources/WasmParser/InstructionVisitor.swift @@ -5,6 +5,175 @@ import WasmTypes public enum Instruction: Equatable { + public enum Load: Equatable { + case i32Load + case i64Load + case f32Load + case f64Load + case i32Load8S + case i32Load8U + case i32Load16S + case i32Load16U + case i64Load8S + case i64Load8U + case i64Load16S + case i64Load16U + case i64Load32S + case i64Load32U + } + public enum Store: Equatable { + case i32Store + case i64Store + case f32Store + case f64Store + case i32Store8 + case i32Store16 + case i64Store8 + case i64Store16 + case i64Store32 + } + public enum Cmp: Equatable { + case i32Eq + case i32Ne + case i32LtS + case i32LtU + case i32GtS + case i32GtU + case i32LeS + case i32LeU + case i32GeS + case i32GeU + case i64Eq + case i64Ne + case i64LtS + case i64LtU + case i64GtS + case i64GtU + case i64LeS + case i64LeU + case i64GeS + case i64GeU + case f32Eq + case f32Ne + case f32Lt + case f32Gt + case f32Le + case f32Ge + case f64Eq + case f64Ne + case f64Lt + case f64Gt + case f64Le + case f64Ge + } + public enum Unary: Equatable { + case i32Clz + case i32Ctz + case i32Popcnt + case i64Clz + case i64Ctz + case i64Popcnt + case f32Abs + case f32Neg + case f32Ceil + case f32Floor + case f32Trunc + case f32Nearest + case f32Sqrt + case f64Abs + case f64Neg + case f64Ceil + case f64Floor + case f64Trunc + case f64Nearest + case f64Sqrt + case i32Extend8S + case i32Extend16S + case i64Extend8S + case i64Extend16S + case i64Extend32S + } + public enum Binary: Equatable { + case i32Add + case i32Sub + case i32Mul + case i32DivS + case i32DivU + case i32RemS + case i32RemU + case i32And + case i32Or + case i32Xor + case i32Shl + case i32ShrS + case i32ShrU + case i32Rotl + case i32Rotr + case i64Add + case i64Sub + case i64Mul + case i64DivS + case i64DivU + case i64RemS + case i64RemU + case i64And + case i64Or + case i64Xor + case i64Shl + case i64ShrS + case i64ShrU + case i64Rotl + case i64Rotr + case f32Add + case f32Sub + case f32Mul + case f32Div + case f32Min + case f32Max + case f32Copysign + case f64Add + case f64Sub + case f64Mul + case f64Div + case f64Min + case f64Max + case f64Copysign + } + public enum Conversion: Equatable { + case i32WrapI64 + case i32TruncF32S + case i32TruncF32U + case i32TruncF64S + case i32TruncF64U + case i64ExtendI32S + case i64ExtendI32U + case i64TruncF32S + case i64TruncF32U + case i64TruncF64S + case i64TruncF64U + case f32ConvertI32S + case f32ConvertI32U + case f32ConvertI64S + case f32ConvertI64U + case f32DemoteF64 + case f64ConvertI32S + case f64ConvertI32U + case f64ConvertI64S + case f64ConvertI64U + case f64PromoteF32 + case i32ReinterpretF32 + case i64ReinterpretF64 + case f32ReinterpretI32 + case f64ReinterpretI64 + case i32TruncSatF32S + case i32TruncSatF32U + case i32TruncSatF64S + case i32TruncSatF64U + case i64TruncSatF32S + case i64TruncSatF32U + case i64TruncSatF64S + case i64TruncSatF64U + } case `unreachable` case `nop` case `block`(blockType: BlockType) @@ -26,29 +195,8 @@ public enum Instruction: Equatable { case `localTee`(localIndex: UInt32) case `globalGet`(globalIndex: UInt32) case `globalSet`(globalIndex: UInt32) - case `i32Load`(memarg: MemArg) - case `i64Load`(memarg: MemArg) - case `f32Load`(memarg: MemArg) - case `f64Load`(memarg: MemArg) - case `i32Load8S`(memarg: MemArg) - case `i32Load8U`(memarg: MemArg) - case `i32Load16S`(memarg: MemArg) - case `i32Load16U`(memarg: MemArg) - case `i64Load8S`(memarg: MemArg) - case `i64Load8U`(memarg: MemArg) - case `i64Load16S`(memarg: MemArg) - case `i64Load16U`(memarg: MemArg) - case `i64Load32S`(memarg: MemArg) - case `i64Load32U`(memarg: MemArg) - case `i32Store`(memarg: MemArg) - case `i64Store`(memarg: MemArg) - case `f32Store`(memarg: MemArg) - case `f64Store`(memarg: MemArg) - case `i32Store8`(memarg: MemArg) - case `i32Store16`(memarg: MemArg) - case `i64Store8`(memarg: MemArg) - case `i64Store16`(memarg: MemArg) - case `i64Store32`(memarg: MemArg) + case `load`(Instruction.Load, memarg: MemArg) + case `store`(Instruction.Store, memarg: MemArg) case `memorySize`(memory: UInt32) case `memoryGrow`(memory: UInt32) case `i32Const`(value: Int32) @@ -59,133 +207,11 @@ public enum Instruction: Equatable { case `refIsNull` case `refFunc`(functionIndex: UInt32) case `i32Eqz` - case `i32Eq` - case `i32Ne` - case `i32LtS` - case `i32LtU` - case `i32GtS` - case `i32GtU` - case `i32LeS` - case `i32LeU` - case `i32GeS` - case `i32GeU` + case `cmp`(Instruction.Cmp) case `i64Eqz` - case `i64Eq` - case `i64Ne` - case `i64LtS` - case `i64LtU` - case `i64GtS` - case `i64GtU` - case `i64LeS` - case `i64LeU` - case `i64GeS` - case `i64GeU` - case `f32Eq` - case `f32Ne` - case `f32Lt` - case `f32Gt` - case `f32Le` - case `f32Ge` - case `f64Eq` - case `f64Ne` - case `f64Lt` - case `f64Gt` - case `f64Le` - case `f64Ge` - case `i32Clz` - case `i32Ctz` - case `i32Popcnt` - case `i32Add` - case `i32Sub` - case `i32Mul` - case `i32DivS` - case `i32DivU` - case `i32RemS` - case `i32RemU` - case `i32And` - case `i32Or` - case `i32Xor` - case `i32Shl` - case `i32ShrS` - case `i32ShrU` - case `i32Rotl` - case `i32Rotr` - case `i64Clz` - case `i64Ctz` - case `i64Popcnt` - case `i64Add` - case `i64Sub` - case `i64Mul` - case `i64DivS` - case `i64DivU` - case `i64RemS` - case `i64RemU` - case `i64And` - case `i64Or` - case `i64Xor` - case `i64Shl` - case `i64ShrS` - case `i64ShrU` - case `i64Rotl` - case `i64Rotr` - case `f32Abs` - case `f32Neg` - case `f32Ceil` - case `f32Floor` - case `f32Trunc` - case `f32Nearest` - case `f32Sqrt` - case `f32Add` - case `f32Sub` - case `f32Mul` - case `f32Div` - case `f32Min` - case `f32Max` - case `f32Copysign` - case `f64Abs` - case `f64Neg` - case `f64Ceil` - case `f64Floor` - case `f64Trunc` - case `f64Nearest` - case `f64Sqrt` - case `f64Add` - case `f64Sub` - case `f64Mul` - case `f64Div` - case `f64Min` - case `f64Max` - case `f64Copysign` - case `i32WrapI64` - case `i32TruncF32S` - case `i32TruncF32U` - case `i32TruncF64S` - case `i32TruncF64U` - case `i64ExtendI32S` - case `i64ExtendI32U` - case `i64TruncF32S` - case `i64TruncF32U` - case `i64TruncF64S` - case `i64TruncF64U` - case `f32ConvertI32S` - case `f32ConvertI32U` - case `f32ConvertI64S` - case `f32ConvertI64U` - case `f32DemoteF64` - case `f64ConvertI32S` - case `f64ConvertI32U` - case `f64ConvertI64S` - case `f64ConvertI64U` - case `f64PromoteF32` - case `i32ReinterpretF32` - case `i64ReinterpretF64` - case `f32ReinterpretI32` - case `f64ReinterpretI64` - case `i32Extend8S` - case `i32Extend16S` - case `i64Extend8S` - case `i64Extend16S` - case `i64Extend32S` + case `unary`(Instruction.Unary) + case `binary`(Instruction.Binary) + case `conversion`(Instruction.Conversion) case `memoryInit`(dataIndex: UInt32) case `dataDrop`(dataIndex: UInt32) case `memoryCopy`(dstMem: UInt32, srcMem: UInt32) @@ -198,14 +224,6 @@ public enum Instruction: Equatable { case `tableSet`(table: UInt32) case `tableGrow`(table: UInt32) case `tableSize`(table: UInt32) - case `i32TruncSatF32S` - case `i32TruncSatF32U` - case `i32TruncSatF64S` - case `i32TruncSatF64U` - case `i64TruncSatF32S` - case `i64TruncSatF32U` - case `i64TruncSatF64S` - case `i64TruncSatF64U` } /// A visitor that visits all instructions by a single visit method. @@ -236,29 +254,8 @@ extension AnyInstructionVisitor { public mutating func visitLocalTee(localIndex: UInt32) throws { return try self.visit(.localTee(localIndex: localIndex)) } public mutating func visitGlobalGet(globalIndex: UInt32) throws { return try self.visit(.globalGet(globalIndex: globalIndex)) } public mutating func visitGlobalSet(globalIndex: UInt32) throws { return try self.visit(.globalSet(globalIndex: globalIndex)) } - public mutating func visitI32Load(memarg: MemArg) throws { return try self.visit(.i32Load(memarg: memarg)) } - public mutating func visitI64Load(memarg: MemArg) throws { return try self.visit(.i64Load(memarg: memarg)) } - public mutating func visitF32Load(memarg: MemArg) throws { return try self.visit(.f32Load(memarg: memarg)) } - public mutating func visitF64Load(memarg: MemArg) throws { return try self.visit(.f64Load(memarg: memarg)) } - public mutating func visitI32Load8S(memarg: MemArg) throws { return try self.visit(.i32Load8S(memarg: memarg)) } - public mutating func visitI32Load8U(memarg: MemArg) throws { return try self.visit(.i32Load8U(memarg: memarg)) } - public mutating func visitI32Load16S(memarg: MemArg) throws { return try self.visit(.i32Load16S(memarg: memarg)) } - public mutating func visitI32Load16U(memarg: MemArg) throws { return try self.visit(.i32Load16U(memarg: memarg)) } - public mutating func visitI64Load8S(memarg: MemArg) throws { return try self.visit(.i64Load8S(memarg: memarg)) } - public mutating func visitI64Load8U(memarg: MemArg) throws { return try self.visit(.i64Load8U(memarg: memarg)) } - public mutating func visitI64Load16S(memarg: MemArg) throws { return try self.visit(.i64Load16S(memarg: memarg)) } - public mutating func visitI64Load16U(memarg: MemArg) throws { return try self.visit(.i64Load16U(memarg: memarg)) } - public mutating func visitI64Load32S(memarg: MemArg) throws { return try self.visit(.i64Load32S(memarg: memarg)) } - public mutating func visitI64Load32U(memarg: MemArg) throws { return try self.visit(.i64Load32U(memarg: memarg)) } - public mutating func visitI32Store(memarg: MemArg) throws { return try self.visit(.i32Store(memarg: memarg)) } - public mutating func visitI64Store(memarg: MemArg) throws { return try self.visit(.i64Store(memarg: memarg)) } - public mutating func visitF32Store(memarg: MemArg) throws { return try self.visit(.f32Store(memarg: memarg)) } - public mutating func visitF64Store(memarg: MemArg) throws { return try self.visit(.f64Store(memarg: memarg)) } - public mutating func visitI32Store8(memarg: MemArg) throws { return try self.visit(.i32Store8(memarg: memarg)) } - public mutating func visitI32Store16(memarg: MemArg) throws { return try self.visit(.i32Store16(memarg: memarg)) } - public mutating func visitI64Store8(memarg: MemArg) throws { return try self.visit(.i64Store8(memarg: memarg)) } - public mutating func visitI64Store16(memarg: MemArg) throws { return try self.visit(.i64Store16(memarg: memarg)) } - public mutating func visitI64Store32(memarg: MemArg) throws { return try self.visit(.i64Store32(memarg: memarg)) } + public mutating func visitLoad(_ load: Instruction.Load, memarg: MemArg) throws { return try self.visit(.load(load, memarg: memarg)) } + public mutating func visitStore(_ store: Instruction.Store, memarg: MemArg) throws { return try self.visit(.store(store, memarg: memarg)) } public mutating func visitMemorySize(memory: UInt32) throws { return try self.visit(.memorySize(memory: memory)) } public mutating func visitMemoryGrow(memory: UInt32) throws { return try self.visit(.memoryGrow(memory: memory)) } public mutating func visitI32Const(value: Int32) throws { return try self.visit(.i32Const(value: value)) } @@ -269,133 +266,11 @@ extension AnyInstructionVisitor { public mutating func visitRefIsNull() throws { return try self.visit(.refIsNull) } public mutating func visitRefFunc(functionIndex: UInt32) throws { return try self.visit(.refFunc(functionIndex: functionIndex)) } public mutating func visitI32Eqz() throws { return try self.visit(.i32Eqz) } - public mutating func visitI32Eq() throws { return try self.visit(.i32Eq) } - public mutating func visitI32Ne() throws { return try self.visit(.i32Ne) } - public mutating func visitI32LtS() throws { return try self.visit(.i32LtS) } - public mutating func visitI32LtU() throws { return try self.visit(.i32LtU) } - public mutating func visitI32GtS() throws { return try self.visit(.i32GtS) } - public mutating func visitI32GtU() throws { return try self.visit(.i32GtU) } - public mutating func visitI32LeS() throws { return try self.visit(.i32LeS) } - public mutating func visitI32LeU() throws { return try self.visit(.i32LeU) } - public mutating func visitI32GeS() throws { return try self.visit(.i32GeS) } - public mutating func visitI32GeU() throws { return try self.visit(.i32GeU) } + public mutating func visitCmp(_ cmp: Instruction.Cmp) throws { return try self.visit(.cmp(cmp)) } public mutating func visitI64Eqz() throws { return try self.visit(.i64Eqz) } - public mutating func visitI64Eq() throws { return try self.visit(.i64Eq) } - public mutating func visitI64Ne() throws { return try self.visit(.i64Ne) } - public mutating func visitI64LtS() throws { return try self.visit(.i64LtS) } - public mutating func visitI64LtU() throws { return try self.visit(.i64LtU) } - public mutating func visitI64GtS() throws { return try self.visit(.i64GtS) } - public mutating func visitI64GtU() throws { return try self.visit(.i64GtU) } - public mutating func visitI64LeS() throws { return try self.visit(.i64LeS) } - public mutating func visitI64LeU() throws { return try self.visit(.i64LeU) } - public mutating func visitI64GeS() throws { return try self.visit(.i64GeS) } - public mutating func visitI64GeU() throws { return try self.visit(.i64GeU) } - public mutating func visitF32Eq() throws { return try self.visit(.f32Eq) } - public mutating func visitF32Ne() throws { return try self.visit(.f32Ne) } - public mutating func visitF32Lt() throws { return try self.visit(.f32Lt) } - public mutating func visitF32Gt() throws { return try self.visit(.f32Gt) } - public mutating func visitF32Le() throws { return try self.visit(.f32Le) } - public mutating func visitF32Ge() throws { return try self.visit(.f32Ge) } - public mutating func visitF64Eq() throws { return try self.visit(.f64Eq) } - public mutating func visitF64Ne() throws { return try self.visit(.f64Ne) } - public mutating func visitF64Lt() throws { return try self.visit(.f64Lt) } - public mutating func visitF64Gt() throws { return try self.visit(.f64Gt) } - public mutating func visitF64Le() throws { return try self.visit(.f64Le) } - public mutating func visitF64Ge() throws { return try self.visit(.f64Ge) } - public mutating func visitI32Clz() throws { return try self.visit(.i32Clz) } - public mutating func visitI32Ctz() throws { return try self.visit(.i32Ctz) } - public mutating func visitI32Popcnt() throws { return try self.visit(.i32Popcnt) } - public mutating func visitI32Add() throws { return try self.visit(.i32Add) } - public mutating func visitI32Sub() throws { return try self.visit(.i32Sub) } - public mutating func visitI32Mul() throws { return try self.visit(.i32Mul) } - public mutating func visitI32DivS() throws { return try self.visit(.i32DivS) } - public mutating func visitI32DivU() throws { return try self.visit(.i32DivU) } - public mutating func visitI32RemS() throws { return try self.visit(.i32RemS) } - public mutating func visitI32RemU() throws { return try self.visit(.i32RemU) } - public mutating func visitI32And() throws { return try self.visit(.i32And) } - public mutating func visitI32Or() throws { return try self.visit(.i32Or) } - public mutating func visitI32Xor() throws { return try self.visit(.i32Xor) } - public mutating func visitI32Shl() throws { return try self.visit(.i32Shl) } - public mutating func visitI32ShrS() throws { return try self.visit(.i32ShrS) } - public mutating func visitI32ShrU() throws { return try self.visit(.i32ShrU) } - public mutating func visitI32Rotl() throws { return try self.visit(.i32Rotl) } - public mutating func visitI32Rotr() throws { return try self.visit(.i32Rotr) } - public mutating func visitI64Clz() throws { return try self.visit(.i64Clz) } - public mutating func visitI64Ctz() throws { return try self.visit(.i64Ctz) } - public mutating func visitI64Popcnt() throws { return try self.visit(.i64Popcnt) } - public mutating func visitI64Add() throws { return try self.visit(.i64Add) } - public mutating func visitI64Sub() throws { return try self.visit(.i64Sub) } - public mutating func visitI64Mul() throws { return try self.visit(.i64Mul) } - public mutating func visitI64DivS() throws { return try self.visit(.i64DivS) } - public mutating func visitI64DivU() throws { return try self.visit(.i64DivU) } - public mutating func visitI64RemS() throws { return try self.visit(.i64RemS) } - public mutating func visitI64RemU() throws { return try self.visit(.i64RemU) } - public mutating func visitI64And() throws { return try self.visit(.i64And) } - public mutating func visitI64Or() throws { return try self.visit(.i64Or) } - public mutating func visitI64Xor() throws { return try self.visit(.i64Xor) } - public mutating func visitI64Shl() throws { return try self.visit(.i64Shl) } - public mutating func visitI64ShrS() throws { return try self.visit(.i64ShrS) } - public mutating func visitI64ShrU() throws { return try self.visit(.i64ShrU) } - public mutating func visitI64Rotl() throws { return try self.visit(.i64Rotl) } - public mutating func visitI64Rotr() throws { return try self.visit(.i64Rotr) } - public mutating func visitF32Abs() throws { return try self.visit(.f32Abs) } - public mutating func visitF32Neg() throws { return try self.visit(.f32Neg) } - public mutating func visitF32Ceil() throws { return try self.visit(.f32Ceil) } - public mutating func visitF32Floor() throws { return try self.visit(.f32Floor) } - public mutating func visitF32Trunc() throws { return try self.visit(.f32Trunc) } - public mutating func visitF32Nearest() throws { return try self.visit(.f32Nearest) } - public mutating func visitF32Sqrt() throws { return try self.visit(.f32Sqrt) } - public mutating func visitF32Add() throws { return try self.visit(.f32Add) } - public mutating func visitF32Sub() throws { return try self.visit(.f32Sub) } - public mutating func visitF32Mul() throws { return try self.visit(.f32Mul) } - public mutating func visitF32Div() throws { return try self.visit(.f32Div) } - public mutating func visitF32Min() throws { return try self.visit(.f32Min) } - public mutating func visitF32Max() throws { return try self.visit(.f32Max) } - public mutating func visitF32Copysign() throws { return try self.visit(.f32Copysign) } - public mutating func visitF64Abs() throws { return try self.visit(.f64Abs) } - public mutating func visitF64Neg() throws { return try self.visit(.f64Neg) } - public mutating func visitF64Ceil() throws { return try self.visit(.f64Ceil) } - public mutating func visitF64Floor() throws { return try self.visit(.f64Floor) } - public mutating func visitF64Trunc() throws { return try self.visit(.f64Trunc) } - public mutating func visitF64Nearest() throws { return try self.visit(.f64Nearest) } - public mutating func visitF64Sqrt() throws { return try self.visit(.f64Sqrt) } - public mutating func visitF64Add() throws { return try self.visit(.f64Add) } - public mutating func visitF64Sub() throws { return try self.visit(.f64Sub) } - public mutating func visitF64Mul() throws { return try self.visit(.f64Mul) } - public mutating func visitF64Div() throws { return try self.visit(.f64Div) } - public mutating func visitF64Min() throws { return try self.visit(.f64Min) } - public mutating func visitF64Max() throws { return try self.visit(.f64Max) } - public mutating func visitF64Copysign() throws { return try self.visit(.f64Copysign) } - public mutating func visitI32WrapI64() throws { return try self.visit(.i32WrapI64) } - public mutating func visitI32TruncF32S() throws { return try self.visit(.i32TruncF32S) } - public mutating func visitI32TruncF32U() throws { return try self.visit(.i32TruncF32U) } - public mutating func visitI32TruncF64S() throws { return try self.visit(.i32TruncF64S) } - public mutating func visitI32TruncF64U() throws { return try self.visit(.i32TruncF64U) } - public mutating func visitI64ExtendI32S() throws { return try self.visit(.i64ExtendI32S) } - public mutating func visitI64ExtendI32U() throws { return try self.visit(.i64ExtendI32U) } - public mutating func visitI64TruncF32S() throws { return try self.visit(.i64TruncF32S) } - public mutating func visitI64TruncF32U() throws { return try self.visit(.i64TruncF32U) } - public mutating func visitI64TruncF64S() throws { return try self.visit(.i64TruncF64S) } - public mutating func visitI64TruncF64U() throws { return try self.visit(.i64TruncF64U) } - public mutating func visitF32ConvertI32S() throws { return try self.visit(.f32ConvertI32S) } - public mutating func visitF32ConvertI32U() throws { return try self.visit(.f32ConvertI32U) } - public mutating func visitF32ConvertI64S() throws { return try self.visit(.f32ConvertI64S) } - public mutating func visitF32ConvertI64U() throws { return try self.visit(.f32ConvertI64U) } - public mutating func visitF32DemoteF64() throws { return try self.visit(.f32DemoteF64) } - public mutating func visitF64ConvertI32S() throws { return try self.visit(.f64ConvertI32S) } - public mutating func visitF64ConvertI32U() throws { return try self.visit(.f64ConvertI32U) } - public mutating func visitF64ConvertI64S() throws { return try self.visit(.f64ConvertI64S) } - public mutating func visitF64ConvertI64U() throws { return try self.visit(.f64ConvertI64U) } - public mutating func visitF64PromoteF32() throws { return try self.visit(.f64PromoteF32) } - public mutating func visitI32ReinterpretF32() throws { return try self.visit(.i32ReinterpretF32) } - public mutating func visitI64ReinterpretF64() throws { return try self.visit(.i64ReinterpretF64) } - public mutating func visitF32ReinterpretI32() throws { return try self.visit(.f32ReinterpretI32) } - public mutating func visitF64ReinterpretI64() throws { return try self.visit(.f64ReinterpretI64) } - public mutating func visitI32Extend8S() throws { return try self.visit(.i32Extend8S) } - public mutating func visitI32Extend16S() throws { return try self.visit(.i32Extend16S) } - public mutating func visitI64Extend8S() throws { return try self.visit(.i64Extend8S) } - public mutating func visitI64Extend16S() throws { return try self.visit(.i64Extend16S) } - public mutating func visitI64Extend32S() throws { return try self.visit(.i64Extend32S) } + public mutating func visitUnary(_ unary: Instruction.Unary) throws { return try self.visit(.unary(unary)) } + public mutating func visitBinary(_ binary: Instruction.Binary) throws { return try self.visit(.binary(binary)) } + public mutating func visitConversion(_ conversion: Instruction.Conversion) throws { return try self.visit(.conversion(conversion)) } public mutating func visitMemoryInit(dataIndex: UInt32) throws { return try self.visit(.memoryInit(dataIndex: dataIndex)) } public mutating func visitDataDrop(dataIndex: UInt32) throws { return try self.visit(.dataDrop(dataIndex: dataIndex)) } public mutating func visitMemoryCopy(dstMem: UInt32, srcMem: UInt32) throws { return try self.visit(.memoryCopy(dstMem: dstMem, srcMem: srcMem)) } @@ -408,14 +283,6 @@ extension AnyInstructionVisitor { public mutating func visitTableSet(table: UInt32) throws { return try self.visit(.tableSet(table: table)) } public mutating func visitTableGrow(table: UInt32) throws { return try self.visit(.tableGrow(table: table)) } public mutating func visitTableSize(table: UInt32) throws { return try self.visit(.tableSize(table: table)) } - public mutating func visitI32TruncSatF32S() throws { return try self.visit(.i32TruncSatF32S) } - public mutating func visitI32TruncSatF32U() throws { return try self.visit(.i32TruncSatF32U) } - public mutating func visitI32TruncSatF64S() throws { return try self.visit(.i32TruncSatF64S) } - public mutating func visitI32TruncSatF64U() throws { return try self.visit(.i32TruncSatF64U) } - public mutating func visitI64TruncSatF32S() throws { return try self.visit(.i64TruncSatF32S) } - public mutating func visitI64TruncSatF32U() throws { return try self.visit(.i64TruncSatF32U) } - public mutating func visitI64TruncSatF64S() throws { return try self.visit(.i64TruncSatF64S) } - public mutating func visitI64TruncSatF64U() throws { return try self.visit(.i64TruncSatF64U) } } /// A visitor that traces the instructions visited. @@ -518,97 +385,13 @@ public struct InstructionTracingVisitor: InstructionVisit trace(.globalSet(globalIndex: globalIndex)) return try visitor.visitGlobalSet(globalIndex: globalIndex) } - public mutating func visitI32Load(memarg: MemArg) throws { - trace(.i32Load(memarg: memarg)) - return try visitor.visitI32Load(memarg: memarg) - } - public mutating func visitI64Load(memarg: MemArg) throws { - trace(.i64Load(memarg: memarg)) - return try visitor.visitI64Load(memarg: memarg) - } - public mutating func visitF32Load(memarg: MemArg) throws { - trace(.f32Load(memarg: memarg)) - return try visitor.visitF32Load(memarg: memarg) - } - public mutating func visitF64Load(memarg: MemArg) throws { - trace(.f64Load(memarg: memarg)) - return try visitor.visitF64Load(memarg: memarg) - } - public mutating func visitI32Load8S(memarg: MemArg) throws { - trace(.i32Load8S(memarg: memarg)) - return try visitor.visitI32Load8S(memarg: memarg) - } - public mutating func visitI32Load8U(memarg: MemArg) throws { - trace(.i32Load8U(memarg: memarg)) - return try visitor.visitI32Load8U(memarg: memarg) - } - public mutating func visitI32Load16S(memarg: MemArg) throws { - trace(.i32Load16S(memarg: memarg)) - return try visitor.visitI32Load16S(memarg: memarg) - } - public mutating func visitI32Load16U(memarg: MemArg) throws { - trace(.i32Load16U(memarg: memarg)) - return try visitor.visitI32Load16U(memarg: memarg) - } - public mutating func visitI64Load8S(memarg: MemArg) throws { - trace(.i64Load8S(memarg: memarg)) - return try visitor.visitI64Load8S(memarg: memarg) - } - public mutating func visitI64Load8U(memarg: MemArg) throws { - trace(.i64Load8U(memarg: memarg)) - return try visitor.visitI64Load8U(memarg: memarg) - } - public mutating func visitI64Load16S(memarg: MemArg) throws { - trace(.i64Load16S(memarg: memarg)) - return try visitor.visitI64Load16S(memarg: memarg) - } - public mutating func visitI64Load16U(memarg: MemArg) throws { - trace(.i64Load16U(memarg: memarg)) - return try visitor.visitI64Load16U(memarg: memarg) - } - public mutating func visitI64Load32S(memarg: MemArg) throws { - trace(.i64Load32S(memarg: memarg)) - return try visitor.visitI64Load32S(memarg: memarg) - } - public mutating func visitI64Load32U(memarg: MemArg) throws { - trace(.i64Load32U(memarg: memarg)) - return try visitor.visitI64Load32U(memarg: memarg) - } - public mutating func visitI32Store(memarg: MemArg) throws { - trace(.i32Store(memarg: memarg)) - return try visitor.visitI32Store(memarg: memarg) - } - public mutating func visitI64Store(memarg: MemArg) throws { - trace(.i64Store(memarg: memarg)) - return try visitor.visitI64Store(memarg: memarg) - } - public mutating func visitF32Store(memarg: MemArg) throws { - trace(.f32Store(memarg: memarg)) - return try visitor.visitF32Store(memarg: memarg) - } - public mutating func visitF64Store(memarg: MemArg) throws { - trace(.f64Store(memarg: memarg)) - return try visitor.visitF64Store(memarg: memarg) - } - public mutating func visitI32Store8(memarg: MemArg) throws { - trace(.i32Store8(memarg: memarg)) - return try visitor.visitI32Store8(memarg: memarg) + public mutating func visitLoad(_ load: Instruction.Load, memarg: MemArg) throws { + trace(.load(load, memarg: memarg)) + return try visitor.visitLoad(load, memarg: memarg) } - public mutating func visitI32Store16(memarg: MemArg) throws { - trace(.i32Store16(memarg: memarg)) - return try visitor.visitI32Store16(memarg: memarg) - } - public mutating func visitI64Store8(memarg: MemArg) throws { - trace(.i64Store8(memarg: memarg)) - return try visitor.visitI64Store8(memarg: memarg) - } - public mutating func visitI64Store16(memarg: MemArg) throws { - trace(.i64Store16(memarg: memarg)) - return try visitor.visitI64Store16(memarg: memarg) - } - public mutating func visitI64Store32(memarg: MemArg) throws { - trace(.i64Store32(memarg: memarg)) - return try visitor.visitI64Store32(memarg: memarg) + public mutating func visitStore(_ store: Instruction.Store, memarg: MemArg) throws { + trace(.store(store, memarg: memarg)) + return try visitor.visitStore(store, memarg: memarg) } public mutating func visitMemorySize(memory: UInt32) throws { trace(.memorySize(memory: memory)) @@ -650,513 +433,25 @@ public struct InstructionTracingVisitor: InstructionVisit trace(.i32Eqz) return try visitor.visitI32Eqz() } - public mutating func visitI32Eq() throws { - trace(.i32Eq) - return try visitor.visitI32Eq() - } - public mutating func visitI32Ne() throws { - trace(.i32Ne) - return try visitor.visitI32Ne() - } - public mutating func visitI32LtS() throws { - trace(.i32LtS) - return try visitor.visitI32LtS() - } - public mutating func visitI32LtU() throws { - trace(.i32LtU) - return try visitor.visitI32LtU() - } - public mutating func visitI32GtS() throws { - trace(.i32GtS) - return try visitor.visitI32GtS() - } - public mutating func visitI32GtU() throws { - trace(.i32GtU) - return try visitor.visitI32GtU() - } - public mutating func visitI32LeS() throws { - trace(.i32LeS) - return try visitor.visitI32LeS() - } - public mutating func visitI32LeU() throws { - trace(.i32LeU) - return try visitor.visitI32LeU() - } - public mutating func visitI32GeS() throws { - trace(.i32GeS) - return try visitor.visitI32GeS() - } - public mutating func visitI32GeU() throws { - trace(.i32GeU) - return try visitor.visitI32GeU() + public mutating func visitCmp(_ cmp: Instruction.Cmp) throws { + trace(.cmp(cmp)) + return try visitor.visitCmp(cmp) } public mutating func visitI64Eqz() throws { trace(.i64Eqz) return try visitor.visitI64Eqz() } - public mutating func visitI64Eq() throws { - trace(.i64Eq) - return try visitor.visitI64Eq() - } - public mutating func visitI64Ne() throws { - trace(.i64Ne) - return try visitor.visitI64Ne() - } - public mutating func visitI64LtS() throws { - trace(.i64LtS) - return try visitor.visitI64LtS() - } - public mutating func visitI64LtU() throws { - trace(.i64LtU) - return try visitor.visitI64LtU() - } - public mutating func visitI64GtS() throws { - trace(.i64GtS) - return try visitor.visitI64GtS() - } - public mutating func visitI64GtU() throws { - trace(.i64GtU) - return try visitor.visitI64GtU() - } - public mutating func visitI64LeS() throws { - trace(.i64LeS) - return try visitor.visitI64LeS() - } - public mutating func visitI64LeU() throws { - trace(.i64LeU) - return try visitor.visitI64LeU() - } - public mutating func visitI64GeS() throws { - trace(.i64GeS) - return try visitor.visitI64GeS() - } - public mutating func visitI64GeU() throws { - trace(.i64GeU) - return try visitor.visitI64GeU() - } - public mutating func visitF32Eq() throws { - trace(.f32Eq) - return try visitor.visitF32Eq() - } - public mutating func visitF32Ne() throws { - trace(.f32Ne) - return try visitor.visitF32Ne() - } - public mutating func visitF32Lt() throws { - trace(.f32Lt) - return try visitor.visitF32Lt() - } - public mutating func visitF32Gt() throws { - trace(.f32Gt) - return try visitor.visitF32Gt() - } - public mutating func visitF32Le() throws { - trace(.f32Le) - return try visitor.visitF32Le() - } - public mutating func visitF32Ge() throws { - trace(.f32Ge) - return try visitor.visitF32Ge() - } - public mutating func visitF64Eq() throws { - trace(.f64Eq) - return try visitor.visitF64Eq() - } - public mutating func visitF64Ne() throws { - trace(.f64Ne) - return try visitor.visitF64Ne() - } - public mutating func visitF64Lt() throws { - trace(.f64Lt) - return try visitor.visitF64Lt() - } - public mutating func visitF64Gt() throws { - trace(.f64Gt) - return try visitor.visitF64Gt() - } - public mutating func visitF64Le() throws { - trace(.f64Le) - return try visitor.visitF64Le() - } - public mutating func visitF64Ge() throws { - trace(.f64Ge) - return try visitor.visitF64Ge() - } - public mutating func visitI32Clz() throws { - trace(.i32Clz) - return try visitor.visitI32Clz() - } - public mutating func visitI32Ctz() throws { - trace(.i32Ctz) - return try visitor.visitI32Ctz() - } - public mutating func visitI32Popcnt() throws { - trace(.i32Popcnt) - return try visitor.visitI32Popcnt() - } - public mutating func visitI32Add() throws { - trace(.i32Add) - return try visitor.visitI32Add() - } - public mutating func visitI32Sub() throws { - trace(.i32Sub) - return try visitor.visitI32Sub() - } - public mutating func visitI32Mul() throws { - trace(.i32Mul) - return try visitor.visitI32Mul() - } - public mutating func visitI32DivS() throws { - trace(.i32DivS) - return try visitor.visitI32DivS() - } - public mutating func visitI32DivU() throws { - trace(.i32DivU) - return try visitor.visitI32DivU() - } - public mutating func visitI32RemS() throws { - trace(.i32RemS) - return try visitor.visitI32RemS() - } - public mutating func visitI32RemU() throws { - trace(.i32RemU) - return try visitor.visitI32RemU() - } - public mutating func visitI32And() throws { - trace(.i32And) - return try visitor.visitI32And() - } - public mutating func visitI32Or() throws { - trace(.i32Or) - return try visitor.visitI32Or() - } - public mutating func visitI32Xor() throws { - trace(.i32Xor) - return try visitor.visitI32Xor() - } - public mutating func visitI32Shl() throws { - trace(.i32Shl) - return try visitor.visitI32Shl() - } - public mutating func visitI32ShrS() throws { - trace(.i32ShrS) - return try visitor.visitI32ShrS() - } - public mutating func visitI32ShrU() throws { - trace(.i32ShrU) - return try visitor.visitI32ShrU() - } - public mutating func visitI32Rotl() throws { - trace(.i32Rotl) - return try visitor.visitI32Rotl() - } - public mutating func visitI32Rotr() throws { - trace(.i32Rotr) - return try visitor.visitI32Rotr() - } - public mutating func visitI64Clz() throws { - trace(.i64Clz) - return try visitor.visitI64Clz() - } - public mutating func visitI64Ctz() throws { - trace(.i64Ctz) - return try visitor.visitI64Ctz() - } - public mutating func visitI64Popcnt() throws { - trace(.i64Popcnt) - return try visitor.visitI64Popcnt() - } - public mutating func visitI64Add() throws { - trace(.i64Add) - return try visitor.visitI64Add() - } - public mutating func visitI64Sub() throws { - trace(.i64Sub) - return try visitor.visitI64Sub() - } - public mutating func visitI64Mul() throws { - trace(.i64Mul) - return try visitor.visitI64Mul() + public mutating func visitUnary(_ unary: Instruction.Unary) throws { + trace(.unary(unary)) + return try visitor.visitUnary(unary) } - public mutating func visitI64DivS() throws { - trace(.i64DivS) - return try visitor.visitI64DivS() + public mutating func visitBinary(_ binary: Instruction.Binary) throws { + trace(.binary(binary)) + return try visitor.visitBinary(binary) } - public mutating func visitI64DivU() throws { - trace(.i64DivU) - return try visitor.visitI64DivU() - } - public mutating func visitI64RemS() throws { - trace(.i64RemS) - return try visitor.visitI64RemS() - } - public mutating func visitI64RemU() throws { - trace(.i64RemU) - return try visitor.visitI64RemU() - } - public mutating func visitI64And() throws { - trace(.i64And) - return try visitor.visitI64And() - } - public mutating func visitI64Or() throws { - trace(.i64Or) - return try visitor.visitI64Or() - } - public mutating func visitI64Xor() throws { - trace(.i64Xor) - return try visitor.visitI64Xor() - } - public mutating func visitI64Shl() throws { - trace(.i64Shl) - return try visitor.visitI64Shl() - } - public mutating func visitI64ShrS() throws { - trace(.i64ShrS) - return try visitor.visitI64ShrS() - } - public mutating func visitI64ShrU() throws { - trace(.i64ShrU) - return try visitor.visitI64ShrU() - } - public mutating func visitI64Rotl() throws { - trace(.i64Rotl) - return try visitor.visitI64Rotl() - } - public mutating func visitI64Rotr() throws { - trace(.i64Rotr) - return try visitor.visitI64Rotr() - } - public mutating func visitF32Abs() throws { - trace(.f32Abs) - return try visitor.visitF32Abs() - } - public mutating func visitF32Neg() throws { - trace(.f32Neg) - return try visitor.visitF32Neg() - } - public mutating func visitF32Ceil() throws { - trace(.f32Ceil) - return try visitor.visitF32Ceil() - } - public mutating func visitF32Floor() throws { - trace(.f32Floor) - return try visitor.visitF32Floor() - } - public mutating func visitF32Trunc() throws { - trace(.f32Trunc) - return try visitor.visitF32Trunc() - } - public mutating func visitF32Nearest() throws { - trace(.f32Nearest) - return try visitor.visitF32Nearest() - } - public mutating func visitF32Sqrt() throws { - trace(.f32Sqrt) - return try visitor.visitF32Sqrt() - } - public mutating func visitF32Add() throws { - trace(.f32Add) - return try visitor.visitF32Add() - } - public mutating func visitF32Sub() throws { - trace(.f32Sub) - return try visitor.visitF32Sub() - } - public mutating func visitF32Mul() throws { - trace(.f32Mul) - return try visitor.visitF32Mul() - } - public mutating func visitF32Div() throws { - trace(.f32Div) - return try visitor.visitF32Div() - } - public mutating func visitF32Min() throws { - trace(.f32Min) - return try visitor.visitF32Min() - } - public mutating func visitF32Max() throws { - trace(.f32Max) - return try visitor.visitF32Max() - } - public mutating func visitF32Copysign() throws { - trace(.f32Copysign) - return try visitor.visitF32Copysign() - } - public mutating func visitF64Abs() throws { - trace(.f64Abs) - return try visitor.visitF64Abs() - } - public mutating func visitF64Neg() throws { - trace(.f64Neg) - return try visitor.visitF64Neg() - } - public mutating func visitF64Ceil() throws { - trace(.f64Ceil) - return try visitor.visitF64Ceil() - } - public mutating func visitF64Floor() throws { - trace(.f64Floor) - return try visitor.visitF64Floor() - } - public mutating func visitF64Trunc() throws { - trace(.f64Trunc) - return try visitor.visitF64Trunc() - } - public mutating func visitF64Nearest() throws { - trace(.f64Nearest) - return try visitor.visitF64Nearest() - } - public mutating func visitF64Sqrt() throws { - trace(.f64Sqrt) - return try visitor.visitF64Sqrt() - } - public mutating func visitF64Add() throws { - trace(.f64Add) - return try visitor.visitF64Add() - } - public mutating func visitF64Sub() throws { - trace(.f64Sub) - return try visitor.visitF64Sub() - } - public mutating func visitF64Mul() throws { - trace(.f64Mul) - return try visitor.visitF64Mul() - } - public mutating func visitF64Div() throws { - trace(.f64Div) - return try visitor.visitF64Div() - } - public mutating func visitF64Min() throws { - trace(.f64Min) - return try visitor.visitF64Min() - } - public mutating func visitF64Max() throws { - trace(.f64Max) - return try visitor.visitF64Max() - } - public mutating func visitF64Copysign() throws { - trace(.f64Copysign) - return try visitor.visitF64Copysign() - } - public mutating func visitI32WrapI64() throws { - trace(.i32WrapI64) - return try visitor.visitI32WrapI64() - } - public mutating func visitI32TruncF32S() throws { - trace(.i32TruncF32S) - return try visitor.visitI32TruncF32S() - } - public mutating func visitI32TruncF32U() throws { - trace(.i32TruncF32U) - return try visitor.visitI32TruncF32U() - } - public mutating func visitI32TruncF64S() throws { - trace(.i32TruncF64S) - return try visitor.visitI32TruncF64S() - } - public mutating func visitI32TruncF64U() throws { - trace(.i32TruncF64U) - return try visitor.visitI32TruncF64U() - } - public mutating func visitI64ExtendI32S() throws { - trace(.i64ExtendI32S) - return try visitor.visitI64ExtendI32S() - } - public mutating func visitI64ExtendI32U() throws { - trace(.i64ExtendI32U) - return try visitor.visitI64ExtendI32U() - } - public mutating func visitI64TruncF32S() throws { - trace(.i64TruncF32S) - return try visitor.visitI64TruncF32S() - } - public mutating func visitI64TruncF32U() throws { - trace(.i64TruncF32U) - return try visitor.visitI64TruncF32U() - } - public mutating func visitI64TruncF64S() throws { - trace(.i64TruncF64S) - return try visitor.visitI64TruncF64S() - } - public mutating func visitI64TruncF64U() throws { - trace(.i64TruncF64U) - return try visitor.visitI64TruncF64U() - } - public mutating func visitF32ConvertI32S() throws { - trace(.f32ConvertI32S) - return try visitor.visitF32ConvertI32S() - } - public mutating func visitF32ConvertI32U() throws { - trace(.f32ConvertI32U) - return try visitor.visitF32ConvertI32U() - } - public mutating func visitF32ConvertI64S() throws { - trace(.f32ConvertI64S) - return try visitor.visitF32ConvertI64S() - } - public mutating func visitF32ConvertI64U() throws { - trace(.f32ConvertI64U) - return try visitor.visitF32ConvertI64U() - } - public mutating func visitF32DemoteF64() throws { - trace(.f32DemoteF64) - return try visitor.visitF32DemoteF64() - } - public mutating func visitF64ConvertI32S() throws { - trace(.f64ConvertI32S) - return try visitor.visitF64ConvertI32S() - } - public mutating func visitF64ConvertI32U() throws { - trace(.f64ConvertI32U) - return try visitor.visitF64ConvertI32U() - } - public mutating func visitF64ConvertI64S() throws { - trace(.f64ConvertI64S) - return try visitor.visitF64ConvertI64S() - } - public mutating func visitF64ConvertI64U() throws { - trace(.f64ConvertI64U) - return try visitor.visitF64ConvertI64U() - } - public mutating func visitF64PromoteF32() throws { - trace(.f64PromoteF32) - return try visitor.visitF64PromoteF32() - } - public mutating func visitI32ReinterpretF32() throws { - trace(.i32ReinterpretF32) - return try visitor.visitI32ReinterpretF32() - } - public mutating func visitI64ReinterpretF64() throws { - trace(.i64ReinterpretF64) - return try visitor.visitI64ReinterpretF64() - } - public mutating func visitF32ReinterpretI32() throws { - trace(.f32ReinterpretI32) - return try visitor.visitF32ReinterpretI32() - } - public mutating func visitF64ReinterpretI64() throws { - trace(.f64ReinterpretI64) - return try visitor.visitF64ReinterpretI64() - } - public mutating func visitI32Extend8S() throws { - trace(.i32Extend8S) - return try visitor.visitI32Extend8S() - } - public mutating func visitI32Extend16S() throws { - trace(.i32Extend16S) - return try visitor.visitI32Extend16S() - } - public mutating func visitI64Extend8S() throws { - trace(.i64Extend8S) - return try visitor.visitI64Extend8S() - } - public mutating func visitI64Extend16S() throws { - trace(.i64Extend16S) - return try visitor.visitI64Extend16S() - } - public mutating func visitI64Extend32S() throws { - trace(.i64Extend32S) - return try visitor.visitI64Extend32S() + public mutating func visitConversion(_ conversion: Instruction.Conversion) throws { + trace(.conversion(conversion)) + return try visitor.visitConversion(conversion) } public mutating func visitMemoryInit(dataIndex: UInt32) throws { trace(.memoryInit(dataIndex: dataIndex)) @@ -1206,38 +501,6 @@ public struct InstructionTracingVisitor: InstructionVisit trace(.tableSize(table: table)) return try visitor.visitTableSize(table: table) } - public mutating func visitI32TruncSatF32S() throws { - trace(.i32TruncSatF32S) - return try visitor.visitI32TruncSatF32S() - } - public mutating func visitI32TruncSatF32U() throws { - trace(.i32TruncSatF32U) - return try visitor.visitI32TruncSatF32U() - } - public mutating func visitI32TruncSatF64S() throws { - trace(.i32TruncSatF64S) - return try visitor.visitI32TruncSatF64S() - } - public mutating func visitI32TruncSatF64U() throws { - trace(.i32TruncSatF64U) - return try visitor.visitI32TruncSatF64U() - } - public mutating func visitI64TruncSatF32S() throws { - trace(.i64TruncSatF32S) - return try visitor.visitI64TruncSatF32S() - } - public mutating func visitI64TruncSatF32U() throws { - trace(.i64TruncSatF32U) - return try visitor.visitI64TruncSatF32U() - } - public mutating func visitI64TruncSatF64S() throws { - trace(.i64TruncSatF64S) - return try visitor.visitI64TruncSatF64S() - } - public mutating func visitI64TruncSatF64U() throws { - trace(.i64TruncSatF64U) - return try visitor.visitI64TruncSatF64U() - } } /// A visitor for WebAssembly instructions. @@ -1287,52 +550,10 @@ public protocol InstructionVisitor { mutating func visitGlobalGet(globalIndex: UInt32) throws /// Visiting `global.set` instruction. mutating func visitGlobalSet(globalIndex: UInt32) throws - /// Visiting `i32.load` instruction. - mutating func visitI32Load(memarg: MemArg) throws - /// Visiting `i64.load` instruction. - mutating func visitI64Load(memarg: MemArg) throws - /// Visiting `f32.load` instruction. - mutating func visitF32Load(memarg: MemArg) throws - /// Visiting `f64.load` instruction. - mutating func visitF64Load(memarg: MemArg) throws - /// Visiting `i32.load8_s` instruction. - mutating func visitI32Load8S(memarg: MemArg) throws - /// Visiting `i32.load8_u` instruction. - mutating func visitI32Load8U(memarg: MemArg) throws - /// Visiting `i32.load16_s` instruction. - mutating func visitI32Load16S(memarg: MemArg) throws - /// Visiting `i32.load16_u` instruction. - mutating func visitI32Load16U(memarg: MemArg) throws - /// Visiting `i64.load8_s` instruction. - mutating func visitI64Load8S(memarg: MemArg) throws - /// Visiting `i64.load8_u` instruction. - mutating func visitI64Load8U(memarg: MemArg) throws - /// Visiting `i64.load16_s` instruction. - mutating func visitI64Load16S(memarg: MemArg) throws - /// Visiting `i64.load16_u` instruction. - mutating func visitI64Load16U(memarg: MemArg) throws - /// Visiting `i64.load32_s` instruction. - mutating func visitI64Load32S(memarg: MemArg) throws - /// Visiting `i64.load32_u` instruction. - mutating func visitI64Load32U(memarg: MemArg) throws - /// Visiting `i32.store` instruction. - mutating func visitI32Store(memarg: MemArg) throws - /// Visiting `i64.store` instruction. - mutating func visitI64Store(memarg: MemArg) throws - /// Visiting `f32.store` instruction. - mutating func visitF32Store(memarg: MemArg) throws - /// Visiting `f64.store` instruction. - mutating func visitF64Store(memarg: MemArg) throws - /// Visiting `i32.store8` instruction. - mutating func visitI32Store8(memarg: MemArg) throws - /// Visiting `i32.store16` instruction. - mutating func visitI32Store16(memarg: MemArg) throws - /// Visiting `i64.store8` instruction. - mutating func visitI64Store8(memarg: MemArg) throws - /// Visiting `i64.store16` instruction. - mutating func visitI64Store16(memarg: MemArg) throws - /// Visiting `i64.store32` instruction. - mutating func visitI64Store32(memarg: MemArg) throws + /// Visiting `load` category instruction. + mutating func visitLoad(_: Instruction.Load, memarg: MemArg) throws + /// Visiting `store` category instruction. + mutating func visitStore(_: Instruction.Store, memarg: MemArg) throws /// Visiting `memory.size` instruction. mutating func visitMemorySize(memory: UInt32) throws /// Visiting `memory.grow` instruction. @@ -1353,260 +574,16 @@ public protocol InstructionVisitor { mutating func visitRefFunc(functionIndex: UInt32) throws /// Visiting `i32.eqz` instruction. mutating func visitI32Eqz() throws - /// Visiting `i32.eq` instruction. - mutating func visitI32Eq() throws - /// Visiting `i32.ne` instruction. - mutating func visitI32Ne() throws - /// Visiting `i32.lt_s` instruction. - mutating func visitI32LtS() throws - /// Visiting `i32.lt_u` instruction. - mutating func visitI32LtU() throws - /// Visiting `i32.gt_s` instruction. - mutating func visitI32GtS() throws - /// Visiting `i32.gt_u` instruction. - mutating func visitI32GtU() throws - /// Visiting `i32.le_s` instruction. - mutating func visitI32LeS() throws - /// Visiting `i32.le_u` instruction. - mutating func visitI32LeU() throws - /// Visiting `i32.ge_s` instruction. - mutating func visitI32GeS() throws - /// Visiting `i32.ge_u` instruction. - mutating func visitI32GeU() throws + /// Visiting `cmp` category instruction. + mutating func visitCmp(_: Instruction.Cmp) throws /// Visiting `i64.eqz` instruction. mutating func visitI64Eqz() throws - /// Visiting `i64.eq` instruction. - mutating func visitI64Eq() throws - /// Visiting `i64.ne` instruction. - mutating func visitI64Ne() throws - /// Visiting `i64.lt_s` instruction. - mutating func visitI64LtS() throws - /// Visiting `i64.lt_u` instruction. - mutating func visitI64LtU() throws - /// Visiting `i64.gt_s` instruction. - mutating func visitI64GtS() throws - /// Visiting `i64.gt_u` instruction. - mutating func visitI64GtU() throws - /// Visiting `i64.le_s` instruction. - mutating func visitI64LeS() throws - /// Visiting `i64.le_u` instruction. - mutating func visitI64LeU() throws - /// Visiting `i64.ge_s` instruction. - mutating func visitI64GeS() throws - /// Visiting `i64.ge_u` instruction. - mutating func visitI64GeU() throws - /// Visiting `f32.eq` instruction. - mutating func visitF32Eq() throws - /// Visiting `f32.ne` instruction. - mutating func visitF32Ne() throws - /// Visiting `f32.lt` instruction. - mutating func visitF32Lt() throws - /// Visiting `f32.gt` instruction. - mutating func visitF32Gt() throws - /// Visiting `f32.le` instruction. - mutating func visitF32Le() throws - /// Visiting `f32.ge` instruction. - mutating func visitF32Ge() throws - /// Visiting `f64.eq` instruction. - mutating func visitF64Eq() throws - /// Visiting `f64.ne` instruction. - mutating func visitF64Ne() throws - /// Visiting `f64.lt` instruction. - mutating func visitF64Lt() throws - /// Visiting `f64.gt` instruction. - mutating func visitF64Gt() throws - /// Visiting `f64.le` instruction. - mutating func visitF64Le() throws - /// Visiting `f64.ge` instruction. - mutating func visitF64Ge() throws - /// Visiting `i32.clz` instruction. - mutating func visitI32Clz() throws - /// Visiting `i32.ctz` instruction. - mutating func visitI32Ctz() throws - /// Visiting `i32.popcnt` instruction. - mutating func visitI32Popcnt() throws - /// Visiting `i32.add` instruction. - mutating func visitI32Add() throws - /// Visiting `i32.sub` instruction. - mutating func visitI32Sub() throws - /// Visiting `i32.mul` instruction. - mutating func visitI32Mul() throws - /// Visiting `i32.div_s` instruction. - mutating func visitI32DivS() throws - /// Visiting `i32.div_u` instruction. - mutating func visitI32DivU() throws - /// Visiting `i32.rem_s` instruction. - mutating func visitI32RemS() throws - /// Visiting `i32.rem_u` instruction. - mutating func visitI32RemU() throws - /// Visiting `i32.and` instruction. - mutating func visitI32And() throws - /// Visiting `i32.or` instruction. - mutating func visitI32Or() throws - /// Visiting `i32.xor` instruction. - mutating func visitI32Xor() throws - /// Visiting `i32.shl` instruction. - mutating func visitI32Shl() throws - /// Visiting `i32.shr_s` instruction. - mutating func visitI32ShrS() throws - /// Visiting `i32.shr_u` instruction. - mutating func visitI32ShrU() throws - /// Visiting `i32.rotl` instruction. - mutating func visitI32Rotl() throws - /// Visiting `i32.rotr` instruction. - mutating func visitI32Rotr() throws - /// Visiting `i64.clz` instruction. - mutating func visitI64Clz() throws - /// Visiting `i64.ctz` instruction. - mutating func visitI64Ctz() throws - /// Visiting `i64.popcnt` instruction. - mutating func visitI64Popcnt() throws - /// Visiting `i64.add` instruction. - mutating func visitI64Add() throws - /// Visiting `i64.sub` instruction. - mutating func visitI64Sub() throws - /// Visiting `i64.mul` instruction. - mutating func visitI64Mul() throws - /// Visiting `i64.div_s` instruction. - mutating func visitI64DivS() throws - /// Visiting `i64.div_u` instruction. - mutating func visitI64DivU() throws - /// Visiting `i64.rem_s` instruction. - mutating func visitI64RemS() throws - /// Visiting `i64.rem_u` instruction. - mutating func visitI64RemU() throws - /// Visiting `i64.and` instruction. - mutating func visitI64And() throws - /// Visiting `i64.or` instruction. - mutating func visitI64Or() throws - /// Visiting `i64.xor` instruction. - mutating func visitI64Xor() throws - /// Visiting `i64.shl` instruction. - mutating func visitI64Shl() throws - /// Visiting `i64.shr_s` instruction. - mutating func visitI64ShrS() throws - /// Visiting `i64.shr_u` instruction. - mutating func visitI64ShrU() throws - /// Visiting `i64.rotl` instruction. - mutating func visitI64Rotl() throws - /// Visiting `i64.rotr` instruction. - mutating func visitI64Rotr() throws - /// Visiting `f32.abs` instruction. - mutating func visitF32Abs() throws - /// Visiting `f32.neg` instruction. - mutating func visitF32Neg() throws - /// Visiting `f32.ceil` instruction. - mutating func visitF32Ceil() throws - /// Visiting `f32.floor` instruction. - mutating func visitF32Floor() throws - /// Visiting `f32.trunc` instruction. - mutating func visitF32Trunc() throws - /// Visiting `f32.nearest` instruction. - mutating func visitF32Nearest() throws - /// Visiting `f32.sqrt` instruction. - mutating func visitF32Sqrt() throws - /// Visiting `f32.add` instruction. - mutating func visitF32Add() throws - /// Visiting `f32.sub` instruction. - mutating func visitF32Sub() throws - /// Visiting `f32.mul` instruction. - mutating func visitF32Mul() throws - /// Visiting `f32.div` instruction. - mutating func visitF32Div() throws - /// Visiting `f32.min` instruction. - mutating func visitF32Min() throws - /// Visiting `f32.max` instruction. - mutating func visitF32Max() throws - /// Visiting `f32.copysign` instruction. - mutating func visitF32Copysign() throws - /// Visiting `f64.abs` instruction. - mutating func visitF64Abs() throws - /// Visiting `f64.neg` instruction. - mutating func visitF64Neg() throws - /// Visiting `f64.ceil` instruction. - mutating func visitF64Ceil() throws - /// Visiting `f64.floor` instruction. - mutating func visitF64Floor() throws - /// Visiting `f64.trunc` instruction. - mutating func visitF64Trunc() throws - /// Visiting `f64.nearest` instruction. - mutating func visitF64Nearest() throws - /// Visiting `f64.sqrt` instruction. - mutating func visitF64Sqrt() throws - /// Visiting `f64.add` instruction. - mutating func visitF64Add() throws - /// Visiting `f64.sub` instruction. - mutating func visitF64Sub() throws - /// Visiting `f64.mul` instruction. - mutating func visitF64Mul() throws - /// Visiting `f64.div` instruction. - mutating func visitF64Div() throws - /// Visiting `f64.min` instruction. - mutating func visitF64Min() throws - /// Visiting `f64.max` instruction. - mutating func visitF64Max() throws - /// Visiting `f64.copysign` instruction. - mutating func visitF64Copysign() throws - /// Visiting `i32.wrap_i64` instruction. - mutating func visitI32WrapI64() throws - /// Visiting `i32.trunc_f32_s` instruction. - mutating func visitI32TruncF32S() throws - /// Visiting `i32.trunc_f32_u` instruction. - mutating func visitI32TruncF32U() throws - /// Visiting `i32.trunc_f64_s` instruction. - mutating func visitI32TruncF64S() throws - /// Visiting `i32.trunc_f64_u` instruction. - mutating func visitI32TruncF64U() throws - /// Visiting `i64.extend_i32_s` instruction. - mutating func visitI64ExtendI32S() throws - /// Visiting `i64.extend_i32_u` instruction. - mutating func visitI64ExtendI32U() throws - /// Visiting `i64.trunc_f32_s` instruction. - mutating func visitI64TruncF32S() throws - /// Visiting `i64.trunc_f32_u` instruction. - mutating func visitI64TruncF32U() throws - /// Visiting `i64.trunc_f64_s` instruction. - mutating func visitI64TruncF64S() throws - /// Visiting `i64.trunc_f64_u` instruction. - mutating func visitI64TruncF64U() throws - /// Visiting `f32.convert_i32_s` instruction. - mutating func visitF32ConvertI32S() throws - /// Visiting `f32.convert_i32_u` instruction. - mutating func visitF32ConvertI32U() throws - /// Visiting `f32.convert_i64_s` instruction. - mutating func visitF32ConvertI64S() throws - /// Visiting `f32.convert_i64_u` instruction. - mutating func visitF32ConvertI64U() throws - /// Visiting `f32.demote_f64` instruction. - mutating func visitF32DemoteF64() throws - /// Visiting `f64.convert_i32_s` instruction. - mutating func visitF64ConvertI32S() throws - /// Visiting `f64.convert_i32_u` instruction. - mutating func visitF64ConvertI32U() throws - /// Visiting `f64.convert_i64_s` instruction. - mutating func visitF64ConvertI64S() throws - /// Visiting `f64.convert_i64_u` instruction. - mutating func visitF64ConvertI64U() throws - /// Visiting `f64.promote_f32` instruction. - mutating func visitF64PromoteF32() throws - /// Visiting `i32.reinterpret_f32` instruction. - mutating func visitI32ReinterpretF32() throws - /// Visiting `i64.reinterpret_f64` instruction. - mutating func visitI64ReinterpretF64() throws - /// Visiting `f32.reinterpret_i32` instruction. - mutating func visitF32ReinterpretI32() throws - /// Visiting `f64.reinterpret_i64` instruction. - mutating func visitF64ReinterpretI64() throws - /// Visiting `i32.extend8_s` instruction. - mutating func visitI32Extend8S() throws - /// Visiting `i32.extend16_s` instruction. - mutating func visitI32Extend16S() throws - /// Visiting `i64.extend8_s` instruction. - mutating func visitI64Extend8S() throws - /// Visiting `i64.extend16_s` instruction. - mutating func visitI64Extend16S() throws - /// Visiting `i64.extend32_s` instruction. - mutating func visitI64Extend32S() throws + /// Visiting `unary` category instruction. + mutating func visitUnary(_: Instruction.Unary) throws + /// Visiting `binary` category instruction. + mutating func visitBinary(_: Instruction.Binary) throws + /// Visiting `conversion` category instruction. + mutating func visitConversion(_: Instruction.Conversion) throws /// Visiting `memory.init` instruction. mutating func visitMemoryInit(dataIndex: UInt32) throws /// Visiting `data.drop` instruction. @@ -1631,22 +608,6 @@ public protocol InstructionVisitor { mutating func visitTableGrow(table: UInt32) throws /// Visiting `table.size` instruction. mutating func visitTableSize(table: UInt32) throws - /// Visiting `i32.trunc_sat_f32_s` instruction. - mutating func visitI32TruncSatF32S() throws - /// Visiting `i32.trunc_sat_f32_u` instruction. - mutating func visitI32TruncSatF32U() throws - /// Visiting `i32.trunc_sat_f64_s` instruction. - mutating func visitI32TruncSatF64S() throws - /// Visiting `i32.trunc_sat_f64_u` instruction. - mutating func visitI32TruncSatF64U() throws - /// Visiting `i64.trunc_sat_f32_s` instruction. - mutating func visitI64TruncSatF32S() throws - /// Visiting `i64.trunc_sat_f32_u` instruction. - mutating func visitI64TruncSatF32U() throws - /// Visiting `i64.trunc_sat_f64_s` instruction. - mutating func visitI64TruncSatF64S() throws - /// Visiting `i64.trunc_sat_f64_u` instruction. - mutating func visitI64TruncSatF64U() throws } extension InstructionVisitor { @@ -1674,29 +635,8 @@ extension InstructionVisitor { case let .localTee(localIndex): return try visitLocalTee(localIndex: localIndex) case let .globalGet(globalIndex): return try visitGlobalGet(globalIndex: globalIndex) case let .globalSet(globalIndex): return try visitGlobalSet(globalIndex: globalIndex) - case let .i32Load(memarg): return try visitI32Load(memarg: memarg) - case let .i64Load(memarg): return try visitI64Load(memarg: memarg) - case let .f32Load(memarg): return try visitF32Load(memarg: memarg) - case let .f64Load(memarg): return try visitF64Load(memarg: memarg) - case let .i32Load8S(memarg): return try visitI32Load8S(memarg: memarg) - case let .i32Load8U(memarg): return try visitI32Load8U(memarg: memarg) - case let .i32Load16S(memarg): return try visitI32Load16S(memarg: memarg) - case let .i32Load16U(memarg): return try visitI32Load16U(memarg: memarg) - case let .i64Load8S(memarg): return try visitI64Load8S(memarg: memarg) - case let .i64Load8U(memarg): return try visitI64Load8U(memarg: memarg) - case let .i64Load16S(memarg): return try visitI64Load16S(memarg: memarg) - case let .i64Load16U(memarg): return try visitI64Load16U(memarg: memarg) - case let .i64Load32S(memarg): return try visitI64Load32S(memarg: memarg) - case let .i64Load32U(memarg): return try visitI64Load32U(memarg: memarg) - case let .i32Store(memarg): return try visitI32Store(memarg: memarg) - case let .i64Store(memarg): return try visitI64Store(memarg: memarg) - case let .f32Store(memarg): return try visitF32Store(memarg: memarg) - case let .f64Store(memarg): return try visitF64Store(memarg: memarg) - case let .i32Store8(memarg): return try visitI32Store8(memarg: memarg) - case let .i32Store16(memarg): return try visitI32Store16(memarg: memarg) - case let .i64Store8(memarg): return try visitI64Store8(memarg: memarg) - case let .i64Store16(memarg): return try visitI64Store16(memarg: memarg) - case let .i64Store32(memarg): return try visitI64Store32(memarg: memarg) + case let .load(load, memarg): return try visitLoad(load, memarg: memarg) + case let .store(store, memarg): return try visitStore(store, memarg: memarg) case let .memorySize(memory): return try visitMemorySize(memory: memory) case let .memoryGrow(memory): return try visitMemoryGrow(memory: memory) case let .i32Const(value): return try visitI32Const(value: value) @@ -1707,133 +647,11 @@ extension InstructionVisitor { case .refIsNull: return try visitRefIsNull() case let .refFunc(functionIndex): return try visitRefFunc(functionIndex: functionIndex) case .i32Eqz: return try visitI32Eqz() - case .i32Eq: return try visitI32Eq() - case .i32Ne: return try visitI32Ne() - case .i32LtS: return try visitI32LtS() - case .i32LtU: return try visitI32LtU() - case .i32GtS: return try visitI32GtS() - case .i32GtU: return try visitI32GtU() - case .i32LeS: return try visitI32LeS() - case .i32LeU: return try visitI32LeU() - case .i32GeS: return try visitI32GeS() - case .i32GeU: return try visitI32GeU() + case let .cmp(cmp): return try visitCmp(cmp) case .i64Eqz: return try visitI64Eqz() - case .i64Eq: return try visitI64Eq() - case .i64Ne: return try visitI64Ne() - case .i64LtS: return try visitI64LtS() - case .i64LtU: return try visitI64LtU() - case .i64GtS: return try visitI64GtS() - case .i64GtU: return try visitI64GtU() - case .i64LeS: return try visitI64LeS() - case .i64LeU: return try visitI64LeU() - case .i64GeS: return try visitI64GeS() - case .i64GeU: return try visitI64GeU() - case .f32Eq: return try visitF32Eq() - case .f32Ne: return try visitF32Ne() - case .f32Lt: return try visitF32Lt() - case .f32Gt: return try visitF32Gt() - case .f32Le: return try visitF32Le() - case .f32Ge: return try visitF32Ge() - case .f64Eq: return try visitF64Eq() - case .f64Ne: return try visitF64Ne() - case .f64Lt: return try visitF64Lt() - case .f64Gt: return try visitF64Gt() - case .f64Le: return try visitF64Le() - case .f64Ge: return try visitF64Ge() - case .i32Clz: return try visitI32Clz() - case .i32Ctz: return try visitI32Ctz() - case .i32Popcnt: return try visitI32Popcnt() - case .i32Add: return try visitI32Add() - case .i32Sub: return try visitI32Sub() - case .i32Mul: return try visitI32Mul() - case .i32DivS: return try visitI32DivS() - case .i32DivU: return try visitI32DivU() - case .i32RemS: return try visitI32RemS() - case .i32RemU: return try visitI32RemU() - case .i32And: return try visitI32And() - case .i32Or: return try visitI32Or() - case .i32Xor: return try visitI32Xor() - case .i32Shl: return try visitI32Shl() - case .i32ShrS: return try visitI32ShrS() - case .i32ShrU: return try visitI32ShrU() - case .i32Rotl: return try visitI32Rotl() - case .i32Rotr: return try visitI32Rotr() - case .i64Clz: return try visitI64Clz() - case .i64Ctz: return try visitI64Ctz() - case .i64Popcnt: return try visitI64Popcnt() - case .i64Add: return try visitI64Add() - case .i64Sub: return try visitI64Sub() - case .i64Mul: return try visitI64Mul() - case .i64DivS: return try visitI64DivS() - case .i64DivU: return try visitI64DivU() - case .i64RemS: return try visitI64RemS() - case .i64RemU: return try visitI64RemU() - case .i64And: return try visitI64And() - case .i64Or: return try visitI64Or() - case .i64Xor: return try visitI64Xor() - case .i64Shl: return try visitI64Shl() - case .i64ShrS: return try visitI64ShrS() - case .i64ShrU: return try visitI64ShrU() - case .i64Rotl: return try visitI64Rotl() - case .i64Rotr: return try visitI64Rotr() - case .f32Abs: return try visitF32Abs() - case .f32Neg: return try visitF32Neg() - case .f32Ceil: return try visitF32Ceil() - case .f32Floor: return try visitF32Floor() - case .f32Trunc: return try visitF32Trunc() - case .f32Nearest: return try visitF32Nearest() - case .f32Sqrt: return try visitF32Sqrt() - case .f32Add: return try visitF32Add() - case .f32Sub: return try visitF32Sub() - case .f32Mul: return try visitF32Mul() - case .f32Div: return try visitF32Div() - case .f32Min: return try visitF32Min() - case .f32Max: return try visitF32Max() - case .f32Copysign: return try visitF32Copysign() - case .f64Abs: return try visitF64Abs() - case .f64Neg: return try visitF64Neg() - case .f64Ceil: return try visitF64Ceil() - case .f64Floor: return try visitF64Floor() - case .f64Trunc: return try visitF64Trunc() - case .f64Nearest: return try visitF64Nearest() - case .f64Sqrt: return try visitF64Sqrt() - case .f64Add: return try visitF64Add() - case .f64Sub: return try visitF64Sub() - case .f64Mul: return try visitF64Mul() - case .f64Div: return try visitF64Div() - case .f64Min: return try visitF64Min() - case .f64Max: return try visitF64Max() - case .f64Copysign: return try visitF64Copysign() - case .i32WrapI64: return try visitI32WrapI64() - case .i32TruncF32S: return try visitI32TruncF32S() - case .i32TruncF32U: return try visitI32TruncF32U() - case .i32TruncF64S: return try visitI32TruncF64S() - case .i32TruncF64U: return try visitI32TruncF64U() - case .i64ExtendI32S: return try visitI64ExtendI32S() - case .i64ExtendI32U: return try visitI64ExtendI32U() - case .i64TruncF32S: return try visitI64TruncF32S() - case .i64TruncF32U: return try visitI64TruncF32U() - case .i64TruncF64S: return try visitI64TruncF64S() - case .i64TruncF64U: return try visitI64TruncF64U() - case .f32ConvertI32S: return try visitF32ConvertI32S() - case .f32ConvertI32U: return try visitF32ConvertI32U() - case .f32ConvertI64S: return try visitF32ConvertI64S() - case .f32ConvertI64U: return try visitF32ConvertI64U() - case .f32DemoteF64: return try visitF32DemoteF64() - case .f64ConvertI32S: return try visitF64ConvertI32S() - case .f64ConvertI32U: return try visitF64ConvertI32U() - case .f64ConvertI64S: return try visitF64ConvertI64S() - case .f64ConvertI64U: return try visitF64ConvertI64U() - case .f64PromoteF32: return try visitF64PromoteF32() - case .i32ReinterpretF32: return try visitI32ReinterpretF32() - case .i64ReinterpretF64: return try visitI64ReinterpretF64() - case .f32ReinterpretI32: return try visitF32ReinterpretI32() - case .f64ReinterpretI64: return try visitF64ReinterpretI64() - case .i32Extend8S: return try visitI32Extend8S() - case .i32Extend16S: return try visitI32Extend16S() - case .i64Extend8S: return try visitI64Extend8S() - case .i64Extend16S: return try visitI64Extend16S() - case .i64Extend32S: return try visitI64Extend32S() + case let .unary(unary): return try visitUnary(unary) + case let .binary(binary): return try visitBinary(binary) + case let .conversion(conversion): return try visitConversion(conversion) case let .memoryInit(dataIndex): return try visitMemoryInit(dataIndex: dataIndex) case let .dataDrop(dataIndex): return try visitDataDrop(dataIndex: dataIndex) case let .memoryCopy(dstMem, srcMem): return try visitMemoryCopy(dstMem: dstMem, srcMem: srcMem) @@ -1846,14 +664,6 @@ extension InstructionVisitor { case let .tableSet(table): return try visitTableSet(table: table) case let .tableGrow(table): return try visitTableGrow(table: table) case let .tableSize(table): return try visitTableSize(table: table) - case .i32TruncSatF32S: return try visitI32TruncSatF32S() - case .i32TruncSatF32U: return try visitI32TruncSatF32U() - case .i32TruncSatF64S: return try visitI32TruncSatF64S() - case .i32TruncSatF64U: return try visitI32TruncSatF64U() - case .i64TruncSatF32S: return try visitI64TruncSatF32S() - case .i64TruncSatF32U: return try visitI64TruncSatF32U() - case .i64TruncSatF64S: return try visitI64TruncSatF64S() - case .i64TruncSatF64U: return try visitI64TruncSatF64U() } } } @@ -1881,29 +691,8 @@ extension InstructionVisitor { public mutating func visitLocalTee(localIndex: UInt32) throws {} public mutating func visitGlobalGet(globalIndex: UInt32) throws {} public mutating func visitGlobalSet(globalIndex: UInt32) throws {} - public mutating func visitI32Load(memarg: MemArg) throws {} - public mutating func visitI64Load(memarg: MemArg) throws {} - public mutating func visitF32Load(memarg: MemArg) throws {} - public mutating func visitF64Load(memarg: MemArg) throws {} - public mutating func visitI32Load8S(memarg: MemArg) throws {} - public mutating func visitI32Load8U(memarg: MemArg) throws {} - public mutating func visitI32Load16S(memarg: MemArg) throws {} - public mutating func visitI32Load16U(memarg: MemArg) throws {} - public mutating func visitI64Load8S(memarg: MemArg) throws {} - public mutating func visitI64Load8U(memarg: MemArg) throws {} - public mutating func visitI64Load16S(memarg: MemArg) throws {} - public mutating func visitI64Load16U(memarg: MemArg) throws {} - public mutating func visitI64Load32S(memarg: MemArg) throws {} - public mutating func visitI64Load32U(memarg: MemArg) throws {} - public mutating func visitI32Store(memarg: MemArg) throws {} - public mutating func visitI64Store(memarg: MemArg) throws {} - public mutating func visitF32Store(memarg: MemArg) throws {} - public mutating func visitF64Store(memarg: MemArg) throws {} - public mutating func visitI32Store8(memarg: MemArg) throws {} - public mutating func visitI32Store16(memarg: MemArg) throws {} - public mutating func visitI64Store8(memarg: MemArg) throws {} - public mutating func visitI64Store16(memarg: MemArg) throws {} - public mutating func visitI64Store32(memarg: MemArg) throws {} + public mutating func visitLoad(_ load: Instruction.Load, memarg: MemArg) throws {} + public mutating func visitStore(_ store: Instruction.Store, memarg: MemArg) throws {} public mutating func visitMemorySize(memory: UInt32) throws {} public mutating func visitMemoryGrow(memory: UInt32) throws {} public mutating func visitI32Const(value: Int32) throws {} @@ -1914,133 +703,11 @@ extension InstructionVisitor { public mutating func visitRefIsNull() throws {} public mutating func visitRefFunc(functionIndex: UInt32) throws {} public mutating func visitI32Eqz() throws {} - public mutating func visitI32Eq() throws {} - public mutating func visitI32Ne() throws {} - public mutating func visitI32LtS() throws {} - public mutating func visitI32LtU() throws {} - public mutating func visitI32GtS() throws {} - public mutating func visitI32GtU() throws {} - public mutating func visitI32LeS() throws {} - public mutating func visitI32LeU() throws {} - public mutating func visitI32GeS() throws {} - public mutating func visitI32GeU() throws {} + public mutating func visitCmp(_ cmp: Instruction.Cmp) throws {} public mutating func visitI64Eqz() throws {} - public mutating func visitI64Eq() throws {} - public mutating func visitI64Ne() throws {} - public mutating func visitI64LtS() throws {} - public mutating func visitI64LtU() throws {} - public mutating func visitI64GtS() throws {} - public mutating func visitI64GtU() throws {} - public mutating func visitI64LeS() throws {} - public mutating func visitI64LeU() throws {} - public mutating func visitI64GeS() throws {} - public mutating func visitI64GeU() throws {} - public mutating func visitF32Eq() throws {} - public mutating func visitF32Ne() throws {} - public mutating func visitF32Lt() throws {} - public mutating func visitF32Gt() throws {} - public mutating func visitF32Le() throws {} - public mutating func visitF32Ge() throws {} - public mutating func visitF64Eq() throws {} - public mutating func visitF64Ne() throws {} - public mutating func visitF64Lt() throws {} - public mutating func visitF64Gt() throws {} - public mutating func visitF64Le() throws {} - public mutating func visitF64Ge() throws {} - public mutating func visitI32Clz() throws {} - public mutating func visitI32Ctz() throws {} - public mutating func visitI32Popcnt() throws {} - public mutating func visitI32Add() throws {} - public mutating func visitI32Sub() throws {} - public mutating func visitI32Mul() throws {} - public mutating func visitI32DivS() throws {} - public mutating func visitI32DivU() throws {} - public mutating func visitI32RemS() throws {} - public mutating func visitI32RemU() throws {} - public mutating func visitI32And() throws {} - public mutating func visitI32Or() throws {} - public mutating func visitI32Xor() throws {} - public mutating func visitI32Shl() throws {} - public mutating func visitI32ShrS() throws {} - public mutating func visitI32ShrU() throws {} - public mutating func visitI32Rotl() throws {} - public mutating func visitI32Rotr() throws {} - public mutating func visitI64Clz() throws {} - public mutating func visitI64Ctz() throws {} - public mutating func visitI64Popcnt() throws {} - public mutating func visitI64Add() throws {} - public mutating func visitI64Sub() throws {} - public mutating func visitI64Mul() throws {} - public mutating func visitI64DivS() throws {} - public mutating func visitI64DivU() throws {} - public mutating func visitI64RemS() throws {} - public mutating func visitI64RemU() throws {} - public mutating func visitI64And() throws {} - public mutating func visitI64Or() throws {} - public mutating func visitI64Xor() throws {} - public mutating func visitI64Shl() throws {} - public mutating func visitI64ShrS() throws {} - public mutating func visitI64ShrU() throws {} - public mutating func visitI64Rotl() throws {} - public mutating func visitI64Rotr() throws {} - public mutating func visitF32Abs() throws {} - public mutating func visitF32Neg() throws {} - public mutating func visitF32Ceil() throws {} - public mutating func visitF32Floor() throws {} - public mutating func visitF32Trunc() throws {} - public mutating func visitF32Nearest() throws {} - public mutating func visitF32Sqrt() throws {} - public mutating func visitF32Add() throws {} - public mutating func visitF32Sub() throws {} - public mutating func visitF32Mul() throws {} - public mutating func visitF32Div() throws {} - public mutating func visitF32Min() throws {} - public mutating func visitF32Max() throws {} - public mutating func visitF32Copysign() throws {} - public mutating func visitF64Abs() throws {} - public mutating func visitF64Neg() throws {} - public mutating func visitF64Ceil() throws {} - public mutating func visitF64Floor() throws {} - public mutating func visitF64Trunc() throws {} - public mutating func visitF64Nearest() throws {} - public mutating func visitF64Sqrt() throws {} - public mutating func visitF64Add() throws {} - public mutating func visitF64Sub() throws {} - public mutating func visitF64Mul() throws {} - public mutating func visitF64Div() throws {} - public mutating func visitF64Min() throws {} - public mutating func visitF64Max() throws {} - public mutating func visitF64Copysign() throws {} - public mutating func visitI32WrapI64() throws {} - public mutating func visitI32TruncF32S() throws {} - public mutating func visitI32TruncF32U() throws {} - public mutating func visitI32TruncF64S() throws {} - public mutating func visitI32TruncF64U() throws {} - public mutating func visitI64ExtendI32S() throws {} - public mutating func visitI64ExtendI32U() throws {} - public mutating func visitI64TruncF32S() throws {} - public mutating func visitI64TruncF32U() throws {} - public mutating func visitI64TruncF64S() throws {} - public mutating func visitI64TruncF64U() throws {} - public mutating func visitF32ConvertI32S() throws {} - public mutating func visitF32ConvertI32U() throws {} - public mutating func visitF32ConvertI64S() throws {} - public mutating func visitF32ConvertI64U() throws {} - public mutating func visitF32DemoteF64() throws {} - public mutating func visitF64ConvertI32S() throws {} - public mutating func visitF64ConvertI32U() throws {} - public mutating func visitF64ConvertI64S() throws {} - public mutating func visitF64ConvertI64U() throws {} - public mutating func visitF64PromoteF32() throws {} - public mutating func visitI32ReinterpretF32() throws {} - public mutating func visitI64ReinterpretF64() throws {} - public mutating func visitF32ReinterpretI32() throws {} - public mutating func visitF64ReinterpretI64() throws {} - public mutating func visitI32Extend8S() throws {} - public mutating func visitI32Extend16S() throws {} - public mutating func visitI64Extend8S() throws {} - public mutating func visitI64Extend16S() throws {} - public mutating func visitI64Extend32S() throws {} + public mutating func visitUnary(_ unary: Instruction.Unary) throws {} + public mutating func visitBinary(_ binary: Instruction.Binary) throws {} + public mutating func visitConversion(_ conversion: Instruction.Conversion) throws {} public mutating func visitMemoryInit(dataIndex: UInt32) throws {} public mutating func visitDataDrop(dataIndex: UInt32) throws {} public mutating func visitMemoryCopy(dstMem: UInt32, srcMem: UInt32) throws {} @@ -2053,13 +720,5 @@ extension InstructionVisitor { public mutating func visitTableSet(table: UInt32) throws {} public mutating func visitTableGrow(table: UInt32) throws {} public mutating func visitTableSize(table: UInt32) throws {} - public mutating func visitI32TruncSatF32S() throws {} - public mutating func visitI32TruncSatF32U() throws {} - public mutating func visitI32TruncSatF64S() throws {} - public mutating func visitI32TruncSatF64U() throws {} - public mutating func visitI64TruncSatF32S() throws {} - public mutating func visitI64TruncSatF32U() throws {} - public mutating func visitI64TruncSatF64S() throws {} - public mutating func visitI64TruncSatF64U() throws {} } diff --git a/Sources/WasmParser/WasmParser.swift b/Sources/WasmParser/WasmParser.swift index 88861c37..82aa1ad3 100644 --- a/Sources/WasmParser/WasmParser.swift +++ b/Sources/WasmParser/WasmParser.swift @@ -129,13 +129,19 @@ extension Code { // TODO: Move `doParseInstruction` under `ExpressionParser` struct @_documentation(visibility: internal) public struct ExpressionParser { + /// The byte offset of the code in the module + let codeOffset: Int + /// The initial byte offset of the code buffer stream + /// NOTE: This might be different from `codeOffset` if the code buffer + /// is not a part of the initial `FileHandleStream` buffer + let initialStreamOffset: Int @usableFromInline let parser: Parser @usableFromInline var lastCode: InstructionCode? public var offset: Int { - self.parser.currentIndex + self.codeOffset + self.parser.currentIndex - self.initialStreamOffset } public init(code: Code) { @@ -144,6 +150,8 @@ public struct ExpressionParser { features: code.features, hasDataCount: code.hasDataCount ) + self.codeOffset = code.offset + self.initialStreamOffset = self.parser.currentIndex } @inlinable @@ -580,29 +588,29 @@ extension Parser { let index: UInt32 = try parseUnsigned() return try v.visitGlobalSet(globalIndex: index) - case .i32_load: return try v.visitI32Load(memarg: try parseMemarg()) - case .i64_load: return try v.visitI64Load(memarg: try parseMemarg()) - case .f32_load: return try v.visitF32Load(memarg: try parseMemarg()) - case .f64_load: return try v.visitF64Load(memarg: try parseMemarg()) - case .i32_load8_s: return try v.visitI32Load8S(memarg: try parseMemarg()) - case .i32_load8_u: return try v.visitI32Load8U(memarg: try parseMemarg()) - case .i32_load16_s: return try v.visitI32Load16S(memarg: try parseMemarg()) - case .i32_load16_u: return try v.visitI32Load16U(memarg: try parseMemarg()) - case .i64_load8_s: return try v.visitI64Load8S(memarg: try parseMemarg()) - case .i64_load8_u: return try v.visitI64Load8U(memarg: try parseMemarg()) - case .i64_load16_s: return try v.visitI64Load16S(memarg: try parseMemarg()) - case .i64_load16_u: return try v.visitI64Load16U(memarg: try parseMemarg()) - case .i64_load32_s: return try v.visitI64Load32S(memarg: try parseMemarg()) - case .i64_load32_u: return try v.visitI64Load32U(memarg: try parseMemarg()) - case .i32_store: return try v.visitI32Store(memarg: try parseMemarg()) - case .i64_store: return try v.visitI64Store(memarg: try parseMemarg()) - case .f32_store: return try v.visitF32Store(memarg: try parseMemarg()) - case .f64_store: return try v.visitF64Store(memarg: try parseMemarg()) - case .i32_store8: return try v.visitI32Store8(memarg: try parseMemarg()) - case .i32_store16: return try v.visitI32Store16(memarg: try parseMemarg()) - case .i64_store8: return try v.visitI64Store8(memarg: try parseMemarg()) - case .i64_store16: return try v.visitI64Store16(memarg: try parseMemarg()) - case .i64_store32: return try v.visitI64Store32(memarg: try parseMemarg()) + case .i32_load: return try v.visitLoad(.i32Load, memarg: try parseMemarg()) + case .i64_load: return try v.visitLoad(.i64Load, memarg: try parseMemarg()) + case .f32_load: return try v.visitLoad(.f32Load, memarg: try parseMemarg()) + case .f64_load: return try v.visitLoad(.f64Load, memarg: try parseMemarg()) + case .i32_load8_s: return try v.visitLoad(.i32Load8S, memarg: try parseMemarg()) + case .i32_load8_u: return try v.visitLoad(.i32Load8U, memarg: try parseMemarg()) + case .i32_load16_s: return try v.visitLoad(.i32Load16S, memarg: try parseMemarg()) + case .i32_load16_u: return try v.visitLoad(.i32Load16U, memarg: try parseMemarg()) + case .i64_load8_s: return try v.visitLoad(.i64Load8S, memarg: try parseMemarg()) + case .i64_load8_u: return try v.visitLoad(.i64Load8U, memarg: try parseMemarg()) + case .i64_load16_s: return try v.visitLoad(.i64Load16S, memarg: try parseMemarg()) + case .i64_load16_u: return try v.visitLoad(.i64Load16U, memarg: try parseMemarg()) + case .i64_load32_s: return try v.visitLoad(.i64Load32S, memarg: try parseMemarg()) + case .i64_load32_u: return try v.visitLoad(.i64Load32U, memarg: try parseMemarg()) + case .i32_store: return try v.visitStore(.i32Store, memarg: try parseMemarg()) + case .i64_store: return try v.visitStore(.i64Store, memarg: try parseMemarg()) + case .f32_store: return try v.visitStore(.f32Store, memarg: try parseMemarg()) + case .f64_store: return try v.visitStore(.f64Store, memarg: try parseMemarg()) + case .i32_store8: return try v.visitStore(.i32Store8, memarg: try parseMemarg()) + case .i32_store16: return try v.visitStore(.i32Store16, memarg: try parseMemarg()) + case .i64_store8: return try v.visitStore(.i64Store8, memarg: try parseMemarg()) + case .i64_store16: return try v.visitStore(.i64Store16, memarg: try parseMemarg()) + case .i64_store32: return try v.visitStore(.i64Store32, memarg: try parseMemarg()) case .memory_size: let zero = try stream.consumeAny() guard zero == 0x00 else { @@ -630,143 +638,143 @@ extension Parser { return try v.visitF64Const(value: IEEE754.Float64(bitPattern: n)) case .i32_eqz: return try v.visitI32Eqz() - case .i32_eq: return try v.visitI32Eq() - case .i32_ne: return try v.visitI32Ne() - case .i32_lt_s: return try v.visitI32LtS() - case .i32_lt_u: return try v.visitI32LtU() - case .i32_gt_s: return try v.visitI32GtS() - case .i32_gt_u: return try v.visitI32GtU() - case .i32_le_s: return try v.visitI32LeS() - case .i32_le_u: return try v.visitI32LeU() - case .i32_ge_s: return try v.visitI32GeS() - case .i32_ge_u: return try v.visitI32GeU() + case .i32_eq: return try v.visitCmp(.i32Eq) + case .i32_ne: return try v.visitCmp(.i32Ne) + case .i32_lt_s: return try v.visitCmp(.i32LtS) + case .i32_lt_u: return try v.visitCmp(.i32LtU) + case .i32_gt_s: return try v.visitCmp(.i32GtS) + case .i32_gt_u: return try v.visitCmp(.i32GtU) + case .i32_le_s: return try v.visitCmp(.i32LeS) + case .i32_le_u: return try v.visitCmp(.i32LeU) + case .i32_ge_s: return try v.visitCmp(.i32GeS) + case .i32_ge_u: return try v.visitCmp(.i32GeU) case .i64_eqz: return try v.visitI64Eqz() - case .i64_eq: return try v.visitI64Eq() - case .i64_ne: return try v.visitI64Ne() - case .i64_lt_s: return try v.visitI64LtS() - case .i64_lt_u: return try v.visitI64LtU() - case .i64_gt_s: return try v.visitI64GtS() - case .i64_gt_u: return try v.visitI64GtU() - case .i64_le_s: return try v.visitI64LeS() - case .i64_le_u: return try v.visitI64LeU() - case .i64_ge_s: return try v.visitI64GeS() - case .i64_ge_u: return try v.visitI64GeU() - - case .f32_eq: return try v.visitF32Eq() - case .f32_ne: return try v.visitF32Ne() - case .f32_lt: return try v.visitF32Lt() - case .f32_gt: return try v.visitF32Gt() - case .f32_le: return try v.visitF32Le() - case .f32_ge: return try v.visitF32Ge() - - case .f64_eq: return try v.visitF64Eq() - case .f64_ne: return try v.visitF64Ne() - case .f64_lt: return try v.visitF64Lt() - case .f64_gt: return try v.visitF64Gt() - case .f64_le: return try v.visitF64Le() - case .f64_ge: return try v.visitF64Ge() - - case .i32_clz: return try v.visitI32Clz() - case .i32_ctz: return try v.visitI32Ctz() - case .i32_popcnt: return try v.visitI32Popcnt() - case .i32_add: return try v.visitI32Add() - case .i32_sub: return try v.visitI32Sub() - case .i32_mul: return try v.visitI32Mul() - case .i32_div_s: return try v.visitI32DivS() - case .i32_div_u: return try v.visitI32DivU() - case .i32_rem_s: return try v.visitI32RemS() - case .i32_rem_u: return try v.visitI32RemU() - case .i32_and: return try v.visitI32And() - case .i32_or: return try v.visitI32Or() - case .i32_xor: return try v.visitI32Xor() - case .i32_shl: return try v.visitI32Shl() - case .i32_shr_s: return try v.visitI32ShrS() - case .i32_shr_u: return try v.visitI32ShrU() - case .i32_rotl: return try v.visitI32Rotl() - case .i32_rotr: return try v.visitI32Rotr() - - case .i64_clz: return try v.visitI64Clz() - case .i64_ctz: return try v.visitI64Ctz() - case .i64_popcnt: return try v.visitI64Popcnt() - case .i64_add: return try v.visitI64Add() - case .i64_sub: return try v.visitI64Sub() - case .i64_mul: return try v.visitI64Mul() - case .i64_div_s: return try v.visitI64DivS() - case .i64_div_u: return try v.visitI64DivU() - case .i64_rem_s: return try v.visitI64RemS() - case .i64_rem_u: return try v.visitI64RemU() - case .i64_and: return try v.visitI64And() - case .i64_or: return try v.visitI64Or() - case .i64_xor: return try v.visitI64Xor() - case .i64_shl: return try v.visitI64Shl() - case .i64_shr_s: return try v.visitI64ShrS() - case .i64_shr_u: return try v.visitI64ShrU() - case .i64_rotl: return try v.visitI64Rotl() - case .i64_rotr: return try v.visitI64Rotr() - - case .f32_abs: return try v.visitF32Abs() - case .f32_neg: return try v.visitF32Neg() - case .f32_ceil: return try v.visitF32Ceil() - case .f32_floor: return try v.visitF32Floor() - case .f32_trunc: return try v.visitF32Trunc() - case .f32_nearest: return try v.visitF32Nearest() - case .f32_sqrt: return try v.visitF32Sqrt() - - case .f32_add: return try v.visitF32Add() - case .f32_sub: return try v.visitF32Sub() - case .f32_mul: return try v.visitF32Mul() - case .f32_div: return try v.visitF32Div() - case .f32_min: return try v.visitF32Min() - case .f32_max: return try v.visitF32Max() - case .f32_copysign: return try v.visitF32Copysign() - - case .f64_abs: return try v.visitF64Abs() - case .f64_neg: return try v.visitF64Neg() - case .f64_ceil: return try v.visitF64Ceil() - case .f64_floor: return try v.visitF64Floor() - case .f64_trunc: return try v.visitF64Trunc() - case .f64_nearest: return try v.visitF64Nearest() - case .f64_sqrt: return try v.visitF64Sqrt() - - case .f64_add: return try v.visitF64Add() - case .f64_sub: return try v.visitF64Sub() - case .f64_mul: return try v.visitF64Mul() - case .f64_div: return try v.visitF64Div() - case .f64_min: return try v.visitF64Min() - case .f64_max: return try v.visitF64Max() - case .f64_copysign: return try v.visitF64Copysign() - - case .i32_wrap_i64: return try v.visitI32WrapI64() - case .i32_trunc_f32_s: return try v.visitI32TruncF32S() - case .i32_trunc_f32_u: return try v.visitI32TruncF32U() - case .i32_trunc_f64_s: return try v.visitI32TruncF64S() - case .i32_trunc_f64_u: return try v.visitI32TruncF64U() - case .i64_extend_i32_s: return try v.visitI64ExtendI32S() - case .i64_extend_i32_u: return try v.visitI64ExtendI32U() - case .i64_trunc_f32_s: return try v.visitI64TruncF32S() - case .i64_trunc_f32_u: return try v.visitI64TruncF32U() - case .i64_trunc_f64_s: return try v.visitI64TruncF64S() - case .i64_trunc_f64_u: return try v.visitI64TruncF64U() - case .f32_convert_i32_s: return try v.visitF32ConvertI32S() - case .f32_convert_i32_u: return try v.visitF32ConvertI32U() - case .f32_convert_i64_s: return try v.visitF32ConvertI64S() - case .f32_convert_i64_u: return try v.visitF32ConvertI64U() - case .f32_demote_f64: return try v.visitF32DemoteF64() - case .f64_convert_i32_s: return try v.visitF64ConvertI32S() - case .f64_convert_i32_u: return try v.visitF64ConvertI32U() - case .f64_convert_i64_s: return try v.visitF64ConvertI64S() - case .f64_convert_i64_u: return try v.visitF64ConvertI64U() - case .f64_promote_f32: return try v.visitF64PromoteF32() - case .i32_reinterpret_f32: return try v.visitI32ReinterpretF32() - case .i64_reinterpret_f64: return try v.visitI64ReinterpretF64() - case .f32_reinterpret_i32: return try v.visitF32ReinterpretI32() - case .f64_reinterpret_i64: return try v.visitF64ReinterpretI64() - case .i32_extend8_s: return try v.visitI32Extend8S() - case .i32_extend16_s: return try v.visitI32Extend16S() - case .i64_extend8_s: return try v.visitI64Extend8S() - case .i64_extend16_s: return try v.visitI64Extend16S() - case .i64_extend32_s: return try v.visitI64Extend32S() + case .i64_eq: return try v.visitCmp(.i64Eq) + case .i64_ne: return try v.visitCmp(.i64Ne) + case .i64_lt_s: return try v.visitCmp(.i64LtS) + case .i64_lt_u: return try v.visitCmp(.i64LtU) + case .i64_gt_s: return try v.visitCmp(.i64GtS) + case .i64_gt_u: return try v.visitCmp(.i64GtU) + case .i64_le_s: return try v.visitCmp(.i64LeS) + case .i64_le_u: return try v.visitCmp(.i64LeU) + case .i64_ge_s: return try v.visitCmp(.i64GeS) + case .i64_ge_u: return try v.visitCmp(.i64GeU) + + case .f32_eq: return try v.visitCmp(.f32Eq) + case .f32_ne: return try v.visitCmp(.f32Ne) + case .f32_lt: return try v.visitCmp(.f32Lt) + case .f32_gt: return try v.visitCmp(.f32Gt) + case .f32_le: return try v.visitCmp(.f32Le) + case .f32_ge: return try v.visitCmp(.f32Ge) + + case .f64_eq: return try v.visitCmp(.f64Eq) + case .f64_ne: return try v.visitCmp(.f64Ne) + case .f64_lt: return try v.visitCmp(.f64Lt) + case .f64_gt: return try v.visitCmp(.f64Gt) + case .f64_le: return try v.visitCmp(.f64Le) + case .f64_ge: return try v.visitCmp(.f64Ge) + + case .i32_clz: return try v.visitUnary(.i32Clz) + case .i32_ctz: return try v.visitUnary(.i32Ctz) + case .i32_popcnt: return try v.visitUnary(.i32Popcnt) + case .i32_add: return try v.visitBinary(.i32Add) + case .i32_sub: return try v.visitBinary(.i32Sub) + case .i32_mul: return try v.visitBinary(.i32Mul) + case .i32_div_s: return try v.visitBinary(.i32DivS) + case .i32_div_u: return try v.visitBinary(.i32DivU) + case .i32_rem_s: return try v.visitBinary(.i32RemS) + case .i32_rem_u: return try v.visitBinary(.i32RemU) + case .i32_and: return try v.visitBinary(.i32And) + case .i32_or: return try v.visitBinary(.i32Or) + case .i32_xor: return try v.visitBinary(.i32Xor) + case .i32_shl: return try v.visitBinary(.i32Shl) + case .i32_shr_s: return try v.visitBinary(.i32ShrS) + case .i32_shr_u: return try v.visitBinary(.i32ShrU) + case .i32_rotl: return try v.visitBinary(.i32Rotl) + case .i32_rotr: return try v.visitBinary(.i32Rotr) + + case .i64_clz: return try v.visitUnary(.i64Clz) + case .i64_ctz: return try v.visitUnary(.i64Ctz) + case .i64_popcnt: return try v.visitUnary(.i64Popcnt) + case .i64_add: return try v.visitBinary(.i64Add) + case .i64_sub: return try v.visitBinary(.i64Sub) + case .i64_mul: return try v.visitBinary(.i64Mul) + case .i64_div_s: return try v.visitBinary(.i64DivS) + case .i64_div_u: return try v.visitBinary(.i64DivU) + case .i64_rem_s: return try v.visitBinary(.i64RemS) + case .i64_rem_u: return try v.visitBinary(.i64RemU) + case .i64_and: return try v.visitBinary(.i64And) + case .i64_or: return try v.visitBinary(.i64Or) + case .i64_xor: return try v.visitBinary(.i64Xor) + case .i64_shl: return try v.visitBinary(.i64Shl) + case .i64_shr_s: return try v.visitBinary(.i64ShrS) + case .i64_shr_u: return try v.visitBinary(.i64ShrU) + case .i64_rotl: return try v.visitBinary(.i64Rotl) + case .i64_rotr: return try v.visitBinary(.i64Rotr) + + case .f32_abs: return try v.visitUnary(.f32Abs) + case .f32_neg: return try v.visitUnary(.f32Neg) + case .f32_ceil: return try v.visitUnary(.f32Ceil) + case .f32_floor: return try v.visitUnary(.f32Floor) + case .f32_trunc: return try v.visitUnary(.f32Trunc) + case .f32_nearest: return try v.visitUnary(.f32Nearest) + case .f32_sqrt: return try v.visitUnary(.f32Sqrt) + + case .f32_add: return try v.visitBinary(.f32Add) + case .f32_sub: return try v.visitBinary(.f32Sub) + case .f32_mul: return try v.visitBinary(.f32Mul) + case .f32_div: return try v.visitBinary(.f32Div) + case .f32_min: return try v.visitBinary(.f32Min) + case .f32_max: return try v.visitBinary(.f32Max) + case .f32_copysign: return try v.visitBinary(.f32Copysign) + + case .f64_abs: return try v.visitUnary(.f64Abs) + case .f64_neg: return try v.visitUnary(.f64Neg) + case .f64_ceil: return try v.visitUnary(.f64Ceil) + case .f64_floor: return try v.visitUnary(.f64Floor) + case .f64_trunc: return try v.visitUnary(.f64Trunc) + case .f64_nearest: return try v.visitUnary(.f64Nearest) + case .f64_sqrt: return try v.visitUnary(.f64Sqrt) + + case .f64_add: return try v.visitBinary(.f64Add) + case .f64_sub: return try v.visitBinary(.f64Sub) + case .f64_mul: return try v.visitBinary(.f64Mul) + case .f64_div: return try v.visitBinary(.f64Div) + case .f64_min: return try v.visitBinary(.f64Min) + case .f64_max: return try v.visitBinary(.f64Max) + case .f64_copysign: return try v.visitBinary(.f64Copysign) + + case .i32_wrap_i64: return try v.visitConversion(.i32WrapI64) + case .i32_trunc_f32_s: return try v.visitConversion(.i32TruncF32S) + case .i32_trunc_f32_u: return try v.visitConversion(.i32TruncF32U) + case .i32_trunc_f64_s: return try v.visitConversion(.i32TruncF64S) + case .i32_trunc_f64_u: return try v.visitConversion(.i32TruncF64U) + case .i64_extend_i32_s: return try v.visitConversion(.i64ExtendI32S) + case .i64_extend_i32_u: return try v.visitConversion(.i64ExtendI32U) + case .i64_trunc_f32_s: return try v.visitConversion(.i64TruncF32S) + case .i64_trunc_f32_u: return try v.visitConversion(.i64TruncF32U) + case .i64_trunc_f64_s: return try v.visitConversion(.i64TruncF64S) + case .i64_trunc_f64_u: return try v.visitConversion(.i64TruncF64U) + case .f32_convert_i32_s: return try v.visitConversion(.f32ConvertI32S) + case .f32_convert_i32_u: return try v.visitConversion(.f32ConvertI32U) + case .f32_convert_i64_s: return try v.visitConversion(.f32ConvertI64S) + case .f32_convert_i64_u: return try v.visitConversion(.f32ConvertI64U) + case .f32_demote_f64: return try v.visitConversion(.f32DemoteF64) + case .f64_convert_i32_s: return try v.visitConversion(.f64ConvertI32S) + case .f64_convert_i32_u: return try v.visitConversion(.f64ConvertI32U) + case .f64_convert_i64_s: return try v.visitConversion(.f64ConvertI64S) + case .f64_convert_i64_u: return try v.visitConversion(.f64ConvertI64U) + case .f64_promote_f32: return try v.visitConversion(.f64PromoteF32) + case .i32_reinterpret_f32: return try v.visitConversion(.i32ReinterpretF32) + case .i64_reinterpret_f64: return try v.visitConversion(.i64ReinterpretF64) + case .f32_reinterpret_i32: return try v.visitConversion(.f32ReinterpretI32) + case .f64_reinterpret_i64: return try v.visitConversion(.f64ReinterpretI64) + case .i32_extend8_s: return try v.visitUnary(.i32Extend8S) + case .i32_extend16_s: return try v.visitUnary(.i32Extend16S) + case .i64_extend8_s: return try v.visitUnary(.i64Extend8S) + case .i64_extend16_s: return try v.visitUnary(.i64Extend16S) + case .i64_extend32_s: return try v.visitUnary(.i64Extend32S) case .ref_null: let type = try parseValueType() @@ -788,14 +796,14 @@ extension Parser { case .wasm2InstructionPrefix: let codeSuffix: UInt32 = try parseUnsigned() switch codeSuffix { - case 0: return try v.visitI32TruncSatF32S() - case 1: return try v.visitI32TruncSatF32U() - case 2: return try v.visitI32TruncSatF64S() - case 3: return try v.visitI32TruncSatF64U() - case 4: return try v.visitI64TruncSatF32S() - case 5: return try v.visitI64TruncSatF32U() - case 6: return try v.visitI64TruncSatF64S() - case 7: return try v.visitI64TruncSatF64U() + case 0: return try v.visitConversion(.i32TruncSatF32S) + case 1: return try v.visitConversion(.i32TruncSatF32U) + case 2: return try v.visitConversion(.i32TruncSatF64S) + case 3: return try v.visitConversion(.i32TruncSatF64U) + case 4: return try v.visitConversion(.i64TruncSatF32S) + case 5: return try v.visitConversion(.i64TruncSatF32U) + case 6: return try v.visitConversion(.i64TruncSatF64S) + case 7: return try v.visitConversion(.i64TruncSatF64U) case 8: let dataIndex: DataIndex = try parseUnsigned() // memory.init requires data count section @@ -1055,10 +1063,14 @@ extension Parser { let locals = localTypes.flatMap { (n: UInt32, type: ValueType) in return Array(repeating: type, count: Int(n)) } + let expressionStart = stream.currentIndex let expressionBytes = try stream.consume( - count: Int(size) - (stream.currentIndex - bodyStart) + count: Int(size) - (expressionStart - bodyStart) + ) + return Code( + locals: locals, expression: expressionBytes, + offset: expressionStart, hasDataCount: hasDataCount, features: features ) - return Code(locals: locals, expression: expressionBytes, hasDataCount: hasDataCount, features: features) } } diff --git a/Sources/WasmParser/WasmTypes.swift b/Sources/WasmParser/WasmTypes.swift index 7a315e96..c935dd09 100644 --- a/Sources/WasmParser/WasmTypes.swift +++ b/Sources/WasmParser/WasmTypes.swift @@ -11,6 +11,8 @@ public struct Code { // Parser state used to parse the expression body lazily @usableFromInline + internal let offset: Int + @usableFromInline internal let hasDataCount: Bool @usableFromInline internal let features: WasmFeatureSet @@ -327,3 +329,83 @@ extension RawSignedInteger { .init(bitPattern: self) } } + +extension Instruction.Load { + /// The alignment to the storage size of the memory access + /// in log2 form. + @_alwaysEmitIntoClient + public var naturalAlignment: Int { + switch self { + case .i32Load: return 2 + case .i64Load: return 3 + case .f32Load: return 2 + case .f64Load: return 3 + case .i32Load8S: return 0 + case .i32Load8U: return 0 + case .i32Load16S: return 1 + case .i32Load16U: return 1 + case .i64Load8S: return 0 + case .i64Load8U: return 0 + case .i64Load16S: return 1 + case .i64Load16U: return 1 + case .i64Load32S: return 2 + case .i64Load32U: return 2 + } + } + + /// The type of the value loaded from memory + @_alwaysEmitIntoClient + public var type: ValueType { + switch self { + case .i32Load: return .i32 + case .i64Load: return .i64 + case .f32Load: return .f32 + case .f64Load: return .f64 + case .i32Load8S: return .i32 + case .i32Load8U: return .i32 + case .i32Load16S: return .i32 + case .i32Load16U: return .i32 + case .i64Load8S: return .i64 + case .i64Load8U: return .i64 + case .i64Load16S: return .i64 + case .i64Load16U: return .i64 + case .i64Load32S: return .i64 + case .i64Load32U: return .i64 + } + } +} + +extension Instruction.Store { + /// The alignment to the storage size of the memory access + /// in log2 form. + @_alwaysEmitIntoClient + public var naturalAlignment: Int { + switch self { + case .i32Store: return 2 + case .i64Store: return 3 + case .f32Store: return 2 + case .f64Store: return 3 + case .i32Store8: return 0 + case .i32Store16: return 1 + case .i64Store8: return 0 + case .i64Store16: return 1 + case .i64Store32: return 2 + } + } + + /// The type of the value stored to memory + @_alwaysEmitIntoClient + public var type: ValueType { + switch self { + case .i32Store: return .i32 + case .i64Store: return .i64 + case .f32Store: return .f32 + case .f64Store: return .f64 + case .i32Store8: return .i32 + case .i32Store16: return .i32 + case .i64Store8: return .i64 + case .i64Store16: return .i64 + case .i64Store32: return .i64 + } + } +} diff --git a/Utilities/Instructions.json b/Utilities/Instructions.json index 01ecc9ab..6816b73a 100644 --- a/Utilities/Instructions.json +++ b/Utilities/Instructions.json @@ -1,203 +1,203 @@ [ - ["mvp" , "unreachable" , null , "0x00", "unreachable" , "visitUnreachable" , [] ], - ["mvp" , "nop" , null , "0x01", "nop" , "visitNop" , [] ], - ["mvp" , "block" , null , "0x02", "block" , "visitBlock" , [["blockType", "BlockType"]] ], - ["mvp" , "loop" , null , "0x03", "loop" , "visitLoop" , [["blockType", "BlockType"]] ], - ["mvp" , "if" , null , "0x04", "if" , "visitIf" , [["blockType", "BlockType"]] ], - ["mvp" , "else" , null , "0x05", "else" , "visitElse" , [] ], - ["mvp" , "end" , null , "0x0B", "end" , "visitEnd" , [] ], - ["mvp" , "br" , null , "0x0C", "br" , "visitBr" , [["relativeDepth", "UInt32"]] ], - ["mvp" , "br_if" , null , "0x0D", "brIf" , "visitBrIf" , [["relativeDepth", "UInt32"]] ], - ["mvp" , "br_table" , null , "0x0E", "brTable" , "visitBrTable" , [["targets", "BrTable"]] ], - ["mvp" , "return" , null , "0x0F", "return" , "visitReturn" , [] ], - ["mvp" , "call" , null , "0x10", "call" , "visitCall" , [["functionIndex", "UInt32"]] ], - ["mvp" , "call_indirect" , null , "0x11", "callIndirect" , "visitCallIndirect" , [["typeIndex", "UInt32"], ["tableIndex", "UInt32"]]], - ["mvp" , "drop" , null , "0x1A", "drop" , "visitDrop" , [] ], - ["mvp" , "select" , null , "0x1B", "select" , "visitSelect" , [] ], - ["referenceTypes" , null , null , "0x1C", "typedSelect" , "visitTypedSelect" , [["type", "ValueType"]] ], - ["mvp" , "local.get" , null , "0x20", "localGet" , "visitLocalGet" , [["localIndex", "UInt32"]] ], - ["mvp" , "local.set" , null , "0x21", "localSet" , "visitLocalSet" , [["localIndex", "UInt32"]] ], - ["mvp" , "local.tee" , null , "0x22", "localTee" , "visitLocalTee" , [["localIndex", "UInt32"]] ], - ["mvp" , "global.get" , null , "0x23", "globalGet" , "visitGlobalGet" , [["globalIndex", "UInt32"]] ], - ["mvp" , "global.set" , null , "0x24", "globalSet" , "visitGlobalSet" , [["globalIndex", "UInt32"]] ], - ["mvp" , "i32.load" , null , "0x28", "i32Load" , "visitI32Load" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load" , null , "0x29", "i64Load" , "visitI64Load" , [["memarg", "MemArg"]] ], - ["mvp" , "f32.load" , null , "0x2A", "f32Load" , "visitF32Load" , [["memarg", "MemArg"]] ], - ["mvp" , "f64.load" , null , "0x2B", "f64Load" , "visitF64Load" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.load8_s" , null , "0x2C", "i32Load8S" , "visitI32Load8S" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.load8_u" , null , "0x2D", "i32Load8U" , "visitI32Load8U" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.load16_s" , null , "0x2E", "i32Load16S" , "visitI32Load16S" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.load16_u" , null , "0x2F", "i32Load16U" , "visitI32Load16U" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load8_s" , null , "0x30", "i64Load8S" , "visitI64Load8S" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load8_u" , null , "0x31", "i64Load8U" , "visitI64Load8U" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load16_s" , null , "0x32", "i64Load16S" , "visitI64Load16S" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load16_u" , null , "0x33", "i64Load16U" , "visitI64Load16U" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load32_s" , null , "0x34", "i64Load32S" , "visitI64Load32S" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.load32_u" , null , "0x35", "i64Load32U" , "visitI64Load32U" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.store" , null , "0x36", "i32Store" , "visitI32Store" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.store" , null , "0x37", "i64Store" , "visitI64Store" , [["memarg", "MemArg"]] ], - ["mvp" , "f32.store" , null , "0x38", "f32Store" , "visitF32Store" , [["memarg", "MemArg"]] ], - ["mvp" , "f64.store" , null , "0x39", "f64Store" , "visitF64Store" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.store8" , null , "0x3A", "i32Store8" , "visitI32Store8" , [["memarg", "MemArg"]] ], - ["mvp" , "i32.store16" , null , "0x3B", "i32Store16" , "visitI32Store16" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.store8" , null , "0x3C", "i64Store8" , "visitI64Store8" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.store16" , null , "0x3D", "i64Store16" , "visitI64Store16" , [["memarg", "MemArg"]] ], - ["mvp" , "i64.store32" , null , "0x3E", "i64Store32" , "visitI64Store32" , [["memarg", "MemArg"]] ], - ["mvp" , "memory.size" , null , "0x3F", "memorySize" , "visitMemorySize" , [["memory", "UInt32"]] ], - ["mvp" , "memory.grow" , null , "0x40", "memoryGrow" , "visitMemoryGrow" , [["memory", "UInt32"]] ], - ["mvp" , "i32.const" , null , "0x41", "i32Const" , "visitI32Const" , [["value", "Int32"]] ], - ["mvp" , "i64.const" , null , "0x42", "i64Const" , "visitI64Const" , [["value", "Int64"]] ], - ["mvp" , "f32.const" , null , "0x43", "f32Const" , "visitF32Const" , [["value", "IEEE754.Float32"]] ], - ["mvp" , "f64.const" , null , "0x44", "f64Const" , "visitF64Const" , [["value", "IEEE754.Float64"]] ], - ["referenceTypes" , "ref.null" , null , "0xD0", "refNull" , "visitRefNull" , [["type", "ReferenceType"]] ], - ["referenceTypes" , "ref.is_null" , null , "0xD1", "refIsNull" , "visitRefIsNull" , [] ], - ["referenceTypes" , "ref.func" , null , "0xD2", "refFunc" , "visitRefFunc" , [["functionIndex", "UInt32"]] ], - ["mvp" , "i32.eqz" , null , "0x45", "i32Eqz" , "visitI32Eqz" , [] ], - ["mvp" , "i32.eq" , null , "0x46", "i32Eq" , "visitI32Eq" , [] ], - ["mvp" , "i32.ne" , null , "0x47", "i32Ne" , "visitI32Ne" , [] ], - ["mvp" , "i32.lt_s" , null , "0x48", "i32LtS" , "visitI32LtS" , [] ], - ["mvp" , "i32.lt_u" , null , "0x49", "i32LtU" , "visitI32LtU" , [] ], - ["mvp" , "i32.gt_s" , null , "0x4A", "i32GtS" , "visitI32GtS" , [] ], - ["mvp" , "i32.gt_u" , null , "0x4B", "i32GtU" , "visitI32GtU" , [] ], - ["mvp" , "i32.le_s" , null , "0x4C", "i32LeS" , "visitI32LeS" , [] ], - ["mvp" , "i32.le_u" , null , "0x4D", "i32LeU" , "visitI32LeU" , [] ], - ["mvp" , "i32.ge_s" , null , "0x4E", "i32GeS" , "visitI32GeS" , [] ], - ["mvp" , "i32.ge_u" , null , "0x4F", "i32GeU" , "visitI32GeU" , [] ], - ["mvp" , "i64.eqz" , null , "0x50", "i64Eqz" , "visitI64Eqz" , [] ], - ["mvp" , "i64.eq" , null , "0x51", "i64Eq" , "visitI64Eq" , [] ], - ["mvp" , "i64.ne" , null , "0x52", "i64Ne" , "visitI64Ne" , [] ], - ["mvp" , "i64.lt_s" , null , "0x53", "i64LtS" , "visitI64LtS" , [] ], - ["mvp" , "i64.lt_u" , null , "0x54", "i64LtU" , "visitI64LtU" , [] ], - ["mvp" , "i64.gt_s" , null , "0x55", "i64GtS" , "visitI64GtS" , [] ], - ["mvp" , "i64.gt_u" , null , "0x56", "i64GtU" , "visitI64GtU" , [] ], - ["mvp" , "i64.le_s" , null , "0x57", "i64LeS" , "visitI64LeS" , [] ], - ["mvp" , "i64.le_u" , null , "0x58", "i64LeU" , "visitI64LeU" , [] ], - ["mvp" , "i64.ge_s" , null , "0x59", "i64GeS" , "visitI64GeS" , [] ], - ["mvp" , "i64.ge_u" , null , "0x5A", "i64GeU" , "visitI64GeU" , [] ], - ["mvp" , "f32.eq" , null , "0x5B", "f32Eq" , "visitF32Eq" , [] ], - ["mvp" , "f32.ne" , null , "0x5C", "f32Ne" , "visitF32Ne" , [] ], - ["mvp" , "f32.lt" , null , "0x5D", "f32Lt" , "visitF32Lt" , [] ], - ["mvp" , "f32.gt" , null , "0x5E", "f32Gt" , "visitF32Gt" , [] ], - ["mvp" , "f32.le" , null , "0x5F", "f32Le" , "visitF32Le" , [] ], - ["mvp" , "f32.ge" , null , "0x60", "f32Ge" , "visitF32Ge" , [] ], - ["mvp" , "f64.eq" , null , "0x61", "f64Eq" , "visitF64Eq" , [] ], - ["mvp" , "f64.ne" , null , "0x62", "f64Ne" , "visitF64Ne" , [] ], - ["mvp" , "f64.lt" , null , "0x63", "f64Lt" , "visitF64Lt" , [] ], - ["mvp" , "f64.gt" , null , "0x64", "f64Gt" , "visitF64Gt" , [] ], - ["mvp" , "f64.le" , null , "0x65", "f64Le" , "visitF64Le" , [] ], - ["mvp" , "f64.ge" , null , "0x66", "f64Ge" , "visitF64Ge" , [] ], - ["mvp" , "i32.clz" , null , "0x67", "i32Clz" , "visitI32Clz" , [] ], - ["mvp" , "i32.ctz" , null , "0x68", "i32Ctz" , "visitI32Ctz" , [] ], - ["mvp" , "i32.popcnt" , null , "0x69", "i32Popcnt" , "visitI32Popcnt" , [] ], - ["mvp" , "i32.add" , null , "0x6A", "i32Add" , "visitI32Add" , [] ], - ["mvp" , "i32.sub" , null , "0x6B", "i32Sub" , "visitI32Sub" , [] ], - ["mvp" , "i32.mul" , null , "0x6C", "i32Mul" , "visitI32Mul" , [] ], - ["mvp" , "i32.div_s" , null , "0x6D", "i32DivS" , "visitI32DivS" , [] ], - ["mvp" , "i32.div_u" , null , "0x6E", "i32DivU" , "visitI32DivU" , [] ], - ["mvp" , "i32.rem_s" , null , "0x6F", "i32RemS" , "visitI32RemS" , [] ], - ["mvp" , "i32.rem_u" , null , "0x70", "i32RemU" , "visitI32RemU" , [] ], - ["mvp" , "i32.and" , null , "0x71", "i32And" , "visitI32And" , [] ], - ["mvp" , "i32.or" , null , "0x72", "i32Or" , "visitI32Or" , [] ], - ["mvp" , "i32.xor" , null , "0x73", "i32Xor" , "visitI32Xor" , [] ], - ["mvp" , "i32.shl" , null , "0x74", "i32Shl" , "visitI32Shl" , [] ], - ["mvp" , "i32.shr_s" , null , "0x75", "i32ShrS" , "visitI32ShrS" , [] ], - ["mvp" , "i32.shr_u" , null , "0x76", "i32ShrU" , "visitI32ShrU" , [] ], - ["mvp" , "i32.rotl" , null , "0x77", "i32Rotl" , "visitI32Rotl" , [] ], - ["mvp" , "i32.rotr" , null , "0x78", "i32Rotr" , "visitI32Rotr" , [] ], - ["mvp" , "i64.clz" , null , "0x79", "i64Clz" , "visitI64Clz" , [] ], - ["mvp" , "i64.ctz" , null , "0x7A", "i64Ctz" , "visitI64Ctz" , [] ], - ["mvp" , "i64.popcnt" , null , "0x7B", "i64Popcnt" , "visitI64Popcnt" , [] ], - ["mvp" , "i64.add" , null , "0x7C", "i64Add" , "visitI64Add" , [] ], - ["mvp" , "i64.sub" , null , "0x7D", "i64Sub" , "visitI64Sub" , [] ], - ["mvp" , "i64.mul" , null , "0x7E", "i64Mul" , "visitI64Mul" , [] ], - ["mvp" , "i64.div_s" , null , "0x7F", "i64DivS" , "visitI64DivS" , [] ], - ["mvp" , "i64.div_u" , null , "0x80", "i64DivU" , "visitI64DivU" , [] ], - ["mvp" , "i64.rem_s" , null , "0x81", "i64RemS" , "visitI64RemS" , [] ], - ["mvp" , "i64.rem_u" , null , "0x82", "i64RemU" , "visitI64RemU" , [] ], - ["mvp" , "i64.and" , null , "0x83", "i64And" , "visitI64And" , [] ], - ["mvp" , "i64.or" , null , "0x84", "i64Or" , "visitI64Or" , [] ], - ["mvp" , "i64.xor" , null , "0x85", "i64Xor" , "visitI64Xor" , [] ], - ["mvp" , "i64.shl" , null , "0x86", "i64Shl" , "visitI64Shl" , [] ], - ["mvp" , "i64.shr_s" , null , "0x87", "i64ShrS" , "visitI64ShrS" , [] ], - ["mvp" , "i64.shr_u" , null , "0x88", "i64ShrU" , "visitI64ShrU" , [] ], - ["mvp" , "i64.rotl" , null , "0x89", "i64Rotl" , "visitI64Rotl" , [] ], - ["mvp" , "i64.rotr" , null , "0x8A", "i64Rotr" , "visitI64Rotr" , [] ], - ["mvp" , "f32.abs" , null , "0x8B", "f32Abs" , "visitF32Abs" , [] ], - ["mvp" , "f32.neg" , null , "0x8C", "f32Neg" , "visitF32Neg" , [] ], - ["mvp" , "f32.ceil" , null , "0x8D", "f32Ceil" , "visitF32Ceil" , [] ], - ["mvp" , "f32.floor" , null , "0x8E", "f32Floor" , "visitF32Floor" , [] ], - ["mvp" , "f32.trunc" , null , "0x8F", "f32Trunc" , "visitF32Trunc" , [] ], - ["mvp" , "f32.nearest" , null , "0x90", "f32Nearest" , "visitF32Nearest" , [] ], - ["mvp" , "f32.sqrt" , null , "0x91", "f32Sqrt" , "visitF32Sqrt" , [] ], - ["mvp" , "f32.add" , null , "0x92", "f32Add" , "visitF32Add" , [] ], - ["mvp" , "f32.sub" , null , "0x93", "f32Sub" , "visitF32Sub" , [] ], - ["mvp" , "f32.mul" , null , "0x94", "f32Mul" , "visitF32Mul" , [] ], - ["mvp" , "f32.div" , null , "0x95", "f32Div" , "visitF32Div" , [] ], - ["mvp" , "f32.min" , null , "0x96", "f32Min" , "visitF32Min" , [] ], - ["mvp" , "f32.max" , null , "0x97", "f32Max" , "visitF32Max" , [] ], - ["mvp" , "f32.copysign" , null , "0x98", "f32Copysign" , "visitF32Copysign" , [] ], - ["mvp" , "f64.abs" , null , "0x99", "f64Abs" , "visitF64Abs" , [] ], - ["mvp" , "f64.neg" , null , "0x9A", "f64Neg" , "visitF64Neg" , [] ], - ["mvp" , "f64.ceil" , null , "0x9B", "f64Ceil" , "visitF64Ceil" , [] ], - ["mvp" , "f64.floor" , null , "0x9C", "f64Floor" , "visitF64Floor" , [] ], - ["mvp" , "f64.trunc" , null , "0x9D", "f64Trunc" , "visitF64Trunc" , [] ], - ["mvp" , "f64.nearest" , null , "0x9E", "f64Nearest" , "visitF64Nearest" , [] ], - ["mvp" , "f64.sqrt" , null , "0x9F", "f64Sqrt" , "visitF64Sqrt" , [] ], - ["mvp" , "f64.add" , null , "0xA0", "f64Add" , "visitF64Add" , [] ], - ["mvp" , "f64.sub" , null , "0xA1", "f64Sub" , "visitF64Sub" , [] ], - ["mvp" , "f64.mul" , null , "0xA2", "f64Mul" , "visitF64Mul" , [] ], - ["mvp" , "f64.div" , null , "0xA3", "f64Div" , "visitF64Div" , [] ], - ["mvp" , "f64.min" , null , "0xA4", "f64Min" , "visitF64Min" , [] ], - ["mvp" , "f64.max" , null , "0xA5", "f64Max" , "visitF64Max" , [] ], - ["mvp" , "f64.copysign" , null , "0xA6", "f64Copysign" , "visitF64Copysign" , [] ], - ["mvp" , "i32.wrap_i64" , null , "0xA7", "i32WrapI64" , "visitI32WrapI64" , [] ], - ["mvp" , "i32.trunc_f32_s" , null , "0xA8", "i32TruncF32S" , "visitI32TruncF32S" , [] ], - ["mvp" , "i32.trunc_f32_u" , null , "0xA9", "i32TruncF32U" , "visitI32TruncF32U" , [] ], - ["mvp" , "i32.trunc_f64_s" , null , "0xAA", "i32TruncF64S" , "visitI32TruncF64S" , [] ], - ["mvp" , "i32.trunc_f64_u" , null , "0xAB", "i32TruncF64U" , "visitI32TruncF64U" , [] ], - ["mvp" , "i64.extend_i32_s" , null , "0xAC", "i64ExtendI32S" , "visitI64ExtendI32S" , [] ], - ["mvp" , "i64.extend_i32_u" , null , "0xAD", "i64ExtendI32U" , "visitI64ExtendI32U" , [] ], - ["mvp" , "i64.trunc_f32_s" , null , "0xAE", "i64TruncF32S" , "visitI64TruncF32S" , [] ], - ["mvp" , "i64.trunc_f32_u" , null , "0xAF", "i64TruncF32U" , "visitI64TruncF32U" , [] ], - ["mvp" , "i64.trunc_f64_s" , null , "0xB0", "i64TruncF64S" , "visitI64TruncF64S" , [] ], - ["mvp" , "i64.trunc_f64_u" , null , "0xB1", "i64TruncF64U" , "visitI64TruncF64U" , [] ], - ["mvp" , "f32.convert_i32_s" , null , "0xB2", "f32ConvertI32S" , "visitF32ConvertI32S" , [] ], - ["mvp" , "f32.convert_i32_u" , null , "0xB3", "f32ConvertI32U" , "visitF32ConvertI32U" , [] ], - ["mvp" , "f32.convert_i64_s" , null , "0xB4", "f32ConvertI64S" , "visitF32ConvertI64S" , [] ], - ["mvp" , "f32.convert_i64_u" , null , "0xB5", "f32ConvertI64U" , "visitF32ConvertI64U" , [] ], - ["mvp" , "f32.demote_f64" , null , "0xB6", "f32DemoteF64" , "visitF32DemoteF64" , [] ], - ["mvp" , "f64.convert_i32_s" , null , "0xB7", "f64ConvertI32S" , "visitF64ConvertI32S" , [] ], - ["mvp" , "f64.convert_i32_u" , null , "0xB8", "f64ConvertI32U" , "visitF64ConvertI32U" , [] ], - ["mvp" , "f64.convert_i64_s" , null , "0xB9", "f64ConvertI64S" , "visitF64ConvertI64S" , [] ], - ["mvp" , "f64.convert_i64_u" , null , "0xBA", "f64ConvertI64U" , "visitF64ConvertI64U" , [] ], - ["mvp" , "f64.promote_f32" , null , "0xBB", "f64PromoteF32" , "visitF64PromoteF32" , [] ], - ["mvp" , "i32.reinterpret_f32", null , "0xBC", "i32ReinterpretF32", "visitI32ReinterpretF32", [] ], - ["mvp" , "i64.reinterpret_f64", null , "0xBD", "i64ReinterpretF64", "visitI64ReinterpretF64", [] ], - ["mvp" , "f32.reinterpret_i32", null , "0xBE", "f32ReinterpretI32", "visitF32ReinterpretI32", [] ], - ["mvp" , "f64.reinterpret_i64", null , "0xBF", "f64ReinterpretI64", "visitF64ReinterpretI64", [] ], - ["signExtension" , "i32.extend8_s" , null , "0xC0", "i32Extend8S" , "visitI32Extend8S" , [] ], - ["signExtension" , "i32.extend16_s" , null , "0xC1", "i32Extend16S" , "visitI32Extend16S" , [] ], - ["signExtension" , "i64.extend8_s" , null , "0xC2", "i64Extend8S" , "visitI64Extend8S" , [] ], - ["signExtension" , "i64.extend16_s" , null , "0xC3", "i64Extend16S" , "visitI64Extend16S" , [] ], - ["signExtension" , "i64.extend32_s" , null , "0xC4", "i64Extend32S" , "visitI64Extend32S" , [] ], - ["bulkMemory" , "memory.init" , "0xFC", "0x08", "memoryInit" , "visitMemoryInit" , [["dataIndex", "UInt32"]] ], - ["bulkMemory" , "data.drop" , "0xFC", "0x09", "dataDrop" , "visitDataDrop" , [["dataIndex", "UInt32"]] ], - ["bulkMemory" , "memory.copy" , "0xFC", "0x0A", "memoryCopy" , "visitMemoryCopy" , [["dstMem", "UInt32"], ["srcMem", "UInt32"]] ], - ["bulkMemory" , "memory.fill" , "0xFC", "0x0B", "memoryFill" , "visitMemoryFill" , [["memory", "UInt32"]] ], - ["bulkMemory" , "table.init" , "0xFC", "0x0C", "tableInit" , "visitTableInit" , [["elemIndex", "UInt32"], ["table", "UInt32"]] ], - ["bulkMemory" , "elem.drop" , "0xFC", "0x0D", "elemDrop" , "visitElemDrop" , [["elemIndex", "UInt32"]] ], - ["bulkMemory" , "table.copy" , "0xFC", "0x0E", "tableCopy" , "visitTableCopy" , [["dstTable", "UInt32"], ["srcTable", "UInt32"]] ], - ["referenceTypes" , "table.fill" , "0xFC", "0x11", "tableFill" , "visitTableFill" , [["table", "UInt32"]] ], - ["referenceTypes" , "table.get" , null , "0x25", "tableGet" , "visitTableGet" , [["table", "UInt32"]] ], - ["referenceTypes" , "table.set" , null , "0x26", "tableSet" , "visitTableSet" , [["table", "UInt32"]] ], - ["referenceTypes" , "table.grow" , "0xFC", "0x0F", "tableGrow" , "visitTableGrow" , [["table", "UInt32"]] ], - ["referenceTypes" , "table.size" , "0xFC", "0x10", "tableSize" , "visitTableSize" , [["table", "UInt32"]] ], - ["saturatingFloatToInt", "i32.trunc_sat_f32_s", "0xFC", "0x00", "i32TruncSatF32S" , "visitI32TruncSatF32S" , [] ], - ["saturatingFloatToInt", "i32.trunc_sat_f32_u", "0xFC", "0x01", "i32TruncSatF32U" , "visitI32TruncSatF32U" , [] ], - ["saturatingFloatToInt", "i32.trunc_sat_f64_s", "0xFC", "0x02", "i32TruncSatF64S" , "visitI32TruncSatF64S" , [] ], - ["saturatingFloatToInt", "i32.trunc_sat_f64_u", "0xFC", "0x03", "i32TruncSatF64U" , "visitI32TruncSatF64U" , [] ], - ["saturatingFloatToInt", "i64.trunc_sat_f32_s", "0xFC", "0x04", "i64TruncSatF32S" , "visitI64TruncSatF32S" , [] ], - ["saturatingFloatToInt", "i64.trunc_sat_f32_u", "0xFC", "0x05", "i64TruncSatF32U" , "visitI64TruncSatF32U" , [] ], - ["saturatingFloatToInt", "i64.trunc_sat_f64_s", "0xFC", "0x06", "i64TruncSatF64S" , "visitI64TruncSatF64S" , [] ], - ["saturatingFloatToInt", "i64.trunc_sat_f64_u", "0xFC", "0x07", "i64TruncSatF64U" , "visitI64TruncSatF64U" , [] ] + ["mvp" , "unreachable" , null , "0x00", [] , null ], + ["mvp" , "nop" , null , "0x01", [] , null ], + ["mvp" , "block" , null , "0x02", [["blockType", "BlockType"]] , null ], + ["mvp" , "loop" , null , "0x03", [["blockType", "BlockType"]] , null ], + ["mvp" , "if" , null , "0x04", [["blockType", "BlockType"]] , null ], + ["mvp" , "else" , null , "0x05", [] , null ], + ["mvp" , "end" , null , "0x0B", [] , null ], + ["mvp" , "br" , null , "0x0C", [["relativeDepth", "UInt32"]] , null ], + ["mvp" , "br_if" , null , "0x0D", [["relativeDepth", "UInt32"]] , null ], + ["mvp" , "br_table" , null , "0x0E", [["targets", "BrTable"]] , null ], + ["mvp" , "return" , null , "0x0F", [] , null ], + ["mvp" , "call" , null , "0x10", [["functionIndex", "UInt32"]] , null ], + ["mvp" , "call_indirect" , null , "0x11", [["typeIndex", "UInt32"], ["tableIndex", "UInt32"]], null ], + ["mvp" , "drop" , null , "0x1A", [] , null ], + ["mvp" , "select" , null , "0x1B", [] , null ], + ["referenceTypes" , {"enumCase": "typedSelect"}, null , "0x1C", [["type", "ValueType"]] , null ], + ["mvp" , "local.get" , null , "0x20", [["localIndex", "UInt32"]] , null ], + ["mvp" , "local.set" , null , "0x21", [["localIndex", "UInt32"]] , null ], + ["mvp" , "local.tee" , null , "0x22", [["localIndex", "UInt32"]] , null ], + ["mvp" , "global.get" , null , "0x23", [["globalIndex", "UInt32"]] , null ], + ["mvp" , "global.set" , null , "0x24", [["globalIndex", "UInt32"]] , null ], + ["mvp" , "i32.load" , null , "0x28", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load" , null , "0x29", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "f32.load" , null , "0x2A", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "f64.load" , null , "0x2B", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i32.load8_s" , null , "0x2C", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i32.load8_u" , null , "0x2D", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i32.load16_s" , null , "0x2E", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i32.load16_u" , null , "0x2F", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load8_s" , null , "0x30", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load8_u" , null , "0x31", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load16_s" , null , "0x32", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load16_u" , null , "0x33", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load32_s" , null , "0x34", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i64.load32_u" , null , "0x35", [["memarg", "MemArg"]] , "load" ], + ["mvp" , "i32.store" , null , "0x36", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "i64.store" , null , "0x37", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "f32.store" , null , "0x38", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "f64.store" , null , "0x39", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "i32.store8" , null , "0x3A", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "i32.store16" , null , "0x3B", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "i64.store8" , null , "0x3C", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "i64.store16" , null , "0x3D", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "i64.store32" , null , "0x3E", [["memarg", "MemArg"]] , "store" ], + ["mvp" , "memory.size" , null , "0x3F", [["memory", "UInt32"]] , null ], + ["mvp" , "memory.grow" , null , "0x40", [["memory", "UInt32"]] , null ], + ["mvp" , "i32.const" , null , "0x41", [["value", "Int32"]] , null ], + ["mvp" , "i64.const" , null , "0x42", [["value", "Int64"]] , null ], + ["mvp" , "f32.const" , null , "0x43", [["value", "IEEE754.Float32"]] , null ], + ["mvp" , "f64.const" , null , "0x44", [["value", "IEEE754.Float64"]] , null ], + ["referenceTypes" , "ref.null" , null , "0xD0", [["type", "ReferenceType"]] , null ], + ["referenceTypes" , "ref.is_null" , null , "0xD1", [] , null ], + ["referenceTypes" , "ref.func" , null , "0xD2", [["functionIndex", "UInt32"]] , null ], + ["mvp" , "i32.eqz" , null , "0x45", [] , null ], + ["mvp" , "i32.eq" , null , "0x46", [] , "cmp" ], + ["mvp" , "i32.ne" , null , "0x47", [] , "cmp" ], + ["mvp" , "i32.lt_s" , null , "0x48", [] , "cmp" ], + ["mvp" , "i32.lt_u" , null , "0x49", [] , "cmp" ], + ["mvp" , "i32.gt_s" , null , "0x4A", [] , "cmp" ], + ["mvp" , "i32.gt_u" , null , "0x4B", [] , "cmp" ], + ["mvp" , "i32.le_s" , null , "0x4C", [] , "cmp" ], + ["mvp" , "i32.le_u" , null , "0x4D", [] , "cmp" ], + ["mvp" , "i32.ge_s" , null , "0x4E", [] , "cmp" ], + ["mvp" , "i32.ge_u" , null , "0x4F", [] , "cmp" ], + ["mvp" , "i64.eqz" , null , "0x50", [] , null ], + ["mvp" , "i64.eq" , null , "0x51", [] , "cmp" ], + ["mvp" , "i64.ne" , null , "0x52", [] , "cmp" ], + ["mvp" , "i64.lt_s" , null , "0x53", [] , "cmp" ], + ["mvp" , "i64.lt_u" , null , "0x54", [] , "cmp" ], + ["mvp" , "i64.gt_s" , null , "0x55", [] , "cmp" ], + ["mvp" , "i64.gt_u" , null , "0x56", [] , "cmp" ], + ["mvp" , "i64.le_s" , null , "0x57", [] , "cmp" ], + ["mvp" , "i64.le_u" , null , "0x58", [] , "cmp" ], + ["mvp" , "i64.ge_s" , null , "0x59", [] , "cmp" ], + ["mvp" , "i64.ge_u" , null , "0x5A", [] , "cmp" ], + ["mvp" , "f32.eq" , null , "0x5B", [] , "cmp" ], + ["mvp" , "f32.ne" , null , "0x5C", [] , "cmp" ], + ["mvp" , "f32.lt" , null , "0x5D", [] , "cmp" ], + ["mvp" , "f32.gt" , null , "0x5E", [] , "cmp" ], + ["mvp" , "f32.le" , null , "0x5F", [] , "cmp" ], + ["mvp" , "f32.ge" , null , "0x60", [] , "cmp" ], + ["mvp" , "f64.eq" , null , "0x61", [] , "cmp" ], + ["mvp" , "f64.ne" , null , "0x62", [] , "cmp" ], + ["mvp" , "f64.lt" , null , "0x63", [] , "cmp" ], + ["mvp" , "f64.gt" , null , "0x64", [] , "cmp" ], + ["mvp" , "f64.le" , null , "0x65", [] , "cmp" ], + ["mvp" , "f64.ge" , null , "0x66", [] , "cmp" ], + ["mvp" , "i32.clz" , null , "0x67", [] , "unary" ], + ["mvp" , "i32.ctz" , null , "0x68", [] , "unary" ], + ["mvp" , "i32.popcnt" , null , "0x69", [] , "unary" ], + ["mvp" , "i32.add" , null , "0x6A", [] , "binary"], + ["mvp" , "i32.sub" , null , "0x6B", [] , "binary"], + ["mvp" , "i32.mul" , null , "0x6C", [] , "binary"], + ["mvp" , "i32.div_s" , null , "0x6D", [] , "binary"], + ["mvp" , "i32.div_u" , null , "0x6E", [] , "binary"], + ["mvp" , "i32.rem_s" , null , "0x6F", [] , "binary"], + ["mvp" , "i32.rem_u" , null , "0x70", [] , "binary"], + ["mvp" , "i32.and" , null , "0x71", [] , "binary"], + ["mvp" , "i32.or" , null , "0x72", [] , "binary"], + ["mvp" , "i32.xor" , null , "0x73", [] , "binary"], + ["mvp" , "i32.shl" , null , "0x74", [] , "binary"], + ["mvp" , "i32.shr_s" , null , "0x75", [] , "binary"], + ["mvp" , "i32.shr_u" , null , "0x76", [] , "binary"], + ["mvp" , "i32.rotl" , null , "0x77", [] , "binary"], + ["mvp" , "i32.rotr" , null , "0x78", [] , "binary"], + ["mvp" , "i64.clz" , null , "0x79", [] , "unary" ], + ["mvp" , "i64.ctz" , null , "0x7A", [] , "unary" ], + ["mvp" , "i64.popcnt" , null , "0x7B", [] , "unary" ], + ["mvp" , "i64.add" , null , "0x7C", [] , "binary"], + ["mvp" , "i64.sub" , null , "0x7D", [] , "binary"], + ["mvp" , "i64.mul" , null , "0x7E", [] , "binary"], + ["mvp" , "i64.div_s" , null , "0x7F", [] , "binary"], + ["mvp" , "i64.div_u" , null , "0x80", [] , "binary"], + ["mvp" , "i64.rem_s" , null , "0x81", [] , "binary"], + ["mvp" , "i64.rem_u" , null , "0x82", [] , "binary"], + ["mvp" , "i64.and" , null , "0x83", [] , "binary"], + ["mvp" , "i64.or" , null , "0x84", [] , "binary"], + ["mvp" , "i64.xor" , null , "0x85", [] , "binary"], + ["mvp" , "i64.shl" , null , "0x86", [] , "binary"], + ["mvp" , "i64.shr_s" , null , "0x87", [] , "binary"], + ["mvp" , "i64.shr_u" , null , "0x88", [] , "binary"], + ["mvp" , "i64.rotl" , null , "0x89", [] , "binary"], + ["mvp" , "i64.rotr" , null , "0x8A", [] , "binary"], + ["mvp" , "f32.abs" , null , "0x8B", [] , "unary" ], + ["mvp" , "f32.neg" , null , "0x8C", [] , "unary" ], + ["mvp" , "f32.ceil" , null , "0x8D", [] , "unary" ], + ["mvp" , "f32.floor" , null , "0x8E", [] , "unary" ], + ["mvp" , "f32.trunc" , null , "0x8F", [] , "unary" ], + ["mvp" , "f32.nearest" , null , "0x90", [] , "unary" ], + ["mvp" , "f32.sqrt" , null , "0x91", [] , "unary" ], + ["mvp" , "f32.add" , null , "0x92", [] , "binary"], + ["mvp" , "f32.sub" , null , "0x93", [] , "binary"], + ["mvp" , "f32.mul" , null , "0x94", [] , "binary"], + ["mvp" , "f32.div" , null , "0x95", [] , "binary"], + ["mvp" , "f32.min" , null , "0x96", [] , "binary"], + ["mvp" , "f32.max" , null , "0x97", [] , "binary"], + ["mvp" , "f32.copysign" , null , "0x98", [] , "binary"], + ["mvp" , "f64.abs" , null , "0x99", [] , "unary" ], + ["mvp" , "f64.neg" , null , "0x9A", [] , "unary" ], + ["mvp" , "f64.ceil" , null , "0x9B", [] , "unary" ], + ["mvp" , "f64.floor" , null , "0x9C", [] , "unary" ], + ["mvp" , "f64.trunc" , null , "0x9D", [] , "unary" ], + ["mvp" , "f64.nearest" , null , "0x9E", [] , "unary" ], + ["mvp" , "f64.sqrt" , null , "0x9F", [] , "unary" ], + ["mvp" , "f64.add" , null , "0xA0", [] , "binary"], + ["mvp" , "f64.sub" , null , "0xA1", [] , "binary"], + ["mvp" , "f64.mul" , null , "0xA2", [] , "binary"], + ["mvp" , "f64.div" , null , "0xA3", [] , "binary"], + ["mvp" , "f64.min" , null , "0xA4", [] , "binary"], + ["mvp" , "f64.max" , null , "0xA5", [] , "binary"], + ["mvp" , "f64.copysign" , null , "0xA6", [] , "binary"], + ["mvp" , "i32.wrap_i64" , null , "0xA7", [] , "conversion"], + ["mvp" , "i32.trunc_f32_s" , null , "0xA8", [] , "conversion"], + ["mvp" , "i32.trunc_f32_u" , null , "0xA9", [] , "conversion"], + ["mvp" , "i32.trunc_f64_s" , null , "0xAA", [] , "conversion"], + ["mvp" , "i32.trunc_f64_u" , null , "0xAB", [] , "conversion"], + ["mvp" , "i64.extend_i32_s" , null , "0xAC", [] , "conversion"], + ["mvp" , "i64.extend_i32_u" , null , "0xAD", [] , "conversion"], + ["mvp" , "i64.trunc_f32_s" , null , "0xAE", [] , "conversion"], + ["mvp" , "i64.trunc_f32_u" , null , "0xAF", [] , "conversion"], + ["mvp" , "i64.trunc_f64_s" , null , "0xB0", [] , "conversion"], + ["mvp" , "i64.trunc_f64_u" , null , "0xB1", [] , "conversion"], + ["mvp" , "f32.convert_i32_s" , null , "0xB2", [] , "conversion"], + ["mvp" , "f32.convert_i32_u" , null , "0xB3", [] , "conversion"], + ["mvp" , "f32.convert_i64_s" , null , "0xB4", [] , "conversion"], + ["mvp" , "f32.convert_i64_u" , null , "0xB5", [] , "conversion"], + ["mvp" , "f32.demote_f64" , null , "0xB6", [] , "conversion"], + ["mvp" , "f64.convert_i32_s" , null , "0xB7", [] , "conversion"], + ["mvp" , "f64.convert_i32_u" , null , "0xB8", [] , "conversion"], + ["mvp" , "f64.convert_i64_s" , null , "0xB9", [] , "conversion"], + ["mvp" , "f64.convert_i64_u" , null , "0xBA", [] , "conversion"], + ["mvp" , "f64.promote_f32" , null , "0xBB", [] , "conversion"], + ["mvp" , "i32.reinterpret_f32" , null , "0xBC", [] , "conversion"], + ["mvp" , "i64.reinterpret_f64" , null , "0xBD", [] , "conversion"], + ["mvp" , "f32.reinterpret_i32" , null , "0xBE", [] , "conversion"], + ["mvp" , "f64.reinterpret_i64" , null , "0xBF", [] , "conversion"], + ["signExtension" , "i32.extend8_s" , null , "0xC0", [] , "unary" ], + ["signExtension" , "i32.extend16_s" , null , "0xC1", [] , "unary" ], + ["signExtension" , "i64.extend8_s" , null , "0xC2", [] , "unary" ], + ["signExtension" , "i64.extend16_s" , null , "0xC3", [] , "unary" ], + ["signExtension" , "i64.extend32_s" , null , "0xC4", [] , "unary" ], + ["bulkMemory" , "memory.init" , "0xFC", "0x08", [["dataIndex", "UInt32"]] , null ], + ["bulkMemory" , "data.drop" , "0xFC", "0x09", [["dataIndex", "UInt32"]] , null ], + ["bulkMemory" , "memory.copy" , "0xFC", "0x0A", [["dstMem", "UInt32"], ["srcMem", "UInt32"]] , null ], + ["bulkMemory" , "memory.fill" , "0xFC", "0x0B", [["memory", "UInt32"]] , null ], + ["bulkMemory" , "table.init" , "0xFC", "0x0C", [["elemIndex", "UInt32"], ["table", "UInt32"]] , null ], + ["bulkMemory" , "elem.drop" , "0xFC", "0x0D", [["elemIndex", "UInt32"]] , null ], + ["bulkMemory" , "table.copy" , "0xFC", "0x0E", [["dstTable", "UInt32"], ["srcTable", "UInt32"]] , null ], + ["referenceTypes" , "table.fill" , "0xFC", "0x11", [["table", "UInt32"]] , null ], + ["referenceTypes" , "table.get" , null , "0x25", [["table", "UInt32"]] , null ], + ["referenceTypes" , "table.set" , null , "0x26", [["table", "UInt32"]] , null ], + ["referenceTypes" , "table.grow" , "0xFC", "0x0F", [["table", "UInt32"]] , null ], + ["referenceTypes" , "table.size" , "0xFC", "0x10", [["table", "UInt32"]] , null ], + ["saturatingFloatToInt", "i32.trunc_sat_f32_s" , "0xFC", "0x00", [] , "conversion" ], + ["saturatingFloatToInt", "i32.trunc_sat_f32_u" , "0xFC", "0x01", [] , "conversion" ], + ["saturatingFloatToInt", "i32.trunc_sat_f64_s" , "0xFC", "0x02", [] , "conversion" ], + ["saturatingFloatToInt", "i32.trunc_sat_f64_u" , "0xFC", "0x03", [] , "conversion" ], + ["saturatingFloatToInt", "i64.trunc_sat_f32_s" , "0xFC", "0x04", [] , "conversion" ], + ["saturatingFloatToInt", "i64.trunc_sat_f32_u" , "0xFC", "0x05", [] , "conversion" ], + ["saturatingFloatToInt", "i64.trunc_sat_f64_s" , "0xFC", "0x06", [] , "conversion" ], + ["saturatingFloatToInt", "i64.trunc_sat_f64_u" , "0xFC", "0x07", [] , "conversion" ] ] diff --git a/Utilities/Sources/WasmGen.swift b/Utilities/Sources/WasmGen.swift index 94d305cd..14ac86da 100644 --- a/Utilities/Sources/WasmGen.swift +++ b/Utilities/Sources/WasmGen.swift @@ -3,14 +3,63 @@ import Foundation /// A utility for generating Core Wasm instruction related code based on the `Instructions.json` file. enum WasmGen { + static func pascalCase(camelCase: String) -> String { + camelCase.prefix(1).uppercased() + camelCase.dropFirst() + } + struct Instruction: Decodable { let feature: String - let name: String? + let name: Name let prefix: UInt8? let opcode: UInt8 - let enumCaseName: String - let visitMethodName: String let immediates: [Immediate] + let category: String? + + var visitMethodName: String { + if let explicitCategory = category { + return "visit" + WasmGen.pascalCase(camelCase: explicitCategory) + } else { + return "visit" + WasmGen.pascalCase(camelCase: name.enumCase) + } + } + + enum Name: Decodable { + struct WithEnumCase: Decodable { + let enumCase: String + } + /// The instruction name in the Wasm text format. + case textual(String) + /// The instruction name in Swift enum case. + case withEnumCase(WithEnumCase) + + var text: String? { + switch self { + case let .textual(text): return text + case .withEnumCase: return nil + } + } + + var enumCase: String { + switch self { + case .textual(let name): + // e.g. i32.load -> i32Load, br_table -> brTable + let components = name.split(separator: ".").flatMap { + $0.split(separator: "_") + } + return components.first! + components.dropFirst().map(\.capitalized).joined() + case let .withEnumCase(name): return name.enumCase + } + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let withEnumCase = try? container.decode(WithEnumCase.self) { + self = .withEnumCase(withEnumCase) + } else { + self = .textual(try container.decode(String.self)) + } + } + } struct Immediate: Comparable, Hashable { let label: String @@ -31,26 +80,16 @@ enum WasmGen { return UInt8(hexString.dropFirst(2), radix: 16)! } feature = try container.decode(String.self) - if (try? container.decodeNil()) == true { - name = nil - } else { - name = try container.decode(String.self) - } + name = try container.decode(Name.self) if (try? container.decodeNil()) == true { prefix = nil } else { prefix = try decodeHex() } opcode = try decodeHex() - enumCaseName = try container.decode(String.self) - visitMethodName = try container.decode(String.self) - let rawImmediates: [[String]] - if container.isAtEnd { - rawImmediates = [] - } else { - rawImmediates = try container.decode([[String]].self) - } + let rawImmediates = try container.decode([[String]].self) immediates = rawImmediates.map { Immediate(label: $0[0], type: $0[1]) } + category = try? container.decode(String.self) } } @@ -65,12 +104,12 @@ enum WasmGen { public protocol InstructionVisitor { """ - for instruction in instructions { + for instruction in instructions.categorized { code += "\n" - code += " /// Visiting `\(instruction.name ?? instruction.enumCaseName)` instruction.\n" + code += " /// Visiting \(instruction.description) instruction.\n" code += " mutating func \(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.type)" + code += instruction.associatedValues.map { i in + "\(i.argumentName ?? "_"): \(i.type)" }.joined(separator: ", ") code += ") throws" } @@ -90,15 +129,19 @@ enum WasmGen { """ - for instruction in instructions { - if instruction.immediates.isEmpty { + for instruction in instructions.categorized { + if instruction.associatedValues.isEmpty { code += " case .\(instruction.enumCaseName): return try \(instruction.visitMethodName)()\n" } else { code += " case let .\(instruction.enumCaseName)(" - code += instruction.immediates.map(\.label).joined(separator: ", ") + code += instruction.associatedValues.map(\.parameterName).joined(separator: ", ") code += "): return try \(instruction.visitMethodName)(" - code += instruction.immediates.map { - "\($0.label): \($0.label)" + code += instruction.associatedValues.map { + if let label = $0.argumentName { + return "\(label): \(label)" + } else { + return $0.parameterName + } }.joined(separator: ", ") code += ")\n" } @@ -114,10 +157,14 @@ enum WasmGen { extension InstructionVisitor { """ - for instruction in instructions { + for instruction in instructions.categorized { code += " public mutating func \(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.type)" + code += instruction.associatedValues.map { i in + if i.argumentName == i.parameterName { + return "\(i.parameterName): \(i.type)" + } else { + return "\(i.argumentName ?? "_") \(i.parameterName): \(i.type)" + } }.joined(separator: ", ") code += ") throws {}\n" } @@ -134,13 +181,29 @@ enum WasmGen { """ - for instruction in instructions { + let categorized = instructions.categorized + + for instruction in categorized { + guard let categoryTypeName = instruction.categoryTypeName else { continue } + code += " public enum \(categoryTypeName): Equatable {\n" + for sourceInstruction in instruction.sourceInstructions { + code += " case \(sourceInstruction.name.enumCase)\n" + } + code += " }\n" + } + + for instruction in categorized { code += " case `\(instruction.enumCaseName)`" - if !instruction.immediates.isEmpty { + let associatedValues = instruction.associatedValues + if !associatedValues.isEmpty { code += "(" - + instruction.immediates.map { - "\($0.label): \($0.type)" + + associatedValues.map { + if let label = $0.argumentName { + return "\(label): \($0.type)" + } else { + return $0.type + } }.joined(separator: ", ") + ")" } code += "\n" @@ -151,14 +214,18 @@ enum WasmGen { return code } - static func buildInstructionInstanceFromContext(_ instruction: Instruction) -> String { + static func buildInstructionInstanceFromContext(_ instruction: CategorizedInstruction) -> String { var code = "" - if instruction.immediates.isEmpty { + if instruction.associatedValues.isEmpty { code += ".\(instruction.enumCaseName)" } else { code += ".\(instruction.enumCaseName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.label)" + code += instruction.associatedValues.map { i in + if let label = i.argumentName { + return "\(label): \(label)" + } else { + return i.parameterName + } }.joined(separator: ", ") code += ")" } @@ -177,10 +244,14 @@ enum WasmGen { """ - for instruction in instructions { + for instruction in instructions.categorized { code += " public mutating func \(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.type)" + code += instruction.associatedValues.map { i in + if i.argumentName == i.parameterName { + return "\(i.parameterName): \(i.type)" + } else { + return "\(i.argumentName ?? "_") \(i.parameterName): \(i.type)" + } }.joined(separator: ", ") code += ") throws { " code += "return try self.visit(" + buildInstructionInstanceFromContext(instruction) + ")" @@ -213,18 +284,26 @@ enum WasmGen { """ - for instruction in instructions { + for instruction in instructions.categorized { code += " public mutating func \(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.type)" + code += instruction.associatedValues.map { i in + if i.argumentName == i.parameterName { + return "\(i.parameterName): \(i.type)" + } else { + return "\(i.argumentName ?? "_") \(i.parameterName): \(i.type)" + } }.joined(separator: ", ") code += ") throws {\n" code += " trace(" code += buildInstructionInstanceFromContext(instruction) code += ")\n" code += " return try visitor.\(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.label)" + code += instruction.associatedValues.map { i in + if let label = i.argumentName { + "\(label): \(i.parameterName)" + } else { + i.parameterName + } }.joined(separator: ", ") code += ")\n" code += " }\n" @@ -253,7 +332,7 @@ enum WasmGen { """ for instruction in instructions { - guard let name = instruction.name else { + guard let name = instruction.name.text else { continue } code += " case \"\(name)\":" @@ -261,14 +340,30 @@ enum WasmGen { code += "\n" code += " let (" code += instruction.immediates.map(\.label).joined(separator: ", ") - code += ") = try expressionParser.\(instruction.visitMethodName)(wat: &wat)\n" + code += ") = try expressionParser.\(instruction.visitMethodName)(" + if instruction.category != nil { + code += ".\(instruction.name.enumCase), " + } + code += "wat: &wat" + code += ")\n" code += " " } else { code += " " } code += "return { return try $0.\(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.label)" + var arguments: [(label: String?, value: String)] = [] + if instruction.category != nil { + arguments.append((label: nil, value: ".\(instruction.name.enumCase)")) + } + for immediate in instruction.immediates { + arguments.append((label: immediate.label, value: immediate.label)) + } + code += arguments.map { i in + if let label = i.label { + return "\(label): \(i.value)" + } else { + return i.value + } }.joined(separator: ", ") code += ") }\n" } @@ -287,7 +382,7 @@ enum WasmGen { guard !instruction.immediates.isEmpty else { continue } - code += " mutating func \(instruction.visitMethodName)() throws -> " + code += " mutating func \(instruction.name.visitMethod)() throws -> " if instruction.immediates.count == 1 { code += instruction.immediates[0].type } else { @@ -353,27 +448,51 @@ enum WasmGen { """ - for instruction in instructions { - var encodeInstrCall = "try encodeInstruction(" - encodeInstrCall += [ - String(format: "0x%02X", instruction.opcode), - instruction.prefix.map { String(format: "0x%02X", $0) } ?? "nil", - ].joined(separator: ", ") - encodeInstrCall += ")" - + for instruction in instructions.categorized { code += " mutating func \(instruction.visitMethodName)(" - code += instruction.immediates.map { i in - "\(i.label): \(i.type)" + code += instruction.associatedValues.map { i in + if i.argumentName == i.parameterName { + return "\(i.parameterName): \(i.type)" + } else { + return "\(i.argumentName ?? "_") \(i.parameterName): \(i.type)" + } }.joined(separator: ", ") code += ") throws {" - if instruction.immediates.isEmpty { + + var encodeInstrCall: String + if let category = instruction.explicitCategory { + code += "\n" + code += " let (prefix, opcode): (UInt8?, UInt8)\n" + code += " switch \(category) {\n" + for sourceInstruction in instruction.sourceInstructions { + code += " case .\(sourceInstruction.name.enumCase): (prefix, opcode) = (" + code += sourceInstruction.prefix.map { String(format: "0x%02X", $0) } ?? "nil" + code += ", " + code += String(format: "0x%02X", sourceInstruction.opcode) + code += ")\n" + } + code += " }\n" + encodeInstrCall = "try encodeInstruction(opcode, prefix)" + } else { + let instruction = instruction.sourceInstructions[0] + encodeInstrCall = "try encodeInstruction(" + encodeInstrCall += [ + String(format: "0x%02X", instruction.opcode), + instruction.prefix.map { String(format: "0x%02X", $0) } ?? "nil", + ].joined(separator: ", ") + encodeInstrCall += ")" + } + + if instruction.immediates.isEmpty, instruction.explicitCategory == nil { code += " \(encodeInstrCall) " } else { code += "\n" code += " \(encodeInstrCall)\n" - code += " try encodeImmediates(" - code += instruction.immediates.map { "\($0.label): \($0.label)" }.joined(separator: ", ") - code += ")\n" + if !instruction.immediates.isEmpty { + code += " try encodeImmediates(" + code += instruction.immediates.map { "\($0.label): \($0.label)" }.joined(separator: ", ") + code += ")\n" + } code += " " } @@ -391,19 +510,22 @@ enum WasmGen { struct ColumnInfo { var header: String - var maxWidth: Int + var maxWidth: Int = 0 var value: (Instruction) -> String } var columns: [ColumnInfo] = [ - ColumnInfo(header: "Feature", maxWidth: 0, value: { "\"" + $0.feature + "\"" }), + ColumnInfo(header: "Feature", value: { "\"" + $0.feature + "\"" }), ColumnInfo( - header: "Name", maxWidth: 0, + header: "Name", value: { - $0.name.map { "\"" + $0 + "\"" } ?? "null" + switch $0.name { + case .textual(let name): return "\"" + name + "\"" + case .withEnumCase(let name): return "{\"enumCase\": \"\(name.enumCase)\"}" + } }), ColumnInfo( - header: "Prefix", maxWidth: 0, + header: "Prefix", value: { i in if let prefix = i.prefix { return "\"" + String(format: "0x%02X", prefix) + "\"" @@ -411,17 +533,24 @@ enum WasmGen { return "null" } }), - ColumnInfo(header: "Opcode", maxWidth: 0, value: { "\"" + String(format: "0x%02X", $0.opcode) + "\"" }), - ColumnInfo(header: "Enum Case", maxWidth: 0, value: { "\"" + $0.enumCaseName + "\"" }), - ColumnInfo(header: "Visit Method", maxWidth: 0, value: { "\"" + $0.visitMethodName + "\"" }), + ColumnInfo(header: "Opcode", value: { "\"" + String(format: "0x%02X", $0.opcode) + "\"" }), ColumnInfo( - header: "Immediates", maxWidth: 0, + header: "Immediates", value: { i in return "[" + i.immediates.map { i in "[\"\(i.label)\", \"\(i.type)\"]" }.joined(separator: ", ") + "]" }), + ColumnInfo( + header: "Category", + value: { i in + if let category = i.category { + return "\"" + category + "\"" + } else { + return "null" + } + }), ] for instruction in instructions { for columnIndex in columns.indices { @@ -433,7 +562,7 @@ enum WasmGen { } for (index, instruction) in instructions.enumerated() { - json += " [" + json += " [" for (columnIndex, column) in columns.enumerated() { let value = column.value(instruction) json += value.padding(toLength: column.maxWidth, withPad: " ", startingAt: 0) @@ -448,7 +577,7 @@ enum WasmGen { json += "],\n" } } - json += "]\n" + json += "]" return json } @@ -500,3 +629,72 @@ enum WasmGen { } } } + +extension WasmGen { + struct CategorizedInstruction { + let enumCaseName: String + let visitMethodName: String + let description: String + let immediates: [Instruction.Immediate] + let explicitCategory: String? + var sourceInstructions: [Instruction] = [] + + private var categoryValue: (argumentName: String?, parameterName: String, type: String)? { + guard let explicitCategory = explicitCategory else { + return nil + } + return (argumentName: nil, parameterName: explicitCategory, type: WasmGen.pascalCase(camelCase: explicitCategory)) + } + + var categoryTypeName: String? { + categoryValue?.type + } + + var associatedValues: [(argumentName: String?, parameterName: String, type: String)] { + var results: [(argumentName: String?, parameterName: String, type: String)] = [] + if var categoryValue = categoryValue { + categoryValue.type = "Instruction.\(categoryValue.type)" + results.append(categoryValue) + } + results += immediates.map { ($0.label, $0.label, $0.type) } + return results + } + } +} + +extension WasmGen.InstructionSet { + var categorized: [WasmGen.CategorizedInstruction] { + var categoryOrder: [String] = [] + var categories: [String: WasmGen.CategorizedInstruction] = [:] + + for instruction in self { + let category = instruction.category ?? instruction.name.enumCase + var categorized: WasmGen.CategorizedInstruction + if let existing = categories[category] { + categorized = existing + assert(categorized.immediates == instruction.immediates, "Inconsistent immediates for instruction \(instruction.name.text ?? instruction.name.enumCase) in category \(category)") + } else { + let enumCaseName: String + let description: String + if let explicitCategory = instruction.category { + enumCaseName = explicitCategory + description = "`\(explicitCategory)` category" + } else { + enumCaseName = instruction.name.enumCase + description = "`\(instruction.name.text ?? instruction.name.enumCase)`" + } + categorized = WasmGen.CategorizedInstruction( + enumCaseName: enumCaseName, + visitMethodName: instruction.visitMethodName, description: description, + immediates: instruction.immediates, + explicitCategory: instruction.category + ) + categoryOrder.append(category) + } + categorized.sourceInstructions.append(instruction) + categories[category] = categorized + } + + return categoryOrder.map { categories[$0]! } + } +}