From e2495878b872b341e6e04eed31dd255b1a6e256f Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 3 Jan 2024 01:35:32 +0900 Subject: feat: implement binary decoder --- src/BinaryFormat/Code.php | 19 + src/BinaryFormat/Decoder.php | 1153 ++++++++++++++++++++ src/BinaryFormat/InvalidBinaryFormatException.php | 11 + src/BinaryFormat/Locals.php | 19 + src/BinaryFormat/SectionId.php | 22 + src/Structure/Instructions/Expr.php | 23 + src/Structure/Instructions/Instr.php | 977 +++++++++++++++++ .../Instructions/Instrs/Control/Block.php | 19 + .../Instructions/Instrs/Control/BlockType.php | 21 + .../Instrs/Control/BlockTypes/TypeIdx.php | 15 + .../Instrs/Control/BlockTypes/ValType.php | 15 + src/Structure/Instructions/Instrs/Control/Br.php | 16 + src/Structure/Instructions/Instrs/Control/BrIf.php | 16 + .../Instructions/Instrs/Control/BrTable.php | 20 + src/Structure/Instructions/Instrs/Control/Call.php | 16 + .../Instructions/Instrs/Control/CallIndirect.php | 18 + .../Instructions/Instrs/Control/Else_.php | 11 + src/Structure/Instructions/Instrs/Control/End.php | 11 + src/Structure/Instructions/Instrs/Control/If_.php | 21 + src/Structure/Instructions/Instrs/Control/Loop.php | 19 + src/Structure/Instructions/Instrs/Control/Nop.php | 11 + .../Instructions/Instrs/Control/Return_.php | 11 + .../Instructions/Instrs/Control/Unreachable.php | 11 + .../Instructions/Instrs/Memory/DataDrop.php | 16 + .../Instructions/Instrs/Memory/F32Load.php | 20 + .../Instructions/Instrs/Memory/F32Store.php | 20 + .../Instructions/Instrs/Memory/F64Load.php | 20 + .../Instructions/Instrs/Memory/F64Store.php | 20 + .../Instructions/Instrs/Memory/I32Load.php | 20 + .../Instructions/Instrs/Memory/I32Load16S.php | 20 + .../Instructions/Instrs/Memory/I32Load16U.php | 20 + .../Instructions/Instrs/Memory/I32Load8S.php | 20 + .../Instructions/Instrs/Memory/I32Load8U.php | 20 + .../Instructions/Instrs/Memory/I32Store.php | 20 + .../Instructions/Instrs/Memory/I32Store16.php | 20 + .../Instructions/Instrs/Memory/I32Store8.php | 20 + .../Instructions/Instrs/Memory/I64Load.php | 20 + .../Instructions/Instrs/Memory/I64Load16S.php | 20 + .../Instructions/Instrs/Memory/I64Load16U.php | 20 + .../Instructions/Instrs/Memory/I64Load32S.php | 20 + .../Instructions/Instrs/Memory/I64Load32U.php | 20 + .../Instructions/Instrs/Memory/I64Load8S.php | 20 + .../Instructions/Instrs/Memory/I64Load8U.php | 20 + .../Instructions/Instrs/Memory/I64Store.php | 20 + .../Instructions/Instrs/Memory/I64Store16.php | 20 + .../Instructions/Instrs/Memory/I64Store32.php | 20 + .../Instructions/Instrs/Memory/I64Store8.php | 20 + .../Instructions/Instrs/Memory/MemoryCopy.php | 11 + .../Instructions/Instrs/Memory/MemoryFill.php | 11 + .../Instructions/Instrs/Memory/MemoryGrow.php | 11 + .../Instructions/Instrs/Memory/MemoryInit.php | 16 + .../Instructions/Instrs/Memory/MemorySize.php | 11 + .../Instructions/Instrs/Numeric/F32Abs.php | 11 + .../Instructions/Instrs/Numeric/F32Add.php | 11 + .../Instructions/Instrs/Numeric/F32Ceil.php | 11 + .../Instructions/Instrs/Numeric/F32Const.php | 18 + .../Instructions/Instrs/Numeric/F32ConvertI32S.php | 11 + .../Instructions/Instrs/Numeric/F32ConvertI32U.php | 11 + .../Instructions/Instrs/Numeric/F32ConvertI64S.php | 11 + .../Instructions/Instrs/Numeric/F32ConvertI64U.php | 11 + .../Instructions/Instrs/Numeric/F32CopySign.php | 11 + .../Instructions/Instrs/Numeric/F32DemoteF64.php | 11 + .../Instructions/Instrs/Numeric/F32Div.php | 11 + .../Instructions/Instrs/Numeric/F32Eq.php | 11 + .../Instructions/Instrs/Numeric/F32Floor.php | 11 + .../Instructions/Instrs/Numeric/F32Ge.php | 11 + .../Instructions/Instrs/Numeric/F32Gt.php | 11 + .../Instructions/Instrs/Numeric/F32Le.php | 11 + .../Instructions/Instrs/Numeric/F32Lt.php | 11 + .../Instructions/Instrs/Numeric/F32Max.php | 11 + .../Instructions/Instrs/Numeric/F32Min.php | 11 + .../Instructions/Instrs/Numeric/F32Mul.php | 11 + .../Instructions/Instrs/Numeric/F32Ne.php | 11 + .../Instructions/Instrs/Numeric/F32Nearest.php | 11 + .../Instructions/Instrs/Numeric/F32Neg.php | 11 + .../Instrs/Numeric/F32ReinterpretI32.php | 11 + .../Instrs/Numeric/F32ReinterpretI64.php | 11 + .../Instructions/Instrs/Numeric/F32Sqrt.php | 11 + .../Instructions/Instrs/Numeric/F32Sub.php | 11 + .../Instructions/Instrs/Numeric/F32Trunc.php | 11 + .../Instructions/Instrs/Numeric/F64Abs.php | 11 + .../Instructions/Instrs/Numeric/F64Add.php | 11 + .../Instructions/Instrs/Numeric/F64Ceil.php | 11 + .../Instructions/Instrs/Numeric/F64Const.php | 18 + .../Instructions/Instrs/Numeric/F64ConvertI32S.php | 11 + .../Instructions/Instrs/Numeric/F64ConvertI32U.php | 11 + .../Instructions/Instrs/Numeric/F64ConvertI64S.php | 11 + .../Instructions/Instrs/Numeric/F64ConvertI64U.php | 11 + .../Instructions/Instrs/Numeric/F64CopySign.php | 11 + .../Instructions/Instrs/Numeric/F64Div.php | 11 + .../Instructions/Instrs/Numeric/F64Eq.php | 11 + .../Instructions/Instrs/Numeric/F64Floor.php | 11 + .../Instructions/Instrs/Numeric/F64Ge.php | 11 + .../Instructions/Instrs/Numeric/F64Gt.php | 11 + .../Instructions/Instrs/Numeric/F64Le.php | 11 + .../Instructions/Instrs/Numeric/F64Lt.php | 11 + .../Instructions/Instrs/Numeric/F64Max.php | 11 + .../Instructions/Instrs/Numeric/F64Min.php | 11 + .../Instructions/Instrs/Numeric/F64Mul.php | 11 + .../Instructions/Instrs/Numeric/F64Ne.php | 11 + .../Instructions/Instrs/Numeric/F64Nearest.php | 11 + .../Instructions/Instrs/Numeric/F64Neg.php | 11 + .../Instructions/Instrs/Numeric/F64PromoteF32.php | 11 + .../Instrs/Numeric/F64ReinterpretI32.php | 11 + .../Instrs/Numeric/F64ReinterpretI64.php | 11 + .../Instructions/Instrs/Numeric/F64Sqrt.php | 11 + .../Instructions/Instrs/Numeric/F64Sub.php | 11 + .../Instructions/Instrs/Numeric/F64Trunc.php | 11 + .../Instructions/Instrs/Numeric/I32Add.php | 11 + .../Instructions/Instrs/Numeric/I32And.php | 11 + .../Instructions/Instrs/Numeric/I32Clz.php | 11 + .../Instructions/Instrs/Numeric/I32Const.php | 18 + .../Instructions/Instrs/Numeric/I32Ctz.php | 11 + .../Instructions/Instrs/Numeric/I32DivS.php | 11 + .../Instructions/Instrs/Numeric/I32DivU.php | 11 + .../Instructions/Instrs/Numeric/I32Eq.php | 11 + .../Instructions/Instrs/Numeric/I32Eqz.php | 11 + .../Instructions/Instrs/Numeric/I32Extend16S.php | 11 + .../Instructions/Instrs/Numeric/I32Extend8S.php | 11 + .../Instructions/Instrs/Numeric/I32GeS.php | 11 + .../Instructions/Instrs/Numeric/I32GeU.php | 11 + .../Instructions/Instrs/Numeric/I32GtS.php | 11 + .../Instructions/Instrs/Numeric/I32GtU.php | 11 + .../Instructions/Instrs/Numeric/I32LeS.php | 11 + .../Instructions/Instrs/Numeric/I32LeU.php | 11 + .../Instructions/Instrs/Numeric/I32LtS.php | 11 + .../Instructions/Instrs/Numeric/I32LtU.php | 11 + .../Instructions/Instrs/Numeric/I32Mul.php | 11 + .../Instructions/Instrs/Numeric/I32Ne.php | 11 + .../Instructions/Instrs/Numeric/I32Or.php | 11 + .../Instructions/Instrs/Numeric/I32Popcnt.php | 11 + .../Instrs/Numeric/I32ReinterpretF32.php | 11 + .../Instrs/Numeric/I32ReinterpretF64.php | 11 + .../Instructions/Instrs/Numeric/I32RemS.php | 11 + .../Instructions/Instrs/Numeric/I32RemU.php | 11 + .../Instructions/Instrs/Numeric/I32RotL.php | 11 + .../Instructions/Instrs/Numeric/I32RotR.php | 11 + .../Instructions/Instrs/Numeric/I32Shl.php | 11 + .../Instructions/Instrs/Numeric/I32ShrS.php | 11 + .../Instructions/Instrs/Numeric/I32ShrU.php | 11 + .../Instructions/Instrs/Numeric/I32Sub.php | 11 + .../Instructions/Instrs/Numeric/I32TruncF32S.php | 11 + .../Instructions/Instrs/Numeric/I32TruncF32U.php | 11 + .../Instructions/Instrs/Numeric/I32TruncF64S.php | 11 + .../Instructions/Instrs/Numeric/I32TruncF64U.php | 11 + .../Instrs/Numeric/I32TruncSatF32S.php | 11 + .../Instrs/Numeric/I32TruncSatF32U.php | 11 + .../Instrs/Numeric/I32TruncSatF64S.php | 11 + .../Instrs/Numeric/I32TruncSatF64U.php | 11 + .../Instructions/Instrs/Numeric/I32WrapI64.php | 11 + .../Instructions/Instrs/Numeric/I32Xor.php | 11 + .../Instructions/Instrs/Numeric/I64Add.php | 11 + .../Instructions/Instrs/Numeric/I64And.php | 11 + .../Instructions/Instrs/Numeric/I64Clz.php | 11 + .../Instructions/Instrs/Numeric/I64Const.php | 18 + .../Instructions/Instrs/Numeric/I64Ctz.php | 11 + .../Instructions/Instrs/Numeric/I64DivS.php | 11 + .../Instructions/Instrs/Numeric/I64DivU.php | 11 + .../Instructions/Instrs/Numeric/I64Eq.php | 11 + .../Instructions/Instrs/Numeric/I64Eqz.php | 11 + .../Instructions/Instrs/Numeric/I64Extend16S.php | 11 + .../Instructions/Instrs/Numeric/I64Extend32S.php | 11 + .../Instructions/Instrs/Numeric/I64Extend8S.php | 11 + .../Instructions/Instrs/Numeric/I64ExtendI32S.php | 11 + .../Instructions/Instrs/Numeric/I64ExtendI32U.php | 11 + .../Instructions/Instrs/Numeric/I64GeS.php | 11 + .../Instructions/Instrs/Numeric/I64GeU.php | 11 + .../Instructions/Instrs/Numeric/I64GtS.php | 11 + .../Instructions/Instrs/Numeric/I64GtU.php | 11 + .../Instructions/Instrs/Numeric/I64LeS.php | 11 + .../Instructions/Instrs/Numeric/I64LeU.php | 11 + .../Instructions/Instrs/Numeric/I64LtS.php | 11 + .../Instructions/Instrs/Numeric/I64LtU.php | 11 + .../Instructions/Instrs/Numeric/I64Mul.php | 11 + .../Instructions/Instrs/Numeric/I64Ne.php | 11 + .../Instructions/Instrs/Numeric/I64Or.php | 11 + .../Instructions/Instrs/Numeric/I64Popcnt.php | 11 + .../Instrs/Numeric/I64ReinterpretF32.php | 11 + .../Instrs/Numeric/I64ReinterpretF64.php | 11 + .../Instructions/Instrs/Numeric/I64RemS.php | 11 + .../Instructions/Instrs/Numeric/I64RemU.php | 11 + .../Instructions/Instrs/Numeric/I64RotL.php | 11 + .../Instructions/Instrs/Numeric/I64RotR.php | 11 + .../Instructions/Instrs/Numeric/I64Shl.php | 11 + .../Instructions/Instrs/Numeric/I64ShrS.php | 11 + .../Instructions/Instrs/Numeric/I64ShrU.php | 11 + .../Instructions/Instrs/Numeric/I64Sub.php | 11 + .../Instructions/Instrs/Numeric/I64TruncF32S.php | 11 + .../Instructions/Instrs/Numeric/I64TruncF32U.php | 11 + .../Instructions/Instrs/Numeric/I64TruncF64S.php | 11 + .../Instructions/Instrs/Numeric/I64TruncF64U.php | 11 + .../Instrs/Numeric/I64TruncSatF32S.php | 11 + .../Instrs/Numeric/I64TruncSatF32U.php | 11 + .../Instrs/Numeric/I64TruncSatF64S.php | 11 + .../Instrs/Numeric/I64TruncSatF64U.php | 11 + .../Instructions/Instrs/Numeric/I64Xor.php | 11 + .../Instructions/Instrs/Parametric/Drop.php | 11 + .../Instructions/Instrs/Parametric/Select.php | 19 + .../Instructions/Instrs/Reference/RefFunc.php | 16 + .../Instructions/Instrs/Reference/RefIsNull.php | 11 + .../Instructions/Instrs/Reference/RefNull.php | 16 + .../Instructions/Instrs/Table/ElemDrop.php | 16 + .../Instructions/Instrs/Table/TableCopy.php | 17 + .../Instructions/Instrs/Table/TableFill.php | 16 + .../Instructions/Instrs/Table/TableGet.php | 16 + .../Instructions/Instrs/Table/TableGrow.php | 16 + .../Instructions/Instrs/Table/TableInit.php | 18 + .../Instructions/Instrs/Table/TableSet.php | 16 + .../Instructions/Instrs/Table/TableSize.php | 16 + .../Instructions/Instrs/Variable/GlobalGet.php | 16 + .../Instructions/Instrs/Variable/GlobalSet.php | 16 + .../Instructions/Instrs/Variable/LocalGet.php | 16 + .../Instructions/Instrs/Variable/LocalSet.php | 16 + .../Instructions/Instrs/Variable/LocalTee.php | 16 + src/Structure/Modules/Data.php | 17 + src/Structure/Modules/DataMode.php | 23 + src/Structure/Modules/DataModes/Active.php | 18 + src/Structure/Modules/DataModes/Passive.php | 14 + src/Structure/Modules/Elem.php | 21 + src/Structure/Modules/ElemMode.php | 28 + src/Structure/Modules/ElemModes/Active.php | 18 + src/Structure/Modules/ElemModes/Declarative.php | 14 + src/Structure/Modules/ElemModes/Passive.php | 14 + src/Structure/Modules/Export.php | 17 + src/Structure/Modules/ExportDesc.php | 33 + src/Structure/Modules/ExportDescs/Func.php | 16 + src/Structure/Modules/ExportDescs/Global_.php | 16 + src/Structure/Modules/ExportDescs/Mem.php | 16 + src/Structure/Modules/ExportDescs/Table.php | 16 + src/Structure/Modules/Func.php | 21 + src/Structure/Modules/Global_.php | 17 + src/Structure/Modules/Import.php | 19 + src/Structure/Modules/ImportDesc.php | 33 + src/Structure/Modules/ImportDescs/Func.php | 16 + src/Structure/Modules/ImportDescs/Global_.php | 16 + src/Structure/Modules/ImportDescs/Mem.php | 16 + src/Structure/Modules/ImportDescs/Table.php | 16 + src/Structure/Modules/Local.php | 15 + src/Structure/Modules/Mem.php | 15 + src/Structure/Modules/Module.php | 35 + src/Structure/Modules/Start.php | 15 + src/Structure/Modules/Table.php | 15 + src/Structure/Types/DataIdx.php | 16 + src/Structure/Types/ElemIdx.php | 16 + src/Structure/Types/ExternType.php | 28 + src/Structure/Types/ExternTypes/Func.php | 16 + src/Structure/Types/ExternTypes/Global_.php | 16 + src/Structure/Types/ExternTypes/Mem.php | 16 + src/Structure/Types/ExternTypes/Table.php | 16 + src/Structure/Types/FuncIdx.php | 16 + src/Structure/Types/FuncType.php | 14 + src/Structure/Types/GlobalIdx.php | 16 + src/Structure/Types/GlobalType.php | 14 + src/Structure/Types/LabelIdx.php | 16 + src/Structure/Types/Limits.php | 18 + src/Structure/Types/LocalIdx.php | 16 + src/Structure/Types/MemIdx.php | 16 + src/Structure/Types/MemType.php | 13 + src/Structure/Types/Mut.php | 11 + src/Structure/Types/NumType.php | 13 + src/Structure/Types/RefType.php | 11 + src/Structure/Types/ResultType.php | 16 + src/Structure/Types/TableIdx.php | 16 + src/Structure/Types/TableType.php | 14 + src/Structure/Types/TypeIdx.php | 16 + src/Structure/Types/ValType.php | 23 + src/Structure/Types/ValTypes/NumType.php | 15 + src/Structure/Types/ValTypes/RefType.php | 15 + src/Structure/Types/ValTypes/VecType.php | 15 + src/Structure/Types/VecType.php | 10 + 270 files changed, 5875 insertions(+) create mode 100644 src/BinaryFormat/Code.php create mode 100644 src/BinaryFormat/Decoder.php create mode 100644 src/BinaryFormat/InvalidBinaryFormatException.php create mode 100644 src/BinaryFormat/Locals.php create mode 100644 src/BinaryFormat/SectionId.php create mode 100644 src/Structure/Instructions/Expr.php create mode 100644 src/Structure/Instructions/Instr.php create mode 100644 src/Structure/Instructions/Instrs/Control/Block.php create mode 100644 src/Structure/Instructions/Instrs/Control/BlockType.php create mode 100644 src/Structure/Instructions/Instrs/Control/BlockTypes/TypeIdx.php create mode 100644 src/Structure/Instructions/Instrs/Control/BlockTypes/ValType.php create mode 100644 src/Structure/Instructions/Instrs/Control/Br.php create mode 100644 src/Structure/Instructions/Instrs/Control/BrIf.php create mode 100644 src/Structure/Instructions/Instrs/Control/BrTable.php create mode 100644 src/Structure/Instructions/Instrs/Control/Call.php create mode 100644 src/Structure/Instructions/Instrs/Control/CallIndirect.php create mode 100644 src/Structure/Instructions/Instrs/Control/Else_.php create mode 100644 src/Structure/Instructions/Instrs/Control/End.php create mode 100644 src/Structure/Instructions/Instrs/Control/If_.php create mode 100644 src/Structure/Instructions/Instrs/Control/Loop.php create mode 100644 src/Structure/Instructions/Instrs/Control/Nop.php create mode 100644 src/Structure/Instructions/Instrs/Control/Return_.php create mode 100644 src/Structure/Instructions/Instrs/Control/Unreachable.php create mode 100644 src/Structure/Instructions/Instrs/Memory/DataDrop.php create mode 100644 src/Structure/Instructions/Instrs/Memory/F32Load.php create mode 100644 src/Structure/Instructions/Instrs/Memory/F32Store.php create mode 100644 src/Structure/Instructions/Instrs/Memory/F64Load.php create mode 100644 src/Structure/Instructions/Instrs/Memory/F64Store.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Load.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Load16S.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Load16U.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Load8S.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Load8U.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Store.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Store16.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I32Store8.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load16S.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load16U.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load32S.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load32U.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load8S.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Load8U.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Store.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Store16.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Store32.php create mode 100644 src/Structure/Instructions/Instrs/Memory/I64Store8.php create mode 100644 src/Structure/Instructions/Instrs/Memory/MemoryCopy.php create mode 100644 src/Structure/Instructions/Instrs/Memory/MemoryFill.php create mode 100644 src/Structure/Instructions/Instrs/Memory/MemoryGrow.php create mode 100644 src/Structure/Instructions/Instrs/Memory/MemoryInit.php create mode 100644 src/Structure/Instructions/Instrs/Memory/MemorySize.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Abs.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Add.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Ceil.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Const.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32ConvertI32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32ConvertI32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32ConvertI64S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32ConvertI64U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32CopySign.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32DemoteF64.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Div.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Eq.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Floor.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Ge.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Gt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Le.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Lt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Max.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Min.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Mul.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Ne.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Nearest.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Neg.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32ReinterpretI32.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32ReinterpretI64.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Sqrt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Sub.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F32Trunc.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Abs.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Add.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Ceil.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Const.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64ConvertI32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64ConvertI32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64ConvertI64S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64ConvertI64U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64CopySign.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Div.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Eq.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Floor.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Ge.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Gt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Le.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Lt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Max.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Min.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Mul.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Ne.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Nearest.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Neg.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64PromoteF32.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64ReinterpretI32.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64ReinterpretI64.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Sqrt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Sub.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/F64Trunc.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Add.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32And.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Clz.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Const.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Ctz.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32DivS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32DivU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Eq.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Eqz.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Extend16S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Extend8S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32GeS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32GeU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32GtS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32GtU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32LeS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32LeU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32LtS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32LtU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Mul.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Ne.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Or.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Popcnt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32ReinterpretF32.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32ReinterpretF64.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32RemS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32RemU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32RotL.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32RotR.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Shl.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32ShrS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32ShrU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Sub.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncF32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncF32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncF64S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncF64U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncSatF32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncSatF32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncSatF64S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32TruncSatF64U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32WrapI64.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I32Xor.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Add.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64And.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Clz.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Const.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Ctz.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64DivS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64DivU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Eq.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Eqz.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Extend16S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Extend32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Extend8S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64ExtendI32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64ExtendI32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64GeS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64GeU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64GtS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64GtU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64LeS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64LeU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64LtS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64LtU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Mul.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Ne.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Or.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Popcnt.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64ReinterpretF32.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64ReinterpretF64.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64RemS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64RemU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64RotL.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64RotR.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Shl.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64ShrS.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64ShrU.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Sub.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncF32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncF32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncF64S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncF64U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncSatF32S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncSatF32U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncSatF64S.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64TruncSatF64U.php create mode 100644 src/Structure/Instructions/Instrs/Numeric/I64Xor.php create mode 100644 src/Structure/Instructions/Instrs/Parametric/Drop.php create mode 100644 src/Structure/Instructions/Instrs/Parametric/Select.php create mode 100644 src/Structure/Instructions/Instrs/Reference/RefFunc.php create mode 100644 src/Structure/Instructions/Instrs/Reference/RefIsNull.php create mode 100644 src/Structure/Instructions/Instrs/Reference/RefNull.php create mode 100644 src/Structure/Instructions/Instrs/Table/ElemDrop.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableCopy.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableFill.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableGet.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableGrow.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableInit.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableSet.php create mode 100644 src/Structure/Instructions/Instrs/Table/TableSize.php create mode 100644 src/Structure/Instructions/Instrs/Variable/GlobalGet.php create mode 100644 src/Structure/Instructions/Instrs/Variable/GlobalSet.php create mode 100644 src/Structure/Instructions/Instrs/Variable/LocalGet.php create mode 100644 src/Structure/Instructions/Instrs/Variable/LocalSet.php create mode 100644 src/Structure/Instructions/Instrs/Variable/LocalTee.php create mode 100644 src/Structure/Modules/Data.php create mode 100644 src/Structure/Modules/DataMode.php create mode 100644 src/Structure/Modules/DataModes/Active.php create mode 100644 src/Structure/Modules/DataModes/Passive.php create mode 100644 src/Structure/Modules/Elem.php create mode 100644 src/Structure/Modules/ElemMode.php create mode 100644 src/Structure/Modules/ElemModes/Active.php create mode 100644 src/Structure/Modules/ElemModes/Declarative.php create mode 100644 src/Structure/Modules/ElemModes/Passive.php create mode 100644 src/Structure/Modules/Export.php create mode 100644 src/Structure/Modules/ExportDesc.php create mode 100644 src/Structure/Modules/ExportDescs/Func.php create mode 100644 src/Structure/Modules/ExportDescs/Global_.php create mode 100644 src/Structure/Modules/ExportDescs/Mem.php create mode 100644 src/Structure/Modules/ExportDescs/Table.php create mode 100644 src/Structure/Modules/Func.php create mode 100644 src/Structure/Modules/Global_.php create mode 100644 src/Structure/Modules/Import.php create mode 100644 src/Structure/Modules/ImportDesc.php create mode 100644 src/Structure/Modules/ImportDescs/Func.php create mode 100644 src/Structure/Modules/ImportDescs/Global_.php create mode 100644 src/Structure/Modules/ImportDescs/Mem.php create mode 100644 src/Structure/Modules/ImportDescs/Table.php create mode 100644 src/Structure/Modules/Local.php create mode 100644 src/Structure/Modules/Mem.php create mode 100644 src/Structure/Modules/Module.php create mode 100644 src/Structure/Modules/Start.php create mode 100644 src/Structure/Modules/Table.php create mode 100644 src/Structure/Types/DataIdx.php create mode 100644 src/Structure/Types/ElemIdx.php create mode 100644 src/Structure/Types/ExternType.php create mode 100644 src/Structure/Types/ExternTypes/Func.php create mode 100644 src/Structure/Types/ExternTypes/Global_.php create mode 100644 src/Structure/Types/ExternTypes/Mem.php create mode 100644 src/Structure/Types/ExternTypes/Table.php create mode 100644 src/Structure/Types/FuncIdx.php create mode 100644 src/Structure/Types/FuncType.php create mode 100644 src/Structure/Types/GlobalIdx.php create mode 100644 src/Structure/Types/GlobalType.php create mode 100644 src/Structure/Types/LabelIdx.php create mode 100644 src/Structure/Types/Limits.php create mode 100644 src/Structure/Types/LocalIdx.php create mode 100644 src/Structure/Types/MemIdx.php create mode 100644 src/Structure/Types/MemType.php create mode 100644 src/Structure/Types/Mut.php create mode 100644 src/Structure/Types/NumType.php create mode 100644 src/Structure/Types/RefType.php create mode 100644 src/Structure/Types/ResultType.php create mode 100644 src/Structure/Types/TableIdx.php create mode 100644 src/Structure/Types/TableType.php create mode 100644 src/Structure/Types/TypeIdx.php create mode 100644 src/Structure/Types/ValType.php create mode 100644 src/Structure/Types/ValTypes/NumType.php create mode 100644 src/Structure/Types/ValTypes/RefType.php create mode 100644 src/Structure/Types/ValTypes/VecType.php create mode 100644 src/Structure/Types/VecType.php (limited to 'src') diff --git a/src/BinaryFormat/Code.php b/src/BinaryFormat/Code.php new file mode 100644 index 0000000..cb0dbe6 --- /dev/null +++ b/src/BinaryFormat/Code.php @@ -0,0 +1,19 @@ + $compressedLocals + */ + public function __construct( + public array $compressedLocals, + public Expr $body, + ) { + } +} diff --git a/src/BinaryFormat/Decoder.php b/src/BinaryFormat/Decoder.php new file mode 100644 index 0000000..f95c26e --- /dev/null +++ b/src/BinaryFormat/Decoder.php @@ -0,0 +1,1153 @@ +input = $wasmBinary; + $this->inputSize = strlen($wasmBinary); + $this->pos = 0; + } + + 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->eof()) { + throw new InvalidBinaryFormatException("eof"); + } + if ($dataCount === null) { + // TODO: dataidx(code) must be empty + } else { + if (count($datas) !== $dataCount) { + throw new InvalidBinaryFormatException("datasec"); + } + } + + $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 + { + assert($this->pos === 0); + $this->ensureNBytesRemains(4); + $b1 = ord($this->input[0]); + $b2 = ord($this->input[1]); + $b3 = ord($this->input[2]); + $b4 = ord($this->input[3]); + if ([$b1, $b2, $b3, $b4] !== [0x00, 0x61, 0x73, 0x6D]) { + throw new InvalidBinaryFormatException("magic"); + } + $this->pos += 4; + } + + private function checkVersion(): void + { + assert($this->pos === 4); + $this->ensureNBytesRemains(4); + $b1 = ord($this->input[0]); + $b2 = ord($this->input[1]); + $b3 = ord($this->input[2]); + $b4 = ord($this->input[3]); + if ([$b1, $b2, $b3, $b4] !== [0x01, 0x00, 0x00, 0x00]) { + throw new InvalidBinaryFormatException("version"); + } + $this->pos += 4; + } + + /** + * @template T + * @param callable(): T $decoder + * @return ?T + */ + private function decodeSection(SectionId $sectionId, callable $decoder): mixed + { + $this->skipCustomSections(); + + $idValue = $this->peekByte(); + $id = SectionId::tryFrom($idValue); + if ($id === null) { + throw new InvalidBinaryFormatException("section id"); + } + if ($id !== $sectionId) { + return null; + } + $this->skipNBytes(1); + + $size = $this->decodeU32(); + $prevPos = $this->pos; + $result = $decoder(); + if ($this->pos - $prevPos !== $size) { + throw new InvalidBinaryFormatException("type section size"); + } + return $result; + } + + private function skipCustomSections(): void + { + while (!$this->eof()) { + $b = $this->peekByte(); + if ($b !== SectionId::Custom->value) { + break; + } + $this->skipNBytes(1); + $size = $this->decodeU32(); + $prevPos = $this->pos; + $this->decodeName(); + $encodedSizeOfName = $this->pos - $prevPos; + $this->skipNBytes($size - $encodedSizeOfName); + } + } + + /** + * @return list + */ + private function decodeTypeSecRest(): array + { + return $this->decodeVec($this->decodeFuncType(...)); + } + + /** + * @return list + */ + private function decodeImportSecRest(): array + { + return $this->decodeVec($this->decodeImport(...)); + } + + /** + * @return list + */ + private function decodeFuncSecRest(): array + { + return $this->decodeVec($this->decodeTypeIdx(...)); + } + + /** + * @return list + */ + private function decodeTableSecRest(): array + { + return $this->decodeVec($this->decodeTable(...)); + } + + /** + * @return list + */ + private function decodeMemSecRest(): array + { + return $this->decodeVec($this->decodeMem(...)); + } + + /** + * @return list + */ + private function decodeGlobalSecRest(): array + { + return $this->decodeVec($this->decodeGlobal(...)); + } + + /** + * @return list + */ + private function decodeExportSecRest(): array + { + return $this->decodeVec($this->decodeExport(...)); + } + + private function decodeStartSecRest(): Start + { + return new Start($this->decodeFuncIdx()); + } + + /** + * @return list + */ + private function decodeElemSecRest(): array + { + return $this->decodeVec($this->decodeElem(...)); + } + + /** + * @return list + */ + private function decodeCodeSecRest(): array + { + return $this->decodeVec($this->decodeCode(...)); + } + + /** + * @return list + */ + 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"); + } + $args = $this->decodeResultType(); + $returns = $this->decodeResultType(); + return new FuncType( + $args, + $returns, + ); + } + + private function decodeValType(): ValType + { + $b = $this->peekByte(); + if ($b === 0x7F) { + $this->skipNBytes(1); + return ValType::NumType(NumType::I32); + } elseif ($b === 0x7E) { + $this->skipNBytes(1); + return ValType::NumType(NumType::I64); + } elseif ($b === 0x7D) { + $this->skipNBytes(1); + return ValType::NumType(NumType::F32); + } elseif ($b === 0x7C) { + $this->skipNBytes(1); + return ValType::NumType(NumType::F64); + } elseif ($b === 0x7B) { + $this->skipNBytes(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 + { + $type = $this->decodeMemType(); + return new Mem( + $type, + ); + } + + 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) => new Expr([Instr::RefFunc($funcRef)]), + $initFuncRefs, + ), + ElemMode::Active(new TableIdx(0), $offset), + ); + } elseif ($mode === 1) { + $refType = $this->decodeElemKind(); + $initFuncRefs = $this->decodeVec($this->decodeFuncIdx(...)); + return new Elem( + $refType, + array_map( + fn ($funcRef) => new Expr([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) => new Expr([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) => new Expr([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(new TableIdx(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->pos; + $compressedLocals = $this->decodeVec($this->decodeLocals(...)); + $body = $this->decodeExpr(); + if ($this->pos - $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( + new MemIdx(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(); + $type = $this->decodeValType(); + return new Locals( + $count, + $type, + ); + } + + private function decodeTypeIdx(): TypeIdx + { + return new TypeIdx($this->decodeU32()); + } + + private function decodeMemIdx(): MemIdx + { + return new MemIdx($this->decodeU32()); + } + + private function decodeFuncIdx(): FuncIdx + { + return new FuncIdx($this->decodeU32()); + } + + private function decodeTableIdx(): TableIdx + { + return new TableIdx($this->decodeU32()); + } + + private function decodeGlobalIdx(): GlobalIdx + { + return new GlobalIdx($this->decodeU32()); + } + + private function decodeLocalIdx(): LocalIdx + { + return new LocalIdx($this->decodeU32()); + } + + private function decodeLabelIdx(): LabelIdx + { + return new LabelIdx($this->decodeU32()); + } + + private function decodeDataIdx(): DataIdx + { + return new DataIdx($this->decodeU32()); + } + + private function decodeElemIdx(): ElemIdx + { + return new ElemIdx($this->decodeU32()); + } + + private function decodeExpr(): Expr + { + return new Expr($this->decodeInstrsUntil([Instrs\Control\End::class])[0]); + } + + private function decodeInstr(): Instr + { + switch ($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: + if ($this->decodeByte() !== 0) { + throw new InvalidBinaryFormatException("memory size"); + } + return Instr::MemorySize(); + case 0x40: + if ($this->decodeByte() !== 0) { + throw new InvalidBinaryFormatException("memory grow"); + } + 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("instr"); + } + } + + /** + * @return array{0: U32, 1: U32} + */ + private function decodeMemArg(): array + { + $align = $this->decodeU32(); + $offset = $this->decodeU32(); + return [$align, $offset]; + } + + private function decodeBlockType(): BlockType + { + $b = $this->peekByte(); + if ($b === 0x40) { + $this->skipNBytes(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(new TypeIdx($type)); + } + } + + /** + * @param list> $delimiters + * @return array{0: list, 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 + */ + private function decodeVec(callable $decoder): array + { + $count = $this->decodeU32(); + $result = []; + for ($i = 0; $i < $count; $i++) { + $result[] = $decoder(); + } + return $result; + } + + private function eof(): bool + { + return strlen($this->input) <= $this->pos; + } + + private function ensureNBytesRemains(int $n): void + { + if ($this->inputSize < $this->pos + $n) { + throw new InvalidBinaryFormatException("ensureNBytesRemains"); + } + } + + private function skipNBytes(int $n): void + { + $this->ensureNBytesRemains($n); + $this->pos += $n; + } + + private function peekByte(): int + { + $this->ensureNBytesRemains(1); + return ord($this->input[$this->pos]); + } + + /** + * @phpstan-impure + */ + private function decodeByte(): int + { + $this->ensureNBytesRemains(1); + return ord($this->input[$this->pos++]); + } + + private function decodeU32(): int + { + return $this->decodeUnsignedLeb128(32); + } + + private function decodeUnsignedLeb128(int $maxBits): int + { + $result = 0; + $shiftBits = 0; + while (true) { + $b = $this->decodeByte(); + $result |= ($b & 0b01111111) << $shiftBits; + if ($b < 0b10000000) { + return $result; + } + $shiftBits += 7; + if ($maxBits <= $shiftBits) { + throw new InvalidBinaryFormatException("unsigned leb128"); + } + } + } + + private function decodeSignedLeb128(int $bits): int + { + $result = 0; + $shiftBits = 0; + while (true) { + $b = $this->decodeByte(); + $result |= ($b & 0b01111111) << $shiftBits; + if ($b < 0b10000000) { + if (($b & 0b01000000) !== 0) { + $result |= -(1 << $shiftBits); + } + return $result; + } + $shiftBits += 7; + if ($bits <= $shiftBits) { + throw new InvalidBinaryFormatException("signed leb128"); + } + } + } + + /** + * @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 + { + $this->ensureNBytesRemains(4); + $result = unpack('g', $this->input, $this->pos); + if ($result === false) { + throw new InvalidBinaryFormatException("f32"); + } + assert(isset($result[1]) && is_float($result[1])); + return $result[1]; + } + + /** + * @return F64 + */ + private function decodeF64(): float + { + $this->ensureNBytesRemains(8); + $result = unpack('e', $this->input, $this->pos); + 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 $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; + } +} diff --git a/src/BinaryFormat/InvalidBinaryFormatException.php b/src/BinaryFormat/InvalidBinaryFormatException.php new file mode 100644 index 0000000..59b046c --- /dev/null +++ b/src/BinaryFormat/InvalidBinaryFormatException.php @@ -0,0 +1,11 @@ + + */ + public array $instrs; + + /** + * @param list $instrs + */ + public function __construct( + array $instrs, + ) { + $instrs[] = Instr::End(); + $this->instrs = $instrs; + } +} diff --git a/src/Structure/Instructions/Instr.php b/src/Structure/Instructions/Instr.php new file mode 100644 index 0000000..f4f85cc --- /dev/null +++ b/src/Structure/Instructions/Instr.php @@ -0,0 +1,977 @@ + $types + */ + final public static function Select(array $types): Parametric\Select + { + return new Parametric\Select($types); + } + + // Variable instructions + final public static function GlobalGet(GlobalIdx $var): Variable\GlobalGet + { + return new Variable\GlobalGet($var); + } + final public static function GlobalSet(GlobalIdx $var): Variable\GlobalSet + { + return new Variable\GlobalSet($var); + } + final public static function LocalGet(LocalIdx $var): Variable\LocalGet + { + return new Variable\LocalGet($var); + } + final public static function LocalSet(LocalIdx $var): Variable\LocalSet + { + return new Variable\LocalSet($var); + } + final public static function LocalTee(LocalIdx $var): Variable\LocalTee + { + return new Variable\LocalTee($var); + } + + // Table instructions + final public static function ElemDrop(ElemIdx $elem): Table\ElemDrop + { + return new Table\ElemDrop($elem); + } + final public static function TableCopy(TableIdx $to, TableIdx $from): Table\TableCopy + { + return new Table\TableCopy($to, $from); + } + final public static function TableFill(TableIdx $table): Table\TableFill + { + return new Table\TableFill($table); + } + final public static function TableGet(TableIdx $table): Table\TableGet + { + return new Table\TableGet($table); + } + final public static function TableGrow(TableIdx $table): Table\TableGrow + { + return new Table\TableGrow($table); + } + final public static function TableInit(TableIdx $to, ElemIdx $from): Table\TableInit + { + return new Table\TableInit($to, $from); + } + final public static function TableSet(TableIdx $table): Table\TableSet + { + return new Table\TableSet($table); + } + final public static function TableSize(TableIdx $table): Table\TableSize + { + return new Table\TableSize($table); + } + + // Memory instructions + final public static function DataDrop(DataIdx $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(DataIdx $data): Memory\MemoryInit + { + return new Memory\MemoryInit($data); + } + final public static function MemorySize(): Memory\MemorySize + { + return new Memory\MemorySize(); + } + + // Control instructions + /** + * @param list $body + */ + final public static function Block(BlockType $type, array $body): Control\Block + { + return new Control\Block($type, $body); + } + final public static function Br(LabelIdx $label): Control\Br + { + return new Control\Br($label); + } + final public static function BrIf(LabelIdx $label): Control\BrIf + { + return new Control\BrIf($label); + } + /** + * @param list $labelTable + */ + final public static function BrTable(array $labelTable, LabelIdx $defaultLabel): Control\BrTable + { + return new Control\BrTable($labelTable, $defaultLabel); + } + final public static function Call(FuncIdx $func): Control\Call + { + return new Control\Call($func); + } + final public static function CallIndirect(TableIdx $funcTable, TypeIdx $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 $thenBody + * @param list $elseBody + */ + final public static function If_(BlockType $type, array $thenBody, array $elseBody): Control\If_ + { + return new Control\If_($type, $thenBody, $elseBody); + } + /** + * @param list $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(); + } +} diff --git a/src/Structure/Instructions/Instrs/Control/Block.php b/src/Structure/Instructions/Instrs/Control/Block.php new file mode 100644 index 0000000..2be7a1f --- /dev/null +++ b/src/Structure/Instructions/Instrs/Control/Block.php @@ -0,0 +1,19 @@ + $body + */ + public function __construct( + public BlockType $type, + public array $body, + ) { + } +} diff --git a/src/Structure/Instructions/Instrs/Control/BlockType.php b/src/Structure/Instructions/Instrs/Control/BlockType.php new file mode 100644 index 0000000..68c6bd4 --- /dev/null +++ b/src/Structure/Instructions/Instrs/Control/BlockType.php @@ -0,0 +1,21 @@ + $labelTable + */ + public function __construct( + public array $labelTable, + public LabelIdx $defaultLabel, + ) { + } +} diff --git a/src/Structure/Instructions/Instrs/Control/Call.php b/src/Structure/Instructions/Instrs/Control/Call.php new file mode 100644 index 0000000..c8702d3 --- /dev/null +++ b/src/Structure/Instructions/Instrs/Control/Call.php @@ -0,0 +1,16 @@ + $thenBody + * @param list $elseBody + */ + public function __construct( + public BlockType $type, + public array $thenBody, + public array $elseBody, + ) { + } +} diff --git a/src/Structure/Instructions/Instrs/Control/Loop.php b/src/Structure/Instructions/Instrs/Control/Loop.php new file mode 100644 index 0000000..30c85ef --- /dev/null +++ b/src/Structure/Instructions/Instrs/Control/Loop.php @@ -0,0 +1,19 @@ + $body + */ + public function __construct( + public BlockType $type, + public array $body, + ) { + } +} diff --git a/src/Structure/Instructions/Instrs/Control/Nop.php b/src/Structure/Instructions/Instrs/Control/Nop.php new file mode 100644 index 0000000..dbb1b6c --- /dev/null +++ b/src/Structure/Instructions/Instrs/Control/Nop.php @@ -0,0 +1,11 @@ + $types + */ + public function __construct( + public array $types, + ) { + } +} diff --git a/src/Structure/Instructions/Instrs/Reference/RefFunc.php b/src/Structure/Instructions/Instrs/Reference/RefFunc.php new file mode 100644 index 0000000..2849f5f --- /dev/null +++ b/src/Structure/Instructions/Instrs/Reference/RefFunc.php @@ -0,0 +1,16 @@ + $init + */ + public function __construct( + public array $init, + public DataMode $mode, + ) { + } +} diff --git a/src/Structure/Modules/DataMode.php b/src/Structure/Modules/DataMode.php new file mode 100644 index 0000000..08228d9 --- /dev/null +++ b/src/Structure/Modules/DataMode.php @@ -0,0 +1,23 @@ + $init + */ + public function __construct( + public RefType $type, + public array $init, + public ElemMode $mode, + ) { + } +} diff --git a/src/Structure/Modules/ElemMode.php b/src/Structure/Modules/ElemMode.php new file mode 100644 index 0000000..d6496dd --- /dev/null +++ b/src/Structure/Modules/ElemMode.php @@ -0,0 +1,28 @@ + $locals + */ + public function __construct( + public TypeIdx $type, + public array $locals, + public Expr $body, + ) { + } +} diff --git a/src/Structure/Modules/Global_.php b/src/Structure/Modules/Global_.php new file mode 100644 index 0000000..9d6d371 --- /dev/null +++ b/src/Structure/Modules/Global_.php @@ -0,0 +1,17 @@ + $types + * @param list $funcs + * @param list
$tables + * @param list $mems + * @param list $globals + * @param list $elems + * @param list $datas + * @param list $imports + * @param list $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/Structure/Modules/Start.php b/src/Structure/Modules/Start.php new file mode 100644 index 0000000..afb583b --- /dev/null +++ b/src/Structure/Modules/Start.php @@ -0,0 +1,15 @@ + $types + */ + public function __construct( + public array $types, + ) { + } +} diff --git a/src/Structure/Types/TableIdx.php b/src/Structure/Types/TableIdx.php new file mode 100644 index 0000000..af2d72b --- /dev/null +++ b/src/Structure/Types/TableIdx.php @@ -0,0 +1,16 @@ +