aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-06-28 00:30:17 +0900
committernsfisis <nsfisis@gmail.com>2024-06-28 00:40:06 +0900
commitde8914e4080350b74ba9de9c8ceeef38809da8d9 (patch)
treeca85710d18c5e41688f70e7b1dda85d1b25a3771
parent00925ff256fdf96d3bb259464e771c553c1ffabb (diff)
downloadphp-waddiwasi-de8914e4080350b74ba9de9c8ceeef38809da8d9.tar.gz
php-waddiwasi-de8914e4080350b74ba9de9c8ceeef38809da8d9.tar.zst
php-waddiwasi-de8914e4080350b74ba9de9c8ceeef38809da8d9.zip
fix: some integral operations
-rw-r--r--src/Execution/Runtime.php19
-rw-r--r--src/Execution/TrapKind.php1
-rw-r--r--tests/src/SpecTestsuites/SpecTestsuiteBase.php5
3 files changed, 14 insertions, 11 deletions
diff --git a/src/Execution/Runtime.php b/src/Execution/Runtime.php
index 53a0e8d..e4fc96e 100644
--- a/src/Execution/Runtime.php
+++ b/src/Execution/Runtime.php
@@ -908,7 +908,7 @@ final class Runtime
{
$c2 = $this->stack->popInt();
$c1 = $this->stack->popInt();
- $this->stack->pushValue(($c1 + $c2) % 0x100000000);
+ $this->stack->pushValue(self::phpIntToWasmI32(($c1 + $c2) & 0xFFFFFFFF));
}
private function execInstrNumericI32And(Instrs\Numeric\I32And $instr): void
@@ -958,20 +958,20 @@ final class Runtime
if ($c2 === 0) {
throw new TrapException("i32.div_s: divide by zero", trapKind: TrapKind::DivideByZero);
}
- if ($c1 === PHP_INT_MIN && $c2 === -1) {
- throw new TrapException("i32.div_s: overflow");
+ 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 = $this->stack->popInt();
- $c1 = $this->stack->popInt();
+ $c2 = self::wasmI32ToPhpInt($this->stack->popInt());
+ $c1 = self::wasmI32ToPhpInt($this->stack->popInt());
if ($c2 === 0) {
throw new TrapException("i32.div_u: divide by zero", trapKind: TrapKind::DivideByZero);
}
- $this->stack->pushValue(intdiv($c1, $c2));
+ $this->stack->pushValue(self::phpIntToWasmI32(intdiv($c1, $c2)));
}
private function execInstrNumericI32Eq(Instrs\Numeric\I32Eq $instr): void
@@ -1176,9 +1176,10 @@ final class Runtime
private function execInstrNumericI32Sub(Instrs\Numeric\I32Sub $instr): void
{
- $c2 = $this->stack->popInt();
- $c1 = $this->stack->popInt();
- $this->stack->pushValue(($c1 - $c2) % 0x100000000);
+ $c2 = self::wasmI32ToPhpInt($this->stack->popInt());
+ $c1 = self::wasmI32ToPhpInt($this->stack->popInt());
+ $c2Neg = ((~$c2 & 0xFFFFFFFF) + 1) & 0xFFFFFFFF;
+ $this->stack->pushValue(self::phpIntToWasmI32(($c1 + $c2Neg) & 0xFFFFFFFF));
}
private function execInstrNumericI32TruncF32S(Instrs\Numeric\I32TruncF32S $instr): void
diff --git a/src/Execution/TrapKind.php b/src/Execution/TrapKind.php
index 5cdc480..e6f15b8 100644
--- a/src/Execution/TrapKind.php
+++ b/src/Execution/TrapKind.php
@@ -14,4 +14,5 @@ enum TrapKind
case IndirectCallTypeMismatch;
case UndefinedElement;
case DivideByZero;
+ case IntegerOverflow;
}
diff --git a/tests/src/SpecTestsuites/SpecTestsuiteBase.php b/tests/src/SpecTestsuites/SpecTestsuiteBase.php
index 06a911e..1e74e13 100644
--- a/tests/src/SpecTestsuites/SpecTestsuiteBase.php
+++ b/tests/src/SpecTestsuites/SpecTestsuiteBase.php
@@ -157,9 +157,9 @@ abstract class SpecTestsuiteBase extends TestCase
$type = $arg['type'];
$value = $arg['value'];
return match ($type) {
- 'i32' => unpack('l', pack('l', (int)$value))[1],
+ 'i32' => unpack('l', pack('V', (int)$value))[1],
'i64' => unpack('q', self::convertInt64ToBinary($value))[1],
- 'f32' => unpack('g', pack('l', (int)$value))[1],
+ 'f32' => unpack('g', pack('V', (int)$value))[1],
'f64' => unpack('e', self::convertInt64ToBinary($value))[1],
'externref' => $value === 'null' ? Ref::RefNull(RefType::ExternRef) : Ref::RefExtern((int)$value),
'funcref' => $value === 'null' ? Ref::RefNull(RefType::FuncRef) : Ref::RefFunc((int)$value),
@@ -270,6 +270,7 @@ abstract class SpecTestsuiteBase extends TestCase
TrapKind::IndirectCallTypeMismatch => 'indirect call type mismatch',
TrapKind::UndefinedElement => 'undefined element',
TrapKind::DivideByZero => 'integer divide by zero',
+ TrapKind::IntegerOverflow => 'integer overflow',
};
$this->assertStringContainsString(
$actualErrorMessage,