aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-07-11 20:02:34 +0900
committernsfisis <nsfisis@gmail.com>2024-07-11 20:02:34 +0900
commitd1c268b76f65e69ea708096d5023c4d731cff594 (patch)
treee48836287272388df613a370fda7a46598c517f8 /src
parente4324d3d1d3bf3568d4e2f3b80c9cc324d324f83 (diff)
downloadphp-waddiwasi-d1c268b76f65e69ea708096d5023c4d731cff594.tar.gz
php-waddiwasi-d1c268b76f65e69ea708096d5023c4d731cff594.tar.zst
php-waddiwasi-d1c268b76f65e69ea708096d5023c4d731cff594.zip
fix: various spectests
Diffstat (limited to 'src')
-rw-r--r--src/WebAssembly/BinaryFormat/Decoder.php10
-rw-r--r--src/WebAssembly/Execution/Allocator.php18
-rw-r--r--src/WebAssembly/Execution/Runtime.php6
-rw-r--r--src/WebAssembly/Execution/Store.php50
4 files changed, 60 insertions, 24 deletions
diff --git a/src/WebAssembly/BinaryFormat/Decoder.php b/src/WebAssembly/BinaryFormat/Decoder.php
index 0ec342c..09d5a14 100644
--- a/src/WebAssembly/BinaryFormat/Decoder.php
+++ b/src/WebAssembly/BinaryFormat/Decoder.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Nsfisis\Waddiwasi\WebAssembly\BinaryFormat;
use Nsfisis\Waddiwasi\Stream\StreamInterface;
+use Nsfisis\Waddiwasi\Stream\UnexpectedEofException;
use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal\Code;
use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal\Locals;
use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Internal\SectionId;
@@ -51,6 +52,15 @@ final class Decoder
public function decode(): Module
{
+ try {
+ return $this->doDecode();
+ } catch (UnexpectedEofException $e) {
+ throw new InvalidBinaryFormatException('eof', previous: $e);
+ }
+ }
+
+ private function doDecode(): Module
+ {
$this->checkMagic();
$this->checkVersion();
diff --git a/src/WebAssembly/Execution/Allocator.php b/src/WebAssembly/Execution/Allocator.php
index 4e2adbf..79f8679 100644
--- a/src/WebAssembly/Execution/Allocator.php
+++ b/src/WebAssembly/Execution/Allocator.php
@@ -12,6 +12,7 @@ use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\MemType;
use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\TableType;
use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType;
use RuntimeException;
+use function assert;
use function count;
final readonly class Allocator
@@ -61,7 +62,7 @@ final readonly class Allocator
foreach ($externVals as $externVal) {
match ($externVal::class) {
- ExternVals\Func::class => null, // handled below.
+ ExternVals\Func::class => $m->funcAddrs[] = $externVal->addr,
ExternVals\Table::class => $m->tableAddrs[] = $externVal->addr,
ExternVals\Mem::class => $m->memAddrs[] = $externVal->addr,
ExternVals\Global_::class => $m->globalAddrs[] = $externVal->addr,
@@ -72,14 +73,13 @@ final readonly class Allocator
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,
- );
- }
+ assert($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));
diff --git a/src/WebAssembly/Execution/Runtime.php b/src/WebAssembly/Execution/Runtime.php
index d0f90b5..07dc0d0 100644
--- a/src/WebAssembly/Execution/Runtime.php
+++ b/src/WebAssembly/Execution/Runtime.php
@@ -20,6 +20,7 @@ use function abs;
use function array_map;
use function array_merge;
use function array_reverse;
+use function array_slice;
use function assert;
use function ceil;
use function count;
@@ -114,7 +115,7 @@ final class Runtime
$externVals,
$vals,
$refsList,
- $moduleInstInit->funcAddrs,
+ array_slice($moduleInstInit->funcAddrs, count(array_filter($externVals, fn ($e) => $e instanceof ExternVals\Func))),
);
$runtime = new self($store, $stack, $moduleInst);
@@ -203,6 +204,9 @@ final class Runtime
{
try {
$export = $this->getExport($name);
+ if ($export === null) {
+ throw new TrapException("invoke($name) not found", trapKind: TrapKind::UninitializedElement);
+ }
assert($export instanceof ExternVals\Func);
$funcAddr = $export->addr;
diff --git a/src/WebAssembly/Execution/Store.php b/src/WebAssembly/Execution/Store.php
index 5bef648..18f8626 100644
--- a/src/WebAssembly/Execution/Store.php
+++ b/src/WebAssembly/Execution/Store.php
@@ -34,19 +34,41 @@ final class Store
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"),
- };
+ switch ($extern::class) {
+ case Externs\Func::class:
+ foreach ($this->funcs as $i => $f) {
+ if ($f === $extern->func) {
+ return ExternVal::Func($i);
+ }
+ }
+ $this->funcs[] = $extern->func;
+ return ExternVal::Func(count($this->funcs) - 1);
+ case Externs\Table::class:
+ foreach ($this->tables as $i => $t) {
+ if ($t === $extern->table) {
+ return ExternVal::Table($i);
+ }
+ }
+ $this->tables[] = $extern->table;
+ return ExternVal::Table(count($this->tables) - 1);
+ case Externs\Mem::class:
+ foreach ($this->mems as $i => $m) {
+ if ($m === $extern->mem) {
+ return ExternVal::Mem($i);
+ }
+ }
+ $this->mems[] = $extern->mem;
+ return ExternVal::Mem(count($this->mems) - 1);
+ case Externs\Global_::class:
+ foreach ($this->globals as $i => $g) {
+ if ($g === $extern->global) {
+ return ExternVal::Global_($i);
+ }
+ }
+ $this->globals[] = $extern->global;
+ return ExternVal::Global_(count($this->globals) - 1);
+ default:
+ throw new RuntimeException("unreachable");
+ }
}
}