aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/WebAssembly
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-07-11 02:57:23 +0900
committernsfisis <nsfisis@gmail.com>2024-07-11 02:57:23 +0900
commit26f49b7e27076e689541b9e13a1b54f60a4ee5c2 (patch)
treea3762813c34a384f21ddeed630ddf333a1cc1b05 /src/WebAssembly
parent326273f20c2d7dfe3d866eb720d1bb914570e3a3 (diff)
downloadphp-waddiwasi-26f49b7e27076e689541b9e13a1b54f60a4ee5c2.tar.gz
php-waddiwasi-26f49b7e27076e689541b9e13a1b54f60a4ee5c2.tar.zst
php-waddiwasi-26f49b7e27076e689541b9e13a1b54f60a4ee5c2.zip
feat: organize namespaces
Diffstat (limited to 'src/WebAssembly')
-rw-r--r--src/WebAssembly/BinaryFormat/Decoder.php1173
-rw-r--r--src/WebAssembly/BinaryFormat/Internal/Code.php23
-rw-r--r--src/WebAssembly/BinaryFormat/Internal/Locals.php22
-rw-r--r--src/WebAssembly/BinaryFormat/Internal/SectionId.php25
-rw-r--r--src/WebAssembly/BinaryFormat/InvalidBinaryFormatException.php11
-rw-r--r--src/WebAssembly/Debug/Debug.php112
-rw-r--r--src/WebAssembly/Execution/Allocator.php165
-rw-r--r--src/WebAssembly/Execution/DataInst.php16
-rw-r--r--src/WebAssembly/Execution/ElemInst.php19
-rw-r--r--src/WebAssembly/Execution/ExportInst.php17
-rw-r--r--src/WebAssembly/Execution/Extern.php28
-rw-r--r--src/WebAssembly/Execution/ExternVal.php28
-rw-r--r--src/WebAssembly/Execution/ExternVals/Func.php15
-rw-r--r--src/WebAssembly/Execution/ExternVals/Global_.php15
-rw-r--r--src/WebAssembly/Execution/ExternVals/Mem.php15
-rw-r--r--src/WebAssembly/Execution/ExternVals/Table.php15
-rw-r--r--src/WebAssembly/Execution/Externs/Func.php16
-rw-r--r--src/WebAssembly/Execution/Externs/Global_.php16
-rw-r--r--src/WebAssembly/Execution/Externs/Mem.php16
-rw-r--r--src/WebAssembly/Execution/Externs/Table.php16
-rw-r--r--src/WebAssembly/Execution/Frame.php20
-rw-r--r--src/WebAssembly/Execution/FuncInst.php21
-rw-r--r--src/WebAssembly/Execution/FuncInsts/Host.php20
-rw-r--r--src/WebAssembly/Execution/FuncInsts/Wasm.php20
-rw-r--r--src/WebAssembly/Execution/GlobalInst.php16
-rw-r--r--src/WebAssembly/Execution/Label.php16
-rw-r--r--src/WebAssembly/Execution/MemInst.php662
-rw-r--r--src/WebAssembly/Execution/ModuleInst.php32
-rw-r--r--src/WebAssembly/Execution/NumericOps.php193
-rw-r--r--src/WebAssembly/Execution/Ref.php25
-rw-r--r--src/WebAssembly/Execution/Refs/RefExtern.php15
-rw-r--r--src/WebAssembly/Execution/Refs/RefFunc.php15
-rw-r--r--src/WebAssembly/Execution/Refs/RefNull.php16
-rw-r--r--src/WebAssembly/Execution/Result.php21
-rw-r--r--src/WebAssembly/Execution/Results/Trap.php11
-rw-r--r--src/WebAssembly/Execution/Results/Values.php19
-rw-r--r--src/WebAssembly/Execution/Runtime.php2668
-rw-r--r--src/WebAssembly/Execution/Stack.php212
-rw-r--r--src/WebAssembly/Execution/StackOverflowException.php19
-rw-r--r--src/WebAssembly/Execution/Store.php52
-rw-r--r--src/WebAssembly/Execution/TableInst.php19
-rw-r--r--src/WebAssembly/Execution/TrapException.php28
-rw-r--r--src/WebAssembly/Execution/TrapKind.php19
-rw-r--r--src/WebAssembly/Structure/Instructions/Instr.php971
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Block.php24
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/BlockType.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/TypeIdx.php14
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/ValType.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Br.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/BrIf.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/BrTable.php24
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Call.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/CallIndirect.php21
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Else_.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/End.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/If_.php26
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Loop.php24
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Nop.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Return_.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Control/Unreachable.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/DataDrop.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Load.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Store.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Load.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Store.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16S.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16U.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8S.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8U.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store16.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store8.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16S.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16U.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32S.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32U.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8S.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8U.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store16.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store32.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store8.php25
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryCopy.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryFill.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryGrow.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryInit.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Memory/MemorySize.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Abs.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Add.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ceil.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Const.php23
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32CopySign.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32DemoteF64.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Div.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Eq.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Floor.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ge.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Gt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Le.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Lt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Max.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Min.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Mul.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ne.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Nearest.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Neg.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI32.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI64.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sqrt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sub.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Trunc.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Abs.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Add.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ceil.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Const.php23
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64CopySign.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Div.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Eq.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Floor.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ge.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Gt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Le.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Lt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Max.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Min.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Mul.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ne.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Nearest.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Neg.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64PromoteF32.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI32.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI64.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sqrt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sub.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Trunc.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Add.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32And.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Clz.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Const.php23
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ctz.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eq.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eqz.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend16S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend8S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Mul.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ne.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Or.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Popcnt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF32.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF64.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotL.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotR.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Shl.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Sub.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32WrapI64.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Xor.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Add.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64And.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Clz.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Const.php23
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ctz.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eq.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eqz.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend16S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend8S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Mul.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ne.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Or.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Popcnt.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF32.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF64.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotL.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotR.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Shl.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrS.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrU.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Sub.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64S.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64U.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Xor.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Parametric/Drop.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Parametric/Select.php24
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Reference/RefFunc.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Reference/RefIsNull.php15
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Reference/RefNull.php21
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/ElemDrop.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableCopy.php21
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableFill.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableGet.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableGrow.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableInit.php21
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableSet.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Table/TableSize.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalGet.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalSet.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalGet.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalSet.php20
-rw-r--r--src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalTee.php20
-rw-r--r--src/WebAssembly/Structure/Modules/Data.php17
-rw-r--r--src/WebAssembly/Structure/Modules/DataMode.php25
-rw-r--r--src/WebAssembly/Structure/Modules/DataModes/Active.php20
-rw-r--r--src/WebAssembly/Structure/Modules/DataModes/Passive.php14
-rw-r--r--src/WebAssembly/Structure/Modules/Elem.php21
-rw-r--r--src/WebAssembly/Structure/Modules/ElemMode.php30
-rw-r--r--src/WebAssembly/Structure/Modules/ElemModes/Active.php20
-rw-r--r--src/WebAssembly/Structure/Modules/ElemModes/Declarative.php14
-rw-r--r--src/WebAssembly/Structure/Modules/ElemModes/Passive.php14
-rw-r--r--src/WebAssembly/Structure/Modules/Export.php17
-rw-r--r--src/WebAssembly/Structure/Modules/ExportDesc.php28
-rw-r--r--src/WebAssembly/Structure/Modules/ExportDescs/Func.php15
-rw-r--r--src/WebAssembly/Structure/Modules/ExportDescs/Global_.php15
-rw-r--r--src/WebAssembly/Structure/Modules/ExportDescs/Mem.php15
-rw-r--r--src/WebAssembly/Structure/Modules/ExportDescs/Table.php15
-rw-r--r--src/WebAssembly/Structure/Modules/Func.php21
-rw-r--r--src/WebAssembly/Structure/Modules/Global_.php20
-rw-r--r--src/WebAssembly/Structure/Modules/Import.php19
-rw-r--r--src/WebAssembly/Structure/Modules/ImportDesc.php32
-rw-r--r--src/WebAssembly/Structure/Modules/ImportDescs/Func.php15
-rw-r--r--src/WebAssembly/Structure/Modules/ImportDescs/Global_.php16
-rw-r--r--src/WebAssembly/Structure/Modules/ImportDescs/Mem.php16
-rw-r--r--src/WebAssembly/Structure/Modules/ImportDescs/Table.php16
-rw-r--r--src/WebAssembly/Structure/Modules/Local.php15
-rw-r--r--src/WebAssembly/Structure/Modules/Mem.php15
-rw-r--r--src/WebAssembly/Structure/Modules/Module.php35
-rw-r--r--src/WebAssembly/Structure/Modules/Start.php13
-rw-r--r--src/WebAssembly/Structure/Modules/Table.php15
-rw-r--r--src/WebAssembly/Structure/Types/ExternType.php28
-rw-r--r--src/WebAssembly/Structure/Types/ExternTypes/Func.php16
-rw-r--r--src/WebAssembly/Structure/Types/ExternTypes/Global_.php16
-rw-r--r--src/WebAssembly/Structure/Types/ExternTypes/Mem.php16
-rw-r--r--src/WebAssembly/Structure/Types/ExternTypes/Table.php16
-rw-r--r--src/WebAssembly/Structure/Types/FuncType.php20
-rw-r--r--src/WebAssembly/Structure/Types/GlobalType.php14
-rw-r--r--src/WebAssembly/Structure/Types/Limits.php24
-rw-r--r--src/WebAssembly/Structure/Types/MemType.php13
-rw-r--r--src/WebAssembly/Structure/Types/Mut.php11
-rw-r--r--src/WebAssembly/Structure/Types/NumType.php13
-rw-r--r--src/WebAssembly/Structure/Types/RefType.php11
-rw-r--r--src/WebAssembly/Structure/Types/ResultType.php31
-rw-r--r--src/WebAssembly/Structure/Types/TableType.php14
-rw-r--r--src/WebAssembly/Structure/Types/ValType.php25
-rw-r--r--src/WebAssembly/Structure/Types/ValTypes/NumType.php21
-rw-r--r--src/WebAssembly/Structure/Types/ValTypes/RefType.php21
-rw-r--r--src/WebAssembly/Structure/Types/ValTypes/VecType.php21
-rw-r--r--src/WebAssembly/Structure/Types/VecType.php10
298 files changed, 11279 insertions, 0 deletions
diff --git a/src/WebAssembly/BinaryFormat/Decoder.php b/src/WebAssembly/BinaryFormat/Decoder.php
new file mode 100644
index 0000000..cc408a9
--- /dev/null
+++ b/src/WebAssembly/BinaryFormat/Decoder.php
@@ -0,0 +1,1173 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\BinaryFormat;
+
+use Nsfisis\Waddiwasi\Stream\StreamInterface;
+use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal\Code;
+use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal\Locals;
+use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal\SectionId;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Data;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\DataMode;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Elem;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemMode;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Export;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDesc;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Func;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Global_;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Import;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDesc;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Local;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Mem;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Module;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Start;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Table;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\Limits;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\Mut;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\NumType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ResultType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\VecType;
+use function array_reduce;
+use function assert;
+use function count;
+use function get_class;
+use function in_array;
+use function is_float;
+use function is_int;
+use function ord;
+
+final class Decoder
+{
+ public function __construct(
+ private readonly StreamInterface $stream,
+ ) {
+ }
+
+ public function decode(): Module
+ {
+ $this->checkMagic();
+ $this->checkVersion();
+
+ $types = $this->decodeSection(SectionId::Type, $this->decodeTypeSecRest(...)) ?? [];
+ $imports = $this->decodeSection(SectionId::Import, $this->decodeImportSecRest(...)) ?? [];
+ $typeIndices = $this->decodeSection(SectionId::Func, $this->decodeFuncSecRest(...)) ?? [];
+ $tables = $this->decodeSection(SectionId::Table, $this->decodeTableSecRest(...)) ?? [];
+ $mems = $this->decodeSection(SectionId::Mem, $this->decodeMemSecRest(...)) ?? [];
+ $globals = $this->decodeSection(SectionId::Global, $this->decodeGlobalSecRest(...)) ?? [];
+ $exports = $this->decodeSection(SectionId::Export, $this->decodeExportSecRest(...)) ?? [];
+ $start = $this->decodeSection(SectionId::Start, $this->decodeStartSecRest(...));
+ $elems = $this->decodeSection(SectionId::Elem, $this->decodeElemSecRest(...)) ?? [];
+ $dataCount = $this->decodeSection(SectionId::DataCount, $this->decodeDataCountSecRest(...));
+ $codes = $this->decodeSection(SectionId::Code, $this->decodeCodeSecRest(...)) ?? [];
+ $datas = $this->decodeSection(SectionId::Data, $this->decodeDataSecRest(...)) ?? [];
+
+ if (!$this->stream->eof()) {
+ throw new InvalidBinaryFormatException("eof");
+ }
+ if ($dataCount === null) {
+ foreach ($codes as $code) {
+ if ($this->countDataIndicesUsedInCode($code) !== 0) {
+ throw new InvalidBinaryFormatException("datacount section is required");
+ }
+ }
+ } else {
+ if (count($datas) !== $dataCount) {
+ throw new InvalidBinaryFormatException("datasec");
+ }
+ }
+ if (count($typeIndices) !== count($codes)) {
+ throw new InvalidBinaryFormatException("number of funcs and codes does not match");
+ }
+
+ $funcs = [];
+ foreach ($typeIndices as $i => $type) {
+ $code = $codes[$i];
+ $decompressedLocals = array_map(
+ fn ($l) => array_fill(0, $l->count, new Local($l->type)),
+ $code->compressedLocals,
+ );
+ $funcs[] = new Func(
+ $type,
+ array_merge(...$decompressedLocals),
+ $code->body,
+ );
+ }
+
+ return new Module(
+ $types,
+ $funcs,
+ $tables,
+ $mems,
+ $globals,
+ $elems,
+ $datas,
+ $start,
+ $imports,
+ $exports,
+ );
+ }
+
+ private function checkMagic(): void
+ {
+ $bs = $this->stream->read(4);
+ $b1 = ord($bs[0]);
+ $b2 = ord($bs[1]);
+ $b3 = ord($bs[2]);
+ $b4 = ord($bs[3]);
+ if ([$b1, $b2, $b3, $b4] !== [0x00, 0x61, 0x73, 0x6D]) {
+ throw new InvalidBinaryFormatException("magic");
+ }
+ }
+
+ private function checkVersion(): void
+ {
+ $bs = $this->stream->read(4);
+ $b1 = ord($bs[0]);
+ $b2 = ord($bs[1]);
+ $b3 = ord($bs[2]);
+ $b4 = ord($bs[3]);
+ if ([$b1, $b2, $b3, $b4] !== [0x01, 0x00, 0x00, 0x00]) {
+ throw new InvalidBinaryFormatException(sprintf("version: [%x, %x, %x, %x]", $b1, $b2, $b3, $b4));
+ }
+ }
+
+ /**
+ * @template T
+ * @param callable(): T $decoder
+ * @return ?T
+ */
+ private function decodeSection(SectionId $sectionId, callable $decoder): mixed
+ {
+ $this->skipCustomSections();
+ if ($this->stream->eof()) {
+ return null;
+ }
+
+ $idValue = $this->stream->peekByte();
+ $id = SectionId::tryFrom($idValue);
+ if ($id === null) {
+ throw new InvalidBinaryFormatException("section id");
+ }
+ if ($id !== $sectionId) {
+ return null;
+ }
+ $this->stream->seek(1);
+
+ $size = $this->decodeU32();
+ $prevPos = $this->stream->tell();
+ $result = $decoder();
+ if ($this->stream->tell() - $prevPos !== $size) {
+ throw new InvalidBinaryFormatException("type section size");
+ }
+ return $result;
+ }
+
+ private function skipCustomSections(): void
+ {
+ while (!$this->stream->eof()) {
+ $b = $this->stream->peekByte();
+ if ($b !== SectionId::Custom->value) {
+ break;
+ }
+ $this->stream->seek(1);
+ $size = $this->decodeU32();
+ $prevPos = $this->stream->tell();
+ $this->decodeName();
+ $encodedSizeOfName = $this->stream->tell() - $prevPos;
+ $offset = $size - $encodedSizeOfName;
+ if ($offset < 0) {
+ throw new InvalidBinaryFormatException("custom section size");
+ }
+ if ($offset !== 0) {
+ $this->stream->seek($offset);
+ }
+ }
+ }
+
+ /**
+ * @return list<FuncType>
+ */
+ private function decodeTypeSecRest(): array
+ {
+ return $this->decodeVec($this->decodeFuncType(...));
+ }
+
+ /**
+ * @return list<Import>
+ */
+ private function decodeImportSecRest(): array
+ {
+ return $this->decodeVec($this->decodeImport(...));
+ }
+
+ /**
+ * @return list<int>
+ */
+ private function decodeFuncSecRest(): array
+ {
+ return $this->decodeVec($this->decodeTypeIdx(...));
+ }
+
+ /**
+ * @return list<Table>
+ */
+ private function decodeTableSecRest(): array
+ {
+ return $this->decodeVec($this->decodeTable(...));
+ }
+
+ /**
+ * @return list<Mem>
+ */
+ private function decodeMemSecRest(): array
+ {
+ return $this->decodeVec($this->decodeMem(...));
+ }
+
+ /**
+ * @return list<Global_>
+ */
+ private function decodeGlobalSecRest(): array
+ {
+ return $this->decodeVec($this->decodeGlobal(...));
+ }
+
+ /**
+ * @return list<Export>
+ */
+ private function decodeExportSecRest(): array
+ {
+ return $this->decodeVec($this->decodeExport(...));
+ }
+
+ private function decodeStartSecRest(): Start
+ {
+ return new Start($this->decodeFuncIdx());
+ }
+
+ /**
+ * @return list<Elem>
+ */
+ private function decodeElemSecRest(): array
+ {
+ return $this->decodeVec($this->decodeElem(...));
+ }
+
+ /**
+ * @return list<Code>
+ */
+ private function decodeCodeSecRest(): array
+ {
+ return $this->decodeVec($this->decodeCode(...));
+ }
+
+ /**
+ * @return list<Data>
+ */
+ private function decodeDataSecRest(): array
+ {
+ return $this->decodeVec($this->decodeData(...));
+ }
+
+ /**
+ * @return U32
+ */
+ private function decodeDataCountSecRest(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeResultType(): ResultType
+ {
+ return new ResultType($this->decodeVec($this->decodeValType(...)));
+ }
+
+ private function decodeFuncType(): FuncType
+ {
+ $b = $this->decodeByte();
+ if ($b !== 0x60) {
+ throw new InvalidBinaryFormatException("functype");
+ }
+ $params = $this->decodeResultType();
+ $results = $this->decodeResultType();
+ return new FuncType(
+ $params,
+ $results,
+ );
+ }
+
+ private function decodeValType(): ValType
+ {
+ $b = $this->stream->peekByte();
+ if ($b === 0x7F) {
+ $this->stream->seek(1);
+ return ValType::NumType(NumType::I32);
+ } elseif ($b === 0x7E) {
+ $this->stream->seek(1);
+ return ValType::NumType(NumType::I64);
+ } elseif ($b === 0x7D) {
+ $this->stream->seek(1);
+ return ValType::NumType(NumType::F32);
+ } elseif ($b === 0x7C) {
+ $this->stream->seek(1);
+ return ValType::NumType(NumType::F64);
+ } elseif ($b === 0x7B) {
+ $this->stream->seek(1);
+ return ValType::VecType(VecType::V128);
+ } else {
+ return ValType::RefType($this->decodeRefType());
+ }
+ }
+
+ private function decodeRefType(): RefType
+ {
+ return match ($this->decodeByte()) {
+ 0x70 => RefType::FuncRef,
+ 0x6F => RefType::ExternRef,
+ default => throw new InvalidBinaryFormatException("reftype"),
+ };
+ }
+
+ private function decodeLimits(): Limits
+ {
+ $b = $this->decodeByte();
+ if ($b === 0x00) {
+ $min = $this->decodeU32();
+ return new Limits($min, null);
+ } elseif ($b === 0x01) {
+ $min = $this->decodeU32();
+ $max = $this->decodeU32();
+ return new Limits($min, $max);
+ } else {
+ throw new InvalidBinaryFormatException("limits");
+ }
+ }
+
+ private function decodeMemType(): MemType
+ {
+ return new MemType($this->decodeLimits());
+ }
+
+ private function decodeTableType(): TableType
+ {
+ $refType = $this->decodeRefType();
+ $limits = $this->decodeLimits();
+ return new TableType(
+ $limits,
+ $refType,
+ );
+ }
+
+ private function decodeGlobalType(): GlobalType
+ {
+ $valType = $this->decodeValType();
+ $mut = $this->decodeMut();
+ return new GlobalType(
+ $mut,
+ $valType,
+ );
+ }
+
+ private function decodeMut(): Mut
+ {
+ return match ($this->decodeByte()) {
+ 0x00 => Mut::Const,
+ 0x01 => Mut::Var,
+ default => throw new InvalidBinaryFormatException("mutability"),
+ };
+ }
+
+ private function decodeImport(): Import
+ {
+ $module = $this->decodeName();
+ $name = $this->decodeName();
+ $desc = $this->decodeImportDesc();
+ return new Import(
+ $module,
+ $name,
+ $desc,
+ );
+ }
+
+ private function decodeTable(): Table
+ {
+ return new Table($this->decodeTableType());
+ }
+
+ private function decodeMem(): Mem
+ {
+ return new Mem($this->decodeMemType());
+ }
+
+ private function decodeGlobal(): Global_
+ {
+ $type = $this->decodeGlobalType();
+ $init = $this->decodeExpr();
+ return new Global_(
+ $type,
+ $init,
+ );
+ }
+
+ private function decodeExport(): Export
+ {
+ $name = $this->decodeName();
+ $desc = $this->decodeExportDesc();
+ return new Export(
+ $name,
+ $desc,
+ );
+ }
+
+ private function decodeElem(): Elem
+ {
+ $mode = $this->decodeU32();
+ if ($mode === 0) {
+ $offset = $this->decodeExpr();
+ $initFuncRefs = $this->decodeVec($this->decodeFuncIdx(...));
+ return new Elem(
+ RefType::FuncRef,
+ array_map(
+ fn ($funcRef) => [Instr::RefFunc($funcRef)],
+ $initFuncRefs,
+ ),
+ ElemMode::Active(0, $offset),
+ );
+ } elseif ($mode === 1) {
+ $refType = $this->decodeElemKind();
+ $initFuncRefs = $this->decodeVec($this->decodeFuncIdx(...));
+ return new Elem(
+ $refType,
+ array_map(
+ fn ($funcRef) => [Instr::RefFunc($funcRef)],
+ $initFuncRefs,
+ ),
+ ElemMode::Passive(),
+ );
+ } elseif ($mode === 2) {
+ $table = $this->decodeTableIdx();
+ $offset = $this->decodeExpr();
+ $refType = $this->decodeElemKind();
+ $initFuncRefs = $this->decodeVec($this->decodeFuncIdx(...));
+ return new Elem(
+ $refType,
+ array_map(
+ fn ($funcRef) => [Instr::RefFunc($funcRef)],
+ $initFuncRefs,
+ ),
+ ElemMode::Active($table, $offset),
+ );
+ } elseif ($mode === 3) {
+ $refType = $this->decodeElemKind();
+ $initFuncRefs = $this->decodeVec($this->decodeFuncIdx(...));
+ return new Elem(
+ $refType,
+ array_map(
+ fn ($funcRef) => [Instr::RefFunc($funcRef)],
+ $initFuncRefs,
+ ),
+ ElemMode::Declarative(),
+ );
+ } elseif ($mode === 4) {
+ $offset = $this->decodeExpr();
+ $init = $this->decodeVec($this->decodeExpr(...));
+ return new Elem(
+ RefType::FuncRef,
+ $init,
+ ElemMode::Active(0, $offset),
+ );
+ } elseif ($mode === 5) {
+ $refType = $this->decodeRefType();
+ $init = $this->decodeVec($this->decodeExpr(...));
+ return new Elem(
+ $refType,
+ $init,
+ ElemMode::Passive(),
+ );
+ } elseif ($mode === 6) {
+ $table = $this->decodeTableIdx();
+ $offset = $this->decodeExpr();
+ $refType = $this->decodeRefType();
+ $init = $this->decodeVec($this->decodeExpr(...));
+ return new Elem(
+ $refType,
+ $init,
+ ElemMode::Active($table, $offset),
+ );
+ } elseif ($mode === 7) {
+ $refType = $this->decodeRefType();
+ $init = $this->decodeVec($this->decodeExpr(...));
+ return new Elem(
+ $refType,
+ $init,
+ ElemMode::Declarative(),
+ );
+ } else {
+ throw new InvalidBinaryFormatException("code");
+ }
+ }
+
+ private function decodeCode(): Code
+ {
+ $size = $this->decodeU32();
+ $prevPos = $this->stream->tell();
+ $compressedLocals = $this->decodeVec($this->decodeLocals(...));
+ $body = $this->decodeExpr();
+ if ($this->stream->tell() - $prevPos !== $size) {
+ throw new InvalidBinaryFormatException("code size");
+ }
+ return new Code(
+ $compressedLocals,
+ $body,
+ );
+ }
+
+ private function decodeData(): Data
+ {
+ $mode = $this->decodeU32();
+ if ($mode === 0) {
+ $offset = $this->decodeExpr();
+ $init = $this->decodeVec($this->decodeByte(...));
+ return new Data(
+ $init,
+ DataMode::Active(
+ 0,
+ $offset,
+ ),
+ );
+ } elseif ($mode === 1) {
+ $init = $this->decodeVec($this->decodeByte(...));
+ return new Data(
+ $init,
+ DataMode::Passive(),
+ );
+ } elseif ($mode === 2) {
+ $memory = $this->decodeMemIdx();
+ $offset = $this->decodeExpr();
+ $init = $this->decodeVec($this->decodeByte(...));
+ return new Data(
+ $init,
+ DataMode::Active(
+ $memory,
+ $offset,
+ ),
+ );
+ } else {
+ throw new InvalidBinaryFormatException("data");
+ }
+ }
+
+ private function decodeImportDesc(): ImportDesc
+ {
+ return match ($this->decodeByte()) {
+ 0x00 => ImportDesc::Func($this->decodeTypeIdx()),
+ 0x01 => ImportDesc::Table($this->decodeTableType()),
+ 0x02 => ImportDesc::Mem($this->decodeMemType()),
+ 0x03 => ImportDesc::Global($this->decodeGlobalType()),
+ default => throw new InvalidBinaryFormatException("importdesc"),
+ };
+ }
+
+ private function decodeExportDesc(): ExportDesc
+ {
+ return match ($this->decodeByte()) {
+ 0x00 => ExportDesc::Func($this->decodeFuncIdx()),
+ 0x01 => ExportDesc::Table($this->decodeTableIdx()),
+ 0x02 => ExportDesc::Mem($this->decodeMemIdx()),
+ 0x03 => ExportDesc::Global($this->decodeGlobalIdx()),
+ default => throw new InvalidBinaryFormatException("exportdesc"),
+ };
+ }
+
+ private function decodeElemKind(): RefType
+ {
+ $b = $this->decodeByte();
+ if ($b === 0x00) {
+ return RefType::FuncRef;
+ } else {
+ throw new InvalidBinaryFormatException("elemkind");
+ }
+ }
+
+ private function decodeLocals(): Locals
+ {
+ $count = $this->decodeU32();
+ // @todo Provide a way to configure the limit.
+ if (1024 < $count) {
+ throw new InvalidBinaryFormatException("too many local variables");
+ }
+ $type = $this->decodeValType();
+ return new Locals(
+ $count,
+ $type,
+ );
+ }
+
+ private function decodeTypeIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeMemIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeFuncIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeTableIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeGlobalIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeLocalIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeLabelIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeDataIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ private function decodeElemIdx(): int
+ {
+ return $this->decodeU32();
+ }
+
+ /**
+ * @return list<Instr>
+ */
+ private function decodeExpr(): array
+ {
+ return $this->decodeInstrsUntil([Instrs\Control\End::class])[0];
+ }
+
+ private function decodeInstr(): Instr
+ {
+ switch ($op = $this->decodeByte()) {
+ case 0x00: return Instr::Unreachable();
+ case 0x01: return Instr::Nop();
+ case 0x02:
+ $blockType = $this->decodeBlockType();
+ $body = $this->decodeInstrsUntil([Instrs\Control\End::class])[0];
+ return Instr::Block($blockType, $body);
+ case 0x03:
+ $blockType = $this->decodeBlockType();
+ $body = $this->decodeInstrsUntil([Instrs\Control\End::class])[0];
+ return Instr::Loop($blockType, $body);
+ case 0x04:
+ $blockType = $this->decodeBlockType();
+ [$thenBody, $delimiter] = $this->decodeInstrsUntil([Instrs\Control\End::class, Instrs\Control\Else_::class]);
+ if ($delimiter instanceof Instrs\Control\End) {
+ return Instr::If_($blockType, $thenBody, []);
+ }
+ $elseBody = $this->decodeInstrsUntil([Instrs\Control\End::class])[0];
+ return Instr::If_($blockType, $thenBody, $elseBody);
+ case 0x05: return Instr::Else_();
+ case 0x0B: return Instr::End();
+ case 0x0C: return Instr::Br($this->decodeLabelIdx());
+ case 0x0D: return Instr::BrIf($this->decodeLabelIdx());
+ case 0x0E:
+ $labelTable = $this->decodeVec($this->decodeLabelIdx(...));
+ $defaultLabel = $this->decodeLabelIdx();
+ return Instr::BrTable($labelTable, $defaultLabel);
+ case 0x0F: return Instr::Return_();
+ case 0x10: return Instr::Call($this->decodeFuncIdx());
+ case 0x11:
+ $type = $this->decodeTypeIdx();
+ $funcTable = $this->decodeTableIdx();
+ return Instr::CallIndirect($funcTable, $type);
+ case 0x1A: return Instr::Drop();
+ case 0x1B: return Instr::Select([]);
+ case 0x1C: return Instr::Select($this->decodeVec($this->decodeValType(...)));
+ case 0x20: return Instr::LocalGet($this->decodeLocalIdx());
+ case 0x21: return Instr::LocalSet($this->decodeLocalIdx());
+ case 0x22: return Instr::LocalTee($this->decodeLocalIdx());
+ case 0x23: return Instr::GlobalGet($this->decodeGlobalIdx());
+ case 0x24: return Instr::GlobalSet($this->decodeGlobalIdx());
+ case 0x25: return Instr::TableGet($this->decodeTableIdx());
+ case 0x26: return Instr::TableSet($this->decodeTableIdx());
+ case 0x28: return Instr::I32Load(...$this->decodeMemArg());
+ case 0x29: return Instr::I64Load(...$this->decodeMemArg());
+ case 0x2A: return Instr::F32Load(...$this->decodeMemArg());
+ case 0x2B: return Instr::F64Load(...$this->decodeMemArg());
+ case 0x2C: return Instr::I32Load8S(...$this->decodeMemArg());
+ case 0x2D: return Instr::I32Load8U(...$this->decodeMemArg());
+ case 0x2E: return Instr::I32Load16S(...$this->decodeMemArg());
+ case 0x2F: return Instr::I32Load16U(...$this->decodeMemArg());
+ case 0x30: return Instr::I64Load8S(...$this->decodeMemArg());
+ case 0x31: return Instr::I64Load8U(...$this->decodeMemArg());
+ case 0x32: return Instr::I64Load16S(...$this->decodeMemArg());
+ case 0x33: return Instr::I64Load16U(...$this->decodeMemArg());
+ case 0x34: return Instr::I64Load32S(...$this->decodeMemArg());
+ case 0x35: return Instr::I64Load32U(...$this->decodeMemArg());
+ case 0x36: return Instr::I32Store(...$this->decodeMemArg());
+ case 0x37: return Instr::I64Store(...$this->decodeMemArg());
+ case 0x38: return Instr::F32Store(...$this->decodeMemArg());
+ case 0x39: return Instr::F64Store(...$this->decodeMemArg());
+ case 0x3A: return Instr::I32Store8(...$this->decodeMemArg());
+ case 0x3B: return Instr::I32Store16(...$this->decodeMemArg());
+ case 0x3C: return Instr::I64Store8(...$this->decodeMemArg());
+ case 0x3D: return Instr::I64Store16(...$this->decodeMemArg());
+ case 0x3E: return Instr::I64Store32(...$this->decodeMemArg());
+ case 0x3F:
+ $c = $this->decodeByte();
+ if ($c !== 0) {
+ throw new InvalidBinaryFormatException("Unexpected value while decoding an instruction `memory.size`, expected 0, but got $c");
+ }
+ return Instr::MemorySize();
+ case 0x40:
+ $c = $this->decodeByte();
+ if ($c !== 0) {
+ throw new InvalidBinaryFormatException("Unexpected value while decoding an instruction `memory.grow`, expected 0, but got $c");
+ }
+ return Instr::MemoryGrow();
+ case 0x41: return Instr::I32Const($this->decodeS32());
+ case 0x42: return Instr::I64Const($this->decodeS64());
+ case 0x43: return Instr::F32Const($this->decodeF32());
+ case 0x44: return Instr::F64Const($this->decodeF64());
+ case 0x45: return Instr::I32Eqz();
+ case 0x46: return Instr::I32Eq();
+ case 0x47: return Instr::I32Ne();
+ case 0x48: return Instr::I32LtS();
+ case 0x49: return Instr::I32LtU();
+ case 0x4A: return Instr::I32GtS();
+ case 0x4B: return Instr::I32GtU();
+ case 0x4C: return Instr::I32LeS();
+ case 0x4D: return Instr::I32LeU();
+ case 0x4E: return Instr::I32GeS();
+ case 0x4F: return Instr::I32GeU();
+ case 0x50: return Instr::I64Eqz();
+ case 0x51: return Instr::I64Eq();
+ case 0x52: return Instr::I64Ne();
+ case 0x53: return Instr::I64LtS();
+ case 0x54: return Instr::I64LtU();
+ case 0x55: return Instr::I64GtS();
+ case 0x56: return Instr::I64GtU();
+ case 0x57: return Instr::I64LeS();
+ case 0x58: return Instr::I64LeU();
+ case 0x59: return Instr::I64GeS();
+ case 0x5A: return Instr::I64GeU();
+ case 0x5B: return Instr::F32Eq();
+ case 0x5C: return Instr::F32Ne();
+ case 0x5D: return Instr::F32Lt();
+ case 0x5E: return Instr::F32Gt();
+ case 0x5F: return Instr::F32Le();
+ case 0x60: return Instr::F32Ge();
+ case 0x61: return Instr::F64Eq();
+ case 0x62: return Instr::F64Ne();
+ case 0x63: return Instr::F64Lt();
+ case 0x64: return Instr::F64Gt();
+ case 0x65: return Instr::F64Le();
+ case 0x66: return Instr::F64Ge();
+ case 0x67: return Instr::I32Clz();
+ case 0x68: return Instr::I32Ctz();
+ case 0x69: return Instr::I32Popcnt();
+ case 0x6A: return Instr::I32Add();
+ case 0x6B: return Instr::I32Sub();
+ case 0x6C: return Instr::I32Mul();
+ case 0x6D: return Instr::I32DivS();
+ case 0x6E: return Instr::I32DivU();
+ case 0x6F: return Instr::I32RemS();
+ case 0x70: return Instr::I32RemU();
+ case 0x71: return Instr::I32And();
+ case 0x72: return Instr::I32Or();
+ case 0x73: return Instr::I32Xor();
+ case 0x74: return Instr::I32Shl();
+ case 0x75: return Instr::I32ShrS();
+ case 0x76: return Instr::I32ShrU();
+ case 0x77: return Instr::I32RotL();
+ case 0x78: return Instr::I32RotR();
+ case 0x79: return Instr::I64Clz();
+ case 0x7A: return Instr::I64Ctz();
+ case 0x7B: return Instr::I64Popcnt();
+ case 0x7C: return Instr::I64Add();
+ case 0x7D: return Instr::I64Sub();
+ case 0x7E: return Instr::I64Mul();
+ case 0x7F: return Instr::I64DivS();
+ case 0x80: return Instr::I64DivU();
+ case 0x81: return Instr::I64RemS();
+ case 0x82: return Instr::I64RemU();
+ case 0x83: return Instr::I64And();
+ case 0x84: return Instr::I64Or();
+ case 0x85: return Instr::I64Xor();
+ case 0x86: return Instr::I64Shl();
+ case 0x87: return Instr::I64ShrS();
+ case 0x88: return Instr::I64ShrU();
+ case 0x89: return Instr::I64RotL();
+ case 0x8A: return Instr::I64RotR();
+ case 0x8B: return Instr::F32Abs();
+ case 0x8C: return Instr::F32Neg();
+ case 0x8D: return Instr::F32Ceil();
+ case 0x8E: return Instr::F32Floor();
+ case 0x8F: return Instr::F32Trunc();
+ case 0x90: return Instr::F32Nearest();
+ case 0x91: return Instr::F32Sqrt();
+ case 0x92: return Instr::F32Add();
+ case 0x93: return Instr::F32Sub();
+ case 0x94: return Instr::F32Mul();
+ case 0x95: return Instr::F32Div();
+ case 0x96: return Instr::F32Min();
+ case 0x97: return Instr::F32Max();
+ case 0x98: return Instr::F32CopySign();
+ case 0x99: return Instr::F64Abs();
+ case 0x9A: return Instr::F64Neg();
+ case 0x9B: return Instr::F64Ceil();
+ case 0x9C: return Instr::F64Floor();
+ case 0x9D: return Instr::F64Trunc();
+ case 0x9E: return Instr::F64Nearest();
+ case 0x9F: return Instr::F64Sqrt();
+ case 0xA0: return Instr::F64Add();
+ case 0xA1: return Instr::F64Sub();
+ case 0xA2: return Instr::F64Mul();
+ case 0xA3: return Instr::F64Div();
+ case 0xA4: return Instr::F64Min();
+ case 0xA5: return Instr::F64Max();
+ case 0xA6: return Instr::F64CopySign();
+ case 0xA7: return Instr::I32WrapI64();
+ case 0xA8: return Instr::I32TruncF32S();
+ case 0xA9: return Instr::I32TruncF32U();
+ case 0xAA: return Instr::I32TruncF64S();
+ case 0xAB: return Instr::I32TruncF64U();
+ case 0xAC: return Instr::I64ExtendI32S();
+ case 0xAD: return Instr::I64ExtendI32U();
+ case 0xAE: return Instr::I64TruncF32S();
+ case 0xAF: return Instr::I64TruncF32U();
+ case 0xB0: return Instr::I64TruncF64S();
+ case 0xB1: return Instr::I64TruncF64U();
+ case 0xB2: return Instr::F32ConvertI32S();
+ case 0xB3: return Instr::F32ConvertI32U();
+ case 0xB4: return Instr::F32ConvertI64S();
+ case 0xB5: return Instr::F32ConvertI64U();
+ case 0xB6: return Instr::F32DemoteF64();
+ case 0xB7: return Instr::F64ConvertI32S();
+ case 0xB8: return Instr::F64ConvertI32U();
+ case 0xB9: return Instr::F64ConvertI64S();
+ case 0xBA: return Instr::F64ConvertI64U();
+ case 0xBB: return Instr::F64PromoteF32();
+ case 0xBC: return Instr::I32ReinterpretF32();
+ case 0xBD: return Instr::I64ReinterpretF64();
+ case 0xBE: return Instr::F32ReinterpretI32();
+ case 0xBF: return Instr::F64ReinterpretI64();
+ case 0xC0: return Instr::I32Extend8S();
+ case 0xC1: return Instr::I32Extend16S();
+ case 0xC2: return Instr::I64Extend8S();
+ case 0xC3: return Instr::I64Extend16S();
+ case 0xC4: return Instr::I64Extend32S();
+ case 0xD0: return Instr::RefNull($this->decodeRefType());
+ case 0xD1: return Instr::RefIsNull();
+ case 0xD2: return Instr::RefFunc($this->decodeFuncIdx());
+ case 0xFC:
+ switch ($this->decodeU32()) {
+ case 0: return Instr::I32TruncSatF32S();
+ case 1: return Instr::I32TruncSatF32U();
+ case 2: return Instr::I32TruncSatF64S();
+ case 3: return Instr::I32TruncSatF64U();
+ case 4: return Instr::I64TruncSatF32S();
+ case 5: return Instr::I64TruncSatF32U();
+ case 6: return Instr::I64TruncSatF64S();
+ case 7: return Instr::I64TruncSatF64U();
+ case 8:
+ $data = $this->decodeDataIdx();
+ if ($this->decodeByte() !== 0) {
+ throw new InvalidBinaryFormatException("memory init");
+ }
+ return Instr::MemoryInit($data);
+ case 9: return Instr::DataDrop($this->decodeDataIdx());
+ case 10:
+ if ($this->decodeByte() !== 0) {
+ throw new InvalidBinaryFormatException("memory copy");
+ }
+ if ($this->decodeByte() !== 0) {
+ throw new InvalidBinaryFormatException("memory copy");
+ }
+ return Instr::MemoryCopy();
+ case 11:
+ if ($this->decodeByte() !== 0) {
+ throw new InvalidBinaryFormatException("memory fill");
+ }
+ return Instr::MemoryFill();
+ case 12:
+ $from = $this->decodeElemIdx();
+ $to = $this->decodeTableIdx();
+ return Instr::TableInit($to, $from);
+ case 13: return Instr::ElemDrop($this->decodeElemIdx());
+ case 14:
+ $to = $this->decodeTableIdx();
+ $from = $this->decodeTableIdx();
+ return Instr::TableCopy($to, $from);
+ case 15: return Instr::TableGrow($this->decodeTableIdx());
+ case 16: return Instr::TableSize($this->decodeTableIdx());
+ case 17: return Instr::TableFill($this->decodeTableIdx());
+ default:
+ throw new InvalidBinaryFormatException("instr");
+ }
+ // no break
+ default:
+ throw new InvalidBinaryFormatException("Unexpected opcode $op while decoding an instruction");
+ }
+ }
+
+ /**
+ * @return array{0: U32, 1: U32}
+ */
+ private function decodeMemArg(): array
+ {
+ $align = $this->decodeU32();
+ $offset = $this->decodeU32();
+ return [$offset, $align];
+ }
+
+ private function decodeBlockType(): BlockType
+ {
+ $b = $this->stream->peekByte();
+ if ($b === 0x40) {
+ $this->stream->seek(1);
+ return BlockType::ValType(null);
+ } elseif (in_array($b, [0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x70, 0x6F], true)) {
+ return BlockType::ValType($this->decodeValType());
+ } else {
+ $type = $this->decodeS33();
+ if ($type < 0) {
+ throw new InvalidBinaryFormatException("blocktype");
+ }
+ return BlockType::TypeIdx($type);
+ }
+ }
+
+ /**
+ * @param list<class-string<Instr>> $delimiters
+ * @return array{0: list<Instr>, 1: Instr}
+ */
+ private function decodeInstrsUntil(array $delimiters): array
+ {
+ $result = [];
+ while (true) {
+ $instr = $this->decodeInstr();
+ if (in_array(get_class($instr), $delimiters, true)) {
+ return [$result, $instr];
+ }
+ $result[] = $instr;
+ }
+ }
+
+ /**
+ * @template T
+ * @param callable(): T $decoder
+ * @return list<T>
+ */
+ private function decodeVec(callable $decoder): array
+ {
+ $count = $this->decodeU32();
+ $result = [];
+ for ($i = 0; $i < $count; $i++) {
+ $result[] = $decoder();
+ }
+ return $result;
+ }
+
+ /**
+ * @phpstan-impure
+ */
+ private function decodeByte(): int
+ {
+ return $this->stream->readByte();
+ }
+
+ private function decodeU32(): int
+ {
+ return $this->decodeUnsignedLeb128(32);
+ }
+
+ private function decodeUnsignedLeb128(int $maxBits): int
+ {
+ $result = 0;
+ for ($shiftBits = 0; $shiftBits < $maxBits; $shiftBits += 7) {
+ $b = $this->decodeByte();
+ $leftBitsCount = $maxBits - $shiftBits;
+ if ($leftBitsCount < 7) {
+ if ((($b & 0b01111111) >> $leftBitsCount) !== 0) {
+ throw new InvalidBinaryFormatException("unsigned leb128 ($maxBits): too large");
+ }
+ }
+ $result |= ($b & 0b01111111) << $shiftBits;
+ if (($b & 0b10000000) === 0) {
+ return $result;
+ }
+ }
+ throw new InvalidBinaryFormatException("unsigned leb128 ($maxBits): too large");
+ }
+
+ private function decodeSignedLeb128(int $maxBits): int
+ {
+ $result = 0;
+ for ($shiftBits = 0; $shiftBits < $maxBits; $shiftBits += 7) {
+ $b = $this->decodeByte();
+ $leftBitsCount = $maxBits - $shiftBits;
+ if ($leftBitsCount < 7) {
+ if (($b & (1 << ($leftBitsCount - 1))) === 0) {
+ if ((($b & 0b01111111) >> $leftBitsCount) !== 0) {
+ throw new InvalidBinaryFormatException("signed leb128 ($maxBits): too large");
+ }
+ } else {
+ if ((($b & 0b01111111) >> $leftBitsCount) + 1 !== (1 << (7 - $leftBitsCount))) {
+ throw new InvalidBinaryFormatException("signed leb128 ($maxBits): too large");
+ }
+ }
+ }
+ $result |= ($b & 0b01111111) << $shiftBits;
+ if (($b & 0b10000000) === 0) {
+ if (($b & 0b01000000) === 0) {
+ return $result;
+ } else {
+ return $result | (~0 << ($shiftBits + 7));
+ }
+ }
+ }
+ throw new InvalidBinaryFormatException("signed leb128 ($maxBits): too large");
+ }
+
+ /**
+ * @return S32
+ */
+ private function decodeS32(): int
+ {
+ return $this->decodeSignedLeb128(32);
+ }
+
+ /**
+ * @return S33
+ */
+ private function decodeS33(): int
+ {
+ return $this->decodeSignedLeb128(33);
+ }
+
+ /**
+ * @return S64
+ */
+ private function decodeS64(): int
+ {
+ return $this->decodeSignedLeb128(64);
+ }
+
+ /**
+ * @return F32
+ */
+ private function decodeF32(): float
+ {
+ $buf = $this->stream->read(4);
+ $result = unpack('g', $buf);
+ if ($result === false) {
+ throw new InvalidBinaryFormatException("f32");
+ }
+ assert(isset($result[1]) && is_float($result[1]));
+ return $result[1];
+ }
+
+ /**
+ * @return F64
+ */
+ private function decodeF64(): float
+ {
+ $buf = $this->stream->read(8);
+ $result = unpack('e', $buf);
+ if ($result === false) {
+ throw new InvalidBinaryFormatException("f64");
+ }
+ assert(isset($result[1]) && is_float($result[1]));
+ return $result[1];
+ }
+
+ /**
+ * @return Name
+ */
+ private function decodeName(): string
+ {
+ $bytes = $this->decodeVec($this->decodeByte(...));
+ $name = $this->implodeUtf8BytesToString($bytes);
+ if ($name === null) {
+ throw new InvalidBinaryFormatException("name");
+ }
+ return $name;
+ }
+
+ /**
+ * @param list<int> $bytes
+ */
+ private function implodeUtf8BytesToString(array $bytes): ?string
+ {
+ $s = '';
+ $count = count($bytes);
+ for ($i = 0; $i < $count; $i++) {
+ if (($bytes[$i] & 0x80) === 0) {
+ $code = $bytes[$i];
+ } elseif (($bytes[$i] & 0xE0) === 0xC0) {
+ if ($count <= $i + 1) {
+ return null;
+ }
+ $code = (($bytes[$i] & 0x1F) << 6) | ($bytes[$i + 1] & 0x3F);
+ $i++;
+ } elseif (($bytes[$i] & 0xF0) === 0xE0) {
+ if ($count <= $i + 2) {
+ return null;
+ }
+ $code = (($bytes[$i] & 0x0F) << 12) | (($bytes[$i + 1] & 0x3F) << 6) | ($bytes[$i + 2] & 0x3F);
+ $i += 2;
+ } elseif (($bytes[$i] & 0xF8) === 0xF0) {
+ if ($count <= $i + 3) {
+ return null;
+ }
+ $code = (($bytes[$i] & 0x07) << 18) | (($bytes[$i + 1] & 0x3F) << 12) | (($bytes[$i + 2] & 0x3F) << 6) | ($bytes[$i + 3] & 0x3F);
+ $i += 3;
+ } else {
+ return null;
+ }
+ $s .= mb_chr($code, 'UTF-8');
+ }
+ return $s;
+ }
+
+ /**
+ * @return 0|positive-int
+ */
+ private function countDataIndicesUsedInCode(Code $code): int
+ {
+ $result = array_reduce(
+ $code->body,
+ fn ($acc, $instr) => $acc + match ($instr::class) {
+ Instrs\Memory\DataDrop::class => 1,
+ Instrs\Memory\MemoryInit::class => 1,
+ default => 0,
+ },
+ 0,
+ );
+ assert(is_int($result), '$result is guaranteed not to exceed the maximum value of an integer because the number of instructions in $code is limited');
+ assert(0 <= $result, '$result is guaranteed to be non-negative because it is the sum of non-negative integers');
+ return $result;
+ }
+}
diff --git a/src/WebAssembly/BinaryFormat/Internal/Code.php b/src/WebAssembly/BinaryFormat/Internal/Code.php
new file mode 100644
index 0000000..80010e2
--- /dev/null
+++ b/src/WebAssembly/BinaryFormat/Internal/Code.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+/**
+ * @internal
+ */
+final readonly class Code
+{
+ /**
+ * @param list<Locals> $compressedLocals
+ * @param list<Instr> $body
+ */
+ public function __construct(
+ public array $compressedLocals,
+ public array $body,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/BinaryFormat/Internal/Locals.php b/src/WebAssembly/BinaryFormat/Internal/Locals.php
new file mode 100644
index 0000000..7cc0029
--- /dev/null
+++ b/src/WebAssembly/BinaryFormat/Internal/Locals.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+/**
+ * @internal
+ */
+final readonly class Locals
+{
+ /**
+ * @param U32 $count
+ */
+ public function __construct(
+ public int $count,
+ public ValType $type,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/BinaryFormat/Internal/SectionId.php b/src/WebAssembly/BinaryFormat/Internal/SectionId.php
new file mode 100644
index 0000000..e085c37
--- /dev/null
+++ b/src/WebAssembly/BinaryFormat/Internal/SectionId.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal;
+
+/**
+ * @internal
+ */
+enum SectionId: int
+{
+ case Custom = 0;
+ case Type = 1;
+ case Import = 2;
+ case Func = 3;
+ case Table = 4;
+ case Mem = 5;
+ case Global = 6;
+ case Export = 7;
+ case Start = 8;
+ case Elem = 9;
+ case Code = 10;
+ case Data = 11;
+ case DataCount = 12;
+}
diff --git a/src/WebAssembly/BinaryFormat/InvalidBinaryFormatException.php b/src/WebAssembly/BinaryFormat/InvalidBinaryFormatException.php
new file mode 100644
index 0000000..b6b670c
--- /dev/null
+++ b/src/WebAssembly/BinaryFormat/InvalidBinaryFormatException.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\BinaryFormat;
+
+use RuntimeException;
+
+class InvalidBinaryFormatException extends RuntimeException
+{
+}
diff --git a/src/WebAssembly/Debug/Debug.php b/src/WebAssembly/Debug/Debug.php
new file mode 100644
index 0000000..738dff2
--- /dev/null
+++ b/src/WebAssembly/Debug/Debug.php
@@ -0,0 +1,112 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Debug;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDescs;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Module;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\Limits;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\Mut;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\NumType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ResultType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValTypes;
+
+final readonly class Debug
+{
+ public static function printImports(Module $module): void
+ {
+ foreach ($module->imports as $import) {
+ $mod = $import->module;
+ $name = $import->name;
+ $desc = $import->desc;
+ $type = match ($desc::class) {
+ ImportDescs\Func::class => 'func',
+ ImportDescs\Table::class => 'table',
+ ImportDescs\Mem::class => 'mem',
+ ImportDescs\Global_::class => 'global',
+ default => 'unknown',
+ };
+ $extraInfo = match ($desc::class) {
+ ImportDescs\Func::class => self::typeIdxToString($desc->func, $module),
+ ImportDescs\Table::class => self::tableTypeToString($desc->table),
+ ImportDescs\Mem::class => self::memTypeToString($desc->mem),
+ ImportDescs\Global_::class => self::globalTypeToString($desc->global),
+ default => 'unknown',
+ };
+ echo "$mod::$name: $type $extraInfo\n";
+ }
+ }
+
+ private static function typeIdxToString(int $idx, Module $module): string
+ {
+ $type = $module->types[$idx];
+ return self::funcTypeToString($type);
+ }
+
+ private static function tableTypeToString(TableType $type): string
+ {
+ return self::valTypeToString(ValType::RefType($type->refType)) . ' ' . self::limitsToString($type->limits);
+ }
+
+ private static function memTypeToString(MemType $type): string
+ {
+ return self::limitsToString($type->limits);
+ }
+
+ private static function globalTypeToString(GlobalType $type): string
+ {
+ return self::mutToString($type->mut) . ' ' . self::valTypeToString($type->valType);
+ }
+
+ private static function funcTypeToString(FuncType $type): string
+ {
+ $params = self::resultTypeToString($type->params);
+ $results = self::resultTypeToString($type->results);
+ return "($params) -> ($results)";
+ }
+
+ private static function valTypeToString(ValType $type): string
+ {
+ return match ($type::class) {
+ ValTypes\NumType::class => match ($type->inner) {
+ NumType::I32 => 'i32',
+ NumType::I64 => 'i64',
+ NumType::F32 => 'f32',
+ NumType::F64 => 'f64',
+ },
+ ValTypes\VecType::class => 'v128',
+ ValTypes\RefType::class => match ($type->inner) {
+ RefType::FuncRef => 'funcref',
+ RefType::ExternRef => 'externref',
+ },
+ default => 'unknown',
+ };
+ }
+
+ private static function limitsToString(Limits $limit): string
+ {
+ $min = $limit->min;
+ $max = $limit->max;
+ return $max === null ? "[$min, inf)" : "[$min, $max]";
+ }
+
+ private static function mutToString(Mut $mut): string
+ {
+ return match ($mut) {
+ Mut::Const => 'const',
+ Mut::Var => 'var',
+ };
+ }
+
+ private static function resultTypeToString(ResultType $type): string
+ {
+ return implode(', ', array_map(self::valTypeToString(...), $type->types));
+ }
+}
diff --git a/src/WebAssembly/Execution/Allocator.php b/src/WebAssembly/Execution/Allocator.php
new file mode 100644
index 0000000..67eb467
--- /dev/null
+++ b/src/WebAssembly/Execution/Allocator.php
@@ -0,0 +1,165 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDescs;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Func;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Module;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+use RuntimeException;
+use function count;
+
+final readonly class Allocator
+{
+ public function __construct(
+ private readonly Store $store,
+ ) {
+ }
+
+ /**
+ * @param list<ExternVal> $externVals
+ */
+ public function allocPreInitModule(
+ Module $module,
+ array $externVals,
+ ): ModuleInst {
+ $m = new ModuleInst($module->types, [], [], [], [], [], [], []);
+
+ foreach ($externVals as $externVal) {
+ match ($externVal::class) {
+ ExternVals\Func::class => $m->funcAddrs[] = $externVal->addr,
+ ExternVals\Global_::class => $m->globalAddrs[] = $externVal->addr,
+ default => null,
+ };
+ }
+ foreach ($module->funcs as $func) {
+ $m->funcAddrs[] = $this->allocFunc($func, $m);
+ }
+
+ return $m;
+ }
+
+ /**
+ * @param list<ExternVal> $externVals
+ * @param list<int|float|Ref> $vals
+ * @param list<list<Ref>> $refsList
+ * @param list<int> $preAllocatedFuncs
+ */
+ public function allocModule(
+ Module $module,
+ array $externVals,
+ array $vals,
+ array $refsList,
+ array $preAllocatedFuncs,
+ ): ModuleInst {
+ $m = new ModuleInst($module->types, [], [], [], [], [], [], []);
+
+ foreach ($externVals as $externVal) {
+ match ($externVal::class) {
+ ExternVals\Func::class => null, // handled below.
+ ExternVals\Table::class => $m->tableAddrs[] = $externVal->addr,
+ ExternVals\Mem::class => $m->memAddrs[] = $externVal->addr,
+ ExternVals\Global_::class => $m->globalAddrs[] = $externVal->addr,
+ default => throw new RuntimeException("unreachable"),
+ };
+ }
+
+ foreach ($preAllocatedFuncs as $funcAddr) {
+ $m->funcAddrs[] = $funcAddr;
+ $funcInst = $this->store->funcs[$funcAddr];
+ if ($funcInst instanceof FuncInsts\Wasm) {
+ // @phpstan-ignore-next-line
+ $this->store->funcs[$funcAddr] = FuncInst::Wasm(
+ $funcInst->type,
+ $m,
+ $funcInst->code,
+ );
+ }
+ }
+ foreach ($module->tables as $table) {
+ $m->tableAddrs[] = $this->allocTable($table->type, Ref::RefNull($table->type->refType));
+ }
+ foreach ($module->mems as $mem) {
+ $m->memAddrs[] = $this->allocMem($mem->type);
+ }
+ foreach ($module->datas as $data) {
+ $m->dataAddrs[] = $this->allocData($data->init);
+ }
+
+ foreach ($module->globals as $i => $global) {
+ $m->globalAddrs[] = $this->allocGlobal($global->type, $vals[$i]);
+ }
+ foreach ($module->elems as $i => $elem) {
+ $m->elemAddrs[] = $this->allocElem($elem->type, $refsList[$i]);
+ }
+
+ foreach ($module->exports as $export) {
+ $value = match ($export->desc::class) {
+ ExportDescs\Func::class => ExternVal::Func($m->funcAddrs[$export->desc->func]),
+ ExportDescs\Table::class => ExternVal::Table($m->tableAddrs[$export->desc->table]),
+ ExportDescs\Mem::class => ExternVal::Mem($m->memAddrs[$export->desc->mem]),
+ ExportDescs\Global_::class => ExternVal::Global_($m->globalAddrs[$export->desc->global]),
+ default => throw new RuntimeException("unreachable"),
+ };
+ $m->exports[] = new ExportInst($export->name, $value);
+ }
+
+ return $m;
+ }
+
+ private function allocFunc(Func $func, ModuleInst $moduleInst): int
+ {
+ $funcType = $moduleInst->types[$func->type];
+ $funcInst = FuncInst::Wasm($funcType, $moduleInst, $func);
+ $this->store->funcs[] = $funcInst;
+ return count($this->store->funcs) - 1;
+ }
+
+ private function allocTable(TableType $tableType, Ref $ref): int
+ {
+ $minSize = $tableType->limits->min;
+ $elem = array_fill(0, $minSize, $ref);
+ $tableInst = new TableInst($tableType, $elem);
+ $this->store->tables[] = $tableInst;
+ return count($this->store->tables) - 1;
+ }
+
+ private function allocMem(MemType $memType): int
+ {
+ $memInst = new MemInst($memType);
+ $this->store->mems[] = $memInst;
+ return count($this->store->mems) - 1;
+ }
+
+ private function allocGlobal(GlobalType $globalType, int|float|Ref $val): int
+ {
+ $globalInst = new GlobalInst($globalType, $val);
+ $this->store->globals[] = $globalInst;
+ return count($this->store->globals) - 1;
+ }
+
+ /**
+ * @param list<Ref> $elem
+ */
+ private function allocElem(RefType $refType, array $elem): int
+ {
+ $elemInst = new ElemInst($refType, $elem);
+ $this->store->elems[] = $elemInst;
+ return count($this->store->elems) - 1;
+ }
+
+ /**
+ * @param list<Byte> $data
+ */
+ private function allocData(array $data): int
+ {
+ $dataInst = new DataInst($data);
+ $this->store->datas[] = $dataInst;
+ return count($this->store->datas) - 1;
+ }
+}
diff --git a/src/WebAssembly/Execution/DataInst.php b/src/WebAssembly/Execution/DataInst.php
new file mode 100644
index 0000000..f6918c6
--- /dev/null
+++ b/src/WebAssembly/Execution/DataInst.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+final readonly class DataInst
+{
+ /**
+ * @param list<Byte> $data
+ */
+ public function __construct(
+ public array $data,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/ElemInst.php b/src/WebAssembly/Execution/ElemInst.php
new file mode 100644
index 0000000..422cd62
--- /dev/null
+++ b/src/WebAssembly/Execution/ElemInst.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+
+final readonly class ElemInst
+{
+ /**
+ * @param list<Ref> $elem
+ */
+ public function __construct(
+ public RefType $type,
+ public array $elem,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/ExportInst.php b/src/WebAssembly/Execution/ExportInst.php
new file mode 100644
index 0000000..7fe04cd
--- /dev/null
+++ b/src/WebAssembly/Execution/ExportInst.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+final readonly class ExportInst
+{
+ /**
+ * @param Name $name
+ */
+ public function __construct(
+ public string $name,
+ public ExternVal $value,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Extern.php b/src/WebAssembly/Execution/Extern.php
new file mode 100644
index 0000000..dacfad1
--- /dev/null
+++ b/src/WebAssembly/Execution/Extern.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+abstract readonly class Extern
+{
+ final public static function Func(FuncInst $func): Externs\Func
+ {
+ return new Externs\Func($func);
+ }
+
+ final public static function Table(TableInst $table): Externs\Table
+ {
+ return new Externs\Table($table);
+ }
+
+ final public static function Mem(MemInst $mem): Externs\Mem
+ {
+ return new Externs\Mem($mem);
+ }
+
+ final public static function Global_(GlobalInst $global): Externs\Global_
+ {
+ return new Externs\Global_($global);
+ }
+}
diff --git a/src/WebAssembly/Execution/ExternVal.php b/src/WebAssembly/Execution/ExternVal.php
new file mode 100644
index 0000000..116ce53
--- /dev/null
+++ b/src/WebAssembly/Execution/ExternVal.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+abstract readonly class ExternVal
+{
+ final public static function Func(int $addr): ExternVals\Func
+ {
+ return new ExternVals\Func($addr);
+ }
+
+ final public static function Table(int $addr): ExternVals\Table
+ {
+ return new ExternVals\Table($addr);
+ }
+
+ final public static function Mem(int $addr): ExternVals\Mem
+ {
+ return new ExternVals\Mem($addr);
+ }
+
+ final public static function Global_(int $addr): ExternVals\Global_
+ {
+ return new ExternVals\Global_($addr);
+ }
+}
diff --git a/src/WebAssembly/Execution/ExternVals/Func.php b/src/WebAssembly/Execution/ExternVals/Func.php
new file mode 100644
index 0000000..cc3c82a
--- /dev/null
+++ b/src/WebAssembly/Execution/ExternVals/Func.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVals;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVal;
+
+final readonly class Func extends ExternVal
+{
+ protected function __construct(
+ public int $addr,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/ExternVals/Global_.php b/src/WebAssembly/Execution/ExternVals/Global_.php
new file mode 100644
index 0000000..cc28f26
--- /dev/null
+++ b/src/WebAssembly/Execution/ExternVals/Global_.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVals;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVal;
+
+final readonly class Global_ extends ExternVal
+{
+ protected function __construct(
+ public int $addr,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/ExternVals/Mem.php b/src/WebAssembly/Execution/ExternVals/Mem.php
new file mode 100644
index 0000000..1b76d3f
--- /dev/null
+++ b/src/WebAssembly/Execution/ExternVals/Mem.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVals;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVal;
+
+final readonly class Mem extends ExternVal
+{
+ protected function __construct(
+ public int $addr,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/ExternVals/Table.php b/src/WebAssembly/Execution/ExternVals/Table.php
new file mode 100644
index 0000000..787adb9
--- /dev/null
+++ b/src/WebAssembly/Execution/ExternVals/Table.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVals;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\ExternVal;
+
+final readonly class Table extends ExternVal
+{
+ protected function __construct(
+ public int $addr,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Externs/Func.php b/src/WebAssembly/Execution/Externs/Func.php
new file mode 100644
index 0000000..3bfc116
--- /dev/null
+++ b/src/WebAssembly/Execution/Externs/Func.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Externs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Extern;
+use Nsfisis\Waddiwasi\WebAssembly\Execution\FuncInst;
+
+final readonly class Func extends Extern
+{
+ protected function __construct(
+ public FuncInst $func,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Externs/Global_.php b/src/WebAssembly/Execution/Externs/Global_.php
new file mode 100644
index 0000000..562e934
--- /dev/null
+++ b/src/WebAssembly/Execution/Externs/Global_.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Externs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Extern;
+use Nsfisis\Waddiwasi\WebAssembly\Execution\GlobalInst;
+
+final readonly class Global_ extends Extern
+{
+ protected function __construct(
+ public GlobalInst $global,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Externs/Mem.php b/src/WebAssembly/Execution/Externs/Mem.php
new file mode 100644
index 0000000..8924e00
--- /dev/null
+++ b/src/WebAssembly/Execution/Externs/Mem.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Externs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Extern;
+use Nsfisis\Waddiwasi\WebAssembly\Execution\MemInst;
+
+final readonly class Mem extends Extern
+{
+ protected function __construct(
+ public MemInst $mem,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Externs/Table.php b/src/WebAssembly/Execution/Externs/Table.php
new file mode 100644
index 0000000..65a833f
--- /dev/null
+++ b/src/WebAssembly/Execution/Externs/Table.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Externs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Extern;
+use Nsfisis\Waddiwasi\WebAssembly\Execution\TableInst;
+
+final readonly class Table extends Extern
+{
+ protected function __construct(
+ public TableInst $table,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Frame.php b/src/WebAssembly/Execution/Frame.php
new file mode 100644
index 0000000..331b43a
--- /dev/null
+++ b/src/WebAssembly/Execution/Frame.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+final class Frame
+{
+ /**
+ * @param int<0, max> $arity
+ * @param list<int|float|Ref> $locals
+ */
+ public function __construct(
+ public readonly int $arity,
+ public array $locals,
+ public readonly ModuleInst $module,
+ public string $debugName,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/FuncInst.php b/src/WebAssembly/Execution/FuncInst.php
new file mode 100644
index 0000000..dda32cf
--- /dev/null
+++ b/src/WebAssembly/Execution/FuncInst.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Func;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+
+abstract readonly class FuncInst
+{
+ final public static function Wasm(FuncType $type, ModuleInst $module, Func $code): FuncInsts\Wasm
+ {
+ return new FuncInsts\Wasm($type, $module, $code);
+ }
+
+ final public static function Host(FuncType $type, callable $callback): FuncInsts\Host
+ {
+ return new FuncInsts\Host($type, $callback);
+ }
+}
diff --git a/src/WebAssembly/Execution/FuncInsts/Host.php b/src/WebAssembly/Execution/FuncInsts/Host.php
new file mode 100644
index 0000000..6a66325
--- /dev/null
+++ b/src/WebAssembly/Execution/FuncInsts/Host.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\FuncInsts;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\FuncInst;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+
+final readonly class Host extends FuncInst
+{
+ /**
+ * @param callable $callback
+ */
+ public function __construct(
+ public FuncType $type,
+ public mixed $callback,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/FuncInsts/Wasm.php b/src/WebAssembly/Execution/FuncInsts/Wasm.php
new file mode 100644
index 0000000..d0780ab
--- /dev/null
+++ b/src/WebAssembly/Execution/FuncInsts/Wasm.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\FuncInsts;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\FuncInst;
+use Nsfisis\Waddiwasi\WebAssembly\Execution\ModuleInst;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Func;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+
+final readonly class Wasm extends FuncInst
+{
+ public function __construct(
+ public FuncType $type,
+ public ModuleInst $module,
+ public Func $code,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/GlobalInst.php b/src/WebAssembly/Execution/GlobalInst.php
new file mode 100644
index 0000000..75f764f
--- /dev/null
+++ b/src/WebAssembly/Execution/GlobalInst.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+
+final class GlobalInst
+{
+ public function __construct(
+ public readonly GlobalType $type,
+ public int|float|Ref $value,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Label.php b/src/WebAssembly/Execution/Label.php
new file mode 100644
index 0000000..85e90a7
--- /dev/null
+++ b/src/WebAssembly/Execution/Label.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+final readonly class Label
+{
+ /**
+ * @param int<0, max> $arity
+ */
+ public function __construct(
+ public int $arity,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/MemInst.php b/src/WebAssembly/Execution/MemInst.php
new file mode 100644
index 0000000..802f334
--- /dev/null
+++ b/src/WebAssembly/Execution/MemInst.php
@@ -0,0 +1,662 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use FFI;
+use FFI\CData;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\Limits;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+use function assert;
+use function count;
+
+final class MemInst
+{
+ private const PAGE_SIZE = 64 * 1024;
+
+ private const MAX_PAGES = 0x10000;
+
+ private CData $dataU8;
+ private CData $dataS8;
+
+ private CData $dataU16_0;
+ private CData $dataU16_1;
+ private CData $dataS16_0;
+ private CData $dataS16_1;
+
+ private CData $dataU32_0;
+ private CData $dataU32_1;
+ private CData $dataU32_2;
+ private CData $dataU32_3;
+ private CData $dataS32_0;
+ private CData $dataS32_1;
+ private CData $dataS32_2;
+ private CData $dataS32_3;
+
+ private CData $dataS64_0;
+ private CData $dataS64_1;
+ private CData $dataS64_2;
+ private CData $dataS64_3;
+ private CData $dataS64_4;
+ private CData $dataS64_5;
+ private CData $dataS64_6;
+ private CData $dataS64_7;
+
+ private CData $dataF32_0;
+ private CData $dataF32_1;
+ private CData $dataF32_2;
+ private CData $dataF32_3;
+
+ private CData $dataF64_0;
+ private CData $dataF64_1;
+ private CData $dataF64_2;
+ private CData $dataF64_3;
+ private CData $dataF64_4;
+ private CData $dataF64_5;
+ private CData $dataF64_6;
+ private CData $dataF64_7;
+
+ private int $dataSize;
+
+ private readonly FFI $ffi;
+
+ public function __construct(
+ public MemType $type,
+ ) {
+ $this->ffi = FFI::cdef();
+ $this->initInternalMemory($type->limits->min);
+ }
+
+ public function size(): int
+ {
+ return $this->dataSize;
+ }
+
+ public function nPages(): int
+ {
+ return $this->size() / self::PAGE_SIZE;
+ }
+
+ /**
+ * @return int
+ * Returns the original size of the memory in pages or -1 if failed.
+ */
+ public function grow(int $n): int
+ {
+ $sz = $this->nPages();
+ $len = $sz + $n;
+ if (self::MAX_PAGES < $len) {
+ return -1;
+ }
+
+ $limits = $this->type->limits;
+ $limits_ = new Limits($len, $limits->max);
+ if (!$limits_->isValid()) {
+ return -1;
+ }
+
+ $originalSize = $this->size();
+ // @phpstan-ignore-next-line
+ $originalData = $this->ffi->new("uint8_t[$originalSize+8]");
+ assert($originalData !== null);
+ FFI::memcpy($originalData, $this->dataU8, $originalSize);
+
+ $this->initInternalMemory($len);
+
+ FFI::memcpy($this->dataU8, $originalData, $originalSize);
+
+ return $sz;
+ }
+
+ private function initInternalMemory(int $n): void
+ {
+ $this->dataSize = $n * self::PAGE_SIZE;
+
+ // @phpstan-ignore-next-line
+ $this->dataU8 = $this->ffi->new("uint8_t[$this->dataSize+8]");
+ // @phpstan-ignore-next-line
+ $this->dataS8 = $this->ffi->cast("int8_t[$this->dataSize]", $this->dataU8);
+
+ // @phpstan-ignore-next-line
+ $castInt = fn ($n, $signed, $offset) => $this->ffi->cast(
+ sprintf("%sint%d_t[$this->dataSize/%d]", $signed ? "" : "u", $n, $n / 8),
+ // @phpstan-ignore-next-line
+ $this->ffi->cast("uint8_t[$this->dataSize+8]", $this->dataU8 + $offset),
+ );
+
+ // @phpstan-ignore-next-line
+ $castFloat = fn ($n, $offset) => $this->ffi->cast(
+ sprintf("%s[$this->dataSize/%d]", $n === 32 ? "float" : "double", $n / 8),
+ // @phpstan-ignore-next-line
+ $this->ffi->cast("uint8_t[$this->dataSize+8]", $this->dataU8 + $offset),
+ );
+
+ // @phpstan-ignore-next-line
+ $this->dataU16_0 = $castInt(16, false, 0);
+ // @phpstan-ignore-next-line
+ $this->dataU16_1 = $castInt(16, false, 1);
+ // @phpstan-ignore-next-line
+ $this->dataS16_0 = $castInt(16, true, 0);
+ // @phpstan-ignore-next-line
+ $this->dataS16_1 = $castInt(16, true, 1);
+
+ // @phpstan-ignore-next-line
+ $this->dataU32_0 = $castInt(32, false, 0);
+ // @phpstan-ignore-next-line
+ $this->dataU32_1 = $castInt(32, false, 1);
+ // @phpstan-ignore-next-line
+ $this->dataU32_2 = $castInt(32, false, 2);
+ // @phpstan-ignore-next-line
+ $this->dataU32_3 = $castInt(32, false, 3);
+ // @phpstan-ignore-next-line
+ $this->dataS32_0 = $castInt(32, true, 0);
+ // @phpstan-ignore-next-line
+ $this->dataS32_1 = $castInt(32, true, 1);
+ // @phpstan-ignore-next-line
+ $this->dataS32_2 = $castInt(32, true, 2);
+ // @phpstan-ignore-next-line
+ $this->dataS32_3 = $castInt(32, true, 3);
+
+ // @phpstan-ignore-next-line
+ $this->dataS64_0 = $castInt(64, true, 0);
+ // @phpstan-ignore-next-line
+ $this->dataS64_1 = $castInt(64, true, 1);
+ // @phpstan-ignore-next-line
+ $this->dataS64_2 = $castInt(64, true, 2);
+ // @phpstan-ignore-next-line
+ $this->dataS64_3 = $castInt(64, true, 3);
+ // @phpstan-ignore-next-line
+ $this->dataS64_4 = $castInt(64, true, 4);
+ // @phpstan-ignore-next-line
+ $this->dataS64_5 = $castInt(64, true, 5);
+ // @phpstan-ignore-next-line
+ $this->dataS64_6 = $castInt(64, true, 6);
+ // @phpstan-ignore-next-line
+ $this->dataS64_7 = $castInt(64, true, 7);
+
+ // @phpstan-ignore-next-line
+ $this->dataF32_0 = $castFloat(32, 0);
+ // @phpstan-ignore-next-line
+ $this->dataF32_1 = $castFloat(32, 1);
+ // @phpstan-ignore-next-line
+ $this->dataF32_2 = $castFloat(32, 2);
+ // @phpstan-ignore-next-line
+ $this->dataF32_3 = $castFloat(32, 3);
+
+ // @phpstan-ignore-next-line
+ $this->dataF64_0 = $castFloat(64, 0);
+ // @phpstan-ignore-next-line
+ $this->dataF64_1 = $castFloat(64, 1);
+ // @phpstan-ignore-next-line
+ $this->dataF64_2 = $castFloat(64, 2);
+ // @phpstan-ignore-next-line
+ $this->dataF64_3 = $castFloat(64, 3);
+ // @phpstan-ignore-next-line
+ $this->dataF64_4 = $castFloat(64, 4);
+ // @phpstan-ignore-next-line
+ $this->dataF64_5 = $castFloat(64, 5);
+ // @phpstan-ignore-next-line
+ $this->dataF64_6 = $castFloat(64, 6);
+ // @phpstan-ignore-next-line
+ $this->dataF64_7 = $castFloat(64, 7);
+
+ // @phpstan-ignore-next-line
+ FFI::memset($this->dataU8, 0, $this->dataSize);
+ }
+
+ /**
+ * @param list<int> $data
+ */
+ public function copyData(array $data, int $src, int $dst, int $len): void
+ {
+ assert(0 <= $len);
+ assert(0 <= $src);
+ assert(0 <= $dst);
+ assert($src + $len <= count($data));
+ assert($dst + $len <= $this->size());
+ for ($i = 0; $i < $len; $i++) {
+ $this->storeByte($dst + $i, $data[$src + $i]);
+ }
+ }
+
+ public function memcpy(int $dst, int $src, int $len): void
+ {
+ assert(0 <= $len);
+ assert(0 <= $src);
+ assert(0 <= $dst);
+ assert($src + $len <= $this->size());
+ assert($dst + $len <= $this->size());
+ if ($src === $dst || $len === 0) {
+ return;
+ }
+ for ($i = 0; $i < $len; $i++) {
+ $s = ($dst < $src) ? ($src + $i) : ($src + $len - 1 - $i);
+ $d = ($dst < $src) ? ($dst + $i) : ($dst + $len - 1 - $i);
+ $x = $this->loadByte($s);
+ assert($x !== null);
+ $this->storeByte($d, $x);
+ }
+ }
+
+ public function memset(int $dst, int $c, int $len): void
+ {
+ assert(0 <= $len);
+ assert(0 <= $dst);
+ assert($dst + $len <= $this->size());
+ for ($i = 0; $i < $len; $i++) {
+ $this->storeI32_s8($dst + $i, $c);
+ }
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_s8(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 1) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS8[$ptr];
+ assert(-0x80 <= $c && $c <= 0x7F, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_u8(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 1) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataU8[$ptr];
+ assert(0 <= $c && $c <= 0xFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_s16(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 2) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS16($ptr)[$ptr >> 1];
+ assert(-0x8000 <= $c && $c <= 0x7FFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_u16(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 2) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataU16($ptr)[$ptr >> 1];
+ assert(0 <= $c && $c <= 0xFFFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S32
+ */
+ public function loadI32_s32(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 4) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS32($ptr)[$ptr >> 2];
+ assert(-0x80000000 <= $c && $c <= 0x7FFFFFFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s8(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 1) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS8[$ptr];
+ assert(-0x80 <= $c && $c <= 0x7F, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_u8(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 1) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataU8[$ptr];
+ assert(0 <= $c && $c <= 0xFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s16(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 2) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS16($ptr)[$ptr >> 1];
+ assert(-0x8000 <= $c && $c <= 0x7FFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_u16(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 2) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataU16($ptr)[$ptr >> 1];
+ assert(0 <= $c && $c <= 0xFFFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s32(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 4) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS32($ptr)[$ptr >> 2];
+ assert(-0x80000000 <= $c && $c <= 0x7FFFFFFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_u32(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 4) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataU32($ptr)[$ptr >> 2];
+ assert(0 <= $c && $c <= 0xFFFFFFFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?S64
+ */
+ public function loadI64_s64(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 8) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ $c = $this->dataS64($ptr)[$ptr >> 3];
+ assert(-0x8000000000000000 <= $c && $c <= 0x7FFFFFFFFFFFFFFF, "$c");
+ return $c;
+ }
+
+ /**
+ * @return ?F32
+ */
+ public function loadF32(int $ptr): ?float
+ {
+ if ($this->size() < $ptr + 4) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ return $this->dataF32($ptr)[$ptr >> 2];
+ }
+
+ /**
+ * @return ?F64
+ */
+ public function loadF64(int $ptr): ?float
+ {
+ if ($this->size() < $ptr + 8) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ return $this->dataF64($ptr)[$ptr >> 3];
+ }
+
+ /**
+ * @return ?int
+ */
+ public function loadByte(int $ptr): ?int
+ {
+ if ($this->size() < $ptr + 1) {
+ return null;
+ }
+ // @phpstan-ignore-next-line
+ return $this->dataU8[$ptr];
+ }
+
+ /**
+ * @return bool
+ */
+ public function storeByte(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 1) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataU8[$ptr] = $c;
+ return true;
+ }
+
+ /**
+ * @param S32 $c
+ * @return bool
+ */
+ public function storeI32_s8(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 1) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS8[$ptr] = $c;
+ return true;
+ }
+
+ /**
+ * @param S32 $c
+ * @return bool
+ */
+ public function storeI32_s16(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 2) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS16($ptr)[$ptr >> 1] = $c;
+ return true;
+ }
+
+ /**
+ * @param S32 $c
+ * @return bool
+ */
+ public function storeI32_s32(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 4) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS32($ptr)[$ptr >> 2] = $c;
+ return true;
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s8(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 1) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS8[$ptr] = $c;
+ return true;
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s16(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 2) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS16($ptr)[$ptr >> 1] = $c;
+ return true;
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s32(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 4) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS32($ptr)[$ptr >> 2] = $c;
+ return true;
+ }
+
+ /**
+ * @param S64 $c
+ * @return bool
+ */
+ public function storeI64_s64(int $ptr, int $c): bool
+ {
+ if ($this->size() < $ptr + 8) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataS64($ptr)[$ptr >> 3] = $c;
+ return true;
+ }
+
+ /**
+ * @param F32 $c
+ * @return bool
+ */
+ public function storeF32(int $ptr, float $c): bool
+ {
+ if ($this->size() < $ptr + 4) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataF32($ptr)[$ptr >> 2] = $c;
+ return true;
+ }
+
+ /**
+ * @param F64 $c
+ * @return bool
+ */
+ public function storeF64(int $ptr, float $c): bool
+ {
+ if ($this->size() < $ptr + 8) {
+ return false;
+ }
+ // @phpstan-ignore-next-line
+ $this->dataF64($ptr)[$ptr >> 3] = $c;
+ return true;
+ }
+
+ private function dataU16(int $ptr): CData
+ {
+ return ($ptr & 1) !== 0 ? $this->dataU16_1 : $this->dataU16_0;
+ }
+
+ private function dataS16(int $ptr): CData
+ {
+ return ($ptr & 1) !== 0 ? $this->dataS16_1 : $this->dataS16_0;
+ }
+
+ private function dataU32(int $ptr): CData
+ {
+ return match ($ptr & 3) {
+ 0 => $this->dataU32_0,
+ 1 => $this->dataU32_1,
+ 2 => $this->dataU32_2,
+ 3 => $this->dataU32_3,
+ };
+ }
+
+ private function dataS32(int $ptr): CData
+ {
+ return match ($ptr & 3) {
+ 0 => $this->dataS32_0,
+ 1 => $this->dataS32_1,
+ 2 => $this->dataS32_2,
+ 3 => $this->dataS32_3,
+ };
+ }
+
+ private function dataS64(int $ptr): CData
+ {
+ return match ($ptr & 7) {
+ 0 => $this->dataS64_0,
+ 1 => $this->dataS64_1,
+ 2 => $this->dataS64_2,
+ 3 => $this->dataS64_3,
+ 4 => $this->dataS64_4,
+ 5 => $this->dataS64_5,
+ 6 => $this->dataS64_6,
+ 7 => $this->dataS64_7,
+ };
+ }
+
+ private function dataF32(int $ptr): CData
+ {
+ return match ($ptr & 3) {
+ 0 => $this->dataF32_0,
+ 1 => $this->dataF32_1,
+ 2 => $this->dataF32_2,
+ 3 => $this->dataF32_3,
+ };
+ }
+
+ private function dataF64(int $ptr): CData
+ {
+ return match ($ptr & 7) {
+ 0 => $this->dataF64_0,
+ 1 => $this->dataF64_1,
+ 2 => $this->dataF64_2,
+ 3 => $this->dataF64_3,
+ 4 => $this->dataF64_4,
+ 5 => $this->dataF64_5,
+ 6 => $this->dataF64_6,
+ 7 => $this->dataF64_7,
+ };
+ }
+}
diff --git a/src/WebAssembly/Execution/ModuleInst.php b/src/WebAssembly/Execution/ModuleInst.php
new file mode 100644
index 0000000..37bbcfd
--- /dev/null
+++ b/src/WebAssembly/Execution/ModuleInst.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+
+final class ModuleInst
+{
+ /**
+ * @param list<FuncType> $types
+ * @param list<int> $funcAddrs
+ * @param list<int> $tableAddrs
+ * @param list<int> $memAddrs
+ * @param list<int> $globalAddrs
+ * @param list<int> $elemAddrs
+ * @param list<int> $dataAddrs
+ * @param list<ExportInst> $exports
+ */
+ public function __construct(
+ public array $types,
+ public array $funcAddrs,
+ public array $tableAddrs,
+ public array $memAddrs,
+ public array $globalAddrs,
+ public array $elemAddrs,
+ public array $dataAddrs,
+ public array $exports,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/NumericOps.php b/src/WebAssembly/Execution/NumericOps.php
new file mode 100644
index 0000000..895b8c2
--- /dev/null
+++ b/src/WebAssembly/Execution/NumericOps.php
@@ -0,0 +1,193 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use InvalidArgumentException;
+use function assert;
+use function bcadd;
+use function bccomp;
+use function bcmod;
+use function bcpow;
+use function bcsub;
+use function fdiv;
+use function is_nan;
+use function pack;
+use function unpack;
+
+final readonly class NumericOps
+{
+ private function __construct()
+ {
+ }
+
+ public static function reinterpretI32AsF32(int $x): float
+ {
+ return self::deserializeF32FromBytes(self::serializeI32ToBytes($x));
+ }
+
+ public static function reinterpretI64AsF32(int $x): float
+ {
+ return self::deserializeF32FromBytes(self::serializeI64ToBytes($x));
+ }
+
+ public static function reinterpretI32AsF64(int $x): float
+ {
+ return self::deserializeF64FromBytes(self::serializeI32ToBytes($x));
+ }
+
+ public static function reinterpretI64AsF64(int $x): float
+ {
+ return self::deserializeF64FromBytes(self::serializeI64ToBytes($x));
+ }
+
+ public static function reinterpretF32AsI32(float $x): int
+ {
+ return self::deserializeI32FromBytes(self::serializeF32ToBytes($x));
+ }
+
+ public static function reinterpretF64AsI32(float $x): int
+ {
+ return self::deserializeI32FromBytes(self::serializeF64ToBytes($x));
+ }
+
+ public static function reinterpretF32AsI64(float $x): int
+ {
+ return self::deserializeI64FromBytes(self::serializeF32ToBytes($x));
+ }
+
+ public static function reinterpretF64AsI64(float $x): int
+ {
+ return self::deserializeI64FromBytes(self::serializeF64ToBytes($x));
+ }
+
+ public static function truncateF64ToF32(float $x): float
+ {
+ return self::deserializeF32FromBytes(self::serializeF32ToBytes($x));
+ }
+
+ public static function serializeI32ToBytes(int $x): string
+ {
+ return pack('l', $x);
+ }
+
+ public static function deserializeI32FromBytes(string $s): int
+ {
+ $result = unpack('l', $s);
+ if ($result === false) {
+ throw new InvalidArgumentException("Failed to unpack i32: $s");
+ }
+ return $result[1];
+ }
+
+ public static function serializeI64ToBytes(int $x): string
+ {
+ return pack('q', $x);
+ }
+
+ public static function deserializeI64FromBytes(string $s): int
+ {
+ $result = unpack('q', $s);
+ if ($result === false) {
+ throw new InvalidArgumentException("Failed to unpack i64: $s");
+ }
+ return $result[1];
+ }
+
+ public static function serializeF32ToBytes(float $x): string
+ {
+ return pack('f', $x);
+ }
+
+ public static function deserializeF32FromBytes(string $s): float
+ {
+ $result = unpack('f', $s);
+ if ($result === false) {
+ throw new InvalidArgumentException("Failed to unpack f32: $s");
+ }
+ return $result[1];
+ }
+
+ public static function serializeF64ToBytes(float $x): string
+ {
+ return pack('d', $x);
+ }
+
+ public static function deserializeF64FromBytes(string $s): float
+ {
+ $result = unpack('d', $s);
+ if ($result === false) {
+ throw new InvalidArgumentException("Failed to unpack f64: $s");
+ }
+ return $result[1];
+ }
+
+ public static function convertS32ToU32(int $x): int
+ {
+ // assert(-0x80000000 <= $x && $x <= 0x7FFFFFFF, "convertS32ToU32: out of range $x");
+ if ($x < 0) {
+ $buf = pack('l', $x);
+ $result = unpack('L', $buf);
+ assert($result !== false);
+ assert(0x00000000 <= $result[1] && $result[1] <= 0xFFFFFFFF, "convertS32ToU32: out of range $result[1]");
+ return $result[1];
+ } else {
+ return $x;
+ }
+ }
+
+ public static function convertU32ToS32(int $x): int
+ {
+ assert(0x00000000 <= $x && $x <= 0xFFFFFFFF);
+ if (($x & 0x80000000) !== 0) {
+ $buf = pack('L', $x);
+ $result = unpack('l', $buf);
+ assert($result !== false);
+ assert(-0x80000000 <= $result[1] && $result[1] <= 0x7FFFFFFF, "convertU32ToS32: out of range $result[1]");
+ return $result[1];
+ } else {
+ return $x;
+ }
+ }
+
+ public static function convertS64ToBigUInt(int $x): string
+ {
+ if ($x < 0) {
+ return bcadd((string)$x, '18446744073709551616');
+ } else {
+ return (string)$x;
+ }
+ }
+
+ public static function bigIntToPhpInt(string $s): int
+ {
+ $result = bcmod($s, bcpow('2', '64'));
+ if ($result[0] === '-') {
+ // 2^63 <= -$result
+ if (bccomp(bcpow('2', '63'), bcsub('0', $result)) <= 0) {
+ $result = bcadd($result, bcpow('2', '64'));
+ }
+ } else {
+ // 2^63-1 < $result
+ if (bccomp(bcsub(bcpow('2', '63'), '1'), $result) < 0) {
+ $result = bcsub($result, bcpow('2', '64'));
+ }
+ }
+ return (int)$result;
+ }
+
+ public static function getFloatSign(float $p): int
+ {
+ if (is_nan($p)) {
+ $n = self::reinterpretF64AsI64($p);
+ // The MSB is the sign bit.
+ return (($n >> 63) & 1) === 1 ? -1 : 1;
+ } elseif ($p !== 0.0) {
+ return $p < 0.0 ? -1 : 1;
+ } else {
+ // Comparison with 0 does not work for -0.0.
+ return fdiv(1, $p) < 0.0 ? -1 : 1;
+ }
+ }
+}
diff --git a/src/WebAssembly/Execution/Ref.php b/src/WebAssembly/Execution/Ref.php
new file mode 100644
index 0000000..f7b6760
--- /dev/null
+++ b/src/WebAssembly/Execution/Ref.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+
+abstract readonly class Ref
+{
+ final public static function RefNull(RefType $type): Refs\RefNull
+ {
+ return new Refs\RefNull($type);
+ }
+
+ final public static function RefFunc(int $addr): Refs\RefFunc
+ {
+ return new Refs\RefFunc($addr);
+ }
+
+ final public static function RefExtern(int $addr): Refs\RefExtern
+ {
+ return new Refs\RefExtern($addr);
+ }
+}
diff --git a/src/WebAssembly/Execution/Refs/RefExtern.php b/src/WebAssembly/Execution/Refs/RefExtern.php
new file mode 100644
index 0000000..41f3acd
--- /dev/null
+++ b/src/WebAssembly/Execution/Refs/RefExtern.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Refs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Ref;
+
+final readonly class RefExtern extends Ref
+{
+ public function __construct(
+ public int $addr,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Refs/RefFunc.php b/src/WebAssembly/Execution/Refs/RefFunc.php
new file mode 100644
index 0000000..3eabf4b
--- /dev/null
+++ b/src/WebAssembly/Execution/Refs/RefFunc.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Refs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Ref;
+
+final readonly class RefFunc extends Ref
+{
+ public function __construct(
+ public int $addr,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Refs/RefNull.php b/src/WebAssembly/Execution/Refs/RefNull.php
new file mode 100644
index 0000000..438ed9e
--- /dev/null
+++ b/src/WebAssembly/Execution/Refs/RefNull.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Refs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Ref;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+
+final readonly class RefNull extends Ref
+{
+ public function __construct(
+ public RefType $type,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Result.php b/src/WebAssembly/Execution/Result.php
new file mode 100644
index 0000000..50e543c
--- /dev/null
+++ b/src/WebAssembly/Execution/Result.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+abstract readonly class Result
+{
+ /**
+ * @param list<int|float|Ref> $values
+ */
+ final public static function Values(array $values): Results\Values
+ {
+ return new Results\Values($values);
+ }
+
+ final public static function Trap(): Results\Trap
+ {
+ return new Results\Trap();
+ }
+}
diff --git a/src/WebAssembly/Execution/Results/Trap.php b/src/WebAssembly/Execution/Results/Trap.php
new file mode 100644
index 0000000..e0a9cfd
--- /dev/null
+++ b/src/WebAssembly/Execution/Results/Trap.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Results;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Result;
+
+final readonly class Trap extends Result
+{
+}
diff --git a/src/WebAssembly/Execution/Results/Values.php b/src/WebAssembly/Execution/Results/Values.php
new file mode 100644
index 0000000..9391a2c
--- /dev/null
+++ b/src/WebAssembly/Execution/Results/Values.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution\Results;
+
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Ref;
+use Nsfisis\Waddiwasi\WebAssembly\Execution\Result;
+
+final readonly class Values extends Result
+{
+ /**
+ * @param list<int|float|Ref> $values
+ */
+ protected function __construct(
+ public array $values,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/Runtime.php b/src/WebAssembly/Execution/Runtime.php
new file mode 100644
index 0000000..dbefea2
--- /dev/null
+++ b/src/WebAssembly/Execution/Runtime.php
@@ -0,0 +1,2668 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockTypes;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\DataModes;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemModes;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\Module;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\Limits;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\NumType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ResultType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValTypes;
+use RuntimeException;
+use function abs;
+use function array_map;
+use function array_merge;
+use function array_reverse;
+use function assert;
+use function ceil;
+use function count;
+use function fdiv;
+use function floor;
+use function intdiv;
+use function is_array;
+use function is_infinite;
+use function is_int;
+use function is_nan;
+use function max;
+use function min;
+use function pack;
+use function round;
+use function sqrt;
+use function unpack;
+use const PHP_INT_MIN;
+
+final class Runtime
+{
+ /**
+ * @var array<string, array{int, int}>
+ */
+ private array $instrMetrics = [];
+
+ private function __construct(
+ public readonly Store $store,
+ public readonly Stack $stack,
+ public readonly ModuleInst $module,
+ ) {
+ }
+
+ /**
+ * @param array<string, array<string, Extern>> $imports
+ */
+ public static function instantiate(
+ Store $store,
+ Module $module,
+ array $imports,
+ ): self {
+ $externVals = [];
+ foreach ($module->imports as $import) {
+ $extern = $imports[$import->module][$import->name] ?? null;
+ if ($extern === null) {
+ throw new RuntimeException("instantiate: import not found: {$import->module}::{$import->name}");
+ }
+ $externVals[] = $store->register($extern);
+ }
+ return self::doInstantiate($store, $module, $externVals);
+ }
+
+ /**
+ * @param list<ExternVal> $externVals
+ */
+ private static function doInstantiate(
+ Store $store,
+ Module $module,
+ array $externVals,
+ ): self {
+ $allocator = new Allocator($store);
+
+ $moduleInstInit = $allocator->allocPreInitModule($module, $externVals);
+
+ $stack = new Stack();
+ $frameInit = new Frame(0, [], $moduleInstInit, 'preinit');
+ $stack->pushFrame($frameInit);
+
+ $runtimeInit = new self($store, $stack, $moduleInstInit);
+
+ $vals = [];
+ foreach ($module->globals as $global) {
+ $vals[] = $runtimeInit->evalInstrsForInit($global->init);
+ assert($stack->top() === $frameInit);
+ }
+
+ $refsList = [];
+ foreach ($module->elems as $elem) {
+ $refs = [];
+ foreach ($elem->init as $expr) {
+ $result = $runtimeInit->evalInstrsForInit($expr);
+ assert($result instanceof Ref);
+ $refs[] = $result;
+ }
+ $refsList[] = $refs;
+ }
+
+ assert($stack->top() === $frameInit);
+ $stack->popFrame();
+
+ $moduleInst = $allocator->allocModule(
+ $module,
+ $externVals,
+ $vals,
+ $refsList,
+ $moduleInstInit->funcAddrs,
+ );
+
+ $runtime = new self($store, $stack, $moduleInst);
+
+ $frame = new Frame(0, [], $moduleInst, 'init');
+ $stack->pushFrame($frame);
+
+ foreach ($module->elems as $i => $elem) {
+ if ($elem->mode instanceof ElemModes\Active) {
+ $n = count($elem->init);
+ $instrs = $elem->mode->offset;
+ $instrs[] = Instr::I32Const(0);
+ $instrs[] = Instr::I32Const($n);
+ $instrs[] = Instr::TableInit($elem->mode->table, $i);
+ $instrs[] = Instr::ElemDrop($i);
+ $runtime->execInstrsForInit($instrs);
+ } elseif ($elem->mode instanceof ElemModes\Declarative) {
+ $runtime->execInstrsForInit([Instr::ElemDrop($i)]);
+ }
+ }
+ foreach ($module->datas as $i => $data) {
+ if ($data->mode instanceof DataModes\Active) {
+ assert($data->mode->memory === 0);
+ $n = count($data->init);
+ $instrs = $data->mode->offset;
+ $instrs[] = Instr::I32Const(0);
+ $instrs[] = Instr::I32Const($n);
+ $instrs[] = Instr::MemoryInit($i);
+ $instrs[] = Instr::DataDrop($i);
+ $runtime->execInstrsForInit($instrs);
+ }
+ }
+
+ if ($module->start !== null) {
+ $runtime->execInstrsForInit([Instr::Call($module->start->func)]);
+ }
+
+ assert($stack->top() === $frame);
+ $stack->popFrame();
+
+ return new self($store, $stack, $moduleInst);
+ }
+
+ public function getExport(string $name): ?ExternVal
+ {
+ foreach ($this->module->exports as $export) {
+ if ($name === $export->name) {
+ return $export->value;
+ }
+ }
+ return null;
+ }
+
+ public function getExportedTable(string $name): ?TableInst
+ {
+ $export = $this->getExport($name);
+ if ($export instanceof ExternVals\Table) {
+ return $this->store->tables[$export->addr];
+ }
+ return null;
+ }
+
+ public function getExportedMemory(string $name): ?MemInst
+ {
+ $export = $this->getExport($name);
+ if ($export instanceof ExternVals\Mem) {
+ return $this->store->mems[$export->addr];
+ }
+ return null;
+ }
+
+ /**
+ * @return array<string, array{int, int}>
+ */
+ public function getInstrMetrics(): array
+ {
+ asort($this->instrMetrics);
+ return $this->instrMetrics;
+ }
+
+ /**
+ * @param list<int|float|Ref> $vals
+ * @return list<int|float|Ref>
+ */
+ public function invoke(string $name, array $vals): array
+ {
+ try {
+ $export = $this->getExport($name);
+ assert($export instanceof ExternVals\Func);
+ $funcAddr = $export->addr;
+
+ $funcInst = $this->store->funcs[$funcAddr];
+ assert($funcInst instanceof FuncInsts\Wasm);
+ $paramTypes = $funcInst->type->params->types;
+ $resultTypes = $funcInst->type->results->types;
+ if (count($paramTypes) !== count($vals)) {
+ throw new RuntimeException("invoke($name) invalid function arity: expected " . count($paramTypes) . ", got " . count($vals));
+ }
+ $f = new Frame(0, [], new ModuleInst([], [], [], [], [], [], [], []), "export: $name");
+ $this->stack->pushFrame($f);
+ foreach ($vals as $val) {
+ $this->stack->pushValue($val);
+ }
+ $this->doInvokeFunc($funcAddr);
+ $results = $this->stack->popNValues(count($resultTypes));
+ $this->stack->popFrame();
+ return array_reverse($results);
+ } catch (RuntimeException $e) {
+ // @todo more reliable way to clear the stack
+ $this->stack->clear();
+ throw $e;
+ }
+ }
+
+ public function invokeByFuncAddr(int $funcAddr): void
+ {
+ $this->doInvokeFunc($funcAddr);
+ }
+
+ private function doInvokeFunc(int $funcAddr): void
+ {
+ $fn = $this->store->funcs[$funcAddr];
+ if ($fn instanceof FuncInsts\Wasm) {
+ $this->doInvokeWasmFunc($fn, $funcAddr);
+ } elseif ($fn instanceof FuncInsts\Host) {
+ $this->doInvokeHostFunc($fn);
+ } else {
+ throw new RuntimeException("doInvokeFunc: unreachable");
+ }
+ }
+
+ private function doInvokeWasmFunc(FuncInsts\Wasm $fn, int $funcAddr): void
+ {
+ $paramTypes = $fn->type->params->types;
+ $n = count($paramTypes);
+ $resultTypes = $fn->type->results->types;
+ $m = count($resultTypes);
+ $ts = $fn->code->locals;
+ $vals = $this->stack->popNValues($n);
+ $f = new Frame(
+ $m,
+ array_merge(
+ array_reverse($vals),
+ array_map(fn ($local) => self::defaultValueFromValType($local->type), $ts),
+ ),
+ $fn->module,
+ "wasm: $funcAddr",
+ );
+ $this->activateFrame($f);
+ $l = new Label($m);
+ $this->execInstrs($fn->code->body, $l, null);
+ $this->deactivateFrame($m);
+ }
+
+ private function activateFrame(Frame $f): void
+ {
+ $this->stack->pushFrame($f);
+ }
+
+ private function deactivateFrame(int $arity): void
+ {
+ $vals = $this->stack->popNValues($arity);
+ $this->stack->popEntriesToCurrentFrame();
+ for ($i = $arity - 1; 0 <= $i; $i--) {
+ $this->stack->pushValue($vals[$i]);
+ }
+ }
+
+ private function activateLabel(Label $l): void
+ {
+ $this->stack->pushLabel($l);
+ }
+
+ private function deactivateLabel(?int $arity): void
+ {
+ if ($arity === null) {
+ $vals = $this->stack->popValuesToLabel();
+ } else {
+ $vals = $this->stack->popNValues($arity);
+ $this->stack->popValuesToLabel();
+ }
+ for ($i = count($vals) - 1; 0 <= $i; $i--) {
+ $this->stack->pushValue($vals[$i]);
+ }
+ }
+
+ private function doInvokeHostFunc(FuncInsts\Host $fn): void
+ {
+ $paramTypes = $fn->type->params->types;
+ $n = count($paramTypes);
+ $resultTypes = $fn->type->results->types;
+ $m = count($resultTypes);
+
+ $params = array_reverse($this->stack->popNValues($n));
+ $results = ($fn->callback)($this, ...$params);
+ if ($results === null) {
+ assert($m === 0);
+ return;
+ }
+ if (!is_array($results)) {
+ $results = [$results];
+ }
+ assert($m === count($results));
+ foreach ($results as $result) {
+ $this->stack->pushValue($result);
+ }
+ }
+
+ /**
+ * @param list<Instr> $instrs
+ * @param ?list<int|float|Ref> $params
+ */
+ private function execInstrs(
+ array $instrs,
+ Label $l,
+ ?array $params,
+ ): ?int {
+ $this->activateLabel($l);
+ if ($params !== null) {
+ foreach ($params as $param) {
+ $this->stack->pushValue($param);
+ }
+ }
+
+ foreach ($instrs as $i => $instr) {
+ $result = $this->execInstr($instr);
+ if ($result !== null) {
+ return $result;
+ }
+ }
+
+ $this->deactivateLabel(null);
+ return null;
+ }
+
+ /**
+ * @param list<Instr> $instrs
+ */
+ private function execInstrsForInit(array $instrs): void
+ {
+ foreach ($instrs as $i) {
+ $this->execInstr($i);
+ }
+ }
+
+ /**
+ * @param list<Instr> $instrs
+ */
+ private function evalInstrsForInit(array $instrs): int|float|Ref
+ {
+ $this->execInstrsForInit($instrs);
+ $result = $this->stack->popValue();
+ return $result;
+ }
+
+ private function execInstr(Instr $instr): ?int
+ {
+ return match ($instr::class) {
+ Instrs\Numeric\F32Abs::class => $this->execInstrNumericF32Abs($instr),
+ Instrs\Numeric\F32Add::class => $this->execInstrNumericF32Add($instr),
+ Instrs\Numeric\F32Ceil::class => $this->execInstrNumericF32Ceil($instr),
+ Instrs\Numeric\F32Const::class => $this->execInstrNumericF32Const($instr),
+ Instrs\Numeric\F32ConvertI32S::class => $this->execInstrNumericF32ConvertI32S($instr),
+ Instrs\Numeric\F32ConvertI32U::class => $this->execInstrNumericF32ConvertI32U($instr),
+ Instrs\Numeric\F32ConvertI64S::class => $this->execInstrNumericF32ConvertI64S($instr),
+ Instrs\Numeric\F32ConvertI64U::class => $this->execInstrNumericF32ConvertI64U($instr),
+ Instrs\Numeric\F32CopySign::class => $this->execInstrNumericF32CopySign($instr),
+ Instrs\Numeric\F32DemoteF64::class => $this->execInstrNumericF32DemoteF64($instr),
+ Instrs\Numeric\F32Div::class => $this->execInstrNumericF32Div($instr),
+ Instrs\Numeric\F32Eq::class => $this->execInstrNumericF32Eq($instr),
+ Instrs\Numeric\F32Floor::class => $this->execInstrNumericF32Floor($instr),
+ Instrs\Numeric\F32Ge::class => $this->execInstrNumericF32Ge($instr),
+ Instrs\Numeric\F32Gt::class => $this->execInstrNumericF32Gt($instr),
+ Instrs\Numeric\F32Le::class => $this->execInstrNumericF32Le($instr),
+ Instrs\Numeric\F32Lt::class => $this->execInstrNumericF32Lt($instr),
+ Instrs\Numeric\F32Max::class => $this->execInstrNumericF32Max($instr),
+ Instrs\Numeric\F32Min::class => $this->execInstrNumericF32Min($instr),
+ Instrs\Numeric\F32Mul::class => $this->execInstrNumericF32Mul($instr),
+ Instrs\Numeric\F32Ne::class => $this->execInstrNumericF32Ne($instr),
+ Instrs\Numeric\F32Nearest::class => $this->execInstrNumericF32Nearest($instr),
+ Instrs\Numeric\F32Neg::class => $this->execInstrNumericF32Neg($instr),
+ Instrs\Numeric\F32ReinterpretI32::class => $this->execInstrNumericF32ReinterpretI32($instr),
+ Instrs\Numeric\F32ReinterpretI64::class => $this->execInstrNumericF32ReinterpretI64($instr),
+ Instrs\Numeric\F32Sqrt::class => $this->execInstrNumericF32Sqrt($instr),
+ Instrs\Numeric\F32Sub::class => $this->execInstrNumericF32Sub($instr),
+ Instrs\Numeric\F32Trunc::class => $this->execInstrNumericF32Trunc($instr),
+ Instrs\Numeric\F64Abs::class => $this->execInstrNumericF64Abs($instr),
+ Instrs\Numeric\F64Add::class => $this->execInstrNumericF64Add($instr),
+ Instrs\Numeric\F64Ceil::class => $this->execInstrNumericF64Ceil($instr),
+ Instrs\Numeric\F64Const::class => $this->execInstrNumericF64Const($instr),
+ Instrs\Numeric\F64ConvertI32S::class => $this->execInstrNumericF64ConvertI32S($instr),
+ Instrs\Numeric\F64ConvertI32U::class => $this->execInstrNumericF64ConvertI32U($instr),
+ Instrs\Numeric\F64ConvertI64S::class => $this->execInstrNumericF64ConvertI64S($instr),
+ Instrs\Numeric\F64ConvertI64U::class => $this->execInstrNumericF64ConvertI64U($instr),
+ Instrs\Numeric\F64CopySign::class => $this->execInstrNumericF64CopySign($instr),
+ Instrs\Numeric\F64Div::class => $this->execInstrNumericF64Div($instr),
+ Instrs\Numeric\F64Eq::class => $this->execInstrNumericF64Eq($instr),
+ Instrs\Numeric\F64Floor::class => $this->execInstrNumericF64Floor($instr),
+ Instrs\Numeric\F64Ge::class => $this->execInstrNumericF64Ge($instr),
+ Instrs\Numeric\F64Gt::class => $this->execInstrNumericF64Gt($instr),
+ Instrs\Numeric\F64Le::class => $this->execInstrNumericF64Le($instr),
+ Instrs\Numeric\F64Lt::class => $this->execInstrNumericF64Lt($instr),
+ Instrs\Numeric\F64Max::class => $this->execInstrNumericF64Max($instr),
+ Instrs\Numeric\F64Min::class => $this->execInstrNumericF64Min($instr),
+ Instrs\Numeric\F64Mul::class => $this->execInstrNumericF64Mul($instr),
+ Instrs\Numeric\F64Ne::class => $this->execInstrNumericF64Ne($instr),
+ Instrs\Numeric\F64Nearest::class => $this->execInstrNumericF64Nearest($instr),
+ Instrs\Numeric\F64Neg::class => $this->execInstrNumericF64Neg($instr),
+ Instrs\Numeric\F64PromoteF32::class => $this->execInstrNumericF64PromoteF32($instr),
+ Instrs\Numeric\F64ReinterpretI32::class => $this->execInstrNumericF64ReinterpretI32($instr),
+ Instrs\Numeric\F64ReinterpretI64::class => $this->execInstrNumericF64ReinterpretI64($instr),
+ Instrs\Numeric\F64Sqrt::class => $this->execInstrNumericF64Sqrt($instr),
+ Instrs\Numeric\F64Sub::class => $this->execInstrNumericF64Sub($instr),
+ Instrs\Numeric\F64Trunc::class => $this->execInstrNumericF64Trunc($instr),
+ Instrs\Numeric\I32Add::class => $this->execInstrNumericI32Add($instr),
+ Instrs\Numeric\I32And::class => $this->execInstrNumericI32And($instr),
+ Instrs\Numeric\I32Clz::class => $this->execInstrNumericI32Clz($instr),
+ Instrs\Numeric\I32Const::class => $this->execInstrNumericI32Const($instr),
+ Instrs\Numeric\I32Ctz::class => $this->execInstrNumericI32Ctz($instr),
+ Instrs\Numeric\I32DivS::class => $this->execInstrNumericI32DivS($instr),
+ Instrs\Numeric\I32DivU::class => $this->execInstrNumericI32DivU($instr),
+ Instrs\Numeric\I32Eq::class => $this->execInstrNumericI32Eq($instr),
+ Instrs\Numeric\I32Eqz::class => $this->execInstrNumericI32Eqz($instr),
+ Instrs\Numeric\I32Extend16S::class => $this->execInstrNumericI32Extend16S($instr),
+ Instrs\Numeric\I32Extend8S::class => $this->execInstrNumericI32Extend8S($instr),
+ Instrs\Numeric\I32GeS::class => $this->execInstrNumericI32GeS($instr),
+ Instrs\Numeric\I32GeU::class => $this->execInstrNumericI32GeU($instr),
+ Instrs\Numeric\I32GtS::class => $this->execInstrNumericI32GtS($instr),
+ Instrs\Numeric\I32GtU::class => $this->execInstrNumericI32GtU($instr),
+ Instrs\Numeric\I32LeS::class => $this->execInstrNumericI32LeS($instr),
+ Instrs\Numeric\I32LeU::class => $this->execInstrNumericI32LeU($instr),
+ Instrs\Numeric\I32LtS::class => $this->execInstrNumericI32LtS($instr),
+ Instrs\Numeric\I32LtU::class => $this->execInstrNumericI32LtU($instr),
+ Instrs\Numeric\I32Mul::class => $this->execInstrNumericI32Mul($instr),
+ Instrs\Numeric\I32Ne::class => $this->execInstrNumericI32Ne($instr),
+ Instrs\Numeric\I32Or::class => $this->execInstrNumericI32Or($instr),
+ Instrs\Numeric\I32Popcnt::class => $this->execInstrNumericI32Popcnt($instr),
+ Instrs\Numeric\I32ReinterpretF32::class => $this->execInstrNumericI32ReinterpretF32($instr),
+ Instrs\Numeric\I32ReinterpretF64::class => $this->execInstrNumericI32ReinterpretF64($instr),
+ Instrs\Numeric\I32RemS::class => $this->execInstrNumericI32RemS($instr),
+ Instrs\Numeric\I32RemU::class => $this->execInstrNumericI32RemU($instr),
+ Instrs\Numeric\I32RotL::class => $this->execInstrNumericI32RotL($instr),
+ Instrs\Numeric\I32RotR::class => $this->execInstrNumericI32RotR($instr),
+ Instrs\Numeric\I32Shl::class => $this->execInstrNumericI32Shl($instr),
+ Instrs\Numeric\I32ShrS::class => $this->execInstrNumericI32ShrS($instr),
+ Instrs\Numeric\I32ShrU::class => $this->execInstrNumericI32ShrU($instr),
+ Instrs\Numeric\I32Sub::class => $this->execInstrNumericI32Sub($instr),
+ Instrs\Numeric\I32TruncF32S::class => $this->execInstrNumericI32TruncF32S($instr),
+ Instrs\Numeric\I32TruncF32U::class => $this->execInstrNumericI32TruncF32U($instr),
+ Instrs\Numeric\I32TruncF64S::class => $this->execInstrNumericI32TruncF64S($instr),
+ Instrs\Numeric\I32TruncF64U::class => $this->execInstrNumericI32TruncF64U($instr),
+ Instrs\Numeric\I32TruncSatF32S::class => $this->execInstrNumericI32TruncSatF32S($instr),
+ Instrs\Numeric\I32TruncSatF32U::class => $this->execInstrNumericI32TruncSatF32U($instr),
+ Instrs\Numeric\I32TruncSatF64S::class => $this->execInstrNumericI32TruncSatF64S($instr),
+ Instrs\Numeric\I32TruncSatF64U::class => $this->execInstrNumericI32TruncSatF64U($instr),
+ Instrs\Numeric\I32WrapI64::class => $this->execInstrNumericI32WrapI64($instr),
+ Instrs\Numeric\I32Xor::class => $this->execInstrNumericI32Xor($instr),
+ Instrs\Numeric\I64Add::class => $this->execInstrNumericI64Add($instr),
+ Instrs\Numeric\I64And::class => $this->execInstrNumericI64And($instr),
+ Instrs\Numeric\I64Clz::class => $this->execInstrNumericI64Clz($instr),
+ Instrs\Numeric\I64Const::class => $this->execInstrNumericI64Const($instr),
+ Instrs\Numeric\I64Ctz::class => $this->execInstrNumericI64Ctz($instr),
+ Instrs\Numeric\I64DivS::class => $this->execInstrNumericI64DivS($instr),
+ Instrs\Numeric\I64DivU::class => $this->execInstrNumericI64DivU($instr),
+ Instrs\Numeric\I64Eq::class => $this->execInstrNumericI64Eq($instr),
+ Instrs\Numeric\I64Eqz::class => $this->execInstrNumericI64Eqz($instr),
+ Instrs\Numeric\I64Extend16S::class => $this->execInstrNumericI64Extend16S($instr),
+ Instrs\Numeric\I64Extend32S::class => $this->execInstrNumericI64Extend32S($instr),
+ Instrs\Numeric\I64Extend8S::class => $this->execInstrNumericI64Extend8S($instr),
+ Instrs\Numeric\I64ExtendI32S::class => $this->execInstrNumericI64ExtendI32S($instr),
+ Instrs\Numeric\I64ExtendI32U::class => $this->execInstrNumericI64ExtendI32U($instr),
+ Instrs\Numeric\I64GeS::class => $this->execInstrNumericI64GeS($instr),
+ Instrs\Numeric\I64GeU::class => $this->execInstrNumericI64GeU($instr),
+ Instrs\Numeric\I64GtS::class => $this->execInstrNumericI64GtS($instr),
+ Instrs\Numeric\I64GtU::class => $this->execInstrNumericI64GtU($instr),
+ Instrs\Numeric\I64LeS::class => $this->execInstrNumericI64LeS($instr),
+ Instrs\Numeric\I64LeU::class => $this->execInstrNumericI64LeU($instr),
+ Instrs\Numeric\I64LtS::class => $this->execInstrNumericI64LtS($instr),
+ Instrs\Numeric\I64LtU::class => $this->execInstrNumericI64LtU($instr),
+ Instrs\Numeric\I64Mul::class => $this->execInstrNumericI64Mul($instr),
+ Instrs\Numeric\I64Ne::class => $this->execInstrNumericI64Ne($instr),
+ Instrs\Numeric\I64Or::class => $this->execInstrNumericI64Or($instr),
+ Instrs\Numeric\I64Popcnt::class => $this->execInstrNumericI64Popcnt($instr),
+ Instrs\Numeric\I64ReinterpretF32::class => $this->execInstrNumericI64ReinterpretF32($instr),
+ Instrs\Numeric\I64ReinterpretF64::class => $this->execInstrNumericI64ReinterpretF64($instr),
+ Instrs\Numeric\I64RemS::class => $this->execInstrNumericI64RemS($instr),
+ Instrs\Numeric\I64RemU::class => $this->execInstrNumericI64RemU($instr),
+ Instrs\Numeric\I64RotL::class => $this->execInstrNumericI64RotL($instr),
+ Instrs\Numeric\I64RotR::class => $this->execInstrNumericI64RotR($instr),
+ Instrs\Numeric\I64Shl::class => $this->execInstrNumericI64Shl($instr),
+ Instrs\Numeric\I64ShrS::class => $this->execInstrNumericI64ShrS($instr),
+ Instrs\Numeric\I64ShrU::class => $this->execInstrNumericI64ShrU($instr),
+ Instrs\Numeric\I64Sub::class => $this->execInstrNumericI64Sub($instr),
+ Instrs\Numeric\I64TruncF32S::class => $this->execInstrNumericI64TruncF32S($instr),
+ Instrs\Numeric\I64TruncF32U::class => $this->execInstrNumericI64TruncF32U($instr),
+ Instrs\Numeric\I64TruncF64S::class => $this->execInstrNumericI64TruncF64S($instr),
+ Instrs\Numeric\I64TruncF64U::class => $this->execInstrNumericI64TruncF64U($instr),
+ Instrs\Numeric\I64TruncSatF32S::class => $this->execInstrNumericI64TruncSatF32S($instr),
+ Instrs\Numeric\I64TruncSatF32U::class => $this->execInstrNumericI64TruncSatF32U($instr),
+ Instrs\Numeric\I64TruncSatF64S::class => $this->execInstrNumericI64TruncSatF64S($instr),
+ Instrs\Numeric\I64TruncSatF64U::class => $this->execInstrNumericI64TruncSatF64U($instr),
+ Instrs\Numeric\I64Xor::class => $this->execInstrNumericI64Xor($instr),
+ Instrs\Reference\RefFunc::class => $this->execInstrReferenceRefFunc($instr),
+ Instrs\Reference\RefIsNull::class => $this->execInstrReferenceRefIsNull($instr),
+ Instrs\Reference\RefNull::class => $this->execInstrReferenceRefNull($instr),
+ Instrs\Parametric\Drop::class => $this->execInstrParametricDrop($instr),
+ Instrs\Parametric\Select::class => $this->execInstrParametricSelect($instr),
+ Instrs\Variable\GlobalGet::class => $this->execInstrVariableGlobalGet($instr),
+ Instrs\Variable\GlobalSet::class => $this->execInstrVariableGlobalSet($instr),
+ Instrs\Variable\LocalGet::class => $this->execInstrVariableLocalGet($instr),
+ Instrs\Variable\LocalSet::class => $this->execInstrVariableLocalSet($instr),
+ Instrs\Variable\LocalTee::class => $this->execInstrVariableLocalTee($instr),
+ Instrs\Table\ElemDrop::class => $this->execInstrTableElemDrop($instr),
+ Instrs\Table\TableCopy::class => $this->execInstrTableTableCopy($instr),
+ Instrs\Table\TableFill::class => $this->execInstrTableTableFill($instr),
+ Instrs\Table\TableGet::class => $this->execInstrTableTableGet($instr),
+ Instrs\Table\TableGrow::class => $this->execInstrTableTableGrow($instr),
+ Instrs\Table\TableInit::class => $this->execInstrTableTableInit($instr),
+ Instrs\Table\TableSet::class => $this->execInstrTableTableSet($instr),
+ Instrs\Table\TableSize::class => $this->execInstrTableTableSize($instr),
+ Instrs\Memory\DataDrop::class => $this->execInstrMemoryDataDrop($instr),
+ Instrs\Memory\F32Load::class => $this->execInstrMemoryF32Load($instr),
+ Instrs\Memory\F32Store::class => $this->execInstrMemoryF32Store($instr),
+ Instrs\Memory\F64Load::class => $this->execInstrMemoryF64Load($instr),
+ Instrs\Memory\F64Store::class => $this->execInstrMemoryF64Store($instr),
+ Instrs\Memory\I32Load::class => $this->execInstrMemoryI32Load($instr),
+ Instrs\Memory\I32Load16S::class => $this->execInstrMemoryI32Load16S($instr),
+ Instrs\Memory\I32Load16U::class => $this->execInstrMemoryI32Load16U($instr),
+ Instrs\Memory\I32Load8S::class => $this->execInstrMemoryI32Load8S($instr),
+ Instrs\Memory\I32Load8U::class => $this->execInstrMemoryI32Load8U($instr),
+ Instrs\Memory\I32Store::class => $this->execInstrMemoryI32Store($instr),
+ Instrs\Memory\I32Store16::class => $this->execInstrMemoryI32Store16($instr),
+ Instrs\Memory\I32Store8::class => $this->execInstrMemoryI32Store8($instr),
+ Instrs\Memory\I64Load::class => $this->execInstrMemoryI64Load($instr),
+ Instrs\Memory\I64Load16S::class => $this->execInstrMemoryI64Load16S($instr),
+ Instrs\Memory\I64Load16U::class => $this->execInstrMemoryI64Load16U($instr),
+ Instrs\Memory\I64Load32S::class => $this->execInstrMemoryI64Load32S($instr),
+ Instrs\Memory\I64Load32U::class => $this->execInstrMemoryI64Load32U($instr),
+ Instrs\Memory\I64Load8S::class => $this->execInstrMemoryI64Load8S($instr),
+ Instrs\Memory\I64Load8U::class => $this->execInstrMemoryI64Load8U($instr),
+ Instrs\Memory\I64Store::class => $this->execInstrMemoryI64Store($instr),
+ Instrs\Memory\I64Store16::class => $this->execInstrMemoryI64Store16($instr),
+ Instrs\Memory\I64Store32::class => $this->execInstrMemoryI64Store32($instr),
+ Instrs\Memory\I64Store8::class => $this->execInstrMemoryI64Store8($instr),
+ Instrs\Memory\MemoryCopy::class => $this->execInstrMemoryMemoryCopy($instr),
+ Instrs\Memory\MemoryFill::class => $this->execInstrMemoryMemoryFill($instr),
+ Instrs\Memory\MemoryGrow::class => $this->execInstrMemoryMemoryGrow($instr),
+ Instrs\Memory\MemoryInit::class => $this->execInstrMemoryMemoryInit($instr),
+ Instrs\Memory\MemorySize::class => $this->execInstrMemoryMemorySize($instr),
+ Instrs\Control\Block::class => $this->execInstrControlBlock($instr),
+ Instrs\Control\Br::class => $this->execInstrControlBr($instr),
+ Instrs\Control\BrIf::class => $this->execInstrControlBrIf($instr),
+ Instrs\Control\BrTable::class => $this->execInstrControlBrTable($instr),
+ Instrs\Control\Call::class => $this->execInstrControlCall($instr),
+ Instrs\Control\CallIndirect::class => $this->execInstrControlCallIndirect($instr),
+ Instrs\Control\Else_::class => $this->execInstrControlElse_($instr),
+ Instrs\Control\End::class => $this->execInstrControlEnd($instr),
+ Instrs\Control\If_::class => $this->execInstrControlIf_($instr),
+ Instrs\Control\Loop::class => $this->execInstrControlLoop($instr),
+ Instrs\Control\Nop::class => $this->execInstrControlNop($instr),
+ Instrs\Control\Return_::class => $this->execInstrControlReturn_($instr),
+ Instrs\Control\Unreachable::class => $this->execInstrControlUnreachable($instr),
+ default => throw new RuntimeException("invalid instruction"),
+ };
+ }
+
+ private function execInstrNumericF32Abs(Instrs\Numeric\F32Abs $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(abs($v));
+ }
+
+ private function execInstrNumericF32Add(Instrs\Numeric\F32Add $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32($c1 + $c2));
+ }
+
+ private function execInstrNumericF32Ceil(Instrs\Numeric\F32Ceil $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(ceil($v));
+ }
+
+ private function execInstrNumericF32Const(Instrs\Numeric\F32Const $instr): void
+ {
+ $this->stack->pushValue($instr->value);
+ }
+
+ private function execInstrNumericF32ConvertI32S(Instrs\Numeric\F32ConvertI32S $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32((float) $v));
+ }
+
+ private function execInstrNumericF32ConvertI32U(Instrs\Numeric\F32ConvertI32U $instr): void
+ {
+ $v = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushValue(NumericOps::truncateF64ToF32((float) $v));
+ }
+
+ private function execInstrNumericF32ConvertI64S(Instrs\Numeric\F32ConvertI64S $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32((float) $v));
+ }
+
+ private function execInstrNumericF32ConvertI64U(Instrs\Numeric\F32ConvertI64U $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32((float) $v));
+ }
+
+ private function execInstrNumericF32CopySign(Instrs\Numeric\F32CopySign $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $c1Sign = NumericOps::getFloatSign($c1);
+ $c2Sign = NumericOps::getFloatSign($c2);
+ $this->stack->pushValue($c1Sign === $c2Sign ? $c1 : -$c1);
+ }
+
+ private function execInstrNumericF32DemoteF64(Instrs\Numeric\F32DemoteF64 $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue($v);
+ }
+
+ private function execInstrNumericF32Div(Instrs\Numeric\F32Div $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32(fdiv($c1, $c2)));
+ }
+
+ private function execInstrNumericF32Eq(Instrs\Numeric\F32Eq $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 === $c2);
+ }
+
+ private function execInstrNumericF32Floor(Instrs\Numeric\F32Floor $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(floor($v));
+ }
+
+ private function execInstrNumericF32Ge(Instrs\Numeric\F32Ge $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 >= $c2);
+ }
+
+ private function execInstrNumericF32Gt(Instrs\Numeric\F32Gt $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 > $c2);
+ }
+
+ private function execInstrNumericF32Le(Instrs\Numeric\F32Le $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 <= $c2);
+ }
+
+ private function execInstrNumericF32Lt(Instrs\Numeric\F32Lt $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 < $c2);
+ }
+
+ private function execInstrNumericF32Max(Instrs\Numeric\F32Max $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ if (is_nan($c1) || is_nan($c2)) {
+ // PHP's standard max() handles NaNs in diffrent way than WebAssembly spec does.
+ $this->stack->pushValue(NAN);
+ return;
+ }
+ $this->stack->pushValue(max($c1, $c2));
+ }
+
+ private function execInstrNumericF32Min(Instrs\Numeric\F32Min $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ if (is_nan($c1) || is_nan($c2)) {
+ // PHP's standard min() handles NaNs in diffrent way than WebAssembly spec does.
+ $this->stack->pushValue(NAN);
+ return;
+ }
+ $this->stack->pushValue(min($c1, $c2));
+ }
+
+ private function execInstrNumericF32Mul(Instrs\Numeric\F32Mul $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32($c1 * $c2));
+ }
+
+ private function execInstrNumericF32Ne(Instrs\Numeric\F32Ne $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 !== $c2);
+ }
+
+ private function execInstrNumericF32Nearest(Instrs\Numeric\F32Nearest $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(round($v, mode: PHP_ROUND_HALF_EVEN));
+ }
+
+ private function execInstrNumericF32Neg(Instrs\Numeric\F32Neg $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(-$c1);
+ }
+
+ private function execInstrNumericF32ReinterpretI32(Instrs\Numeric\F32ReinterpretI32 $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::reinterpretI32AsF32($v));
+ }
+
+ private function execInstrNumericF32ReinterpretI64(Instrs\Numeric\F32ReinterpretI64 $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::reinterpretI64AsF32($v));
+ }
+
+ private function execInstrNumericF32Sqrt(Instrs\Numeric\F32Sqrt $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32(sqrt($c1)));
+ }
+
+ private function execInstrNumericF32Sub(Instrs\Numeric\F32Sub $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::truncateF64ToF32($c1 - $c2));
+ }
+
+ private function execInstrNumericF32Trunc(Instrs\Numeric\F32Trunc $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < 0) {
+ $this->stack->pushValue(NumericOps::truncateF64ToF32(ceil($v)));
+ } else {
+ $this->stack->pushValue(NumericOps::truncateF64ToF32(floor($v)));
+ }
+ }
+
+ private function execInstrNumericF64Abs(Instrs\Numeric\F64Abs $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(abs($c1));
+ }
+
+ private function execInstrNumericF64Add(Instrs\Numeric\F64Add $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue($c1 + $c2);
+ }
+
+ private function execInstrNumericF64Ceil(Instrs\Numeric\F64Ceil $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(ceil($c1));
+ }
+
+ private function execInstrNumericF64Const(Instrs\Numeric\F64Const $instr): void
+ {
+ $this->stack->pushValue($instr->value);
+ }
+
+ private function execInstrNumericF64ConvertI32S(Instrs\Numeric\F64ConvertI32S $instr): void
+ {
+ $c = $this->stack->popInt();
+ $this->stack->pushValue((float) $c);
+ }
+
+ private function execInstrNumericF64ConvertI32U(Instrs\Numeric\F64ConvertI32U $instr): void
+ {
+ $c = $this->stack->popInt();
+ $this->stack->pushValue((float) $c);
+ }
+
+ private function execInstrNumericF64ConvertI64S(Instrs\Numeric\F64ConvertI64S $instr): void
+ {
+ $c = $this->stack->popInt();
+ $this->stack->pushValue((float) $c);
+ }
+
+ private function execInstrNumericF64ConvertI64U(Instrs\Numeric\F64ConvertI64U $instr): void
+ {
+ $c = $this->stack->popInt();
+ $this->stack->pushValue((float) $c);
+ }
+
+ private function execInstrNumericF64CopySign(Instrs\Numeric\F64CopySign $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $c1Sign = NumericOps::getFloatSign($c1);
+ $c2Sign = NumericOps::getFloatSign($c2);
+ $this->stack->pushValue($c1Sign === $c2Sign ? $c1 : -$c1);
+ }
+
+ private function execInstrNumericF64Div(Instrs\Numeric\F64Div $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(fdiv($c1, $c2));
+ }
+
+ private function execInstrNumericF64Eq(Instrs\Numeric\F64Eq $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 === $c2);
+ }
+
+ private function execInstrNumericF64Floor(Instrs\Numeric\F64Floor $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(floor($c1));
+ }
+
+ private function execInstrNumericF64Ge(Instrs\Numeric\F64Ge $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 >= $c2);
+ }
+
+ private function execInstrNumericF64Gt(Instrs\Numeric\F64Gt $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 > $c2);
+ }
+
+ private function execInstrNumericF64Le(Instrs\Numeric\F64Le $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 <= $c2);
+ }
+
+ private function execInstrNumericF64Lt(Instrs\Numeric\F64Lt $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 < $c2);
+ }
+
+ private function execInstrNumericF64Max(Instrs\Numeric\F64Max $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ if (is_nan($c1) || is_nan($c2)) {
+ // PHP's standard max() handles NaNs in diffrent way than WebAssembly spec does.
+ $this->stack->pushValue(NAN);
+ return;
+ }
+ $this->stack->pushValue(max($c1, $c2));
+ }
+
+ private function execInstrNumericF64Min(Instrs\Numeric\F64Min $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ if (is_nan($c1) || is_nan($c2)) {
+ // PHP's standard min() handles NaNs in diffrent way than WebAssembly spec does.
+ $this->stack->pushValue(NAN);
+ return;
+ }
+ $this->stack->pushValue(min($c1, $c2));
+ }
+
+ private function execInstrNumericF64Mul(Instrs\Numeric\F64Mul $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue($c1 * $c2);
+ }
+
+ private function execInstrNumericF64Ne(Instrs\Numeric\F64Ne $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushBool($c1 !== $c2);
+ }
+
+ private function execInstrNumericF64Nearest(Instrs\Numeric\F64Nearest $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(round($v, mode: PHP_ROUND_HALF_EVEN));
+ }
+
+ private function execInstrNumericF64Neg(Instrs\Numeric\F64Neg $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(-$c1);
+ }
+
+ private function execInstrNumericF64PromoteF32(Instrs\Numeric\F64PromoteF32 $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue($v);
+ }
+
+ private function execInstrNumericF64ReinterpretI32(Instrs\Numeric\F64ReinterpretI32 $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::reinterpretI32AsF64($v));
+ }
+
+ private function execInstrNumericF64ReinterpretI64(Instrs\Numeric\F64ReinterpretI64 $instr): void
+ {
+ $v = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::reinterpretI64AsF64($v));
+ }
+
+ private function execInstrNumericF64Sqrt(Instrs\Numeric\F64Sqrt $instr): void
+ {
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue(sqrt($c1));
+ }
+
+ private function execInstrNumericF64Sub(Instrs\Numeric\F64Sub $instr): void
+ {
+ $c2 = $this->stack->popFloat();
+ $c1 = $this->stack->popFloat();
+ $this->stack->pushValue($c1 - $c2);
+ }
+
+ private function execInstrNumericF64Trunc(Instrs\Numeric\F64Trunc $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < 0) {
+ $this->stack->pushValue(ceil($v));
+ } else {
+ $this->stack->pushValue(floor($v));
+ }
+ }
+
+ private function execInstrNumericI32Add(Instrs\Numeric\I32Add $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 + $c2) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32And(Instrs\Numeric\I32And $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 & $c2) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32Clz(Instrs\Numeric\I32Clz $instr): void
+ {
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $leadingZeros = 0;
+ for ($j = 31; 0 <= $j; $j--) {
+ if (($i & (1 << $j)) === 0) {
+ $leadingZeros++;
+ } else {
+ break;
+ }
+ }
+ $this->stack->pushValue($leadingZeros);
+ }
+
+ private function execInstrNumericI32Const(Instrs\Numeric\I32Const $instr): void
+ {
+ $this->stack->pushValue($instr->value);
+ }
+
+ private function execInstrNumericI32Ctz(Instrs\Numeric\I32Ctz $instr): void
+ {
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $trailingZeros = 0;
+ for ($j = 0; $j < 32; $j++) {
+ if (($i & (1 << $j)) === 0) {
+ $trailingZeros++;
+ } else {
+ break;
+ }
+ }
+ $this->stack->pushValue($trailingZeros);
+ }
+
+ private function execInstrNumericI32DivS(Instrs\Numeric\I32DivS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ if ($c2 === 0) {
+ throw new TrapException("i32.div_s: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ if ($c1 === -2147483648 && $c2 === -1) {
+ throw new TrapException("i32.div_s: overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue(intdiv($c1, $c2));
+ }
+
+ private function execInstrNumericI32DivU(Instrs\Numeric\I32DivU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ if ($c2 === 0) {
+ throw new TrapException("i32.div_u: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ $this->stack->pushValue(NumericOps::convertU32ToS32(intdiv($c1, $c2)));
+ }
+
+ private function execInstrNumericI32Eq(Instrs\Numeric\I32Eq $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 === $c2);
+ }
+
+ private function execInstrNumericI32Eqz(Instrs\Numeric\I32Eqz $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 === 0);
+ }
+
+ private function execInstrNumericI32Extend16S(Instrs\Numeric\I32Extend16S $instr): void
+ {
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c2 = $c1 & 0xFFFF;
+ $result = unpack('s', pack('S', $c2));
+ assert($result !== false);
+ $this->stack->pushValue($result[1]);
+ }
+
+ private function execInstrNumericI32Extend8S(Instrs\Numeric\I32Extend8S $instr): void
+ {
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c2 = $c1 & 0xFF;
+ $result = unpack('c', pack('C', $c2));
+ assert($result !== false);
+ $this->stack->pushValue($result[1]);
+ }
+
+ private function execInstrNumericI32GeS(Instrs\Numeric\I32GeS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 >= $c2);
+ }
+
+ private function execInstrNumericI32GeU(Instrs\Numeric\I32GeU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushBool($c1 >= $c2);
+ }
+
+ private function execInstrNumericI32GtS(Instrs\Numeric\I32GtS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 > $c2);
+ }
+
+ private function execInstrNumericI32GtU(Instrs\Numeric\I32GtU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushBool($c1 > $c2);
+ }
+
+ private function execInstrNumericI32LeS(Instrs\Numeric\I32LeS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 <= $c2);
+ }
+
+ private function execInstrNumericI32LeU(Instrs\Numeric\I32LeU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushBool($c1 <= $c2);
+ }
+
+ private function execInstrNumericI32LtS(Instrs\Numeric\I32LtS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 < $c2);
+ }
+
+ private function execInstrNumericI32LtU(Instrs\Numeric\I32LtU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushBool($c1 < $c2);
+ }
+
+ private function execInstrNumericI32Mul(Instrs\Numeric\I32Mul $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 * $c2) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32Ne(Instrs\Numeric\I32Ne $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 !== $c2);
+ }
+
+ private function execInstrNumericI32Or(Instrs\Numeric\I32Or $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 | $c2) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32Popcnt(Instrs\Numeric\I32Popcnt $instr): void
+ {
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $popcnt = 0;
+ for ($j = 0; $j < 32; $j++) {
+ if (($i & (1 << $j)) !== 0) {
+ $popcnt++;
+ }
+ }
+ $this->stack->pushValue($popcnt);
+ }
+
+ private function execInstrNumericI32ReinterpretF32(Instrs\Numeric\I32ReinterpretF32 $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::reinterpretF32AsI32($v));
+ }
+
+ private function execInstrNumericI32ReinterpretF64(Instrs\Numeric\I32ReinterpretF64 $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::reinterpretF64AsI32($v));
+ }
+
+ private function execInstrNumericI32RemS(Instrs\Numeric\I32RemS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ if ($c2 === 0) {
+ throw new TrapException("i32.rem_s: divide by zero or overflow", trapKind: TrapKind::DivideByZero);
+ }
+ $this->stack->pushValue($c1 % $c2);
+ }
+
+ private function execInstrNumericI32RemU(Instrs\Numeric\I32RemU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ if ($c2 === 0) {
+ throw new TrapException("i32.rem_u: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ $this->stack->pushValue(NumericOps::convertU32ToS32($c1 % $c2));
+ }
+
+ private function execInstrNumericI32RotL(Instrs\Numeric\I32RotL $instr): void
+ {
+ $i2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $i1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $k = $i2 % 32;
+ $this->stack->pushValue(NumericOps::convertU32ToS32((($i1 << $k) | ($i1 >> (32 - $k))) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32RotR(Instrs\Numeric\I32RotR $instr): void
+ {
+ $i2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $i1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $k = $i2 % 32;
+ $this->stack->pushValue(NumericOps::convertU32ToS32((($i1 >> $k) | ($i1 << (32 - $k))) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32Shl(Instrs\Numeric\I32Shl $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $k = $c2 % 32;
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 << $k) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32ShrS(Instrs\Numeric\I32ShrS $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $k = $c2 % 32;
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $signed = $c1 & 0x80000000;
+ if ($signed !== 0) {
+ $result = $c1;
+ for ($i = 0; $i < $k; $i++) {
+ $result = ($result >> 1) | 0x80000000;
+ }
+ $this->stack->pushValue(NumericOps::convertU32ToS32($result));
+ } else {
+ $this->stack->pushValue($c1 >> $k);
+ }
+ }
+
+ private function execInstrNumericI32ShrU(Instrs\Numeric\I32ShrU $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $k = $c2 % 32;
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushValue(NumericOps::convertU32ToS32($c1 >> $k));
+ }
+
+ private function execInstrNumericI32Sub(Instrs\Numeric\I32Sub $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c2Neg = ((~$c2 & 0xFFFFFFFF) + 1) & 0xFFFFFFFF;
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 + $c2Neg) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32TruncF32S(Instrs\Numeric\I32TruncF32S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -2147483649.0 || 2147483648.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue((int) $v);
+ }
+
+ private function execInstrNumericI32TruncF32U(Instrs\Numeric\I32TruncF32U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 4294967296.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue(NumericOps::convertU32ToS32((int) $v));
+ }
+
+ private function execInstrNumericI32TruncF64S(Instrs\Numeric\I32TruncF64S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -2147483649.0 || 2147483648.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue((int) $v);
+ }
+
+ private function execInstrNumericI32TruncF64U(Instrs\Numeric\I32TruncF64U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 4294967296.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue(NumericOps::convertU32ToS32((int) $v));
+ }
+
+ private function execInstrNumericI32TruncSatF32S(Instrs\Numeric\I32TruncSatF32S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < -2147483648.0) {
+ $this->stack->pushValue(-2147483648);
+ } elseif ($v > 2147483647.0) {
+ $this->stack->pushValue(2147483647);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI32TruncSatF32U(Instrs\Numeric\I32TruncSatF32U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < 0.0) {
+ $this->stack->pushValue(0);
+ } elseif ($v > 4294967295.0) {
+ $this->stack->pushValue(4294967295);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI32TruncSatF64S(Instrs\Numeric\I32TruncSatF64S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < -2147483648.0) {
+ $this->stack->pushValue(-2147483648);
+ } elseif ($v > 2147483647.0) {
+ $this->stack->pushValue(2147483647);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI32TruncSatF64U(Instrs\Numeric\I32TruncSatF64U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < 0.0) {
+ $this->stack->pushValue(0);
+ } elseif ($v > 4294967295.0) {
+ $this->stack->pushValue(4294967295);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI32WrapI64(Instrs\Numeric\I32WrapI64 $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue(NumericOps::convertU32ToS32($c1 & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI32Xor(Instrs\Numeric\I32Xor $instr): void
+ {
+ $c2 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $this->stack->pushValue(NumericOps::convertU32ToS32(($c1 ^ $c2) & 0xFFFFFFFF));
+ }
+
+ private function execInstrNumericI64Add(Instrs\Numeric\I64Add $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $result = NumericOps::bigIntToPhpInt(bcadd((string)$c1, (string)$c2));
+ $this->stack->pushValue($result);
+ }
+
+ private function execInstrNumericI64And(Instrs\Numeric\I64And $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue($c1 & $c2);
+ }
+
+ private function execInstrNumericI64Clz(Instrs\Numeric\I64Clz $instr): void
+ {
+ $i = $this->stack->popInt();
+ $leadingZeros = 0;
+ for ($j = 63; 0 <= $j; $j--) {
+ if ($j === 63) {
+ if ($i < 0) {
+ break;
+ } else {
+ $leadingZeros++;
+ }
+ } else {
+ if (($i & (1 << $j)) === 0) {
+ $leadingZeros++;
+ } else {
+ break;
+ }
+ }
+ }
+ $this->stack->pushValue($leadingZeros);
+ }
+
+ private function execInstrNumericI64Const(Instrs\Numeric\I64Const $instr): void
+ {
+ $this->stack->pushValue($instr->value);
+ }
+
+ private function execInstrNumericI64Ctz(Instrs\Numeric\I64Ctz $instr): void
+ {
+ $i = $this->stack->popInt();
+ $trailingZeros = 0;
+ for ($j = 0; $j < 64; $j++) {
+ if ($j === 63) {
+ if ($i >= 0) {
+ $trailingZeros++;
+ }
+ } else {
+ if (($i & (1 << $j)) === 0) {
+ $trailingZeros++;
+ } else {
+ break;
+ }
+ }
+ }
+ $this->stack->pushValue($trailingZeros);
+ }
+
+ private function execInstrNumericI64DivS(Instrs\Numeric\I64DivS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ if ($c2 === 0) {
+ throw new TrapException("i64.div_s: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ if ($c1 === PHP_INT_MIN && $c2 === -1) {
+ throw new TrapException("i64.div_s: overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue(intdiv($c1, $c2));
+ }
+
+ private function execInstrNumericI64DivU(Instrs\Numeric\I64DivU $instr): void
+ {
+ $c2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $c1 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ if ($c2 === '0') {
+ throw new TrapException("i64.div_u: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ $this->stack->pushValue(NumericOps::bigIntToPhpInt(bcdiv($c1, $c2, 0)));
+ }
+
+ private function execInstrNumericI64Eq(Instrs\Numeric\I64Eq $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 === $c2);
+ }
+
+ private function execInstrNumericI64Eqz(Instrs\Numeric\I64Eqz $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 === 0);
+ }
+
+ private function execInstrNumericI64Extend16S(Instrs\Numeric\I64Extend16S $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $c2 = $c1 & 0xFFFF;
+ $result = unpack('s', pack('S', $c2));
+ assert($result !== false);
+ $this->stack->pushValue($result[1]);
+ }
+
+ private function execInstrNumericI64Extend32S(Instrs\Numeric\I64Extend32S $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $c2 = $c1 & 0xFFFFFFFF;
+ $result = unpack('l', pack('L', $c2));
+ assert($result !== false);
+ $this->stack->pushValue($result[1]);
+ }
+
+ private function execInstrNumericI64Extend8S(Instrs\Numeric\I64Extend8S $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $c2 = $c1 & 0xFF;
+ $result = unpack('c', pack('C', $c2));
+ assert($result !== false);
+ $this->stack->pushValue($result[1]);
+ }
+
+ private function execInstrNumericI64ExtendI32S(Instrs\Numeric\I64ExtendI32S $instr): void
+ {
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue($c1);
+ }
+
+ private function execInstrNumericI64ExtendI32U(Instrs\Numeric\I64ExtendI32U $instr): void
+ {
+ $c1 = NumericOps::convertS32ToU32($this->stack->popInt());
+ $c2 = $c1 & 0xFFFFFFFF;
+ $this->stack->pushValue($c2);
+ }
+
+ private function execInstrNumericI64GeS(Instrs\Numeric\I64GeS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 >= $c2);
+ }
+
+ private function execInstrNumericI64GeU(Instrs\Numeric\I64GeU $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c2Packed = pack('J', $c2);
+ $c1 = $this->stack->popInt();
+ $c1Packed = pack('J', $c1);
+ $this->stack->pushBool($c1Packed >= $c2Packed);
+ }
+
+ private function execInstrNumericI64GtS(Instrs\Numeric\I64GtS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 > $c2);
+ }
+
+ private function execInstrNumericI64GtU(Instrs\Numeric\I64GtU $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c2Packed = pack('J', $c2);
+ $c1 = $this->stack->popInt();
+ $c1Packed = pack('J', $c1);
+ $this->stack->pushBool($c1Packed > $c2Packed);
+ }
+
+ private function execInstrNumericI64LeS(Instrs\Numeric\I64LeS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 <= $c2);
+ }
+
+ private function execInstrNumericI64LeU(Instrs\Numeric\I64LeU $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c2Packed = pack('J', $c2);
+ $c1 = $this->stack->popInt();
+ $c1Packed = pack('J', $c1);
+ $this->stack->pushBool($c1Packed <= $c2Packed);
+ }
+
+ private function execInstrNumericI64LtS(Instrs\Numeric\I64LtS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 < $c2);
+ }
+
+ private function execInstrNumericI64LtU(Instrs\Numeric\I64LtU $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c2Packed = pack('J', $c2);
+ $c1 = $this->stack->popInt();
+ $c1Packed = pack('J', $c1);
+ $this->stack->pushBool($c1Packed < $c2Packed);
+ }
+
+ private function execInstrNumericI64Mul(Instrs\Numeric\I64Mul $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $result = NumericOps::bigIntToPhpInt(bcmul((string)$c1, (string)$c2));
+ $this->stack->pushValue($result);
+ }
+
+ private function execInstrNumericI64Ne(Instrs\Numeric\I64Ne $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushBool($c1 !== $c2);
+ }
+
+ private function execInstrNumericI64Or(Instrs\Numeric\I64Or $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue($c1 | $c2);
+ }
+
+ private function execInstrNumericI64Popcnt(Instrs\Numeric\I64Popcnt $instr): void
+ {
+ $i = $this->stack->popInt();
+ $popcnt = 0;
+ for ($j = 0; $j < 64; $j++) {
+ if (($i & (1 << $j)) !== 0) {
+ $popcnt++;
+ }
+ }
+ $this->stack->pushValue($popcnt);
+ }
+
+ private function execInstrNumericI64ReinterpretF32(Instrs\Numeric\I64ReinterpretF32 $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::reinterpretF32AsI64($v));
+ }
+
+ private function execInstrNumericI64ReinterpretF64(Instrs\Numeric\I64ReinterpretF64 $instr): void
+ {
+ $v = $this->stack->popFloat();
+ $this->stack->pushValue(NumericOps::reinterpretF64AsI64($v));
+ }
+
+ private function execInstrNumericI64RemS(Instrs\Numeric\I64RemS $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ if ($c2 === 0) {
+ throw new TrapException("i64.rem_s: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ $this->stack->pushValue($c1 % $c2);
+ }
+
+ private function execInstrNumericI64RemU(Instrs\Numeric\I64RemU $instr): void
+ {
+ $c2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $c1 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ if ($c2 === '0') {
+ throw new TrapException("i64.rem_u: divide by zero", trapKind: TrapKind::DivideByZero);
+ }
+ $this->stack->pushValue(NumericOps::bigIntToPhpInt(bcmod($c1, $c2, 0)));
+ }
+
+ private function execInstrNumericI64RotL(Instrs\Numeric\I64RotL $instr): void
+ {
+ $i2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $k = (int)bcmod($i2, '64');
+ $i1 = $this->stack->popInt();
+ $left = $i1 << $k;
+ $right = $i1;
+ for ($i = 0; $i < 64 - $k; $i++) {
+ $right = ($right >> 1) & 0x7FFFFFFFFFFFFFFF;
+ }
+ $this->stack->pushValue($left | $right);
+ }
+
+ private function execInstrNumericI64RotR(Instrs\Numeric\I64RotR $instr): void
+ {
+ $i2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $k = (int)bcmod($i2, '64');
+ $i1 = $this->stack->popInt();
+ $left = $i1;
+ for ($i = 0; $i < $k; $i++) {
+ $left = ($left >> 1) & 0x7FFFFFFFFFFFFFFF;
+ }
+ $right = $i1 << (64 - $k);
+ $this->stack->pushValue($left | $right);
+ }
+
+ private function execInstrNumericI64Shl(Instrs\Numeric\I64Shl $instr): void
+ {
+ $c2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $k = (int)bcmod($c2, '64');
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue($c1 << $k);
+ }
+
+ private function execInstrNumericI64ShrS(Instrs\Numeric\I64ShrS $instr): void
+ {
+ $c2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $k = (int)bcmod($c2, '64');
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue($c1 >> $k);
+ }
+
+ private function execInstrNumericI64ShrU(Instrs\Numeric\I64ShrU $instr): void
+ {
+ $c2 = NumericOps::convertS64ToBigUInt($this->stack->popInt());
+ $k = (int)bcmod($c2, '64');
+ if ($k === 0) {
+ return;
+ }
+ // Perform shr_u based on string manipulation because PHP does not
+ // support shr_u operation.
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue(bindec(substr(decbin($c1), 0, -$k)));
+ }
+
+ private function execInstrNumericI64Sub(Instrs\Numeric\I64Sub $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $result = NumericOps::bigIntToPhpInt(bcsub((string)$c1, (string)$c2));
+ $this->stack->pushValue($result);
+ }
+
+ private function execInstrNumericI64TruncF32S(Instrs\Numeric\I64TruncF32S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion ($v)", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow ($v)", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -9223372036854775809.0 || 9223372036854775808.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow ($v)", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue((int) $v);
+ }
+
+ private function execInstrNumericI64TruncF32U(Instrs\Numeric\I64TruncF32U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 18446744073709551616.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue((int) $v);
+ }
+
+ private function execInstrNumericI64TruncF64S(Instrs\Numeric\I64TruncF64S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -9223372036854775809.0 || 9223372036854775808.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue((int) $v);
+ }
+
+ private function execInstrNumericI64TruncF64U(Instrs\Numeric\I64TruncF64U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 18446744073709551616.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue((int) $v);
+ }
+
+ private function execInstrNumericI64TruncSatF32S(Instrs\Numeric\I64TruncSatF32S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < -9223372036854775808.0) {
+ $this->stack->pushValue(-9223372036854775808);
+ } elseif ($v > 9223372036854775807.0) {
+ $this->stack->pushValue(9223372036854775807);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI64TruncSatF32U(Instrs\Numeric\I64TruncSatF32U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < 0.0) {
+ $this->stack->pushValue(0);
+ } elseif ($v > 18446744073709551615.0) {
+ $this->stack->pushValue(18446744073709551615);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI64TruncSatF64S(Instrs\Numeric\I64TruncSatF64S $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < -9223372036854775808.0) {
+ $this->stack->pushValue(-9223372036854775808);
+ } elseif ($v > 9223372036854775807.0) {
+ $this->stack->pushValue(9223372036854775807);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI64TruncSatF64U(Instrs\Numeric\I64TruncSatF64U $instr): void
+ {
+ $v = $this->stack->popFloat();
+ if ($v < 0.0) {
+ $this->stack->pushValue(0);
+ } elseif ($v > 18446744073709551615.0) {
+ $this->stack->pushValue(18446744073709551615);
+ } else {
+ $this->stack->pushValue((int) $v);
+ }
+ }
+
+ private function execInstrNumericI64Xor(Instrs\Numeric\I64Xor $instr): void
+ {
+ $c2 = $this->stack->popInt();
+ $c1 = $this->stack->popInt();
+ $this->stack->pushValue($c1 ^ $c2);
+ }
+
+ private function execInstrReferenceRefFunc(Instrs\Reference\RefFunc $instr): void
+ {
+ $x = $instr->func;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->funcAddrs[$x];
+ $this->stack->pushRefFunc($a);
+ }
+
+ private function execInstrReferenceRefIsNull(Instrs\Reference\RefIsNull $instr): void
+ {
+ $val = $this->stack->popRef();
+ $this->stack->pushBool($val instanceof Refs\RefNull);
+ }
+
+ private function execInstrReferenceRefNull(Instrs\Reference\RefNull $instr): void
+ {
+ $t = $instr->type;
+ $this->stack->pushRefNull($t);
+ }
+
+ private function execInstrParametricDrop(Instrs\Parametric\Drop $instr): void
+ {
+ $this->stack->popValue();
+ }
+
+ private function execInstrParametricSelect(Instrs\Parametric\Select $instr): void
+ {
+ $c = $this->stack->popInt();
+ $val2 = $this->stack->popValue();
+ $val1 = $this->stack->popValue();
+ if ($c !== 0) {
+ $this->stack->pushValue($val1);
+ } else {
+ $this->stack->pushValue($val2);
+ }
+ }
+
+ private function execInstrVariableGlobalGet(Instrs\Variable\GlobalGet $instr): void
+ {
+ $x = $instr->var;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->globalAddrs[$x];
+ $glob = $this->store->globals[$a];
+ $val = $glob->value;
+ $this->stack->pushValue($val);
+ }
+
+ private function execInstrVariableGlobalSet(Instrs\Variable\GlobalSet $instr): void
+ {
+ $x = $instr->var;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->globalAddrs[$x];
+ $glob = $this->store->globals[$a];
+ $val = $this->stack->popValue();
+ $glob->value = $val;
+ }
+
+ private function execInstrVariableLocalGet(Instrs\Variable\LocalGet $instr): void
+ {
+ $x = $instr->var;
+ $f = $this->stack->currentFrame();
+ $val = $f->locals[$x] ?? null;
+ if ($val === null) {
+ throw new RuntimeException("local.get: local $x not found in [$f->debugName]");
+ }
+ $this->stack->pushValue($val);
+ }
+
+ private function execInstrVariableLocalSet(Instrs\Variable\LocalSet $instr): void
+ {
+ $x = $instr->var;
+ $f = $this->stack->currentFrame();
+ $val = $this->stack->popValue();
+ // @phpstan-ignore-next-line
+ $f->locals[$x] = $val;
+ }
+
+ private function execInstrVariableLocalTee(Instrs\Variable\LocalTee $instr): void
+ {
+ $x = $instr->var;
+ $f = $this->stack->currentFrame();
+ $val = $this->stack->popValue();
+ // @phpstan-ignore-next-line
+ $f->locals[$x] = $val;
+ $this->stack->pushValue($val);
+ }
+
+ private function execInstrTableElemDrop(Instrs\Table\ElemDrop $instr): void
+ {
+ $x = $instr->elem;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->elemAddrs[$x];
+ $elem = $this->store->elems[$a];
+ // @phpstan-ignore-next-line
+ $this->store->elems[$a] = new ElemInst($elem->type, []);
+ }
+
+ private function execInstrTableTableCopy(Instrs\Table\TableCopy $instr): void
+ {
+ $x = $instr->to;
+ $y = $instr->from;
+ $f = $this->stack->currentFrame();
+ $taX = $f->module->tableAddrs[$x];
+ $tabX = $this->store->tables[$taX];
+ $taY = $f->module->tableAddrs[$y];
+ $tabY = $this->store->tables[$taY];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $s = NumericOps::convertS32ToU32($this->stack->popInt());
+ $d = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($tabX->elem) < $d + $n || count($tabY->elem) < $s + $n) {
+ throw new TrapException("table.copy: out of bounds", trapKind: TrapKind::OutOfBoundsTableAccess);
+ }
+ if ($n === 0 || ($x === $y && $d === $s)) {
+ return;
+ }
+ for ($i = 0; $i < $n; $i++) {
+ $s_ = ($d < $s) ? ($s + $i) : ($s + $n - 1 - $i);
+ $d_ = ($d < $s) ? ($d + $i) : ($d + $n - 1 - $i);
+ // @phpstan-ignore-next-line
+ $tabX->elem[$d_] = $tabY->elem[$s_];
+ }
+ }
+
+ private function execInstrTableTableFill(Instrs\Table\TableFill $instr): void
+ {
+ $x = $instr->table;
+ $f = $this->stack->currentFrame();
+ $ta = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$ta];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $val = $this->stack->popRef();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($tab->elem) < $i + $n) {
+ throw new TrapException("table.fill: out of bounds", trapKind: TrapKind::OutOfBoundsTableAccess);
+ }
+ for ($k = 0; $k < $n; $k++) {
+ // @phpstan-ignore-next-line
+ $tab->elem[$i + $k] = $val;
+ }
+ }
+
+ private function execInstrTableTableGet(Instrs\Table\TableGet $instr): void
+ {
+ $x = $instr->table;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($tab->elem) <= $i) {
+ throw new TrapException("table.get: out of bounds", trapKind: TrapKind::OutOfBoundsTableAccess);
+ }
+ $val = $tab->elem[$i];
+ $this->stack->pushValue($val);
+ }
+
+ private function execInstrTableTableGrow(Instrs\Table\TableGrow $instr): void
+ {
+ $x = $instr->table;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$a];
+ $sz = count($tab->elem);
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $val = $this->stack->popRef();
+
+ $len = $sz + $n;
+ if ((1 << 32) <= $len) {
+ $this->stack->pushValue(-1);
+ return;
+ }
+
+ $limits = $tab->type->limits;
+ $limits_ = new Limits($len, $limits->max);
+ if (!$limits_->isValid()) {
+ $this->stack->pushValue(-1);
+ return;
+ }
+
+ for ($i = 0; $i < $n; $i++) {
+ $tab->elem[] = $val;
+ }
+ $tab->type = new TableType($limits_, $tab->type->refType);
+
+ $this->stack->pushValue($sz);
+ }
+
+ private function execInstrTableTableInit(Instrs\Table\TableInit $instr): void
+ {
+ $x = $instr->to;
+ $y = $instr->from;
+ $f = $this->stack->currentFrame();
+ $ta = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$ta];
+ $ea = $f->module->elemAddrs[$y];
+ $elem = $this->store->elems[$ea];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $s = NumericOps::convertS32ToU32($this->stack->popInt());
+ $d = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($elem->elem) < $s + $n) {
+ throw new TrapException("table.init: out of bounds", trapKind: TrapKind::OutOfBoundsTableAccess);
+ }
+ if (count($tab->elem) < $d + $n) {
+ throw new TrapException("table.init: out of bounds", trapKind: TrapKind::OutOfBoundsTableAccess);
+ }
+ for ($i = 0; $i < $n; $i++) {
+ // @phpstan-ignore-next-line
+ $tab->elem[$d + $i] = $elem->elem[$s + $i];
+ }
+ }
+
+ private function execInstrTableTableSet(Instrs\Table\TableSet $instr): void
+ {
+ $x = $instr->table;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$a];
+ $val = $this->stack->popRef();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($tab->elem) <= $i) {
+ throw new TrapException("table.set: out of bounds", trapKind: TrapKind::OutOfBoundsTableAccess);
+ }
+ // @phpstan-ignore-next-line
+ $tab->elem[$i] = $val;
+ }
+
+ private function execInstrTableTableSize(Instrs\Table\TableSize $instr): void
+ {
+ $x = $instr->table;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$a];
+ $sz = count($tab->elem);
+ $this->stack->pushValue($sz);
+ }
+
+ private function execInstrMemoryDataDrop(Instrs\Memory\DataDrop $instr): void
+ {
+ $x = $instr->data;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->dataAddrs[$x];
+ // @phpstan-ignore-next-line
+ $this->store->datas[$a] = new DataInst([]);
+ }
+
+ private function execInstrMemoryF32Load(Instrs\Memory\F32Load $instr): void
+ {
+ $this->doLoadF32($instr->offset, $instr::opName());
+ }
+
+ private function execInstrMemoryF32Store(Instrs\Memory\F32Store $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popFloat();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeF32($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryF64Load(Instrs\Memory\F64Load $instr): void
+ {
+ $this->doLoadF64($instr->offset, $instr::opName());
+ }
+
+ private function execInstrMemoryF64Store(Instrs\Memory\F64Store $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popFloat();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeF64($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI32Load(Instrs\Memory\I32Load $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI32_s32($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI32Load16S(Instrs\Memory\I32Load16S $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI32_s16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI32Load16U(Instrs\Memory\I32Load16U $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI32_u16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI32Load8S(Instrs\Memory\I32Load8S $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI32_s8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI32Load8U(Instrs\Memory\I32Load8U $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI32_u8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI32Store(Instrs\Memory\I32Store $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI32_s32($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI32Store16(Instrs\Memory\I32Store16 $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI32_s16($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI32Store8(Instrs\Memory\I32Store8 $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI32_s8($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI64Load(Instrs\Memory\I64Load $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s64($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Load16S(Instrs\Memory\I64Load16S $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Load16U(Instrs\Memory\I64Load16U $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_u16($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Load32S(Instrs\Memory\I64Load32S $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s32($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Load32U(Instrs\Memory\I64Load32U $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_u32($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Load8S(Instrs\Memory\I64Load8S $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_s8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Load8U(Instrs\Memory\I64Load8U $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadI64_u8($ea);
+ if ($c === null) {
+ throw new TrapException($instr::opName() . ": out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function execInstrMemoryI64Store(Instrs\Memory\I64Store $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s64($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size(), trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI64Store16(Instrs\Memory\I64Store16 $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s16($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size(), trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI64Store32(Instrs\Memory\I64Store32 $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s32($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size(), trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryI64Store8(Instrs\Memory\I64Store8 $instr): void
+ {
+ $offset = $instr->offset;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $c = $this->stack->popInt();
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $ok = $mem->storeI64_s8($ea, $c);
+ if (!$ok) {
+ throw new TrapException($instr::opName() . ": out of bounds: $ea >= " . $mem->size(), trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ }
+
+ private function execInstrMemoryMemoryCopy(Instrs\Memory\MemoryCopy $instr): void
+ {
+ $f = $this->stack->currentFrame();
+ $ma = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$ma];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $s = NumericOps::convertS32ToU32($this->stack->popInt());
+ $d = NumericOps::convertS32ToU32($this->stack->popInt());
+ if ($mem->size() < $s + $n || $mem->size() < $d + $n) {
+ throw new TrapException("memory.copy: out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $mem->memcpy($d, $s, $n);
+ }
+
+ private function execInstrMemoryMemoryFill(Instrs\Memory\MemoryFill $instr): void
+ {
+ $f = $this->stack->currentFrame();
+ $ma = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$ma];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $val = $this->stack->popInt();
+ $d = NumericOps::convertS32ToU32($this->stack->popInt());
+ if ($mem->size() < $d + $n) {
+ throw new TrapException("memory.fill: out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $mem->memset($d, $val, $n);
+ }
+
+ private function execInstrMemoryMemoryGrow(Instrs\Memory\MemoryGrow $instr): void
+ {
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $result = $mem->grow($n);
+ $this->stack->pushValue($result);
+ }
+
+ private function execInstrMemoryMemoryInit(Instrs\Memory\MemoryInit $instr): void
+ {
+ $x = $instr->data;
+ $f = $this->stack->currentFrame();
+ $ma = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$ma];
+ $da = $f->module->dataAddrs[$x];
+ $data = $this->store->datas[$da];
+ $n = NumericOps::convertS32ToU32($this->stack->popInt());
+ $s = NumericOps::convertS32ToU32($this->stack->popInt());
+ $d = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($data->data) < $s + $n) {
+ throw new TrapException("memory.init: out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ if ($mem->size() < $d + $n) {
+ throw new TrapException("memory.init: out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $mem->copyData($data->data, $s, $d, $n);
+ }
+
+ private function execInstrMemoryMemorySize(Instrs\Memory\MemorySize $instr): void
+ {
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $szInByte = $mem->size();
+ assert(is_int($szInByte / (64 * 1024)));
+ $sz = $szInByte / (64 * 1024);
+ $this->stack->pushValue($sz);
+ }
+
+ private function execInstrControlBlock(Instrs\Control\Block $instr): ?int
+ {
+ $blockType = $instr->type;
+ $instrs = $instr->body;
+ $f = $this->stack->currentFrame();
+ $bt = self::expandBlockType($blockType, $f->module);
+ $params = array_reverse($this->stack->popNValues(count($bt->params->types)));
+ $n = count($bt->results->types);
+ $l = new Label($n);
+ $result = $this->execInstrs($instrs, $l, $params);
+ if ($result === null) {
+ // Do nothing.
+ } elseif ($result === -1) {
+ return -1;
+ } elseif ($result === 0) {
+ $this->deactivateLabel($n);
+ } else {
+ $this->deactivateLabel(null);
+ return $result - 1;
+ }
+ return null;
+ }
+
+ private function execInstrControlBr(Instrs\Control\Br $instr): int
+ {
+ return $instr->label;
+ }
+
+ private function execInstrControlBrIf(Instrs\Control\BrIf $instr): ?int
+ {
+ $l = $instr->label;
+ $c = $this->stack->popInt();
+ if ($c !== 0) {
+ return $l;
+ } else {
+ return null;
+ }
+ }
+
+ private function execInstrControlBrTable(Instrs\Control\BrTable $instr): int
+ {
+ $ls = $instr->labelTable;
+ $ln = $instr->defaultLabel;
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ if ($i < count($ls)) {
+ return $ls[$i];
+ } else {
+ return $ln;
+ }
+ }
+
+ private function execInstrControlCall(Instrs\Control\Call $instr): void
+ {
+ $x = $instr->func;
+ $f = $this->stack->currentFrame();
+ $a = $f->module->funcAddrs[$x];
+ $this->doInvokeFunc($a);
+ }
+
+ private function execInstrControlCallIndirect(Instrs\Control\CallIndirect $instr): void
+ {
+ $x = $instr->funcTable;
+ $y = $instr->type;
+ $f = $this->stack->currentFrame();
+ $ta = $f->module->tableAddrs[$x];
+ $tab = $this->store->tables[$ta];
+ $ftExpect = $f->module->types[$y];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ if (count($tab->elem) <= $i) {
+ throw new TrapException("call_indirect: out of bounds", trapKind: TrapKind::UndefinedElement);
+ }
+ $r = $tab->elem[$i];
+ if ($r instanceof Refs\RefNull) {
+ throw new TrapException("call_indirect: ref.null", trapKind: TrapKind::UninitializedElement);
+ }
+ assert($r instanceof Refs\RefFunc);
+ $a = $r->addr;
+ $fn = $this->store->funcs[$a];
+ assert($fn instanceof FuncInsts\Wasm || $fn instanceof FuncInsts\Host);
+ $ftActual = $fn->type;
+ if (!$ftExpect->equals($ftActual)) {
+ throw new TrapException("call_indirect: type mismatch", trapKind: TrapKind::IndirectCallTypeMismatch);
+ }
+ $this->doInvokeFunc($a);
+ }
+
+ private function execInstrControlElse_(Instrs\Control\Else_ $instr): void
+ {
+ // Do nothing.
+ }
+
+ private function execInstrControlEnd(Instrs\Control\End $instr): void
+ {
+ // Do nothing.
+ }
+
+ private function execInstrControlIf_(Instrs\Control\If_ $instr): ?int
+ {
+ $blockType = $instr->type;
+ $instrs1 = $instr->thenBody;
+ $instrs2 = $instr->elseBody;
+ $c = $this->stack->popInt();
+ if ($c !== 0) {
+ return $this->execInstr(Instr::Block($blockType, $instrs1));
+ } else {
+ return $this->execInstr(Instr::Block($blockType, $instrs2));
+ }
+ }
+
+ private function execInstrControlLoop(Instrs\Control\Loop $instr): ?int
+ {
+ $blockType = $instr->type;
+ $instrs = $instr->body;
+ $f = $this->stack->currentFrame();
+ $bt = self::expandBlockType($blockType, $f->module);
+ $m = count($bt->params->types);
+ $l = new Label($m);
+ while (true) {
+ $params = array_reverse($this->stack->popNValues($m));
+ $result = $this->execInstrs($instrs, $l, $params);
+ if ($result === null) {
+ return null;
+ } elseif ($result === -1) {
+ return -1;
+ } elseif ($result === 0) {
+ $this->deactivateLabel($m);
+ continue;
+ } else {
+ $this->deactivateLabel(null);
+ return $result - 1;
+ }
+ }
+ }
+
+ private function execInstrControlNop(Instrs\Control\Nop $instr): void
+ {
+ // Do nothing.
+ }
+
+ private function execInstrControlReturn_(Instrs\Control\Return_ $instr): int
+ {
+ return -1;
+ }
+
+ private function execInstrControlUnreachable(Instrs\Control\Unreachable $instr): void
+ {
+ throw new TrapException("unreachable", trapKind: TrapKind::Unreachable);
+ }
+
+ private function doLoadF32(int $offset, string $instrOpName): void
+ {
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadF32($ea);
+ if ($c === null) {
+ throw new TrapException("$instrOpName: out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private function doLoadF64(int $offset, string $instrOpName): void
+ {
+ $f = $this->stack->currentFrame();
+ $a = $f->module->memAddrs[0];
+ $mem = $this->store->mems[$a];
+ $i = NumericOps::convertS32ToU32($this->stack->popInt());
+ $ea = $i + $offset;
+ $c = $mem->loadF64($ea);
+ if ($c === null) {
+ throw new TrapException("$instrOpName: out of bounds", trapKind: TrapKind::OutOfBoundsMemoryAccess);
+ }
+ $this->stack->pushValue($c);
+ }
+
+ private static function defaultValueFromValType(ValType $type): int|float|Ref
+ {
+ return match ($type::class) {
+ ValTypes\NumType::class => match ($type->inner) {
+ NumType::I32 => 0,
+ NumType::I64 => 0,
+ NumType::F32 => 0.0,
+ NumType::F64 => 0.0,
+ },
+ ValTypes\RefType::class => Ref::RefNull($type->inner),
+ default => throw new RuntimeException("unreachable"),
+ };
+ }
+
+ private static function expandBlockType(BlockType $bt, ModuleInst $module): FuncType
+ {
+ if ($bt instanceof BlockTypes\TypeIdx) {
+ return $module->types[$bt->inner];
+ } elseif ($bt instanceof BlockTypes\ValType) {
+ $t = $bt->inner;
+ return new FuncType(
+ new ResultType([]),
+ new ResultType($t === null ? [] : [$t]),
+ );
+ } else {
+ throw new RuntimeException("expand(): invalid blocktype");
+ }
+ }
+}
diff --git a/src/WebAssembly/Execution/Stack.php b/src/WebAssembly/Execution/Stack.php
new file mode 100644
index 0000000..4181dcd
--- /dev/null
+++ b/src/WebAssembly/Execution/Stack.php
@@ -0,0 +1,212 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+use function assert;
+use function count;
+use function is_float;
+use function is_int;
+use function is_null;
+
+final class Stack
+{
+ /**
+ * @var list<Frame>
+ */
+ private array $frames = [];
+
+ private ?Frame $currentFrame = null;
+
+ /**
+ * @var list<int|float|Ref|Frame|Label>
+ */
+ private array $entries;
+
+ public function __construct()
+ {
+ }
+
+ public function pushFrame(Frame $frame): void
+ {
+ if ($this->getCallStackLimit() <= count($this->frames)) {
+ throw new StackOverflowException();
+ }
+ $this->push($frame);
+ $this->frames[] = $frame;
+ $this->currentFrame = $frame;
+ }
+
+ public function pushLabel(Label $label): void
+ {
+ $this->push($label);
+ }
+
+ public function pushValue(int|float|Ref $val): void
+ {
+ $this->push($val);
+ }
+
+ public function pushBool(bool $value): void
+ {
+ $this->pushValue((int)$value);
+ }
+
+ public function pushRefNull(RefType $type): void
+ {
+ $this->pushValue(Ref::RefNull($type));
+ }
+
+ public function pushRefFunc(int $addr): void
+ {
+ $this->pushValue(Ref::RefFunc($addr));
+ }
+
+ public function pushRefExtern(int $addr): void
+ {
+ $this->pushValue(Ref::RefExtern($addr));
+ }
+
+ public function clear(): void
+ {
+ $this->frames = [];
+ $this->currentFrame = null;
+ $this->entries = [];
+ }
+
+ public function popFrame(): Frame
+ {
+ $result = $this->pop();
+ assert($result instanceof Frame);
+ array_pop($this->frames);
+ if (count($this->frames) === 0) {
+ $this->currentFrame = null;
+ } else {
+ $this->currentFrame = end($this->frames);
+ }
+ return $result;
+ }
+
+ public function popValue(): int|float|Ref
+ {
+ $result = $this->pop();
+ assert(
+ is_int($result) || is_float($result) || $result instanceof Ref,
+ 'Expected a value on the stack, but got ' . print_r($result, true),
+ );
+ return $result;
+ }
+
+ /**
+ * @return list<int|float|Ref>
+ */
+ public function popNValues(int $n): array
+ {
+ $results = [];
+ for ($i = 0; $i < $n; $i++) {
+ $results[] = $this->popValue();
+ }
+ return $results;
+ }
+
+ public function popInt(): int
+ {
+ $v = $this->popValue();
+ assert(is_int($v), "Expected an int on top of the stack, but got " . self::getValueTypeName($v));
+ return $v;
+ }
+
+ /**
+ * @return F32
+ */
+ public function popFloat(): float
+ {
+ $v = $this->popValue();
+ assert(is_float($v), "Expected a float on top of the stack, but got " . self::getValueTypeName($v));
+ return $v;
+ }
+
+ public function popRef(): Ref
+ {
+ $v = $this->popValue();
+ assert($v instanceof Ref, "Expected a Ref on top of the stack, but got " . self::getValueTypeName($v));
+ return $v;
+ }
+
+ /**
+ * @return list<int|float|Ref>
+ */
+ public function popValuesToLabel(): array
+ {
+ $results = [];
+ while (!$this->isEmpty()) {
+ $top = $this->pop();
+ if ($top instanceof Label) {
+ break;
+ } else {
+ assert(is_int($top) || is_float($top) || $top instanceof Ref);
+ $results[] = $top;
+ }
+ }
+ return $results;
+ }
+
+ public function popEntriesToCurrentFrame(): void
+ {
+ while (!$this->isEmpty() && !$this->top() instanceof Frame) {
+ $this->pop();
+ }
+ $this->popFrame();
+ }
+
+ public function top(): int|float|Ref|Frame|Label|null
+ {
+ $n = array_key_last($this->entries);
+ return $n === null ? null : $this->entries[$n];
+ }
+
+ public function count(): int
+ {
+ return count($this->entries);
+ }
+
+ public function isEmpty(): bool
+ {
+ return $this->count() === 0;
+ }
+
+ public function currentFrame(): Frame
+ {
+ assert($this->currentFrame !== null);
+ return $this->currentFrame;
+ }
+
+ public function getCallStackLimit(): int
+ {
+ return 1024;
+ }
+
+ private function push(int|float|Ref|Frame|Label $entry): void
+ {
+ $this->entries[] = $entry;
+ }
+
+ private function pop(): int|float|Ref|Frame|Label|null
+ {
+ return array_pop($this->entries);
+ }
+
+ private static function getValueTypeName(int|float|Ref|Frame|Label|null $value): string
+ {
+ return match (true) {
+ is_null($value) => 'null',
+ is_int($value) => 'int',
+ is_float($value) => 'float',
+ $value instanceof Ref => 'Ref',
+ $value instanceof Frame => 'Frame',
+ $value instanceof Label => 'Label',
+ };
+ }
+}
diff --git a/src/WebAssembly/Execution/StackOverflowException.php b/src/WebAssembly/Execution/StackOverflowException.php
new file mode 100644
index 0000000..c5ff3a4
--- /dev/null
+++ b/src/WebAssembly/Execution/StackOverflowException.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use RuntimeException;
+use Throwable;
+
+final class StackOverflowException extends RuntimeException
+{
+ public function __construct(
+ string $message = 'Stack overflow',
+ int $code = 0,
+ Throwable $previous = null,
+ ) {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/src/WebAssembly/Execution/Store.php b/src/WebAssembly/Execution/Store.php
new file mode 100644
index 0000000..5bef648
--- /dev/null
+++ b/src/WebAssembly/Execution/Store.php
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use RuntimeException;
+use function count;
+
+final class Store
+{
+ /**
+ * @param list<FuncInst> $funcs
+ * @param list<TableInst> $tables
+ * @param list<MemInst> $mems
+ * @param list<GlobalInst> $globals
+ * @param list<ElemInst> $elems
+ * @param list<DataInst> $datas
+ */
+ public function __construct(
+ public array $funcs,
+ public array $tables,
+ public array $mems,
+ public array $globals,
+ public array $elems,
+ public array $datas,
+ ) {
+ }
+
+ public static function empty(): self
+ {
+ return new self([], [], [], [], [], []);
+ }
+
+ public function register(Extern $extern): ExternVal
+ {
+ match ($extern::class) {
+ Externs\Func::class => $this->funcs[] = $extern->func,
+ Externs\Table::class => $this->tables[] = $extern->table,
+ Externs\Mem::class => $this->mems[] = $extern->mem,
+ Externs\Global_::class => $this->globals[] = $extern->global,
+ default => throw new RuntimeException("unreachable"),
+ };
+ return match ($extern::class) {
+ Externs\Func::class => ExternVal::Func(count($this->funcs) - 1),
+ Externs\Table::class => ExternVal::Table(count($this->tables) - 1),
+ Externs\Mem::class => ExternVal::Mem(count($this->mems) - 1),
+ Externs\Global_::class => ExternVal::Global_(count($this->globals) - 1),
+ default => throw new RuntimeException("unreachable"),
+ };
+ }
+}
diff --git a/src/WebAssembly/Execution/TableInst.php b/src/WebAssembly/Execution/TableInst.php
new file mode 100644
index 0000000..9f4cbe7
--- /dev/null
+++ b/src/WebAssembly/Execution/TableInst.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+
+final class TableInst
+{
+ /**
+ * @param list<Ref> $elem
+ */
+ public function __construct(
+ public TableType $type,
+ public array $elem,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Execution/TrapException.php b/src/WebAssembly/Execution/TrapException.php
new file mode 100644
index 0000000..449f9ca
--- /dev/null
+++ b/src/WebAssembly/Execution/TrapException.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+use RuntimeException;
+use Throwable;
+
+class TrapException extends RuntimeException
+{
+ private readonly TrapKind $trapKind;
+
+ public function __construct(
+ string $message = "",
+ int $code = 0,
+ ?Throwable $previous = null,
+ TrapKind $trapKind = TrapKind::Unknown,
+ ) {
+ parent::__construct($message, $code, $previous);
+ $this->trapKind = $trapKind;
+ }
+
+ public function getTrapKind(): TrapKind
+ {
+ return $this->trapKind;
+ }
+}
diff --git a/src/WebAssembly/Execution/TrapKind.php b/src/WebAssembly/Execution/TrapKind.php
new file mode 100644
index 0000000..35a4372
--- /dev/null
+++ b/src/WebAssembly/Execution/TrapKind.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Execution;
+
+enum TrapKind
+{
+ case Unknown;
+ case Unreachable;
+ case OutOfBoundsMemoryAccess;
+ case OutOfBoundsTableAccess;
+ case UninitializedElement;
+ case IndirectCallTypeMismatch;
+ case UndefinedElement;
+ case DivideByZero;
+ case IntegerOverflow;
+ case InvalidConversionToInteger;
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instr.php b/src/WebAssembly/Structure/Instructions/Instr.php
new file mode 100644
index 0000000..18531c6
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instr.php
@@ -0,0 +1,971 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Parametric;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Reference;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Variable;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+abstract readonly class Instr
+{
+ // Numeric instructions
+ final public static function F32Abs(): Numeric\F32Abs
+ {
+ return new Numeric\F32Abs();
+ }
+ final public static function F32Add(): Numeric\F32Add
+ {
+ return new Numeric\F32Add();
+ }
+ final public static function F32Ceil(): Numeric\F32Ceil
+ {
+ return new Numeric\F32Ceil();
+ }
+ /**
+ * @param F32 $value
+ */
+ final public static function F32Const(float $value): Numeric\F32Const
+ {
+ return new Numeric\F32Const($value);
+ }
+ final public static function F32ConvertI32S(): Numeric\F32ConvertI32S
+ {
+ return new Numeric\F32ConvertI32S();
+ }
+ final public static function F32ConvertI32U(): Numeric\F32ConvertI32U
+ {
+ return new Numeric\F32ConvertI32U();
+ }
+ final public static function F32ConvertI64S(): Numeric\F32ConvertI64S
+ {
+ return new Numeric\F32ConvertI64S();
+ }
+ final public static function F32ConvertI64U(): Numeric\F32ConvertI64U
+ {
+ return new Numeric\F32ConvertI64U();
+ }
+ final public static function F32CopySign(): Numeric\F32CopySign
+ {
+ return new Numeric\F32CopySign();
+ }
+ final public static function F32DemoteF64(): Numeric\F32DemoteF64
+ {
+ return new Numeric\F32DemoteF64();
+ }
+ final public static function F32Div(): Numeric\F32Div
+ {
+ return new Numeric\F32Div();
+ }
+ final public static function F32Eq(): Numeric\F32Eq
+ {
+ return new Numeric\F32Eq();
+ }
+ final public static function F32Floor(): Numeric\F32Floor
+ {
+ return new Numeric\F32Floor();
+ }
+ final public static function F32Ge(): Numeric\F32Ge
+ {
+ return new Numeric\F32Ge();
+ }
+ final public static function F32Gt(): Numeric\F32Gt
+ {
+ return new Numeric\F32Gt();
+ }
+ final public static function F32Le(): Numeric\F32Le
+ {
+ return new Numeric\F32Le();
+ }
+ final public static function F32Lt(): Numeric\F32Lt
+ {
+ return new Numeric\F32Lt();
+ }
+ final public static function F32Max(): Numeric\F32Max
+ {
+ return new Numeric\F32Max();
+ }
+ final public static function F32Min(): Numeric\F32Min
+ {
+ return new Numeric\F32Min();
+ }
+ final public static function F32Mul(): Numeric\F32Mul
+ {
+ return new Numeric\F32Mul();
+ }
+ final public static function F32Ne(): Numeric\F32Ne
+ {
+ return new Numeric\F32Ne();
+ }
+ final public static function F32Nearest(): Numeric\F32Nearest
+ {
+ return new Numeric\F32Nearest();
+ }
+ final public static function F32Neg(): Numeric\F32Neg
+ {
+ return new Numeric\F32Neg();
+ }
+ final public static function F32ReinterpretI32(): Numeric\F32ReinterpretI32
+ {
+ return new Numeric\F32ReinterpretI32();
+ }
+ final public static function F32ReinterpretI64(): Numeric\F32ReinterpretI64
+ {
+ return new Numeric\F32ReinterpretI64();
+ }
+ final public static function F32Sqrt(): Numeric\F32Sqrt
+ {
+ return new Numeric\F32Sqrt();
+ }
+ final public static function F32Sub(): Numeric\F32Sub
+ {
+ return new Numeric\F32Sub();
+ }
+ final public static function F32Trunc(): Numeric\F32Trunc
+ {
+ return new Numeric\F32Trunc();
+ }
+ final public static function F64Abs(): Numeric\F64Abs
+ {
+ return new Numeric\F64Abs();
+ }
+ final public static function F64Add(): Numeric\F64Add
+ {
+ return new Numeric\F64Add();
+ }
+ final public static function F64Ceil(): Numeric\F64Ceil
+ {
+ return new Numeric\F64Ceil();
+ }
+ /**
+ * @param F64 $value
+ */
+ final public static function F64Const(float $value): Numeric\F64Const
+ {
+ return new Numeric\F64Const($value);
+ }
+ final public static function F64ConvertI32S(): Numeric\F64ConvertI32S
+ {
+ return new Numeric\F64ConvertI32S();
+ }
+ final public static function F64ConvertI32U(): Numeric\F64ConvertI32U
+ {
+ return new Numeric\F64ConvertI32U();
+ }
+ final public static function F64ConvertI64S(): Numeric\F64ConvertI64S
+ {
+ return new Numeric\F64ConvertI64S();
+ }
+ final public static function F64ConvertI64U(): Numeric\F64ConvertI64U
+ {
+ return new Numeric\F64ConvertI64U();
+ }
+ final public static function F64CopySign(): Numeric\F64CopySign
+ {
+ return new Numeric\F64CopySign();
+ }
+ final public static function F64Div(): Numeric\F64Div
+ {
+ return new Numeric\F64Div();
+ }
+ final public static function F64Eq(): Numeric\F64Eq
+ {
+ return new Numeric\F64Eq();
+ }
+ final public static function F64Floor(): Numeric\F64Floor
+ {
+ return new Numeric\F64Floor();
+ }
+ final public static function F64Ge(): Numeric\F64Ge
+ {
+ return new Numeric\F64Ge();
+ }
+ final public static function F64Gt(): Numeric\F64Gt
+ {
+ return new Numeric\F64Gt();
+ }
+ final public static function F64Le(): Numeric\F64Le
+ {
+ return new Numeric\F64Le();
+ }
+ final public static function F64Lt(): Numeric\F64Lt
+ {
+ return new Numeric\F64Lt();
+ }
+ final public static function F64Max(): Numeric\F64Max
+ {
+ return new Numeric\F64Max();
+ }
+ final public static function F64Min(): Numeric\F64Min
+ {
+ return new Numeric\F64Min();
+ }
+ final public static function F64Mul(): Numeric\F64Mul
+ {
+ return new Numeric\F64Mul();
+ }
+ final public static function F64Ne(): Numeric\F64Ne
+ {
+ return new Numeric\F64Ne();
+ }
+ final public static function F64Nearest(): Numeric\F64Nearest
+ {
+ return new Numeric\F64Nearest();
+ }
+ final public static function F64Neg(): Numeric\F64Neg
+ {
+ return new Numeric\F64Neg();
+ }
+ final public static function F64PromoteF32(): Numeric\F64PromoteF32
+ {
+ return new Numeric\F64PromoteF32();
+ }
+ final public static function F64ReinterpretI32(): Numeric\F64ReinterpretI32
+ {
+ return new Numeric\F64ReinterpretI32();
+ }
+ final public static function F64ReinterpretI64(): Numeric\F64ReinterpretI64
+ {
+ return new Numeric\F64ReinterpretI64();
+ }
+ final public static function F64Sqrt(): Numeric\F64Sqrt
+ {
+ return new Numeric\F64Sqrt();
+ }
+ final public static function F64Sub(): Numeric\F64Sub
+ {
+ return new Numeric\F64Sub();
+ }
+ final public static function F64Trunc(): Numeric\F64Trunc
+ {
+ return new Numeric\F64Trunc();
+ }
+ final public static function I32Add(): Numeric\I32Add
+ {
+ return new Numeric\I32Add();
+ }
+ final public static function I32And(): Numeric\I32And
+ {
+ return new Numeric\I32And();
+ }
+ final public static function I32Clz(): Numeric\I32Clz
+ {
+ return new Numeric\I32Clz();
+ }
+ /**
+ * @param S64 $value
+ */
+ final public static function I32Const(int $value): Numeric\I32Const
+ {
+ return new Numeric\I32Const($value);
+ }
+ final public static function I32Ctz(): Numeric\I32Ctz
+ {
+ return new Numeric\I32Ctz();
+ }
+ final public static function I32DivS(): Numeric\I32DivS
+ {
+ return new Numeric\I32DivS();
+ }
+ final public static function I32DivU(): Numeric\I32DivU
+ {
+ return new Numeric\I32DivU();
+ }
+ final public static function I32Eq(): Numeric\I32Eq
+ {
+ return new Numeric\I32Eq();
+ }
+ final public static function I32Eqz(): Numeric\I32Eqz
+ {
+ return new Numeric\I32Eqz();
+ }
+ final public static function I32Extend16S(): Numeric\I32Extend16S
+ {
+ return new Numeric\I32Extend16S();
+ }
+ final public static function I32Extend8S(): Numeric\I32Extend8S
+ {
+ return new Numeric\I32Extend8S();
+ }
+ final public static function I32GeS(): Numeric\I32GeS
+ {
+ return new Numeric\I32GeS();
+ }
+ final public static function I32GeU(): Numeric\I32GeU
+ {
+ return new Numeric\I32GeU();
+ }
+ final public static function I32GtS(): Numeric\I32GtS
+ {
+ return new Numeric\I32GtS();
+ }
+ final public static function I32GtU(): Numeric\I32GtU
+ {
+ return new Numeric\I32GtU();
+ }
+ final public static function I32LeS(): Numeric\I32LeS
+ {
+ return new Numeric\I32LeS();
+ }
+ final public static function I32LeU(): Numeric\I32LeU
+ {
+ return new Numeric\I32LeU();
+ }
+ final public static function I32LtS(): Numeric\I32LtS
+ {
+ return new Numeric\I32LtS();
+ }
+ final public static function I32LtU(): Numeric\I32LtU
+ {
+ return new Numeric\I32LtU();
+ }
+ final public static function I32Mul(): Numeric\I32Mul
+ {
+ return new Numeric\I32Mul();
+ }
+ final public static function I32Ne(): Numeric\I32Ne
+ {
+ return new Numeric\I32Ne();
+ }
+ final public static function I32Or(): Numeric\I32Or
+ {
+ return new Numeric\I32Or();
+ }
+ final public static function I32Popcnt(): Numeric\I32Popcnt
+ {
+ return new Numeric\I32Popcnt();
+ }
+ final public static function I32ReinterpretF32(): Numeric\I32ReinterpretF32
+ {
+ return new Numeric\I32ReinterpretF32();
+ }
+ final public static function I32ReinterpretF64(): Numeric\I32ReinterpretF64
+ {
+ return new Numeric\I32ReinterpretF64();
+ }
+ final public static function I32RemS(): Numeric\I32RemS
+ {
+ return new Numeric\I32RemS();
+ }
+ final public static function I32RemU(): Numeric\I32RemU
+ {
+ return new Numeric\I32RemU();
+ }
+ final public static function I32RotL(): Numeric\I32RotL
+ {
+ return new Numeric\I32RotL();
+ }
+ final public static function I32RotR(): Numeric\I32RotR
+ {
+ return new Numeric\I32RotR();
+ }
+ final public static function I32Shl(): Numeric\I32Shl
+ {
+ return new Numeric\I32Shl();
+ }
+ final public static function I32ShrS(): Numeric\I32ShrS
+ {
+ return new Numeric\I32ShrS();
+ }
+ final public static function I32ShrU(): Numeric\I32ShrU
+ {
+ return new Numeric\I32ShrU();
+ }
+ final public static function I32Sub(): Numeric\I32Sub
+ {
+ return new Numeric\I32Sub();
+ }
+ final public static function I32TruncF32S(): Numeric\I32TruncF32S
+ {
+ return new Numeric\I32TruncF32S();
+ }
+ final public static function I32TruncF32U(): Numeric\I32TruncF32U
+ {
+ return new Numeric\I32TruncF32U();
+ }
+ final public static function I32TruncF64S(): Numeric\I32TruncF64S
+ {
+ return new Numeric\I32TruncF64S();
+ }
+ final public static function I32TruncF64U(): Numeric\I32TruncF64U
+ {
+ return new Numeric\I32TruncF64U();
+ }
+ final public static function I32TruncSatF32S(): Numeric\I32TruncSatF32S
+ {
+ return new Numeric\I32TruncSatF32S();
+ }
+ final public static function I32TruncSatF32U(): Numeric\I32TruncSatF32U
+ {
+ return new Numeric\I32TruncSatF32U();
+ }
+ final public static function I32TruncSatF64S(): Numeric\I32TruncSatF64S
+ {
+ return new Numeric\I32TruncSatF64S();
+ }
+ final public static function I32TruncSatF64U(): Numeric\I32TruncSatF64U
+ {
+ return new Numeric\I32TruncSatF64U();
+ }
+ final public static function I32WrapI64(): Numeric\I32WrapI64
+ {
+ return new Numeric\I32WrapI64();
+ }
+ final public static function I32Xor(): Numeric\I32Xor
+ {
+ return new Numeric\I32Xor();
+ }
+ final public static function I64Add(): Numeric\I64Add
+ {
+ return new Numeric\I64Add();
+ }
+ final public static function I64And(): Numeric\I64And
+ {
+ return new Numeric\I64And();
+ }
+ final public static function I64Clz(): Numeric\I64Clz
+ {
+ return new Numeric\I64Clz();
+ }
+ /**
+ * @param S64 $value
+ */
+ final public static function I64Const(int $value): Numeric\I64Const
+ {
+ return new Numeric\I64Const($value);
+ }
+ final public static function I64Ctz(): Numeric\I64Ctz
+ {
+ return new Numeric\I64Ctz();
+ }
+ final public static function I64DivS(): Numeric\I64DivS
+ {
+ return new Numeric\I64DivS();
+ }
+ final public static function I64DivU(): Numeric\I64DivU
+ {
+ return new Numeric\I64DivU();
+ }
+ final public static function I64Eq(): Numeric\I64Eq
+ {
+ return new Numeric\I64Eq();
+ }
+ final public static function I64Eqz(): Numeric\I64Eqz
+ {
+ return new Numeric\I64Eqz();
+ }
+ final public static function I64Extend16S(): Numeric\I64Extend16S
+ {
+ return new Numeric\I64Extend16S();
+ }
+ final public static function I64Extend32S(): Numeric\I64Extend32S
+ {
+ return new Numeric\I64Extend32S();
+ }
+ final public static function I64Extend8S(): Numeric\I64Extend8S
+ {
+ return new Numeric\I64Extend8S();
+ }
+ final public static function I64ExtendI32S(): Numeric\I64ExtendI32S
+ {
+ return new Numeric\I64ExtendI32S();
+ }
+ final public static function I64ExtendI32U(): Numeric\I64ExtendI32U
+ {
+ return new Numeric\I64ExtendI32U();
+ }
+ final public static function I64GeS(): Numeric\I64GeS
+ {
+ return new Numeric\I64GeS();
+ }
+ final public static function I64GeU(): Numeric\I64GeU
+ {
+ return new Numeric\I64GeU();
+ }
+ final public static function I64GtS(): Numeric\I64GtS
+ {
+ return new Numeric\I64GtS();
+ }
+ final public static function I64GtU(): Numeric\I64GtU
+ {
+ return new Numeric\I64GtU();
+ }
+ final public static function I64LeS(): Numeric\I64LeS
+ {
+ return new Numeric\I64LeS();
+ }
+ final public static function I64LeU(): Numeric\I64LeU
+ {
+ return new Numeric\I64LeU();
+ }
+ final public static function I64LtS(): Numeric\I64LtS
+ {
+ return new Numeric\I64LtS();
+ }
+ final public static function I64LtU(): Numeric\I64LtU
+ {
+ return new Numeric\I64LtU();
+ }
+ final public static function I64Mul(): Numeric\I64Mul
+ {
+ return new Numeric\I64Mul();
+ }
+ final public static function I64Ne(): Numeric\I64Ne
+ {
+ return new Numeric\I64Ne();
+ }
+ final public static function I64Or(): Numeric\I64Or
+ {
+ return new Numeric\I64Or();
+ }
+ final public static function I64Popcnt(): Numeric\I64Popcnt
+ {
+ return new Numeric\I64Popcnt();
+ }
+ final public static function I64ReinterpretF32(): Numeric\I64ReinterpretF32
+ {
+ return new Numeric\I64ReinterpretF32();
+ }
+ final public static function I64ReinterpretF64(): Numeric\I64ReinterpretF64
+ {
+ return new Numeric\I64ReinterpretF64();
+ }
+ final public static function I64RemS(): Numeric\I64RemS
+ {
+ return new Numeric\I64RemS();
+ }
+ final public static function I64RemU(): Numeric\I64RemU
+ {
+ return new Numeric\I64RemU();
+ }
+ final public static function I64RotL(): Numeric\I64RotL
+ {
+ return new Numeric\I64RotL();
+ }
+ final public static function I64RotR(): Numeric\I64RotR
+ {
+ return new Numeric\I64RotR();
+ }
+ final public static function I64Shl(): Numeric\I64Shl
+ {
+ return new Numeric\I64Shl();
+ }
+ final public static function I64ShrS(): Numeric\I64ShrS
+ {
+ return new Numeric\I64ShrS();
+ }
+ final public static function I64ShrU(): Numeric\I64ShrU
+ {
+ return new Numeric\I64ShrU();
+ }
+ final public static function I64Sub(): Numeric\I64Sub
+ {
+ return new Numeric\I64Sub();
+ }
+ final public static function I64TruncF32S(): Numeric\I64TruncF32S
+ {
+ return new Numeric\I64TruncF32S();
+ }
+ final public static function I64TruncF32U(): Numeric\I64TruncF32U
+ {
+ return new Numeric\I64TruncF32U();
+ }
+ final public static function I64TruncF64S(): Numeric\I64TruncF64S
+ {
+ return new Numeric\I64TruncF64S();
+ }
+ final public static function I64TruncF64U(): Numeric\I64TruncF64U
+ {
+ return new Numeric\I64TruncF64U();
+ }
+ final public static function I64TruncSatF32S(): Numeric\I64TruncSatF32S
+ {
+ return new Numeric\I64TruncSatF32S();
+ }
+ final public static function I64TruncSatF32U(): Numeric\I64TruncSatF32U
+ {
+ return new Numeric\I64TruncSatF32U();
+ }
+ final public static function I64TruncSatF64S(): Numeric\I64TruncSatF64S
+ {
+ return new Numeric\I64TruncSatF64S();
+ }
+ final public static function I64TruncSatF64U(): Numeric\I64TruncSatF64U
+ {
+ return new Numeric\I64TruncSatF64U();
+ }
+ final public static function I64Xor(): Numeric\I64Xor
+ {
+ return new Numeric\I64Xor();
+ }
+
+ // Reference instructions
+ final public static function RefFunc(int $func): Reference\RefFunc
+ {
+ return new Reference\RefFunc($func);
+ }
+ final public static function RefIsNull(): Reference\RefIsNull
+ {
+ return new Reference\RefIsNull();
+ }
+ final public static function RefNull(RefType $type): Reference\RefNull
+ {
+ return new Reference\RefNull($type);
+ }
+
+ // Parametric instructions
+ final public static function Drop(): Parametric\Drop
+ {
+ return new Parametric\Drop();
+ }
+ /**
+ * @param list<ValType> $types
+ */
+ final public static function Select(array $types): Parametric\Select
+ {
+ return new Parametric\Select($types);
+ }
+
+ // Variable instructions
+ final public static function GlobalGet(int $var): Variable\GlobalGet
+ {
+ return new Variable\GlobalGet($var);
+ }
+ final public static function GlobalSet(int $var): Variable\GlobalSet
+ {
+ return new Variable\GlobalSet($var);
+ }
+ final public static function LocalGet(int $var): Variable\LocalGet
+ {
+ return new Variable\LocalGet($var);
+ }
+ final public static function LocalSet(int $var): Variable\LocalSet
+ {
+ return new Variable\LocalSet($var);
+ }
+ final public static function LocalTee(int $var): Variable\LocalTee
+ {
+ return new Variable\LocalTee($var);
+ }
+
+ // Table instructions
+ final public static function ElemDrop(int $elem): Table\ElemDrop
+ {
+ return new Table\ElemDrop($elem);
+ }
+ final public static function TableCopy(int $to, int $from): Table\TableCopy
+ {
+ return new Table\TableCopy($to, $from);
+ }
+ final public static function TableFill(int $table): Table\TableFill
+ {
+ return new Table\TableFill($table);
+ }
+ final public static function TableGet(int $table): Table\TableGet
+ {
+ return new Table\TableGet($table);
+ }
+ final public static function TableGrow(int $table): Table\TableGrow
+ {
+ return new Table\TableGrow($table);
+ }
+ final public static function TableInit(int $to, int $from): Table\TableInit
+ {
+ return new Table\TableInit($to, $from);
+ }
+ final public static function TableSet(int $table): Table\TableSet
+ {
+ return new Table\TableSet($table);
+ }
+ final public static function TableSize(int $table): Table\TableSize
+ {
+ return new Table\TableSize($table);
+ }
+
+ // Memory instructions
+ final public static function DataDrop(int $data): Memory\DataDrop
+ {
+ return new Memory\DataDrop($data);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function F32Load(int $offset, int $align): Memory\F32Load
+ {
+ return new Memory\F32Load($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function F32Store(int $offset, int $align): Memory\F32Store
+ {
+ return new Memory\F32Store($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function F64Load(int $offset, int $align): Memory\F64Load
+ {
+ return new Memory\F64Load($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function F64Store(int $offset, int $align): Memory\F64Store
+ {
+ return new Memory\F64Store($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Load(int $offset, int $align): Memory\I32Load
+ {
+ return new Memory\I32Load($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Load16S(int $offset, int $align): Memory\I32Load16S
+ {
+ return new Memory\I32Load16S($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Load16U(int $offset, int $align): Memory\I32Load16U
+ {
+ return new Memory\I32Load16U($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Load8S(int $offset, int $align): Memory\I32Load8S
+ {
+ return new Memory\I32Load8S($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Load8U(int $offset, int $align): Memory\I32Load8U
+ {
+ return new Memory\I32Load8U($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Store(int $offset, int $align): Memory\I32Store
+ {
+ return new Memory\I32Store($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Store16(int $offset, int $align): Memory\I32Store16
+ {
+ return new Memory\I32Store16($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I32Store8(int $offset, int $align): Memory\I32Store8
+ {
+ return new Memory\I32Store8($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load(int $offset, int $align): Memory\I64Load
+ {
+ return new Memory\I64Load($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load16S(int $offset, int $align): Memory\I64Load16S
+ {
+ return new Memory\I64Load16S($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load16U(int $offset, int $align): Memory\I64Load16U
+ {
+ return new Memory\I64Load16U($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load32S(int $offset, int $align): Memory\I64Load32S
+ {
+ return new Memory\I64Load32S($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load32U(int $offset, int $align): Memory\I64Load32U
+ {
+ return new Memory\I64Load32U($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load8S(int $offset, int $align): Memory\I64Load8S
+ {
+ return new Memory\I64Load8S($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Load8U(int $offset, int $align): Memory\I64Load8U
+ {
+ return new Memory\I64Load8U($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Store(int $offset, int $align): Memory\I64Store
+ {
+ return new Memory\I64Store($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Store16(int $offset, int $align): Memory\I64Store16
+ {
+ return new Memory\I64Store16($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Store32(int $offset, int $align): Memory\I64Store32
+ {
+ return new Memory\I64Store32($offset, $align);
+ }
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ final public static function I64Store8(int $offset, int $align): Memory\I64Store8
+ {
+ return new Memory\I64Store8($offset, $align);
+ }
+ final public static function MemoryCopy(): Memory\MemoryCopy
+ {
+ return new Memory\MemoryCopy();
+ }
+ final public static function MemoryFill(): Memory\MemoryFill
+ {
+ return new Memory\MemoryFill();
+ }
+ final public static function MemoryGrow(): Memory\MemoryGrow
+ {
+ return new Memory\MemoryGrow();
+ }
+ final public static function MemoryInit(int $data): Memory\MemoryInit
+ {
+ return new Memory\MemoryInit($data);
+ }
+ final public static function MemorySize(): Memory\MemorySize
+ {
+ return new Memory\MemorySize();
+ }
+
+ // Control instructions
+ /**
+ * @param list<Instr> $body
+ */
+ final public static function Block(BlockType $type, array $body): Control\Block
+ {
+ return new Control\Block($type, $body);
+ }
+ final public static function Br(int $label): Control\Br
+ {
+ return new Control\Br($label);
+ }
+ final public static function BrIf(int $label): Control\BrIf
+ {
+ return new Control\BrIf($label);
+ }
+ /**
+ * @param list<int> $labelTable
+ */
+ final public static function BrTable(array $labelTable, int $defaultLabel): Control\BrTable
+ {
+ return new Control\BrTable($labelTable, $defaultLabel);
+ }
+ final public static function Call(int $func): Control\Call
+ {
+ return new Control\Call($func);
+ }
+ final public static function CallIndirect(int $funcTable, int $type): Control\CallIndirect
+ {
+ return new Control\CallIndirect($funcTable, $type);
+ }
+ final public static function Else_(): Control\Else_
+ {
+ return new Control\Else_();
+ }
+ final public static function End(): Control\End
+ {
+ return new Control\End();
+ }
+ /**
+ * @param list<Instr> $thenBody
+ * @param list<Instr> $elseBody
+ */
+ final public static function If_(BlockType $type, array $thenBody, array $elseBody): Control\If_
+ {
+ return new Control\If_($type, $thenBody, $elseBody);
+ }
+ /**
+ * @param list<Instr> $body
+ */
+ final public static function Loop(BlockType $type, array $body): Control\Loop
+ {
+ return new Control\Loop($type, $body);
+ }
+ final public static function Nop(): Control\Nop
+ {
+ return new Control\Nop();
+ }
+ final public static function Return_(): Control\Return_
+ {
+ return new Control\Return_();
+ }
+ final public static function Unreachable(): Control\Unreachable
+ {
+ return new Control\Unreachable();
+ }
+
+ abstract public static function opName(): string;
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Block.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Block.php
new file mode 100644
index 0000000..af2c97f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Block.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Block extends Instr
+{
+ /**
+ * @param list<Instr> $body
+ */
+ protected function __construct(
+ public BlockType $type,
+ public array $body,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "block";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockType.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockType.php
new file mode 100644
index 0000000..1188625
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockType.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+abstract readonly class BlockType
+{
+ final public static function TypeIdx(int $type): BlockTypes\TypeIdx
+ {
+ return new BlockTypes\TypeIdx($type);
+ }
+
+ final public static function ValType(?ValType $type): BlockTypes\ValType
+ {
+ return new BlockTypes\ValType($type);
+ }
+
+ public static function opName(): string
+ {
+ return "hoge";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/TypeIdx.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/TypeIdx.php
new file mode 100644
index 0000000..2ed694b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/TypeIdx.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockType;
+
+final readonly class TypeIdx extends BlockType
+{
+ protected function __construct(public int $inner)
+ {
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/ValType.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/ValType.php
new file mode 100644
index 0000000..e7caa3f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/BlockTypes/ValType.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control\BlockType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType as OrigValType;
+
+final readonly class ValType extends BlockType
+{
+ protected function __construct(public ?OrigValType $inner)
+ {
+ }
+
+ public static function opName(): string
+ {
+ return "hoge";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Br.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Br.php
new file mode 100644
index 0000000..6235a36
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Br.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Br extends Instr
+{
+ protected function __construct(
+ public int $label,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "br";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/BrIf.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/BrIf.php
new file mode 100644
index 0000000..7c8a896
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/BrIf.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class BrIf extends Instr
+{
+ protected function __construct(
+ public int $label,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "br_if";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/BrTable.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/BrTable.php
new file mode 100644
index 0000000..2841814
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/BrTable.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class BrTable extends Instr
+{
+ /**
+ * @param list<int> $labelTable
+ */
+ protected function __construct(
+ public array $labelTable,
+ public int $defaultLabel,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "br_table";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Call.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Call.php
new file mode 100644
index 0000000..461f561
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Call.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Call extends Instr
+{
+ protected function __construct(
+ public int $func,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "call";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/CallIndirect.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/CallIndirect.php
new file mode 100644
index 0000000..7017723
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/CallIndirect.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class CallIndirect extends Instr
+{
+ protected function __construct(
+ public int $funcTable,
+ public int $type,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "call_indirect";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Else_.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Else_.php
new file mode 100644
index 0000000..1407543
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Else_.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Else_ extends Instr
+{
+ public static function opName(): string
+ {
+ return "else";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/End.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/End.php
new file mode 100644
index 0000000..5bdb8b9
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/End.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class End extends Instr
+{
+ public static function opName(): string
+ {
+ return "end";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/If_.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/If_.php
new file mode 100644
index 0000000..8afdc8b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/If_.php
@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class If_ extends Instr
+{
+ /**
+ * @param list<Instr> $thenBody
+ * @param list<Instr> $elseBody
+ */
+ protected function __construct(
+ public BlockType $type,
+ public array $thenBody,
+ public array $elseBody,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "if";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Loop.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Loop.php
new file mode 100644
index 0000000..ca48ca1
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Loop.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Loop extends Instr
+{
+ /**
+ * @param list<Instr> $body
+ */
+ protected function __construct(
+ public BlockType $type,
+ public array $body,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "loop";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Nop.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Nop.php
new file mode 100644
index 0000000..50a3773
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Nop.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Nop extends Instr
+{
+ public static function opName(): string
+ {
+ return "nop";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Return_.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Return_.php
new file mode 100644
index 0000000..b80fdfe
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Return_.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Return_ extends Instr
+{
+ public static function opName(): string
+ {
+ return "return";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Control/Unreachable.php b/src/WebAssembly/Structure/Instructions/Instrs/Control/Unreachable.php
new file mode 100644
index 0000000..e43ade8
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Control/Unreachable.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Control;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Unreachable extends Instr
+{
+ public static function opName(): string
+ {
+ return "unreachable";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/DataDrop.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/DataDrop.php
new file mode 100644
index 0000000..3525b80
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/DataDrop.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class DataDrop extends Instr
+{
+ protected function __construct(
+ public int $data,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "data.drop";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Load.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Load.php
new file mode 100644
index 0000000..82b7cf4
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Load.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Load extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "f32.load";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Store.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Store.php
new file mode 100644
index 0000000..06d9055
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F32Store.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Store extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "f32.store";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Load.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Load.php
new file mode 100644
index 0000000..13e2385
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Load.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Load extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "f64.load";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Store.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Store.php
new file mode 100644
index 0000000..261b276
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/F64Store.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Store extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "f64.store";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load.php
new file mode 100644
index 0000000..4554a77
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Load extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.load";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16S.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16S.php
new file mode 100644
index 0000000..56bdb3f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16S.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Load16S extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.load16_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16U.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16U.php
new file mode 100644
index 0000000..1cc243c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load16U.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Load16U extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.load16_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8S.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8S.php
new file mode 100644
index 0000000..a76607f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8S.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Load8S extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.load8_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8U.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8U.php
new file mode 100644
index 0000000..7cab471
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Load8U.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Load8U extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.load8_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store.php
new file mode 100644
index 0000000..3021639
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Store extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.store";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store16.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store16.php
new file mode 100644
index 0000000..3463fdf
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store16.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Store16 extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.store16";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store8.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store8.php
new file mode 100644
index 0000000..5298ad5
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I32Store8.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Store8 extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.store8";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load.php
new file mode 100644
index 0000000..33fa4e1
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16S.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16S.php
new file mode 100644
index 0000000..47ef776
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16S.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load16S extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load16_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16U.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16U.php
new file mode 100644
index 0000000..8825b89
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load16U.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load16U extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load16_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32S.php
new file mode 100644
index 0000000..bd2575b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32S.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load32S extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32U.php
new file mode 100644
index 0000000..404bc8a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load32U.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load32U extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8S.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8S.php
new file mode 100644
index 0000000..f28bad9
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8S.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load8S extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load8_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8U.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8U.php
new file mode 100644
index 0000000..66b5575
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Load8U.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Load8U extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.load8_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store.php
new file mode 100644
index 0000000..0b4778b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Store extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.store";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store16.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store16.php
new file mode 100644
index 0000000..984ecd2
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store16.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Store16 extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.store16";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store32.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store32.php
new file mode 100644
index 0000000..e486308
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store32.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Store32 extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.store32";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store8.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store8.php
new file mode 100644
index 0000000..7897197
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/I64Store8.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Store8 extends Instr
+{
+ /**
+ * @param U32 $offset
+ * @param U32 $align
+ */
+ protected function __construct(
+ public int $offset,
+ public int $align,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.store8";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryCopy.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryCopy.php
new file mode 100644
index 0000000..5ef7106
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryCopy.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class MemoryCopy extends Instr
+{
+ public static function opName(): string
+ {
+ return "memory.copy";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryFill.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryFill.php
new file mode 100644
index 0000000..be388ff
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryFill.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class MemoryFill extends Instr
+{
+ public static function opName(): string
+ {
+ return "memory.fill";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryGrow.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryGrow.php
new file mode 100644
index 0000000..9e6c320
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryGrow.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class MemoryGrow extends Instr
+{
+ public static function opName(): string
+ {
+ return "memory.grow";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryInit.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryInit.php
new file mode 100644
index 0000000..7843ff1
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemoryInit.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class MemoryInit extends Instr
+{
+ protected function __construct(
+ public int $data,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "memory.init";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemorySize.php b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemorySize.php
new file mode 100644
index 0000000..075878a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Memory/MemorySize.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Memory;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class MemorySize extends Instr
+{
+ public static function opName(): string
+ {
+ return "memory.size";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Abs.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Abs.php
new file mode 100644
index 0000000..7711f7f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Abs.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Abs extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.abs";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Add.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Add.php
new file mode 100644
index 0000000..5f92829
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Add.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Add extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.add";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ceil.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ceil.php
new file mode 100644
index 0000000..be6f11e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ceil.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Ceil extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.ceil";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Const.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Const.php
new file mode 100644
index 0000000..fd2670e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Const.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Const extends Instr
+{
+ /**
+ * @param F32 $value
+ */
+ protected function __construct(
+ public float $value,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "f32.const";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32S.php
new file mode 100644
index 0000000..5e68989
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32ConvertI32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.convert_i32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32U.php
new file mode 100644
index 0000000..fdaa709
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32ConvertI32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.convert_i32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64S.php
new file mode 100644
index 0000000..b6444cc
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32ConvertI64S extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.convert_i64_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64U.php
new file mode 100644
index 0000000..4b0f578
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ConvertI64U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32ConvertI64U extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.convert_i64_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32CopySign.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32CopySign.php
new file mode 100644
index 0000000..539682a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32CopySign.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32CopySign extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.copy_sign";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32DemoteF64.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32DemoteF64.php
new file mode 100644
index 0000000..24cff4f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32DemoteF64.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32DemoteF64 extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.demote_f64";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Div.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Div.php
new file mode 100644
index 0000000..3cdafb0
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Div.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Div extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.div";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Eq.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Eq.php
new file mode 100644
index 0000000..cae6c2e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Eq.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Eq extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.eq";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Floor.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Floor.php
new file mode 100644
index 0000000..9c1b23f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Floor.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Floor extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.floor";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ge.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ge.php
new file mode 100644
index 0000000..ef75922
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ge.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Ge extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.ge";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Gt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Gt.php
new file mode 100644
index 0000000..0efda96
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Gt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Gt extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.gt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Le.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Le.php
new file mode 100644
index 0000000..50cbb71
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Le.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Le extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.le";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Lt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Lt.php
new file mode 100644
index 0000000..e4b490a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Lt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Lt extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.lt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Max.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Max.php
new file mode 100644
index 0000000..81f9b3e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Max.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Max extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.max";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Min.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Min.php
new file mode 100644
index 0000000..20518ea
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Min.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Min extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.min";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Mul.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Mul.php
new file mode 100644
index 0000000..8282273
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Mul.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Mul extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.mul";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ne.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ne.php
new file mode 100644
index 0000000..8b5db5e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Ne.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Ne extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.ne";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Nearest.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Nearest.php
new file mode 100644
index 0000000..ae51359
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Nearest.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Nearest extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.nearest";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Neg.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Neg.php
new file mode 100644
index 0000000..82b72c3
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Neg.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Neg extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.neg";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI32.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI32.php
new file mode 100644
index 0000000..3cd93c4
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI32.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32ReinterpretI32 extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.reinterpret_i32";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI64.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI64.php
new file mode 100644
index 0000000..dd0f66f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32ReinterpretI64.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32ReinterpretI64 extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.reinterpret_i64";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sqrt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sqrt.php
new file mode 100644
index 0000000..9cdeba2
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sqrt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Sqrt extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.sqrt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sub.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sub.php
new file mode 100644
index 0000000..54b5991
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Sub.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Sub extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.sub";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Trunc.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Trunc.php
new file mode 100644
index 0000000..627406e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F32Trunc.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F32Trunc extends Instr
+{
+ public static function opName(): string
+ {
+ return "f32.trunc";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Abs.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Abs.php
new file mode 100644
index 0000000..a985933
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Abs.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Abs extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.abs";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Add.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Add.php
new file mode 100644
index 0000000..60a6a05
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Add.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Add extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.add";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ceil.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ceil.php
new file mode 100644
index 0000000..3c88a4b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ceil.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Ceil extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.ceil";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Const.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Const.php
new file mode 100644
index 0000000..46c61fe
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Const.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Const extends Instr
+{
+ /**
+ * @param F64 $value
+ */
+ protected function __construct(
+ public float $value,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "f64.const";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32S.php
new file mode 100644
index 0000000..5deaec0
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64ConvertI32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.convert_i32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32U.php
new file mode 100644
index 0000000..657e8e2
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64ConvertI32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.convert_i32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64S.php
new file mode 100644
index 0000000..af7d5af
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64ConvertI64S extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.convert_i64_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64U.php
new file mode 100644
index 0000000..575c8e5
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ConvertI64U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64ConvertI64U extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.convert_i64_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64CopySign.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64CopySign.php
new file mode 100644
index 0000000..bab91f2
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64CopySign.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64CopySign extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.copy_sign";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Div.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Div.php
new file mode 100644
index 0000000..7304a8d
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Div.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Div extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.div";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Eq.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Eq.php
new file mode 100644
index 0000000..1c9e31c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Eq.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Eq extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.eq";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Floor.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Floor.php
new file mode 100644
index 0000000..8c76753
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Floor.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Floor extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.floor";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ge.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ge.php
new file mode 100644
index 0000000..28f6da1
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ge.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Ge extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.ge";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Gt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Gt.php
new file mode 100644
index 0000000..9b6e91e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Gt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Gt extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.gt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Le.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Le.php
new file mode 100644
index 0000000..1852d66
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Le.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Le extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.le";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Lt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Lt.php
new file mode 100644
index 0000000..fb96301
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Lt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Lt extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.lt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Max.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Max.php
new file mode 100644
index 0000000..da79a2e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Max.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Max extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.max";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Min.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Min.php
new file mode 100644
index 0000000..79bb77b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Min.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Min extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.min";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Mul.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Mul.php
new file mode 100644
index 0000000..f0932ea
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Mul.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Mul extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.mul";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ne.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ne.php
new file mode 100644
index 0000000..226b1e4
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Ne.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Ne extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.ne";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Nearest.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Nearest.php
new file mode 100644
index 0000000..0863099
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Nearest.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Nearest extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.nearest";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Neg.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Neg.php
new file mode 100644
index 0000000..c4e0ce7
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Neg.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Neg extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.neg";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64PromoteF32.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64PromoteF32.php
new file mode 100644
index 0000000..8692806
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64PromoteF32.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64PromoteF32 extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.promote_f32";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI32.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI32.php
new file mode 100644
index 0000000..4721e07
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI32.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64ReinterpretI32 extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.reinterpret_i32";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI64.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI64.php
new file mode 100644
index 0000000..22faa67
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64ReinterpretI64.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64ReinterpretI64 extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.reinterpret_i64";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sqrt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sqrt.php
new file mode 100644
index 0000000..77d708a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sqrt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Sqrt extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.sqrt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sub.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sub.php
new file mode 100644
index 0000000..b20c0c9
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Sub.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Sub extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.sub";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Trunc.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Trunc.php
new file mode 100644
index 0000000..62d6c12
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/F64Trunc.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class F64Trunc extends Instr
+{
+ public static function opName(): string
+ {
+ return "f64.trunc";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Add.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Add.php
new file mode 100644
index 0000000..429dfdf
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Add.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Add extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.add";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32And.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32And.php
new file mode 100644
index 0000000..135f038
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32And.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32And extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.and";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Clz.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Clz.php
new file mode 100644
index 0000000..7bdfa52
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Clz.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Clz extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.clz";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Const.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Const.php
new file mode 100644
index 0000000..4900a1c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Const.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Const extends Instr
+{
+ /**
+ * @param U32 $value
+ */
+ protected function __construct(
+ public int $value,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i32.const";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ctz.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ctz.php
new file mode 100644
index 0000000..4577729
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ctz.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Ctz extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.ctz";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivS.php
new file mode 100644
index 0000000..bbc0f08
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32DivS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.div_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivU.php
new file mode 100644
index 0000000..3db3fa0
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32DivU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32DivU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.div_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eq.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eq.php
new file mode 100644
index 0000000..eb24aad
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eq.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Eq extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.eq";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eqz.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eqz.php
new file mode 100644
index 0000000..b99341a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Eqz.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Eqz extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.eqz";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend16S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend16S.php
new file mode 100644
index 0000000..50e3951
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend16S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Extend16S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.extend16_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend8S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend8S.php
new file mode 100644
index 0000000..9f5aa4b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Extend8S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Extend8S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.extend8_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeS.php
new file mode 100644
index 0000000..7f2746f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32GeS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.ge_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeU.php
new file mode 100644
index 0000000..3018605
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GeU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32GeU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.ge_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtS.php
new file mode 100644
index 0000000..093f47d
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32GtS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.gt_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtU.php
new file mode 100644
index 0000000..e7c07e3
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32GtU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32GtU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.gt_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeS.php
new file mode 100644
index 0000000..078535a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32LeS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.le_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeU.php
new file mode 100644
index 0000000..0fe2ae2
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LeU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32LeU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.le_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtS.php
new file mode 100644
index 0000000..6070881
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32LtS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.lt_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtU.php
new file mode 100644
index 0000000..ccb520e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32LtU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32LtU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.lt_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Mul.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Mul.php
new file mode 100644
index 0000000..7ddf1e6
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Mul.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Mul extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.mul";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ne.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ne.php
new file mode 100644
index 0000000..7624909
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Ne.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Ne extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.ne";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Or.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Or.php
new file mode 100644
index 0000000..4d985a7
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Or.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Or extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.or";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Popcnt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Popcnt.php
new file mode 100644
index 0000000..ea2e5af
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Popcnt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Popcnt extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.popcnt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF32.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF32.php
new file mode 100644
index 0000000..3ca1a3c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF32.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32ReinterpretF32 extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.reinterpret_f32";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF64.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF64.php
new file mode 100644
index 0000000..2990a21
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ReinterpretF64.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32ReinterpretF64 extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.reinterpret_f64";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemS.php
new file mode 100644
index 0000000..0814085
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32RemS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.rem_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemU.php
new file mode 100644
index 0000000..b945e4e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RemU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32RemU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.rem_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotL.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotL.php
new file mode 100644
index 0000000..509a39e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotL.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32RotL extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.rot_l";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotR.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotR.php
new file mode 100644
index 0000000..7104869
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32RotR.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32RotR extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.rot_r";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Shl.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Shl.php
new file mode 100644
index 0000000..199cace
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Shl.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Shl extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.shl";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrS.php
new file mode 100644
index 0000000..5645907
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32ShrS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.shr_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrU.php
new file mode 100644
index 0000000..c5435cd
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32ShrU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32ShrU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.shr_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Sub.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Sub.php
new file mode 100644
index 0000000..5ca4dec
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Sub.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Sub extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.sub";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32S.php
new file mode 100644
index 0000000..31ab093
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncF32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_f32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32U.php
new file mode 100644
index 0000000..afeda9c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncF32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_f32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64S.php
new file mode 100644
index 0000000..8b27805
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncF64S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_f64_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64U.php
new file mode 100644
index 0000000..5b7550c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncF64U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncF64U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_f64_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32S.php
new file mode 100644
index 0000000..c2fbdf1
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncSatF32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_sat_f32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32U.php
new file mode 100644
index 0000000..0ae1090
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncSatF32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_sat_f32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64S.php
new file mode 100644
index 0000000..38731db
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncSatF64S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_sat_f64_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64U.php
new file mode 100644
index 0000000..22f5335
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32TruncSatF64U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32TruncSatF64U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.trunc_sat_f64_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32WrapI64.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32WrapI64.php
new file mode 100644
index 0000000..9c7ed4b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32WrapI64.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32WrapI64 extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.wrap_i64";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Xor.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Xor.php
new file mode 100644
index 0000000..804b881
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I32Xor.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I32Xor extends Instr
+{
+ public static function opName(): string
+ {
+ return "i32.xor";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Add.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Add.php
new file mode 100644
index 0000000..9d81af7
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Add.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Add extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.add";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64And.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64And.php
new file mode 100644
index 0000000..4c1f4b3
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64And.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64And extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.and";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Clz.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Clz.php
new file mode 100644
index 0000000..eb03da7
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Clz.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Clz extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.clz";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Const.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Const.php
new file mode 100644
index 0000000..01e9e72
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Const.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Const extends Instr
+{
+ /**
+ * @param U64 $value
+ */
+ protected function __construct(
+ public int $value,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "i64.const";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ctz.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ctz.php
new file mode 100644
index 0000000..3c6fdaa
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ctz.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Ctz extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.ctz";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivS.php
new file mode 100644
index 0000000..8a8759b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64DivS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.div_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivU.php
new file mode 100644
index 0000000..67f50f7
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64DivU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64DivU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.div_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eq.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eq.php
new file mode 100644
index 0000000..5480197
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eq.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Eq extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.eq";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eqz.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eqz.php
new file mode 100644
index 0000000..8bd7f04
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Eqz.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Eqz extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.eqz";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend16S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend16S.php
new file mode 100644
index 0000000..8733d84
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend16S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Extend16S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.extend16_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend32S.php
new file mode 100644
index 0000000..3594cf4
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Extend32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.extend32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend8S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend8S.php
new file mode 100644
index 0000000..8579635
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Extend8S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Extend8S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.extend8_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32S.php
new file mode 100644
index 0000000..9db4c55
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64ExtendI32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.extend_i32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32U.php
new file mode 100644
index 0000000..9219f97
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ExtendI32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64ExtendI32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.extend_i32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeS.php
new file mode 100644
index 0000000..bddbffb
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64GeS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.ge_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeU.php
new file mode 100644
index 0000000..9b5df84
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GeU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64GeU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.ge_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtS.php
new file mode 100644
index 0000000..4ac4063
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64GtS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.gt_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtU.php
new file mode 100644
index 0000000..4cd0f84
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64GtU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64GtU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.gt_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeS.php
new file mode 100644
index 0000000..259cc99
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64LeS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.le_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeU.php
new file mode 100644
index 0000000..69c880b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LeU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64LeU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.le_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtS.php
new file mode 100644
index 0000000..9c8d434
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64LtS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.lt_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtU.php
new file mode 100644
index 0000000..8142792
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64LtU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64LtU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.lt_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Mul.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Mul.php
new file mode 100644
index 0000000..1a69448
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Mul.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Mul extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.mul";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ne.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ne.php
new file mode 100644
index 0000000..4cf363e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Ne.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Ne extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.ne";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Or.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Or.php
new file mode 100644
index 0000000..c09caab
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Or.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Or extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.or";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Popcnt.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Popcnt.php
new file mode 100644
index 0000000..3db978b
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Popcnt.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Popcnt extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.popcnt";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF32.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF32.php
new file mode 100644
index 0000000..6446e50
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF32.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64ReinterpretF32 extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.reinterpret_f32";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF64.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF64.php
new file mode 100644
index 0000000..b570008
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ReinterpretF64.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64ReinterpretF64 extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.reinterpret_f64";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemS.php
new file mode 100644
index 0000000..7833dcd
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64RemS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.rem_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemU.php
new file mode 100644
index 0000000..97117dc
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RemU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64RemU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.rem_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotL.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotL.php
new file mode 100644
index 0000000..b39a2ac
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotL.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64RotL extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.rot_l";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotR.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotR.php
new file mode 100644
index 0000000..aa62ee8
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64RotR.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64RotR extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.rot_r";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Shl.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Shl.php
new file mode 100644
index 0000000..f43018a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Shl.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Shl extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.shl";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrS.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrS.php
new file mode 100644
index 0000000..f8da95e
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrS.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64ShrS extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.shr_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrU.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrU.php
new file mode 100644
index 0000000..7ea2b3a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64ShrU.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64ShrU extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.shr_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Sub.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Sub.php
new file mode 100644
index 0000000..7cb6f26
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Sub.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Sub extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.sub";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32S.php
new file mode 100644
index 0000000..9f6ed66
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncF32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_f32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32U.php
new file mode 100644
index 0000000..9724897
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncF32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_f32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64S.php
new file mode 100644
index 0000000..70c235c
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncF64S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_f64_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64U.php
new file mode 100644
index 0000000..f787fe3
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncF64U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncF64U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_f64_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32S.php
new file mode 100644
index 0000000..98082e5
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncSatF32S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_sat_f32_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32U.php
new file mode 100644
index 0000000..6b0b833
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF32U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncSatF32U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_sat_f32_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64S.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64S.php
new file mode 100644
index 0000000..2291eab
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64S.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncSatF64S extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_sat_f64_s";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64U.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64U.php
new file mode 100644
index 0000000..90c1f49
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64TruncSatF64U.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64TruncSatF64U extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.trunc_sat_f64_u";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Xor.php b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Xor.php
new file mode 100644
index 0000000..994e47f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Numeric/I64Xor.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Numeric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class I64Xor extends Instr
+{
+ public static function opName(): string
+ {
+ return "i64.xor";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Parametric/Drop.php b/src/WebAssembly/Structure/Instructions/Instrs/Parametric/Drop.php
new file mode 100644
index 0000000..5a5ed18
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Parametric/Drop.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Parametric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Drop extends Instr
+{
+ public static function opName(): string
+ {
+ return "drop";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Parametric/Select.php b/src/WebAssembly/Structure/Instructions/Instrs/Parametric/Select.php
new file mode 100644
index 0000000..2562764
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Parametric/Select.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Parametric;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+final readonly class Select extends Instr
+{
+ /**
+ * @param list<ValType> $types
+ */
+ protected function __construct(
+ public array $types,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "select";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefFunc.php b/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefFunc.php
new file mode 100644
index 0000000..3539ede
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefFunc.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Reference;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class RefFunc extends Instr
+{
+ protected function __construct(
+ public int $func,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "ref.func";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefIsNull.php b/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefIsNull.php
new file mode 100644
index 0000000..21c9a26
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefIsNull.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Reference;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class RefIsNull extends Instr
+{
+ public static function opName(): string
+ {
+ return "ref.is_null";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefNull.php b/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefNull.php
new file mode 100644
index 0000000..39d0f8f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Reference/RefNull.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Reference;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+
+final readonly class RefNull extends Instr
+{
+ protected function __construct(
+ public RefType $type,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "ref.null";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/ElemDrop.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/ElemDrop.php
new file mode 100644
index 0000000..4ead3cb
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/ElemDrop.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class ElemDrop extends Instr
+{
+ protected function __construct(
+ public int $elem,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "elem.drop";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableCopy.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableCopy.php
new file mode 100644
index 0000000..ca4e01a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableCopy.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableCopy extends Instr
+{
+ protected function __construct(
+ public int $to,
+ public int $from,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.copy";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableFill.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableFill.php
new file mode 100644
index 0000000..8a8fba4
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableFill.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableFill extends Instr
+{
+ protected function __construct(
+ public int $table,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.fill";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableGet.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableGet.php
new file mode 100644
index 0000000..0a562cb
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableGet.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableGet extends Instr
+{
+ protected function __construct(
+ public int $table,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.get";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableGrow.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableGrow.php
new file mode 100644
index 0000000..fae1bd0
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableGrow.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableGrow extends Instr
+{
+ protected function __construct(
+ public int $table,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.grow";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableInit.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableInit.php
new file mode 100644
index 0000000..221c938
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableInit.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableInit extends Instr
+{
+ protected function __construct(
+ public int $to,
+ public int $from,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.init";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableSet.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableSet.php
new file mode 100644
index 0000000..46ce56f
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableSet.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableSet extends Instr
+{
+ protected function __construct(
+ public int $table,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.set";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Table/TableSize.php b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableSize.php
new file mode 100644
index 0000000..8a1625a
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Table/TableSize.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Table;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class TableSize extends Instr
+{
+ protected function __construct(
+ public int $table,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "table.size";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalGet.php b/src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalGet.php
new file mode 100644
index 0000000..2358325
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalGet.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Variable;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class GlobalGet extends Instr
+{
+ protected function __construct(
+ public int $var,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "global.get";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalSet.php b/src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalSet.php
new file mode 100644
index 0000000..a8d2cf4
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Variable/GlobalSet.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Variable;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class GlobalSet extends Instr
+{
+ protected function __construct(
+ public int $var,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "global.set";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalGet.php b/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalGet.php
new file mode 100644
index 0000000..de610d3
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalGet.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Variable;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class LocalGet extends Instr
+{
+ protected function __construct(
+ public int $var,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "local.get";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalSet.php b/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalSet.php
new file mode 100644
index 0000000..350c6bd
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalSet.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Variable;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class LocalSet extends Instr
+{
+ protected function __construct(
+ public int $var,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "local.set";
+ }
+}
diff --git a/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalTee.php b/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalTee.php
new file mode 100644
index 0000000..62d42c5
--- /dev/null
+++ b/src/WebAssembly/Structure/Instructions/Instrs/Variable/LocalTee.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instrs\Variable;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class LocalTee extends Instr
+{
+ protected function __construct(
+ public int $var,
+ ) {
+ }
+
+ public static function opName(): string
+ {
+ return "local.tee";
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Data.php b/src/WebAssembly/Structure/Modules/Data.php
new file mode 100644
index 0000000..3994a01
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Data.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+final readonly class Data
+{
+ /**
+ * @param list<Byte> $init
+ */
+ public function __construct(
+ public array $init,
+ public DataMode $mode,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/DataMode.php b/src/WebAssembly/Structure/Modules/DataMode.php
new file mode 100644
index 0000000..37205bc
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/DataMode.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+abstract readonly class DataMode
+{
+ final public static function Passive(): DataModes\Passive
+ {
+ return new DataModes\Passive();
+ }
+
+ /**
+ * @param list<Instr> $offset
+ */
+ final public static function Active(
+ int $memory,
+ array $offset,
+ ): DataModes\Active {
+ return new DataModes\Active($memory, $offset);
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/DataModes/Active.php b/src/WebAssembly/Structure/Modules/DataModes/Active.php
new file mode 100644
index 0000000..41cc9c7
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/DataModes/Active.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\DataModes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\DataMode;
+
+final readonly class Active extends DataMode
+{
+ /**
+ * @param list<Instr> $offset
+ */
+ protected function __construct(
+ public int $memory,
+ public array $offset,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/DataModes/Passive.php b/src/WebAssembly/Structure/Modules/DataModes/Passive.php
new file mode 100644
index 0000000..6ef6ba9
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/DataModes/Passive.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\DataModes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\DataMode;
+
+final readonly class Passive extends DataMode
+{
+ protected function __construct()
+ {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Elem.php b/src/WebAssembly/Structure/Modules/Elem.php
new file mode 100644
index 0000000..1b9831f
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Elem.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType;
+
+final readonly class Elem
+{
+ /**
+ * @param list<list<Instr>> $init
+ */
+ public function __construct(
+ public RefType $type,
+ public array $init,
+ public ElemMode $mode,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ElemMode.php b/src/WebAssembly/Structure/Modules/ElemMode.php
new file mode 100644
index 0000000..0777bd4
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ElemMode.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+abstract readonly class ElemMode
+{
+ final public static function Passive(): ElemModes\Passive
+ {
+ return new ElemModes\Passive();
+ }
+
+ /**
+ * @param list<Instr> $offset
+ */
+ final public static function Active(
+ int $table,
+ array $offset,
+ ): ElemModes\Active {
+ return new ElemModes\Active($table, $offset);
+ }
+
+ final public static function Declarative(): ElemModes\Declarative
+ {
+ return new ElemModes\Declarative();
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ElemModes/Active.php b/src/WebAssembly/Structure/Modules/ElemModes/Active.php
new file mode 100644
index 0000000..e66e080
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ElemModes/Active.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemModes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemMode;
+
+final readonly class Active extends ElemMode
+{
+ /**
+ * @param list<Instr> $offset
+ */
+ protected function __construct(
+ public int $table,
+ public array $offset,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ElemModes/Declarative.php b/src/WebAssembly/Structure/Modules/ElemModes/Declarative.php
new file mode 100644
index 0000000..28f917a
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ElemModes/Declarative.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemModes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemMode;
+
+final readonly class Declarative extends ElemMode
+{
+ protected function __construct()
+ {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ElemModes/Passive.php b/src/WebAssembly/Structure/Modules/ElemModes/Passive.php
new file mode 100644
index 0000000..5fb323e
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ElemModes/Passive.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemModes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ElemMode;
+
+final readonly class Passive extends ElemMode
+{
+ protected function __construct()
+ {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Export.php b/src/WebAssembly/Structure/Modules/Export.php
new file mode 100644
index 0000000..fea3f04
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Export.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+final readonly class Export
+{
+ /**
+ * @param Name $name
+ */
+ public function __construct(
+ public string $name,
+ public ExportDesc $desc,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ExportDesc.php b/src/WebAssembly/Structure/Modules/ExportDesc.php
new file mode 100644
index 0000000..3462569
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ExportDesc.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+abstract readonly class ExportDesc
+{
+ final public static function Func(int $func): ExportDescs\Func
+ {
+ return new ExportDescs\Func($func);
+ }
+
+ final public static function Table(int $table): ExportDescs\Table
+ {
+ return new ExportDescs\Table($table);
+ }
+
+ final public static function Mem(int $mem): ExportDescs\Mem
+ {
+ return new ExportDescs\Mem($mem);
+ }
+
+ final public static function Global(int $global): ExportDescs\Global_
+ {
+ return new ExportDescs\Global_($global);
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ExportDescs/Func.php b/src/WebAssembly/Structure/Modules/ExportDescs/Func.php
new file mode 100644
index 0000000..85926c6
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ExportDescs/Func.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDesc;
+
+final readonly class Func extends ExportDesc
+{
+ protected function __construct(
+ public int $func,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ExportDescs/Global_.php b/src/WebAssembly/Structure/Modules/ExportDescs/Global_.php
new file mode 100644
index 0000000..9e1d481
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ExportDescs/Global_.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDesc;
+
+final readonly class Global_ extends ExportDesc
+{
+ protected function __construct(
+ public int $global,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ExportDescs/Mem.php b/src/WebAssembly/Structure/Modules/ExportDescs/Mem.php
new file mode 100644
index 0000000..9212f45
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ExportDescs/Mem.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDesc;
+
+final readonly class Mem extends ExportDesc
+{
+ protected function __construct(
+ public int $mem,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ExportDescs/Table.php b/src/WebAssembly/Structure/Modules/ExportDescs/Table.php
new file mode 100644
index 0000000..e89f2d8
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ExportDescs/Table.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ExportDesc;
+
+final readonly class Table extends ExportDesc
+{
+ protected function __construct(
+ public int $table,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Func.php b/src/WebAssembly/Structure/Modules/Func.php
new file mode 100644
index 0000000..f1c305e
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Func.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+
+final readonly class Func
+{
+ /**
+ * @param list<Local> $locals
+ * @param list<Instr> $body
+ */
+ public function __construct(
+ public int $type,
+ public array $locals,
+ public array $body,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Global_.php b/src/WebAssembly/Structure/Modules/Global_.php
new file mode 100644
index 0000000..04ffbc6
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Global_.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Instructions\Instr;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+
+final readonly class Global_
+{
+ /**
+ * @param list<Instr> $init
+ */
+ public function __construct(
+ public GlobalType $type,
+ public array $init,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Import.php b/src/WebAssembly/Structure/Modules/Import.php
new file mode 100644
index 0000000..e764fcb
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Import.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+final readonly class Import
+{
+ /**
+ * @param Name $module
+ * @param Name $name
+ */
+ public function __construct(
+ public string $module,
+ public string $name,
+ public ImportDesc $desc,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ImportDesc.php b/src/WebAssembly/Structure/Modules/ImportDesc.php
new file mode 100644
index 0000000..240ad2b
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ImportDesc.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+
+abstract readonly class ImportDesc
+{
+ final public static function Func(int $func): ImportDescs\Func
+ {
+ return new ImportDescs\Func($func);
+ }
+
+ final public static function Table(TableType $table): ImportDescs\Table
+ {
+ return new ImportDescs\Table($table);
+ }
+
+ final public static function Mem(MemType $mem): ImportDescs\Mem
+ {
+ return new ImportDescs\Mem($mem);
+ }
+
+ final public static function Global(GlobalType $global): ImportDescs\Global_
+ {
+ return new ImportDescs\Global_($global);
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ImportDescs/Func.php b/src/WebAssembly/Structure/Modules/ImportDescs/Func.php
new file mode 100644
index 0000000..4b5da18
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ImportDescs/Func.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDesc;
+
+final readonly class Func extends ImportDesc
+{
+ protected function __construct(
+ public int $func,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ImportDescs/Global_.php b/src/WebAssembly/Structure/Modules/ImportDescs/Global_.php
new file mode 100644
index 0000000..bab51b9
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ImportDescs/Global_.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDesc;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+
+final readonly class Global_ extends ImportDesc
+{
+ protected function __construct(
+ public GlobalType $global,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ImportDescs/Mem.php b/src/WebAssembly/Structure/Modules/ImportDescs/Mem.php
new file mode 100644
index 0000000..934d1c9
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ImportDescs/Mem.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDesc;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+
+final readonly class Mem extends ImportDesc
+{
+ protected function __construct(
+ public MemType $mem,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/ImportDescs/Table.php b/src/WebAssembly/Structure/Modules/ImportDescs/Table.php
new file mode 100644
index 0000000..f8b2fa3
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/ImportDescs/Table.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDescs;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Modules\ImportDesc;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+
+final readonly class Table extends ImportDesc
+{
+ protected function __construct(
+ public TableType $table,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Local.php b/src/WebAssembly/Structure/Modules/Local.php
new file mode 100644
index 0000000..699d7a3
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Local.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+final readonly class Local
+{
+ public function __construct(
+ public ValType $type,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Mem.php b/src/WebAssembly/Structure/Modules/Mem.php
new file mode 100644
index 0000000..45f0066
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Mem.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+
+final readonly class Mem
+{
+ public function __construct(
+ public MemType $type,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Module.php b/src/WebAssembly/Structure/Modules/Module.php
new file mode 100644
index 0000000..a6ce2c8
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Module.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+
+final readonly class Module
+{
+ /**
+ * @param list<FuncType> $types
+ * @param list<Func> $funcs
+ * @param list<Table> $tables
+ * @param list<Mem> $mems
+ * @param list<Global_> $globals
+ * @param list<Elem> $elems
+ * @param list<Data> $datas
+ * @param list<Import> $imports
+ * @param list<Export> $exports
+ */
+ public function __construct(
+ public array $types,
+ public array $funcs,
+ public array $tables,
+ public array $mems,
+ public array $globals,
+ public array $elems,
+ public array $datas,
+ public ?Start $start,
+ public array $imports,
+ public array $exports,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Start.php b/src/WebAssembly/Structure/Modules/Start.php
new file mode 100644
index 0000000..6659929
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Start.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+final readonly class Start
+{
+ public function __construct(
+ public int $func,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Modules/Table.php b/src/WebAssembly/Structure/Modules/Table.php
new file mode 100644
index 0000000..f0125a2
--- /dev/null
+++ b/src/WebAssembly/Structure/Modules/Table.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Modules;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+
+final readonly class Table
+{
+ public function __construct(
+ public TableType $type,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ExternType.php b/src/WebAssembly/Structure/Types/ExternType.php
new file mode 100644
index 0000000..bffeacf
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ExternType.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+abstract readonly class ExternType
+{
+ final public static function Func(FuncType $type): ExternTypes\Func
+ {
+ return new ExternTypes\Func($type);
+ }
+
+ final public static function Table(TableType $type): ExternTypes\Table
+ {
+ return new ExternTypes\Table($type);
+ }
+
+ final public static function Mem(MemType $type): ExternTypes\Mem
+ {
+ return new ExternTypes\Mem($type);
+ }
+
+ final public static function Global(GlobalType $type): ExternTypes\Global_
+ {
+ return new ExternTypes\Global_($type);
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ExternTypes/Func.php b/src/WebAssembly/Structure/Types/ExternTypes/Func.php
new file mode 100644
index 0000000..d41ed61
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ExternTypes/Func.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType;
+
+final readonly class Func extends ExternType
+{
+ protected function __construct(
+ public FuncType $inner,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ExternTypes/Global_.php b/src/WebAssembly/Structure/Types/ExternTypes/Global_.php
new file mode 100644
index 0000000..1e78370
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ExternTypes/Global_.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\GlobalType;
+
+final readonly class Global_ extends ExternType
+{
+ protected function __construct(
+ public GlobalType $inner,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ExternTypes/Mem.php b/src/WebAssembly/Structure/Types/ExternTypes/Mem.php
new file mode 100644
index 0000000..92f1a39
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ExternTypes/Mem.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
+
+final readonly class Mem extends ExternType
+{
+ protected function __construct(
+ public MemType $inner,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ExternTypes/Table.php b/src/WebAssembly/Structure/Types/ExternTypes/Table.php
new file mode 100644
index 0000000..034d9a8
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ExternTypes/Table.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ExternType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
+
+final readonly class Table extends ExternType
+{
+ protected function __construct(
+ public TableType $inner,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/FuncType.php b/src/WebAssembly/Structure/Types/FuncType.php
new file mode 100644
index 0000000..6c53519
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/FuncType.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+final readonly class FuncType
+{
+ public function __construct(
+ public ResultType $params,
+ public ResultType $results,
+ ) {
+ }
+
+ public function equals(FuncType $other): bool
+ {
+ return $this->params->equals($other->params)
+ && $this->results->equals($other->results);
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/GlobalType.php b/src/WebAssembly/Structure/Types/GlobalType.php
new file mode 100644
index 0000000..3e8ab6c
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/GlobalType.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+final readonly class GlobalType
+{
+ public function __construct(
+ public Mut $mut,
+ public ValType $valType,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/Limits.php b/src/WebAssembly/Structure/Types/Limits.php
new file mode 100644
index 0000000..e60b842
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/Limits.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+final readonly class Limits
+{
+ /**
+ * @param U32 $min
+ * @param ?U32 $max
+ */
+ public function __construct(
+ public int $min,
+ public ?int $max,
+ ) {
+ }
+
+ public function isValid(): bool
+ {
+ return 0 <= $this->min &&
+ ($this->max === null || $this->min <= $this->max);
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/MemType.php b/src/WebAssembly/Structure/Types/MemType.php
new file mode 100644
index 0000000..8d01150
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/MemType.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+final readonly class MemType
+{
+ public function __construct(
+ public Limits $limits,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/Mut.php b/src/WebAssembly/Structure/Types/Mut.php
new file mode 100644
index 0000000..5bf366c
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/Mut.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+enum Mut
+{
+ case Const;
+ case Var;
+}
diff --git a/src/WebAssembly/Structure/Types/NumType.php b/src/WebAssembly/Structure/Types/NumType.php
new file mode 100644
index 0000000..2d5a3b1
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/NumType.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+enum NumType
+{
+ case I32;
+ case I64;
+ case F32;
+ case F64;
+}
diff --git a/src/WebAssembly/Structure/Types/RefType.php b/src/WebAssembly/Structure/Types/RefType.php
new file mode 100644
index 0000000..2225f56
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/RefType.php
@@ -0,0 +1,11 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+enum RefType
+{
+ case FuncRef;
+ case ExternRef;
+}
diff --git a/src/WebAssembly/Structure/Types/ResultType.php b/src/WebAssembly/Structure/Types/ResultType.php
new file mode 100644
index 0000000..dff2e59
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ResultType.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+use function count;
+
+final readonly class ResultType
+{
+ /**
+ * @param list<ValType> $types
+ */
+ public function __construct(
+ public array $types,
+ ) {
+ }
+
+ public function equals(ResultType $other): bool
+ {
+ if (count($this->types) !== count($other->types)) {
+ return false;
+ }
+ foreach ($this->types as $i => $type) {
+ if (!$type->equals($other->types[$i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/TableType.php b/src/WebAssembly/Structure/Types/TableType.php
new file mode 100644
index 0000000..7e4b957
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/TableType.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+final readonly class TableType
+{
+ public function __construct(
+ public Limits $limits,
+ public RefType $refType,
+ ) {
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ValType.php b/src/WebAssembly/Structure/Types/ValType.php
new file mode 100644
index 0000000..f6f3111
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ValType.php
@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+abstract readonly class ValType
+{
+ final public static function NumType(NumType $type): ValTypes\NumType
+ {
+ return new ValTypes\NumType($type);
+ }
+
+ final public static function VecType(VecType $type): ValTypes\VecType
+ {
+ return new ValTypes\VecType($type);
+ }
+
+ final public static function RefType(RefType $type): ValTypes\RefType
+ {
+ return new ValTypes\RefType($type);
+ }
+
+ abstract public function equals(ValType $other): bool;
+}
diff --git a/src/WebAssembly/Structure/Types/ValTypes/NumType.php b/src/WebAssembly/Structure/Types/ValTypes/NumType.php
new file mode 100644
index 0000000..1836679
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ValTypes/NumType.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\NumType as OrigNumType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+final readonly class NumType extends ValType
+{
+ protected function __construct(public OrigNumType $inner)
+ {
+ }
+
+ public function equals(ValType $other): bool
+ {
+ return $other instanceof self
+ && $this->inner === $other->inner;
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ValTypes/RefType.php b/src/WebAssembly/Structure/Types/ValTypes/RefType.php
new file mode 100644
index 0000000..a31b7c3
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ValTypes/RefType.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\RefType as OrigRefType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+
+final readonly class RefType extends ValType
+{
+ protected function __construct(public OrigRefType $inner)
+ {
+ }
+
+ public function equals(ValType $other): bool
+ {
+ return $other instanceof self
+ && $this->inner === $other->inner;
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/ValTypes/VecType.php b/src/WebAssembly/Structure/Types/ValTypes/VecType.php
new file mode 100644
index 0000000..03cc95e
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/ValTypes/VecType.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValTypes;
+
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
+use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\VecType as OrigVecType;
+
+final readonly class VecType extends ValType
+{
+ protected function __construct(public OrigVecType $inner)
+ {
+ }
+
+ public function equals(ValType $other): bool
+ {
+ return $other instanceof self
+ && $this->inner === $other->inner; // @phpstan-ignore-line
+ }
+}
diff --git a/src/WebAssembly/Structure/Types/VecType.php b/src/WebAssembly/Structure/Types/VecType.php
new file mode 100644
index 0000000..dcf7d68
--- /dev/null
+++ b/src/WebAssembly/Structure/Types/VecType.php
@@ -0,0 +1,10 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\Waddiwasi\WebAssembly\Structure\Types;
+
+enum VecType
+{
+ case V128;
+}