diff options
Diffstat (limited to 'src/WebAssembly')
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; +} |
