aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-06-30 02:02:24 +0900
committernsfisis <nsfisis@gmail.com>2024-07-04 02:40:27 +0900
commita312e95a95d243943535f94653822d6796d4637f (patch)
tree74ab3e10cd33d687d2516e20d932f638cf65f2a6
parent1a1629d6b1d06d5af18987b96eb974c0e7dda75a (diff)
downloadphp-waddiwasi-a312e95a95d243943535f94653822d6796d4637f.tar.gz
php-waddiwasi-a312e95a95d243943535f94653822d6796d4637f.tar.zst
php-waddiwasi-a312e95a95d243943535f94653822d6796d4637f.zip
feat: RubyVM on PHP on Wasm
-rw-r--r--examples/rubyvm-on-php-on-wasm/.gitignore1
-rw-r--r--examples/rubyvm-on-php-on-wasm/HelloWorld.php20
-rw-r--r--examples/rubyvm-on-php-on-wasm/HelloWorld.rb1
-rwxr-xr-xexamples/rubyvm-on-php-on-wasm/HelloWorld.sh1
-rw-r--r--examples/rubyvm-on-php-on-wasm/HelloWorld.yarvbin0 -> 221 bytes
-rw-r--r--examples/rubyvm-on-php-on-wasm/composer.json20
-rw-r--r--examples/rubyvm-on-php-on-wasm/composer.lock920
-rw-r--r--examples/rubyvm-on-php-on-wasm/php-wasm.php1615
-rwxr-xr-xexamples/rubyvm-on-php-on-wasm/php-wasm.wasmbin0 -> 4863136 bytes
9 files changed, 2578 insertions, 0 deletions
diff --git a/examples/rubyvm-on-php-on-wasm/.gitignore b/examples/rubyvm-on-php-on-wasm/.gitignore
new file mode 100644
index 0000000..61ead86
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/.gitignore
@@ -0,0 +1 @@
+/vendor
diff --git a/examples/rubyvm-on-php-on-wasm/HelloWorld.php b/examples/rubyvm-on-php-on-wasm/HelloWorld.php
new file mode 100644
index 0000000..7c37ac2
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/HelloWorld.php
@@ -0,0 +1,20 @@
+<?php
+
+require_once __DIR__ . '/vendor/autoload.php';
+
+define('STDIN', fopen('php://stdin', 'r'));
+define('STDOUT', fopen('php://stdout', 'r'));
+define('STDERR', fopen('php://stderr', 'r'));
+
+$rubyVM = new \RubyVM\VM\Core\Runtime\RubyVM(
+ new \RubyVM\VM\Core\Runtime\Option(
+ reader: new \RubyVM\VM\Stream\BinaryStreamReader(
+ streamHandler: new \RubyVM\VM\Stream\FileStreamHandler(
+ __DIR__ . '/HelloWorld.yarv',
+ ),
+ ),
+ logger: new \Psr\Log\NullLogger(),
+ ),
+);
+$executor = $rubyVM->disassemble();
+$executor->execute();
diff --git a/examples/rubyvm-on-php-on-wasm/HelloWorld.rb b/examples/rubyvm-on-php-on-wasm/HelloWorld.rb
new file mode 100644
index 0000000..f94759e
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/HelloWorld.rb
@@ -0,0 +1 @@
+puts RubyVM::InstructionSequence.compile("puts 'HelloWorld!\n'", "HelloWorld.rb").to_binary
diff --git a/examples/rubyvm-on-php-on-wasm/HelloWorld.sh b/examples/rubyvm-on-php-on-wasm/HelloWorld.sh
new file mode 100755
index 0000000..c5fc8ae
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/HelloWorld.sh
@@ -0,0 +1 @@
+php -d memory_limit=-1 -d opcache.enable_cli=on -d opcache.jit=on -d opcache.jit_buffer_size=1G ./php-wasm.php
diff --git a/examples/rubyvm-on-php-on-wasm/HelloWorld.yarv b/examples/rubyvm-on-php-on-wasm/HelloWorld.yarv
new file mode 100644
index 0000000..4a4cb1c
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/HelloWorld.yarv
Binary files differ
diff --git a/examples/rubyvm-on-php-on-wasm/composer.json b/examples/rubyvm-on-php-on-wasm/composer.json
new file mode 100644
index 0000000..0e4a7b8
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/composer.json
@@ -0,0 +1,20 @@
+{
+ "name": "nsfisis/waddiwasi-example",
+ "type": "project",
+ "description": "Waddiwasi example",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "nsfisis"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "Nsfisis\\Waddiwasi\\": "../../src/",
+ "Nsfisis\\Waddiwasi\\Examples\\": "src/"
+ }
+ },
+ "require": {
+ "m3m0r7/rubyvm-on-php": "^0.3.3"
+ }
+}
diff --git a/examples/rubyvm-on-php-on-wasm/composer.lock b/examples/rubyvm-on-php-on-wasm/composer.lock
new file mode 100644
index 0000000..8bbbef2
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/composer.lock
@@ -0,0 +1,920 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "b1aa666a62b5f0727e6936ef6bf2cd70",
+ "packages": [
+ {
+ "name": "m3m0r7/rubyvm-on-php",
+ "version": "0.3.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/m3m0r7/rubyvm-on-php.git",
+ "reference": "a568cabf4b71e7f8a3efebcaa3b77ea2c8bc2f5c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/m3m0r7/rubyvm-on-php/zipball/a568cabf4b71e7f8a3efebcaa3b77ea2c8bc2f5c",
+ "reference": "a568cabf4b71e7f8a3efebcaa3b77ea2c8bc2f5c",
+ "shasum": ""
+ },
+ "require": {
+ "monolog/monolog": "^3.4",
+ "php": ">=8.2",
+ "symfony/console": "^6.3"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.21",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.2",
+ "rector/rector": "^0.18.3",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "RubyVM\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "m3m0r7",
+ "homepage": "https://i.mem.ooo"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/m3m0r7/rubyvm-on-php/issues",
+ "source": "https://github.com/m3m0r7/rubyvm-on-php/tree/0.3.3.0"
+ },
+ "time": "2023-12-28T04:25:48+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "3.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8",
+ "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/log": "^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/log-implementation": "3.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "elasticsearch/elasticsearch": "^7 || ^8",
+ "ext-json": "*",
+ "graylog2/gelf-php": "^1.4.2 || ^2.0",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/psr7": "^2.2",
+ "mongodb/mongodb": "^1.8",
+ "php-amqplib/php-amqplib": "~2.4 || ^3",
+ "phpstan/phpstan": "^1.9",
+ "phpstan/phpstan-deprecation-rules": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1.4",
+ "phpunit/phpunit": "^10.5.17",
+ "predis/predis": "^1.1 || ^2",
+ "ruflin/elastica": "^7",
+ "symfony/mailer": "^5.4 || ^6",
+ "symfony/mime": "^5.4 || ^6"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+ "ext-mbstring": "Allow to work properly with unicode symbols",
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+ "ext-openssl": "Required to send log messages using SSL",
+ "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "https://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/3.7.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-06-28T09:40:51+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v6.4.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9",
+ "reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^5.4|^6.0|^7.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<5.4",
+ "symfony/dotenv": "<5.4",
+ "symfony/event-dispatcher": "<5.4",
+ "symfony/lock": "<5.4",
+ "symfony/process": "<5.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/console/tree/v6.4.9"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-06-28T09:49:33+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
+ "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-04-18T09:32:20+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.30.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "0424dff1c58f028c451efff2045f5d92410bd540"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540",
+ "reference": "0424dff1c58f028c451efff2045f5d92410bd540",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-05-31T15:07:36+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.30.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a",
+ "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-05-31T15:07:36+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.30.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb",
+ "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-05-31T15:07:36+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.30.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c",
+ "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-06-19T12:30:46+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v3.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
+ "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/service-contracts/tree/v3.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-04-18T09:32:20+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v7.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/14221089ac66cf82e3cf3d1c1da65de305587ff8",
+ "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/emoji": "^7.1",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v7.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-06-28T09:27:18+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.6.0"
+}
diff --git a/examples/rubyvm-on-php-on-wasm/php-wasm.php b/examples/rubyvm-on-php-on-wasm/php-wasm.php
new file mode 100644
index 0000000..398d377
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/php-wasm.php
@@ -0,0 +1,1615 @@
+<?php
+
+declare(strict_types=1);
+
+require_once __DIR__ . '/vendor/autoload.php';
+
+use Nsfisis\Waddiwasi\BinaryFormat\Decoder;
+use Nsfisis\Waddiwasi\BinaryFormat\InvalidBinaryFormatException;
+use Nsfisis\Waddiwasi\Execution\ExternVal;
+use Nsfisis\Waddiwasi\Execution\FuncInst;
+use Nsfisis\Waddiwasi\Execution\MemInst;
+use Nsfisis\Waddiwasi\Execution\Refs;
+use Nsfisis\Waddiwasi\Execution\Runtime;
+use Nsfisis\Waddiwasi\Execution\Store;
+use Nsfisis\Waddiwasi\Structure\Types\FuncType;
+use Nsfisis\Waddiwasi\Structure\Types\NumType;
+use Nsfisis\Waddiwasi\Structure\Types\ResultType;
+use Nsfisis\Waddiwasi\Structure\Types\ValType;
+
+const PHP_EMPTY = '';
+
+const PHP_HELLO_WORLD = <<<'EOS'
+require_once __DIR__ . '/HelloWorld.php';
+EOS;
+
+$wasmBinary = file_get_contents(__DIR__ . '/php-wasm.wasm');
+\assert($wasmBinary !== false);
+
+try {
+ $module = (new Decoder($wasmBinary))->decode();
+} catch (InvalidBinaryFormatException $e) {
+ fprintf(STDERR, $e->getMessage() . "\n");
+ exit(1);
+}
+
+$hostFuncs = [
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env__invoke_iii(...), 'env::invoke_iii'),
+ makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__invoke_iiiii(...), 'env::invoke_iiiii'),
+ makeHostFunc('(i32) -> ()', hostFunc__env__invoke_v(...), 'env::invoke_v'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env__invoke_iiii(...), 'env::invoke_iiii'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env__invoke_ii(...), 'env::invoke_ii'),
+ makeHostFunc('() -> ()', hostFunc__env__abort(...), 'env::abort'),
+ makeHostFunc('(i32) -> ()', hostFunc__env__exit(...), 'env::exit'),
+ makeHostFunc('(i32, i32, i32, i32) -> ()', hostFunc__env__invoke_viii(...), 'env::invoke_viii'),
+ makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env__invoke_vii(...), 'env::invoke_vii'),
+ makeHostFunc('(i32, i32) -> ()', hostFunc__env__invoke_vi(...), 'env::invoke_vi'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env__invoke_i(...), 'env::invoke_i'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__invoke_iiiiiii(...), 'env::invoke_iiiiiii'),
+ makeHostFunc('(i32, i32, i32, i32) -> ()', hostFunc__env____assert_fail(...), 'env::__assert_fail'),
+ makeHostFunc('(i32, i32, i32, i32, i32) -> ()', hostFunc__env__invoke_viiii(...), 'env::invoke_viiii'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> ()', hostFunc__env__invoke_viiiii(...), 'env::invoke_viiiii'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__invoke_iiiiii(...), 'env::invoke_iiiiii'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__invoke_iiiiiiiiii(...), 'env::invoke_iiiiiiiiii'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env__strftime(...), 'env::strftime'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env__getaddrinfo(...), 'env::getaddrinfo'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__gethostbyname_r(...), 'env::gethostbyname_r'),
+ makeHostFunc('() -> (i32)', hostFunc__env__getdtablesize(...), 'env::getdtablesize'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env__getprotobyname(...), 'env::getprotobyname'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env__getprotobynumber(...), 'env::getprotobynumber'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env__strptime(...), 'env::strptime'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__getnameinfo(...), 'env::getnameinfo'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> ()', hostFunc__env__invoke_viiiiii(...), 'env::invoke_viiiiii'),
+ makeHostFunc('(i32, i32, i32, f64, i32, i32) -> ()', hostFunc__env__invoke_viidii(...), 'env::invoke_viidii'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env__getcontext(...), 'env::getcontext'),
+ makeHostFunc('(i32, i32, i32, i32) -> ()', hostFunc__env__makecontext(...), 'env::makecontext'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env__swapcontext(...), 'env::swapcontext'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__environ_sizes_get(...), 'wasi_snapshot_preview1::environ_sizes_get'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__environ_get(...), 'wasi_snapshot_preview1::environ_get'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_fcntl64(...), 'env::__syscall_fcntl64'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_ioctl(...), 'env::__syscall_ioctl'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_close(...), 'wasi_snapshot_preview1::fd_close'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_read(...), 'wasi_snapshot_preview1::fd_read'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_write(...), 'wasi_snapshot_preview1::fd_write'),
+ makeHostFunc('(i32) -> ()', hostFunc__wasi_snapshot_preview1__proc_exit(...), 'wasi_snapshot_preview1::proc_exit'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_faccessat(...), 'env::__syscall_faccessat'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_chdir(...), 'env::__syscall_chdir'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_chmod(...), 'env::__syscall_chmod'),
+ makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_fchownat(...), 'env::__syscall_fchownat'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_dup(...), 'env::__syscall_dup'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_dup3(...), 'env::__syscall_dup3'),
+ makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env__emscripten_memcpy_js(...), 'env::emscripten_memcpy_js'),
+ makeHostFunc('() -> (f64)', hostFunc__env__emscripten_date_now(...), 'env::emscripten_date_now'),
+ makeHostFunc('() -> (i32)', hostFunc__env___emscripten_get_now_is_monotonic(...), 'env::_emscripten_get_now_is_monotonic'),
+ makeHostFunc('() -> (f64)', hostFunc__env__emscripten_get_now(...), 'env::emscripten_get_now'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_fdatasync(...), 'env::__syscall_fdatasync'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_openat(...), 'env::__syscall_openat'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_fstat64(...), 'env::__syscall_fstat64'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_stat64(...), 'env::__syscall_stat64'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_newfstatat(...), 'env::__syscall_newfstatat'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_lstat64(...), 'env::__syscall_lstat64'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_sync(...), 'wasi_snapshot_preview1::fd_sync'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_getcwd(...), 'env::__syscall_getcwd'),
+ makeHostFunc('(i32) -> ()', hostFunc__env__emscripten_err(...), 'env::emscripten_err'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_fdstat_get(...), 'wasi_snapshot_preview1::fd_fdstat_get'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_mkdirat(...), 'env::__syscall_mkdirat'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_pipe(...), 'env::__syscall_pipe'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_poll(...), 'env::__syscall_poll'),
+ makeHostFunc('(i32, i32) -> ()', hostFunc__env____call_sighandler(...), 'env::__call_sighandler'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_getdents64(...), 'env::__syscall_getdents64'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_readlinkat(...), 'env::__syscall_readlinkat'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_renameat(...), 'env::__syscall_renameat'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_rmdir(...), 'env::__syscall_rmdir'),
+ makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall__newselect(...), 'env::__syscall__newselect'),
+ makeHostFunc('(i32, f64) -> (i32)', hostFunc__env___setitimer_js(...), 'env::_setitimer_js'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_statfs64(...), 'env::__syscall_statfs64'),
+ makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_symlink(...), 'env::__syscall_symlink'),
+ makeHostFunc('() -> (i32)', hostFunc__env__emscripten_get_heap_max(...), 'env::emscripten_get_heap_max'),
+ makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___tzset_js(...), 'env::_tzset_js'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_unlinkat(...), 'env::__syscall_unlinkat'),
+ makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_utimensat(...), 'env::__syscall_utimensat'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env__emscripten_resize_heap(...), 'env::emscripten_resize_heap'),
+ makeHostFunc('() -> ()', hostFunc__env___emscripten_throw_longjmp(...), 'env::_emscripten_throw_longjmp'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_accept4(...), 'env::__syscall_accept4'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_bind(...), 'env::__syscall_bind'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_connect(...), 'env::__syscall_connect'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_getpeername(...), 'env::__syscall_getpeername'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_getsockname(...), 'env::__syscall_getsockname'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_getsockopt(...), 'env::__syscall_getsockopt'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_listen(...), 'env::__syscall_listen'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_recvfrom(...), 'env::__syscall_recvfrom'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_sendto(...), 'env::__syscall_sendto'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_socket(...), 'env::__syscall_socket'),
+ makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_ftruncate64(...), 'env::__syscall_ftruncate64'),
+ makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_seek(...), 'wasi_snapshot_preview1::fd_seek'),
+ makeHostFunc('(i32) -> (i32)', hostFunc__env___mktime_js(...), 'env::_mktime_js'),
+ makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___localtime_js(...), 'env::_localtime_js'),
+ makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___gmtime_js(...), 'env::_gmtime_js'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env___munmap_js(...), 'env::_munmap_js'),
+ makeHostFunc('(i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env___mmap_js(...), 'env::_mmap_js'),
+];
+$store = Store::empty();
+$externVals = [];
+foreach ($hostFuncs as $hostFunc) {
+ $store->funcs[] = $hostFunc;
+ $externVals[] = ExternVal::Func(\count($store->funcs) - 1);
+}
+$runtime = Runtime::instantiate($store, $module, $externVals);
+$codePtr = allocateStringOnWasmMemory($runtime, PHP_HELLO_WORLD);
+
+$results = $runtime->invoke("php_wasm_run", [$codePtr]);
+\assert(\count($results) === 1);
+$exitCode = $results[0];
+\assert(\is_int($exitCode));
+
+function dumpMemory(MemInst $mem): void
+{
+ $buf = '';
+ $s = $mem->size();
+ for ($j = 0; $j < $s; $j++) {
+ $c = $mem->loadByte($j);
+ \assert($c !== null);
+ $buf .= \chr($c);
+ if ($j % 1024 === 1023) {
+ fputs(STDOUT, $buf);
+ $buf = "";
+ }
+ }
+ fputs(STDOUT, $buf);
+}
+
+function allocateStringOnWasmMemory(Runtime $runtime, string $str): int
+{
+ // Plus 1 for the null terminator in C.
+ $size = \strlen($str) + 1;
+ $outPtr = wasm_stackAlloc($runtime, $size);
+ copyStringToWasmMemory($runtime, $outPtr, $str);
+ return $outPtr;
+}
+
+function wasm_stackAlloc(Runtime $runtime, int $size): int
+{
+ $results = $runtime->invoke("stackAlloc", [$size]);
+ \assert(\count($results) === 1);
+ $result = $results[0];
+ \assert(\is_int($result));
+ return $result;
+}
+
+function wasm_stackSave(Runtime $runtime): int
+{
+ $results = $runtime->invoke("stackSave", []);
+ \assert(\count($results) === 1);
+ $result = $results[0];
+ \assert(\is_int($result));
+ return $result;
+}
+
+function copyStringToWasmMemory(Runtime $runtime, int $dst, string $src): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ for ($i = 0; $i < \strlen($src); $i++) {
+ $ok = $mem->storeByte($dst + $i, \ord($src[$i]));
+ \assert($ok);
+ }
+ // Terminate the string with a null byte for interoperation with C.
+ $ok = $mem->storeByte($dst + \strlen($src), 0);
+ \assert($ok);
+}
+
+function makeHostFunc(string $typeDef, callable $fn, string $fnName): FuncInst
+{
+ $stringToType = fn (string $s) => match ($s) {
+ 'i32' => ValType::NumType(NumType::I32),
+ 'i64' => ValType::NumType(NumType::I64),
+ 'f32' => ValType::NumType(NumType::F32),
+ 'f64' => ValType::NumType(NumType::F64),
+ default => throw new \RuntimeException('Invalid type: ' . $s),
+ };
+ preg_match('/^\(([^)]*)\) -> \(([^)]*)\)$/', $typeDef, $matches);
+ $paramsDef = $matches[1];
+ $resultsDef = $matches[2];
+ $params = array_map($stringToType, $paramsDef === '' ? [] : explode(', ', $paramsDef));
+ $results = array_map($stringToType, $resultsDef === '' ? [] : explode(', ', $resultsDef));
+ $type = new FuncType(new ResultType($params), new ResultType($results));
+ return FuncInst::Host($type, function ($runtime) use ($fn, $fnName) {
+ // echo "TRACE: $fnName BEGIN\n";
+ $fn($runtime);
+ // echo "TRACE: $fnName END\n";
+ });
+}
+
+function getWasmTableEntry(Runtime $runtime, int $funcPtr): int
+{
+ static $wasmTable = null;
+
+ if ($wasmTable === null) {
+ $wasmTable = $runtime->getExportedTable('__indirect_function_table');
+ \assert($wasmTable !== null);
+ }
+
+ $func = $wasmTable->elem[$funcPtr] ?? null;
+ \assert($func instanceof Refs\RefFunc, "Expected RefFunc, but got " . \get_class($func));
+ return $func->addr;
+}
+
+function convertI32PairToI53Checked(int $lo, int $hi): ?int
+{
+ return $lo + hi * 4294967296;
+}
+
+function syscallGetStr(Runtime $runtime, int $ptr): string
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ $str = '';
+ for ($i = $ptr; $mem->loadByte($i) !== 0; $i++) {
+ $c = $mem->loadByte($i);
+ \assert($c !== null);
+ $str .= \chr($c);
+ }
+ return $str;
+}
+
+function stringToUTF8(Runtime $runtime, string $s, int $ptr, $len): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ for ($i = 0; $i < $len; $i++) {
+ if ($i < \strlen($s)) {
+ $mem->storeByte($ptr + $i, \ord($s[$i]));
+ } else {
+ $mem->storeByte($ptr + $i, 0);
+ }
+ }
+}
+
+function heap8Write(Runtime $runtime, int $ptr, int $value): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ $mem->storeI32_s8($ptr, $value);
+}
+
+function heap16Write(Runtime $runtime, int $ptr, int $value): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ $mem->storeI32_s16($ptr, $value);
+}
+
+function heap32Write(Runtime $runtime, int $ptr, int $value): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ $mem->storeI32_s32($ptr, $value);
+}
+
+function heapU32Write(Runtime $runtime, int $ptr, int $value): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ $mem->storeI32_s32($ptr, $value);
+}
+
+function heap64Write(Runtime $runtime, int $ptr, int $value): void
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ $mem->storeI64_s64($ptr, $value);
+}
+
+function syscallDoStat(Runtime $runtime, callable $func, string $path, int $buf): void
+{
+ $stat = $func($path);
+
+ heap32Write($runtime, $buf, $stat->dev);
+ heap32Write($runtime, $buf + 4, $stat->mode);
+ heapU32Write($runtime, $buf + 8, $stat->nlink);
+ heap32Write($runtime, $buf + 12, $stat->uid);
+ heap32Write($runtime, $buf + 16, $stat->gid);
+ heap32Write($runtime, $buf + 20, $stat->rdev);
+ heap64Write($runtime, $buf + 24, $stat->size);
+ heap32Write($runtime, $buf + 32, 4096);
+ heap32Write($runtime, $buf + 36, $stat->blocks);
+ $atime = $stat->atime;
+ heap64Write($runtime, $buf + 40, $atime);
+ heapU32Write($runtime, $buf + 48, ($atime % 1000) * 1000);
+ $mtime = $stat->mtime;
+ heap64Write($runtime, $buf + 56, $mtime);
+ heapU32Write($runtime, $buf + 64, ($mtime % 1000) * 1000);
+ $ctime = $stat->ctime;
+ heap64Write($runtime, $buf + 72, $ctime);
+ heapU32Write($runtime, $buf + 80, ($ctime % 1000) * 1000);
+ heap64Write($runtime, $buf + 88, $stat->ino);
+}
+
+function syscallCalculateAt(Runtime $runtime, int $dirfd, string $path): string
+{
+ if ($path[0] === '/') {
+ return $path;
+ }
+ if ($dirfd === -100) {
+ $dir = getcwd();
+ \assert($dir !== false);
+ } else {
+ throw new \RuntimeException("syscallCalculateAt: not implemented ($dirfd)");
+ }
+ if ($path === '.') {
+ return $dir;
+ } else {
+ return $dir . '/' . $path;
+ }
+}
+
+function fsStat(string $path, bool $dontFollow): object
+{
+ if ($path === 'php://stdin') {
+ return (object)[
+ 'dev' => 0,
+ 'mode' => 0,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 0,
+ 'blocks' => 0,
+ 'ino' => 0,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ ];
+ } else if ($path === 'php://stdout') {
+ return (object)[
+ 'dev' => 0,
+ 'mode' => 0,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 0,
+ 'blocks' => 0,
+ 'ino' => 1,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ ];
+ } else if ($path === 'php://stderr') {
+ return (object)[
+ 'dev' => 0,
+ 'mode' => 0,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 0,
+ 'blocks' => 0,
+ 'ino' => 2,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ ];
+ }
+
+ $phpStat = $dontFollow ? lstat($path) : stat($path);
+ assert($phpStat !== false);
+ return (object)[
+ 'dev' => $phpStat['dev'],
+ 'mode' => $phpStat['mode'],
+ 'nlink' => $phpStat['nlink'],
+ 'uid' => $phpStat['uid'],
+ 'gid' => $phpStat['gid'],
+ 'rdev' => $phpStat['rdev'],
+ 'size' => $phpStat['size'],
+ 'blocks' => $phpStat['blocks'],
+ 'ino' => $phpStat['ino'],
+ 'atime' => $phpStat['atime'] * 1000,
+ 'mtime' => $phpStat['mtime'] * 1000,
+ 'ctime' => $phpStat['ctime'] * 1000,
+ ];
+}
+
+function fsLstat(string $path): object
+{
+ return fsStat($path, true);
+}
+
+final class VFile {
+ public ?array $getdents = null;
+
+ public function __construct(
+ public readonly int $fd,
+ /**
+ * @param resource $fp
+ */
+ public readonly mixed $fp,
+ public readonly int $flags,
+ public readonly string $path,
+ ) {}
+
+ public function seek(int $offset, int $whence): int
+ {
+ if ($whence === 0) {
+ fseek($this->fp, $offset, SEEK_SET);
+ } elseif ($whence === 1) {
+ fseek($this->fp, $offset, SEEK_CUR);
+ } elseif ($whence === 2) {
+ fseek($this->fp, $offset, SEEK_END);
+ } else {
+ throw new \RuntimeException("VFile::seek: invalid whence");
+ }
+ $pos = ftell($this->fp);
+ return $pos === false ? 0 : $pos;
+ }
+
+ public function read(Runtime $runtime, int $len): string
+ {
+ return fread($this->fp, $len);
+ }
+
+ public function close(): void
+ {
+ fclose($this->fp);
+ }
+}
+
+function fsOpen(string $path, int $flags, int $mode): ?int
+{
+ global $fdTable;
+ if (!isset($fdTable)) {
+ $fdTable = [];
+ }
+ $fp = @fopen($path, 'r');
+ if ($fp === false) {
+ return null;
+ }
+ $nextFd = count($fdTable) + 10;
+ $fdTable[$nextFd] = new VFile(
+ $nextFd,
+ $fp,
+ $flags,
+ $path,
+ );
+ return $nextFd;
+}
+
+function fsDup(int $fd): ?int
+{
+ global $fdTable;
+ if (!isset($fdTable)) {
+ return null;
+ }
+ $nextFd = count($fdTable) + 10;
+ if ($fd === 0) {
+ $fp = fopen('php://stdin', 'r');
+ $fdTable[$nextFd] = new VFile(
+ $nextFd,
+ $fp,
+ 0,
+ 'php://stdin',
+ );
+ } else if ($fd === 1) {
+ $fp = fopen('php://stdout', 'w');
+ $fdTable[$nextFd] = new VFile(
+ $nextFd,
+ $fp,
+ 0,
+ 'php://stdout',
+ );
+ } else if ($fd === 2) {
+ $fp = fopen('php://stderr', 'w');
+ $fdTable[$nextFd] = new VFile(
+ $nextFd,
+ $fp,
+ 0,
+ 'php://stderr',
+ );
+ } else {
+ $file = $fdTable[$fd];
+ $fp = $file->fp;
+ $fdTable[$nextFd] = new VFile(
+ $nextFd,
+ $fp,
+ $file->flags,
+ $file->path,
+ );
+ }
+ return $nextFd;
+}
+
+function fsGetVFileFromFd(int $fd): ?VFile
+{
+ global $fdTable;
+ return $fdTable[$fd] ?? null;
+}
+
+function fsGetPathFromFd(int $fd): ?string
+{
+ return fsGetVFileFromFd($fd)?->path;
+}
+
+function fsGetFpFromFd(int $fd): mixed
+{
+ return fsGetVFileFromFd($fd)?->fp;
+}
+
+function fsGetFlagsFromFd(int $fd): ?int
+{
+ return fsGetVFileFromFd($fd)?->flags;
+}
+
+function fsReaddir(string $p): array
+{
+ $dir = opendir($p);
+ $entries = [];
+ while (($entry = readdir($dir)) !== false) {
+ $entries[] = $entry;
+ }
+ closedir($dir);
+ return $entries;
+}
+
+function fsLookupParentPath(string $p): string
+{
+ return realpath($p . '/..');
+}
+
+function fsLookupChild(string $p, string $c): string
+{
+ return realpath($p . '/' . $c);
+}
+
+function alignMemory(int $size, int $alignment): int
+{
+ return (int)ceil($size / $alignment) * $alignment;
+}
+
+function _emscripten_builtin_memalign(Runtime $runtime, int $alignment, int $size): int
+{
+ $results = $runtime->invoke("emscripten_builtin_memalign", [$alignment, $size]);
+ \assert(\count($results) === 1);
+ $result = $results[0];
+ \assert(\is_int($result));
+ return $result;
+}
+
+function zeroMemory(Runtime $runtime, int $ptr, int $len): int
+{
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ for ($i = 0; $i < $len; $i++) {
+ $mem->storeByte($ptr + $i, 0);
+ }
+ return $ptr;
+}
+
+function mmapAlloc(Runtime $runtime, int $len): int
+{
+ $len = alignMemory($len, 65536);
+ $ptr = _emscripten_builtin_memalign($runtime, 65536, $len);
+ if ($ptr === 0) {
+ return 0;
+ }
+ return zeroMemory($runtime, $ptr, $len);
+}
+
+function fsMmap(Runtime $runtime, int $fd, int $len, int $offset, int $prot, int $flags): array
+{
+ global $fdTable;
+ if (!isset($fdTable[$fd])) {
+ throw new \RuntimeException("fsMmap: invalid fd");
+ }
+ $file = $fdTable[$fd];
+
+ $buf = stream_get_contents($file->fp);
+
+ $ptr = mmapAlloc($runtime, $len);
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ for ($i = 0; $i < $len; $i++) {
+ $mem->storeByte($ptr + $i, ord($buf[$i]));
+ }
+
+ return [$ptr, 1];
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env__invoke_iii(Runtime $runtime): void
+{
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env__invoke_iiiii(Runtime $runtime): void
+{
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32) -> ()
+function hostFunc__env__invoke_v(Runtime $runtime): void
+{
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env__invoke_iiii(Runtime $runtime): void
+{
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env__invoke_ii(Runtime $runtime): void
+{
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: () -> ()
+function hostFunc__env__abort(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::abort: not implemented');
+}
+
+// Type: (i32) -> ()
+function hostFunc__env__exit(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::exit: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> ()
+function hostFunc__env__invoke_viii(Runtime $runtime): void
+{
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32) -> ()
+function hostFunc__env__invoke_vii(Runtime $runtime): void
+{
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32) -> ()
+function hostFunc__env__invoke_vi(Runtime $runtime): void
+{
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env__invoke_i(Runtime $runtime): void
+{
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env__invoke_iiiiiii(Runtime $runtime): void
+{
+ $a6 = $runtime->stack->popInt();
+ $a5 = $runtime->stack->popInt();
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->stack->pushValue($a5);
+ $runtime->stack->pushValue($a6);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32) -> ()
+function hostFunc__env____assert_fail(Runtime $runtime): void
+{
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32, i32) -> ()
+function hostFunc__env__invoke_viiii(Runtime $runtime): void
+{
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> ()
+function hostFunc__env__invoke_viiiii(Runtime $runtime): void
+{
+ $a5 = $runtime->stack->popInt();
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->stack->pushValue($a5);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env__invoke_iiiiii(Runtime $runtime): void
+{
+ $a5 = $runtime->stack->popInt();
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->stack->pushValue($a5);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env__invoke_iiiiiiiiii(Runtime $runtime): void
+{
+ $a9 = $runtime->stack->popInt();
+ $a8 = $runtime->stack->popInt();
+ $a7 = $runtime->stack->popInt();
+ $a6 = $runtime->stack->popInt();
+ $a5 = $runtime->stack->popInt();
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->stack->pushValue($a5);
+ $runtime->stack->pushValue($a6);
+ $runtime->stack->pushValue($a7);
+ $runtime->stack->pushValue($a8);
+ $runtime->stack->pushValue($a9);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env__strftime(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::strftime: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env__getaddrinfo(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::getaddrinfo: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env__gethostbyname_r(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::gethostbyname_r: not implemented');
+}
+
+// Type: () -> (i32)
+function hostFunc__env__getdtablesize(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::getdtablesize: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env__getprotobyname(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::getprotobyname: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env__getprotobynumber(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::getprotobynumber: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env__strptime(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::strptime: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env__getnameinfo(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::getnameinfo: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32, i32) -> ()
+function hostFunc__env__invoke_viiiiii(Runtime $runtime): void
+{
+ $a6 = $runtime->stack->popInt();
+ $a5 = $runtime->stack->popInt();
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popInt();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->stack->pushValue($a5);
+ $runtime->stack->pushValue($a6);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32, i32, i32, f64, i32, i32) -> ()
+function hostFunc__env__invoke_viidii(Runtime $runtime): void
+{
+ $a5 = $runtime->stack->popInt();
+ $a4 = $runtime->stack->popInt();
+ $a3 = $runtime->stack->popFloat();
+ $a2 = $runtime->stack->popInt();
+ $a1 = $runtime->stack->popInt();
+ $index = $runtime->stack->popInt();
+ $sp = wasm_stackSave($runtime);
+ $func = getWasmTableEntry($runtime, $index);
+ $runtime->stack->pushValue($a1);
+ $runtime->stack->pushValue($a2);
+ $runtime->stack->pushValue($a3);
+ $runtime->stack->pushValue($a4);
+ $runtime->stack->pushValue($a5);
+ $runtime->invokeByFuncAddr($func);
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env__getcontext(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::getcontext: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> ()
+function hostFunc__env__makecontext(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::makecontext: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env__swapcontext(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::swapcontext: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__environ_sizes_get(Runtime $runtime): void
+{
+ throw new \RuntimeException('wasi_snapshot_preview1::environ_sizes_get: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__environ_get(Runtime $runtime): void
+{
+ throw new \RuntimeException('wasi_snapshot_preview1::environ_get: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_fcntl64(Runtime $runtime): void
+{
+ $varargs = $runtime->stack->popInt();
+ $cmd = $runtime->stack->popInt();
+ $fd = $runtime->stack->popInt();
+
+ switch ($cmd) {
+ case 0:
+ throw new \RuntimeException("env::__syscall_fcntl64: command $cmd not implemented");
+ case 1:
+ case 2:
+ $runtime->stack->pushValue(0);
+ return;
+ case 3:
+ $runtime->stack->pushValue(fsGetFlagsFromFd($fd));
+ return;
+ case 4:
+ throw new \RuntimeException("env::__syscall_fcntl64: command $cmd not implemented");
+ case 5:
+ throw new \RuntimeException("env::__syscall_fcntl64: command $cmd not implemented");
+ case 6:
+ case 7:
+ $runtime->stack->pushValue(0);
+ return;
+ case 16:
+ case 8:
+ $runtime->stack->pushValue(-28);
+ return;
+ case 9:
+ // setErrno(28);
+ $runtime->stack->pushValue(-1);
+ return;
+ default:
+ $runtime->stack->pushValue(-28);
+ return;
+ }
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_ioctl(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_ioctl: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__fd_close(Runtime $runtime): void
+{
+ $fd = $runtime->stack->popInt();
+ $file = fsGetVFileFromFd($fd);
+ assert($file !== null);
+ $file->close();
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__fd_read(Runtime $runtime): void
+{
+ // Output pointer to the number of bytes written.
+ $pnum = $runtime->stack->popInt();
+ // Length of the array of iov structs.
+ $iovcnt = $runtime->stack->popInt();
+ // Pointer to the array of iov structs.
+ $iov = $runtime->stack->popInt();
+ // File descripter.
+ $fd = $runtime->stack->popInt();
+
+ $file = fsGetVFileFromFd($fd);
+ assert($file !== null);
+
+ // struct iov {
+ // ptr: u32, pointer to the data
+ // len: u32
+ // }
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+
+ $nRead = 0;
+ for ($i = 0; $i < $iovcnt; $i++) {
+ $ptr = $mem->loadI32_s32($iov + $i * 8);
+ \assert($ptr !== null);
+ $len = $mem->loadI32_s32($iov + $i * 8 + 4);
+ \assert($len !== null);
+ $buf = $file->read($runtime, $len);
+ if ($buf === false) {
+ $nRead = -1;
+ break;
+ }
+ $curr = strlen($buf);
+ if ($curr <= 0) {
+ $nRead = -1;
+ break;
+ }
+ // echo "fd_read(fd=$fd, iov=$iov, iovcnt=$iovcnt, pnum=$pnum) = { p=$ptr, l=$len }\n";
+ for ($k = 0; $k < $curr; $k++) {
+ $mem->storeByte($ptr + $k, ord($buf[$k]));
+ // echo " [$k] = ord($buf[$k])\n";
+ }
+ $nRead += $curr;
+ if ($curr < $len) {
+ break;
+ }
+ }
+
+ $mem->storeI32_s32($pnum, $nRead);
+
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__fd_write(Runtime $runtime): void
+{
+ // Output pointer to the number of bytes written.
+ $pnum = $runtime->stack->popInt();
+ // Length of the array of iov structs.
+ $iovcnt = $runtime->stack->popInt();
+ // Pointer to the array of iov structs.
+ $iov = $runtime->stack->popInt();
+ // File descripter.
+ $fd = $runtime->stack->popInt();
+
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+
+ // struct iov {
+ // ptr: u32, pointer to the data
+ // len: u32
+ // }
+ $nWritten = 0;
+ for ($i = 0; $i < $iovcnt; $i++) {
+ $ptr = $mem->loadI32_s32($iov + $i * 8);
+ \assert($ptr !== null);
+ $len = $mem->loadI32_s32($iov + $i * 8 + 4);
+ // echo "fd_write($iovcnt, $iov) [$i] = { p=$ptr, l=$len };\n";
+ \assert($len !== null);
+ $buf = '';
+ for ($j = 0; $j < $len; $j++) {
+ $c = $mem->loadByte($ptr + $j);
+ \assert($c !== null);
+ $buf .= \chr($c);
+ }
+ if ($fd === 1) {
+ fputs(STDOUT, $buf);
+ } else {
+ fputs(STDERR, $buf);
+ }
+ $nWritten += $len;
+ }
+ $mem->storeI32_s32($pnum, $nWritten);
+
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32) -> ()
+function hostFunc__wasi_snapshot_preview1__proc_exit(Runtime $runtime): void
+{
+ throw new \RuntimeException('wasi_snapshot_preview1::proc_exit: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_faccessat(Runtime $runtime): void
+{
+ $flags = $runtime->stack->popInt();
+ $amode = $runtime->stack->popInt();
+ $path = $runtime->stack->popInt();
+ $dirfd = $runtime->stack->popInt();
+
+ $path = syscallGetStr($runtime, $path);
+ $path = syscallCalculateAt($runtime, $dirfd, $path);
+
+ // Always allow accesses.
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env____syscall_chdir(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_chdir: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env____syscall_chmod(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_chmod: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_fchownat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_fchownat: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env____syscall_dup(Runtime $runtime): void
+{
+ $oldFd = $runtime->stack->popInt();
+ $newFd = fsDup($oldFd);
+ $runtime->stack->pushValue($newFd);
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_dup3(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_dup3: not implemented');
+}
+
+// Type: (i32, i32, i32) -> ()
+function hostFunc__env__emscripten_memcpy_js(Runtime $runtime): void
+{
+ $num = $runtime->stack->popInt();
+ $src = $runtime->stack->popInt();
+ $dest = $runtime->stack->popInt();
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+ for ($i = 0; $i < $num; $i++) {
+ $byte = $mem->loadByte($src + $i);
+ \assert($byte !== null);
+ $mem->storeByte($dest + $i, $byte);
+ }
+}
+
+// Type: () -> (f64)
+function hostFunc__env__emscripten_date_now(Runtime $runtime): void
+{
+ $t = round(microtime(true) * 1000);
+ $runtime->stack->pushValue($t);
+}
+
+// Type: () -> (i32)
+function hostFunc__env___emscripten_get_now_is_monotonic(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::_emscripten_get_now_is_monotonic: not implemented');
+}
+
+// Type: () -> (f64)
+function hostFunc__env__emscripten_get_now(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::emscripten_get_now: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env____syscall_fdatasync(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_fdatasync: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_openat(Runtime $runtime): void
+{
+ $varargs = $runtime->stack->popInt();
+ $flags = $runtime->stack->popInt();
+ $path = $runtime->stack->popInt();
+ $dirfd = $runtime->stack->popInt();
+
+ $path = syscallGetStr($runtime, $path);
+ $path = syscallCalculateAt($runtime, $dirfd, $path);
+
+ $mem = $runtime->getExportedMemory('memory');
+ \assert($mem !== null);
+
+ if ($varargs !== 0) {
+ $mode = $mem->loadI32_s32($varargs);
+ $varargs += 4;
+ } else {
+ $mode = 0;
+ }
+
+ $fd = fsOpen($path, $flags, $mode);
+ if ($fd !== null) {
+ $runtime->stack->pushValue($fd);
+ } else {
+ // no such file
+ $runtime->stack->pushValue(-44);
+ }
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env____syscall_fstat64(Runtime $runtime): void
+{
+ $buf = $runtime->stack->popInt();
+ $fd = $runtime->stack->popInt();
+ $path = fsGetPathFromFd($fd);
+ assert($path !== null);
+ syscallDoStat($runtime, fn ($path) => fsStat($path, false), $path, $buf);
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env____syscall_stat64(Runtime $runtime): void
+{
+ $buf = $runtime->stack->popInt();
+ $path = $runtime->stack->popInt();
+ $path = syscallGetStr($runtime, $path);
+ syscallDoStat($runtime, fn ($path) => fsStat($path, false), $path, $buf);
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_newfstatat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_newfstatat: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env____syscall_lstat64(Runtime $runtime): void
+{
+ $buf = $runtime->stack->popInt();
+ $path = $runtime->stack->popInt();
+ $path = syscallGetStr($runtime, $path);
+ syscallDoStat($runtime, fsLstat(...), $path, $buf);
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__fd_sync(Runtime $runtime): void
+{
+ throw new \RuntimeException('wasi_snapshot_preview1::fd_sync: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env____syscall_getcwd(Runtime $runtime): void
+{
+ $size = $runtime->stack->popInt();
+ $bufPtr = $runtime->stack->popInt();
+ if ($size === 0) {
+ $runtime->stack->pushValue(-28);
+ return;
+ }
+ $cwd = getcwd();
+ \assert($cwd !== false);
+ $cwdLen = \strlen($cwd) + 1;
+ if ($size < $cwdLen) {
+ $runtime->stack->pushValue(-68);
+ return;
+ }
+ copyStringToWasmMemory($runtime, $bufPtr, $cwd);
+ $runtime->stack->pushValue($cwdLen);
+}
+
+// Type: (i32) -> ()
+function hostFunc__env__emscripten_err(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::emscripten_err: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__fd_fdstat_get(Runtime $runtime): void
+{
+ throw new \RuntimeException('wasi_snapshot_preview1::fd_fdstat_get: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_mkdirat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_mkdirat: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env____syscall_pipe(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_pipe: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_poll(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_poll: not implemented');
+}
+
+// Type: (i32, i32) -> ()
+function hostFunc__env____call_sighandler(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__call_sighandler: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_getdents64(Runtime $runtime): void
+{
+ $count = $runtime->stack->popInt();
+ $dirp = $runtime->stack->popInt();
+ $fd = $runtime->stack->popInt();
+
+ $file = fsGetVFileFromFd($fd);
+
+ if ($file->getdents === null) {
+ $file->getdents = fsReaddir($file->path);
+ }
+
+ $struct_size = 280;
+ $pos = 0;
+ $off = $file->seek(0, 1);
+
+ $idx = (int)floor($off / $struct_size);
+
+ while ($idx < count($file->getdents) && $pos + $struct_size <= $count) {
+ $name = $file->getdents[$idx];
+ if ($name === '.') {
+ $id = fsStat($file->path, true)->ino;
+ $type = 4;
+ } else if ($name === '..') {
+ $lookup = fsLookupParentPath($file->path);
+ $id = fsStat($lookup, true)->ino;
+ $type = 4;
+ } else {
+ $child = fsLookupChild($file->path, $name);
+ $id = fsStat($child, true)->ino;
+ $type = is_dir($child) ? 4 : (is_file($child) ? 8 : 10);
+ }
+ heap64Write($runtime, $dirp + $pos, $id);
+ heap64Write($runtime, $dirp + $pos + 8, ($idx + 1) * $struct_size);
+ heap16Write($runtime, $dirp + $pos + 16, $struct_size);
+ heap8Write($runtime, $dirp + $pos + 18, $type);
+ stringToUTF8($runtime, $name, $dirp + $pos + 19, 256);
+ $pos += $struct_size;
+ $idx += 1;
+ }
+ $file->seek($idx * $struct_size, 0);
+
+ $runtime->stack->pushValue($pos);
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_readlinkat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_readlinkat: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_renameat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_renameat: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env____syscall_rmdir(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_rmdir: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall__newselect(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall__newselect: not implemented');
+}
+
+// Type: (i32, f64) -> (i32)
+function hostFunc__env___setitimer_js(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::_setitimer_js: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_statfs64(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_statfs64: not implemented');
+}
+
+// Type: (i32, i32) -> (i32)
+function hostFunc__env____syscall_symlink(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_symlink: not implemented');
+}
+
+// Type: () -> (i32)
+function hostFunc__env__emscripten_get_heap_max(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::emscripten_get_heap_max: not implemented');
+}
+
+// Type: (i32, i32, i32) -> ()
+function hostFunc__env___tzset_js(Runtime $runtime): void
+{
+ $tzname = $runtime->stack->popInt();
+ $daylight = $runtime->stack->popInt();
+ $timezone = $runtime->stack->popInt();
+ // Do nothing ;)
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_unlinkat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_unlinkat: not implemented');
+}
+
+// Type: (i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_utimensat(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_utimensat: not implemented');
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env__emscripten_resize_heap(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::emscripten_resize_heap: not implemented');
+}
+
+// Type: () -> ()
+function hostFunc__env___emscripten_throw_longjmp(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::_emscripten_throw_longjmp: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_accept4(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_accept4: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_bind(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_bind: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_connect(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_connect: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_getpeername(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_getpeername: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_getsockname(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_getsockname: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_getsockopt(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_getsockopt: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_listen(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_listen: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_recvfrom(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_recvfrom: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_sendto(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_sendto: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_socket(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_socket: not implemented');
+}
+
+// Type: (i32, i32, i32) -> (i32)
+function hostFunc__env____syscall_ftruncate64(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::__syscall_ftruncate64: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__wasi_snapshot_preview1__fd_seek(Runtime $runtime): void
+{
+ $newOffset = $runtime->stack->popInt();
+ $whence = $runtime->stack->popInt();
+ $offset_high = $runtime->stack->popInt();
+ $offset_low = $runtime->stack->popInt();
+ $fd = $runtime->stack->popInt();
+
+ $offset = $offset_low + $offset_high * 4294967296;
+ $file = fsGetVFileFromFd($fd);
+ $pos = $file->seek($offset, $whence);
+ heap64Write($runtime, $newOffset, $pos);
+
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32) -> (i32)
+function hostFunc__env___mktime_js(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::_mktime_js: not implemented');
+}
+
+// Type: (i32, i32, i32) -> ()
+function hostFunc__env___localtime_js(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::_localtime_js: not implemented');
+}
+
+// Type: (i32, i32, i32) -> ()
+function hostFunc__env___gmtime_js(Runtime $runtime): void
+{
+ throw new \RuntimeException('env::_gmtime_js: not implemented');
+}
+
+// Type: (i32, i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env___munmap_js(Runtime $runtime): void
+{
+ // Do nothing.
+ $_7 = $runtime->stack->popInt();
+ $_6 = $runtime->stack->popInt();
+ $_5 = $runtime->stack->popInt();
+ $_4 = $runtime->stack->popInt();
+ $_3 = $runtime->stack->popInt();
+ $_2 = $runtime->stack->popInt();
+ $_1 = $runtime->stack->popInt();
+
+ $runtime->stack->pushValue(0);
+}
+
+// Type: (i32, i32, i32, i32, i32, i32, i32, i32) -> (i32)
+function hostFunc__env___mmap_js(Runtime $runtime): void
+{
+ $addr = $runtime->stack->popInt();
+ $allocated = $runtime->stack->popInt();
+ $offset_high = $runtime->stack->popInt();
+ $offset_low = $runtime->stack->popInt();
+ $fd = $runtime->stack->popInt();
+ $flags = $runtime->stack->popInt();
+ $prot = $runtime->stack->popInt();
+ $len = $runtime->stack->popInt();
+
+ $offset = $offset_low + $offset_high * 4294967296;
+
+ [$resultPtr, $resultAllocated] = fsMmap($runtime, $fd, $len, $offset, $prot, $flags);
+ heap32Write($runtime, $allocated, $resultAllocated);
+ heapU32Write($runtime, $addr, $resultPtr);
+
+ $runtime->stack->pushValue(0);
+}
diff --git a/examples/rubyvm-on-php-on-wasm/php-wasm.wasm b/examples/rubyvm-on-php-on-wasm/php-wasm.wasm
new file mode 100755
index 0000000..8e91021
--- /dev/null
+++ b/examples/rubyvm-on-php-on-wasm/php-wasm.wasm
Binary files differ