mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05:33 +00:00
Merge branch 'master' into feature/wasi-fs-improvements
This commit is contained in:
commit
21bc4b578a
@ -103,7 +103,7 @@ jobs:
|
||||
- run:
|
||||
name: Install Rust
|
||||
command: |
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
curl -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
cargo --version
|
||||
- run:
|
||||
@ -150,6 +150,11 @@ jobs:
|
||||
- image: circleci/rust:latest
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Pull dependencies"
|
||||
command: |
|
||||
git submodule init
|
||||
git submodule update --remote
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
@ -178,6 +183,7 @@ jobs:
|
||||
command: |
|
||||
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/"
|
||||
make production-release
|
||||
cargo build --release --manifest-path wapm-cli/Cargo.toml --features telemetry
|
||||
mkdir -p artifacts
|
||||
VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||
# GIT_VERSION=$(git describe --exact-match --tags)
|
||||
@ -202,6 +208,9 @@ jobs:
|
||||
- target/release/.fingerprint
|
||||
- target/release/build
|
||||
- target/release/deps
|
||||
- wapm-cli/target/release/.fingerprint
|
||||
- wapm-cli/target/release/build
|
||||
- wapm-cli/target/release/deps
|
||||
key: v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
|
||||
test-and-build-macos:
|
||||
@ -209,6 +218,11 @@ jobs:
|
||||
xcode: "9.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Pull dependencies"
|
||||
command: |
|
||||
git submodule init
|
||||
git submodule update --remote
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
@ -226,7 +240,7 @@ jobs:
|
||||
- run:
|
||||
name: Install Rust
|
||||
command: |
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly-2019-04-11
|
||||
curl -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
cargo --version
|
||||
# Use rust nightly (for singlepass, for now)
|
||||
@ -263,6 +277,7 @@ jobs:
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
|
||||
make production-release
|
||||
cargo build --release --manifest-path wapm-cli/Cargo.toml --features telemetry
|
||||
mkdir -p artifacts
|
||||
make build-install
|
||||
cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh)
|
||||
@ -281,6 +296,9 @@ jobs:
|
||||
- target/release/.fingerprint
|
||||
- target/release/build
|
||||
- target/release/deps
|
||||
- wapm-cli/target/release/.fingerprint
|
||||
- wapm-cli/target/release/build
|
||||
- wapm-cli/target/release/deps
|
||||
key: v8-cargo-cache-darwin-nightly-{ arch }}-{{ checksum "Cargo.lock" }}
|
||||
|
||||
test-rust-nightly:
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "wapm-cli"]
|
||||
path = wapm-cli
|
||||
url = https://github.com/wasmerio/wapm-cli.git
|
28
CHANGELOG.md
28
CHANGELOG.md
@ -5,6 +5,20 @@ All PRs to the Wasmer repository must add to this file.
|
||||
Blocks of changes will separated by version increments.
|
||||
|
||||
## **[Unreleased]**
|
||||
|
||||
## 0.4.1 - 2018-05-06
|
||||
|
||||
- [#426](https://github.com/wasmerio/wasmer/pull/426) Update wapm-cli submodule, bump version to 0.4.1
|
||||
- [#422](https://github.com/wasmerio/wasmer/pull/422) Improved Emscripten functions to run optipng and pngquant compiled to wasm
|
||||
- [#409](https://github.com/wasmerio/wasmer/pull/409) Improved Emscripten functions to run JavascriptCore compiled to wasm
|
||||
- [#399](https://github.com/wasmerio/wasmer/pull/399) Add example of using a plugin extended from WASI
|
||||
- [#397](https://github.com/wasmerio/wasmer/pull/397) Fix WASI fs abstraction to work on Windows
|
||||
- [#390](https://github.com/wasmerio/wasmer/pull/390) Pin released wapm version and add it as a git submodule
|
||||
- [#408](https://github.com/wasmerio/wasmer/pull/408) Add images to windows installer and update installer to add wapm bin directory to path
|
||||
|
||||
## 0.4.0 - 2018-04-23
|
||||
|
||||
- [#383](https://github.com/wasmerio/wasmer/pull/383) Hook up wasi exit code to wasmer cli.
|
||||
- [#382](https://github.com/wasmerio/wasmer/pull/382) Improve error message on `--backend` flag to only suggest currently enabled backends
|
||||
- [#381](https://github.com/wasmerio/wasmer/pull/381) Allow retrieving propagated user errors.
|
||||
- [#379](https://github.com/wasmerio/wasmer/pull/379) Fix small return types from imported functions.
|
||||
@ -19,3 +33,17 @@ Blocks of changes will separated by version increments.
|
||||
- [#351](https://github.com/wasmerio/wasmer/pull/351) Add hidden option to specify wasm program name (can be used to improve error messages)
|
||||
- [#350](https://github.com/wasmerio/wasmer/pull/350) Enforce that CHANGELOG.md is updated through CI.
|
||||
- [#349](https://github.com/wasmerio/wasmer/pull/349) Add [CHANGELOG.md](https://github.com/wasmerio/wasmer/blob/master/CHANGELOG.md).
|
||||
|
||||
## 0.3.0 - 2018-04-12
|
||||
|
||||
- [#276](https://github.com/wasmerio/wasmer/pull/276) [#288](https://github.com/wasmerio/wasmer/pull/288) [#344](https://github.com/wasmerio/wasmer/pull/344) Use new singlepass backend (with the `--backend=singlepass` when running Wasmer)
|
||||
- [#338](https://github.com/wasmerio/wasmer/pull/338) Actually catch traps/panics/etc when using a typed func.
|
||||
- [#325](https://github.com/wasmerio/wasmer/pull/325) Fixed func_index in debug mode
|
||||
- [#323](https://github.com/wasmerio/wasmer/pull/323) Add validate subcommand to validate Wasm files
|
||||
- [#321](https://github.com/wasmerio/wasmer/pull/321) Upgrade to Cranelift 0.3.0
|
||||
- [#319](https://github.com/wasmerio/wasmer/pull/319) Add Export and GlobalDescriptor to Runtime API
|
||||
- [#310](https://github.com/wasmerio/wasmer/pull/310) Cleanup warnings
|
||||
- [#299](https://github.com/wasmerio/wasmer/pull/299) [#300](https://github.com/wasmerio/wasmer/pull/300) [#301](https://github.com/wasmerio/wasmer/pull/301) [#303](https://github.com/wasmerio/wasmer/pull/303) [#304](https://github.com/wasmerio/wasmer/pull/304) [#305](https://github.com/wasmerio/wasmer/pull/305) [#306](https://github.com/wasmerio/wasmer/pull/306) [#307](https://github.com/wasmerio/wasmer/pull/307) Add support for WASI 🎉
|
||||
- [#286](https://github.com/wasmerio/wasmer/pull/286) Add extend to imports
|
||||
- [#278](https://github.com/wasmerio/wasmer/pull/278) Add versioning to cache
|
||||
- [#250](https://github.com/wasmerio/wasmer/pull/250) Setup bors
|
||||
|
115
Cargo.lock
generated
115
Cargo.lock
generated
@ -1317,6 +1317,10 @@ name = "plain"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "plugin-for-example"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "podio"
|
||||
version = "0.1.6"
|
||||
@ -2222,7 +2226,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2230,19 +2234,20 @@ dependencies = [
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-clif-backend 0.3.0",
|
||||
"wasmer-emscripten 0.3.0",
|
||||
"wasmer-llvm-backend 0.3.0",
|
||||
"wasmer-runtime 0.3.0",
|
||||
"wasmer-runtime-abi 0.3.0",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-singlepass-backend 0.3.0",
|
||||
"wasmer-wasi 0.3.0",
|
||||
"wasmer-clif-backend 0.4.1",
|
||||
"wasmer-emscripten 0.4.1",
|
||||
"wasmer-llvm-backend 0.4.1",
|
||||
"wasmer-middleware-common 0.4.1",
|
||||
"wasmer-runtime 0.4.1",
|
||||
"wasmer-runtime-abi 0.4.1",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmer-singlepass-backend 0.4.1",
|
||||
"wasmer-wasi 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-clif-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2258,15 +2263,15 @@ dependencies = [
|
||||
"serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-win-exception-handler 0.3.0",
|
||||
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmer-win-exception-handler 0.4.1",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-emscripten"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2275,15 +2280,15 @@ dependencies = [
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-clif-backend 0.3.0",
|
||||
"wasmer-llvm-backend 0.3.0",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-singlepass-backend 0.3.0",
|
||||
"wasmer-clif-backend 0.4.1",
|
||||
"wasmer-llvm-backend 0.4.1",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmer-singlepass-backend 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-llvm-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2298,53 +2303,60 @@ dependencies = [
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-middleware-common"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-clif-backend 0.3.0",
|
||||
"wasmer-llvm-backend 0.3.0",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-singlepass-backend 0.3.0",
|
||||
"wasmer-clif-backend 0.4.1",
|
||||
"wasmer-llvm-backend 0.4.1",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmer-singlepass-backend 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime-abi"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"zbox 0.6.1 (git+https://github.com/wasmerio/zbox?branch=bundle-libsodium)",
|
||||
"zstd 0.4.22+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime-c-api"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"cbindgen 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime 0.3.0",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-runtime 0.4.1",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime-core"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2370,7 +2382,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-singlepass-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dynasm 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2380,24 +2392,24 @@ dependencies = [
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-spectests"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-clif-backend 0.3.0",
|
||||
"wasmer-llvm-backend 0.3.0",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-singlepass-backend 0.3.0",
|
||||
"wasmer-clif-backend 0.4.1",
|
||||
"wasmer-llvm-backend 0.4.1",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"wasmer-singlepass-backend 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-wasi"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"generational-arena 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2405,32 +2417,21 @@ dependencies = [
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"zbox 0.6.1 (git+https://github.com/wasmerio/zbox?branch=bundle-libsodium)",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-win-exception-handler"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.3.0",
|
||||
"wasmer-runtime-core 0.4.1",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.29.2"
|
||||
@ -2824,8 +2825,6 @@ dependencies = [
|
||||
"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c"
|
||||
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
|
||||
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
|
||||
"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"
|
||||
"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1"
|
||||
"checksum wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)" = "981a8797cf89762e0233ec45fae731cb79a4dfaee12d9f0fe6cee01e4ac58d00"
|
||||
"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
12
Cargo.toml
12
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
@ -25,6 +25,7 @@ wabt = "0.7.2"
|
||||
hashbrown = "0.1.8"
|
||||
wasmer-clif-backend = { path = "lib/clif-backend" }
|
||||
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true }
|
||||
wasmer-middleware-common = { path = "lib/middleware-common" }
|
||||
wasmer-runtime = { path = "lib/runtime" }
|
||||
wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
|
||||
wasmer-runtime-core = { path = "lib/runtime-core" }
|
||||
@ -33,7 +34,7 @@ wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
|
||||
wasmer-wasi = { path = "lib/wasi", optional = true }
|
||||
|
||||
[workspace]
|
||||
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi"]
|
||||
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi", "lib/middleware-common", "examples/plugin-for-example"]
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.7.2"
|
||||
@ -42,10 +43,15 @@ rustc_version = "0.2.3"
|
||||
|
||||
[features]
|
||||
default = ["fast-tests", "wasi"]
|
||||
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
debug = ["wasmer-runtime-core/debug"]
|
||||
extra-debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
# This feature will allow cargo test to run much faster
|
||||
fast-tests = []
|
||||
"backend:llvm" = ["wasmer-llvm-backend"]
|
||||
"backend:singlepass" = ["wasmer-singlepass-backend"]
|
||||
wasi = ["wasmer-wasi"]
|
||||
vfs = ["wasmer-runtime-abi"]
|
||||
|
||||
[[example]]
|
||||
name = "plugin"
|
||||
crate-type = ["bin"]
|
||||
|
7
Makefile
7
Makefile
@ -25,6 +25,7 @@ integration-tests: release
|
||||
echo "Running Integration Tests"
|
||||
./integration_tests/lua/test.sh
|
||||
./integration_tests/nginx/test.sh
|
||||
./integration_tests/cowsay/test.sh
|
||||
|
||||
lint:
|
||||
cargo fmt --all -- --check
|
||||
@ -34,8 +35,9 @@ precommit: lint test
|
||||
|
||||
build-install:
|
||||
mkdir -p ./install/bin
|
||||
cp ./wapm-cli/target/release/wapm ./install/bin/
|
||||
cp ./target/release/wasmer ./install/bin/
|
||||
tar -C ./install -zcvf wasmer.tar.gz bin/wasmer
|
||||
tar -C ./install -zcvf wasmer.tar.gz bin/wapm bin/wasmer
|
||||
|
||||
# For installing the contents locally
|
||||
do-install:
|
||||
@ -82,5 +84,8 @@ production-release:
|
||||
debug-release:
|
||||
cargo build --release --features "debug"
|
||||
|
||||
extra-debug-release:
|
||||
cargo build --release --features "extra-debug"
|
||||
|
||||
publish-release:
|
||||
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION} ./artifacts/
|
||||
|
28
README.md
28
README.md
@ -27,10 +27,12 @@ curl https://get.wasmer.io -sSfL | sh
|
||||
```
|
||||
|
||||
Wasmer runtime can also be embedded in different languages, so you can use WebAssembly anywhere ✨:
|
||||
|
||||
* [**Rust**](https://github.com/wasmerio/wasmer-rust-example)
|
||||
* [**C/C++**](https://github.com/wasmerio/wasmer-c-api)
|
||||
* [**PHP**](https://github.com/wasmerio/php-ext-wasm)
|
||||
* [**Python**](https://github.com/wasmerio/python-ext-wasm)
|
||||
* [**🐘 PHP**](https://github.com/wasmerio/php-ext-wasm)
|
||||
* [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm)
|
||||
* [**💎 Ruby**](https://github.com/wasmerio/ruby-ext-wasm)
|
||||
|
||||
### Usage
|
||||
|
||||
@ -53,6 +55,24 @@ wasmer run examples/sqlite.wasm
|
||||
wasmer run examples/nginx/nginx.wasm -- -p examples/nginx -c nginx.conf
|
||||
```
|
||||
|
||||
#### With WAPM
|
||||
|
||||
Installing Wasmer through `wasmer.io` includes
|
||||
[wapm](https://github.com/wasmerio/wapm-cli), the WebAssembly package manager.
|
||||
|
||||
Wapm allows you to easily download, run, and distribute WebAssembly binaries.
|
||||
|
||||
```sh
|
||||
# Install cowsay globally
|
||||
wapm install -g cowsay
|
||||
|
||||
# Run cowsay
|
||||
wapm run cowsay "Hello, world!"
|
||||
```
|
||||
|
||||
For more information about wapm, check out the [website](https://www.wapm.io)
|
||||
and this [example program](https://github.com/wapm-packages/rust-wasi-example).
|
||||
|
||||
## Code Structure
|
||||
|
||||
Wasmer is structured into different directories:
|
||||
@ -100,7 +120,7 @@ sudo port install cmake
|
||||
#### Debian-based Linuxes
|
||||
|
||||
```sh
|
||||
sudo apt install cmake
|
||||
sudo apt install cmake pkg-config libssl-dev
|
||||
```
|
||||
|
||||
#### FreeBSD
|
||||
@ -181,7 +201,7 @@ Below are some of the goals of this project (in order of priority):
|
||||
|
||||
- [x] It should be 100% compatible with the [WebAssembly spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests)
|
||||
- [x] It should be fast _(partially achieved)_
|
||||
- [ ] Support WASI _(in the works)_
|
||||
- [x] Support WASI - released in [0.3.0](https://github.com/wasmerio/wasmer/releases/tag/0.3.0)
|
||||
- [ ] Support Emscripten calls _(in the works)_
|
||||
- [ ] Support Rust ABI calls
|
||||
- [ ] Support Go ABI calls
|
||||
|
9
examples/README.md
Normal file
9
examples/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# WebAssembly Examples
|
||||
|
||||
In this directory you can find a set of different examples that can run on the Wasmer WebAssembly runtime:
|
||||
|
||||
* Cowsay (WASI ABI) [[source-code](https://github.com/wapm-packages/cowsay)] [[wapm-package](https://wapm.io/package/cowsay)]
|
||||
* Nginx (Emscripten ABI) [[source-code](https://github.com/wapm-packages/nginx)] [[wapm-package](https://wapm.io/package/nginx)]
|
||||
* Lua (Emscripten ABI) [[source-code](https://github.com/wapm-packages/lua)] [[wapm-package](https://wapm.io/package/lua)]
|
||||
* PHP (Emscripten ABI) [[source-code](https://github.com/wapm-packages/php)] [[wapm-package](https://wapm.io/package/php)]
|
||||
* SQLite (Emscripten ABI) [[source-code](https://github.com/wapm-packages/sqlite)] [[wapm-package](https://wapm.io/package/sqlite)]
|
BIN
examples/cowsay.wasm
Executable file
BIN
examples/cowsay.wasm
Executable file
Binary file not shown.
11
examples/exit.wat
Normal file
11
examples/exit.wat
Normal file
@ -0,0 +1,11 @@
|
||||
(module
|
||||
(import "wasi_unstable" "proc_exit" (func $proc_exit (param i32)))
|
||||
(export "_start" (func $_start))
|
||||
|
||||
(memory 10)
|
||||
(export "memory" (memory 0))
|
||||
|
||||
(func $_start
|
||||
(call $proc_exit (i32.const 7))
|
||||
)
|
||||
)
|
BIN
examples/plugin-for-example.wasm
Executable file
BIN
examples/plugin-for-example.wasm
Executable file
Binary file not shown.
7
examples/plugin-for-example/Cargo.toml
Normal file
7
examples/plugin-for-example/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "plugin-for-example"
|
||||
version = "0.1.0"
|
||||
authors = ["The Wasmer Engineering Team <enigneering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
43
examples/plugin-for-example/README.md
Normal file
43
examples/plugin-for-example/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# WASI plugin example
|
||||
|
||||
In this example we extend the imports of Wasmer's WASI ABI to demonstrate how custom plugins work.
|
||||
|
||||
See the `wasmer/examples/plugin.rs` file for the source code of the host system.
|
||||
|
||||
## Compiling
|
||||
_Attention Windows users: WASI target only works with the `nightly-x86_64-pc-windows-gnu` toolchain._
|
||||
```
|
||||
# Install an up to date version of Rust nightly
|
||||
# Add the target
|
||||
rustup target add wasm32-unknown-wasi
|
||||
# build it
|
||||
cargo +nightly build --release --target=wasm32-unknown-wasi
|
||||
# copy it to examples folder
|
||||
cp ../../target/wasm32-unknown-wasi/release/plugin-for-example.wasm ../
|
||||
```
|
||||
|
||||
## Running
|
||||
```
|
||||
# Go back to top level Wasmer dir
|
||||
cd ..
|
||||
# Run the example
|
||||
cargo run --example plugin
|
||||
```
|
||||
|
||||
## Inspecting the plugin
|
||||
```
|
||||
# Install wabt via wapm; installed globally with the `g` flag
|
||||
wapm install -g wabt
|
||||
# Turn the binary WASM file in to a readable WAT text file
|
||||
wapm run wasm2wat examples/plugin-for-example.wasm
|
||||
```
|
||||
|
||||
At the top of the file we can see which functions this plugin expects. Most are covered by WASI, but we handle the rest.
|
||||
|
||||
## Explanation
|
||||
|
||||
In this example, we instantiate a system with an extended (WASI)[wasi] ABI, allowing our program to rely on Wasmer's implementation of the syscalls defined by WASI as well as our own that we made. This allows us to use the full power of an existing ABI, like WASI, and give it super-powers for our specific use case.
|
||||
|
||||
Because the Rust WASI doesn't support the crate type of `cdylib`, we have to include a main function which we don't use. This is being discussed [here](https://github.com/WebAssembly/WASI/issues/24).
|
||||
|
||||
[wasi]: https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/
|
12
examples/plugin-for-example/src/main.rs
Normal file
12
examples/plugin-for-example/src/main.rs
Normal file
@ -0,0 +1,12 @@
|
||||
extern "C" {
|
||||
fn it_works() -> i32;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn plugin_entrypoint(n: i32) -> i32 {
|
||||
println!("Hello from inside WASI");
|
||||
let result = unsafe { it_works() };
|
||||
result + n
|
||||
}
|
||||
|
||||
pub fn main() {}
|
12
examples/plugin-for-example/wapm.toml
Normal file
12
examples/plugin-for-example/wapm.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "plugin-for-example"
|
||||
version = "0.1.0"
|
||||
description = "A plugin for our example system"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/wasmerio/wasmer/examples/plugin-for-example"
|
||||
license = "MIT"
|
||||
|
||||
[[module]]
|
||||
name = "plugin-for-example"
|
||||
source = "../../target/wasm32-unknown-wasi/release/plugin-for-example.wasm"
|
||||
abi = "none"
|
38
examples/plugin.rs
Normal file
38
examples/plugin.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use wasmer_runtime::{func, imports, instantiate};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
use wasmer_wasi::generate_import_object;
|
||||
|
||||
static PLUGIN_LOCATION: &'static str = "examples/plugin-for-example.wasm";
|
||||
|
||||
fn it_works(_ctx: &mut Ctx) -> i32 {
|
||||
println!("Hello from outside WASI");
|
||||
5
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Load the plugin data
|
||||
let wasm_bytes = std::fs::read(PLUGIN_LOCATION).expect(&format!(
|
||||
"Could not read in WASM plugin at {}",
|
||||
PLUGIN_LOCATION
|
||||
));
|
||||
|
||||
// WASI imports
|
||||
let mut base_imports = generate_import_object(vec![], vec![], vec![]);
|
||||
// env is the default namespace for extern functions
|
||||
let custom_imports = imports! {
|
||||
"env" => {
|
||||
"it_works" => func!(it_works),
|
||||
},
|
||||
};
|
||||
// The WASI imports object contains all required import functions for a WASI module to run.
|
||||
// Extend this imports with our custom imports containing "it_works" function so that our custom wasm code may run.
|
||||
base_imports.extend(custom_imports);
|
||||
let instance =
|
||||
instantiate(&wasm_bytes[..], &base_imports).expect("failed to instantiate wasm module");
|
||||
|
||||
// get a reference to the function "plugin_entrypoint" which takes an i32 and returns an i32
|
||||
let entry_point = instance.func::<(i32), i32>("plugin_entrypoint").unwrap();
|
||||
// call the "entry_point" function in WebAssembly with the number "2" as the i32 argument
|
||||
let result = entry_point.call(2).expect("failed to execute plugin");
|
||||
println!("result: {}", result);
|
||||
}
|
23
install.sh
23
install.sh
@ -130,11 +130,11 @@ wasmer_detect_profile() {
|
||||
wasmer_link() {
|
||||
printf "$cyan> Adding to bash profile...$reset\n"
|
||||
WASMER_PROFILE="$(wasmer_detect_profile)"
|
||||
LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n"
|
||||
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
|
||||
LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"$INSTALL_DIRECTORY\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n"
|
||||
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"$INSTALL_DIRECTORY\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$WASMER_DIR/bin:\$WASMER_DIR/globals/wapm_packages/.bin:\$PATH\"\n"
|
||||
|
||||
# We create the wasmer.sh file
|
||||
printf "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
|
||||
printf "$SOURCE_STR" > "$INSTALL_DIRECTORY/wasmer.sh"
|
||||
|
||||
if [ -z "${WASMER_PROFILE-}" ] ; then
|
||||
printf "${red}Profile not found. Tried:\n* ${WASMER_PROFILE} (as defined in \$PROFILE)\n* ~/.bashrc\n* ~/.bash_profile\n* ~/.zshrc\n* ~/.profile.\n"
|
||||
@ -156,13 +156,15 @@ wasmer_link() {
|
||||
echo "If this isn't the profile of your current shell then please add the following to your correct profile:"
|
||||
printf "$LOAD_STR$reset\n"
|
||||
|
||||
version=`$HOME/.wasmer/bin/wasmer --version` || (
|
||||
version=`$INSTALL_DIRECTORY/bin/wasmer --version` || (
|
||||
printf "$red> wasmer was installed, but doesn't seem to be working :($reset\n"
|
||||
exit 1;
|
||||
)
|
||||
|
||||
printf "$green> Successfully installed $version!\n\n${reset}If you want to have the command available now please execute:\nsource $HOME/.wasmer/wasmer.sh$reset\n"
|
||||
printf "\nOtherwise, wasmer will be available the next time you open the terminal.\n"
|
||||
printf "$green> Successfully installed $version!\n\n${reset}If you want to have the command available now please execute:\nsource $INSTALL_DIRECTORY/wasmer.sh$reset\n"
|
||||
printf "\nOtherwise, wasmer and wapm will be available the next time you open the terminal.\n"
|
||||
echo "Note: during the alpha release of wapm, telemetry is enabled by default; if you would like to opt out, run \`wapm config set telemetry.enabled false\`."
|
||||
echo "If you notice anything wrong or have any issues, please file a bug at https://github.com/wasmerio/wapm-cli :)"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -255,7 +257,7 @@ wasmer_install() {
|
||||
|
||||
"
|
||||
fi
|
||||
# if [ -d "$HOME/.wasmer" ]; then
|
||||
# if [ -d "$INSTALL_DIRECTORY" ]; then
|
||||
# if which wasmer; then
|
||||
# local latest_url
|
||||
# local specified_version
|
||||
@ -284,15 +286,14 @@ wasmer_install() {
|
||||
# exit 0
|
||||
# else
|
||||
# printf "$yellow> $wasmer_alt_version is already installed, Specified version: $specified_version.$reset\n"
|
||||
# rm -rf "$HOME/.wasmer"
|
||||
# rm -rf "$INSTALL_DIRECTORY"
|
||||
# fi
|
||||
# else
|
||||
# printf "$red> $HOME/.wasmer already exists, possibly from a past Wasmer install.$reset\n"
|
||||
# printf "$red> Remove it (rm -rf $HOME/.wasmer) and run this script again.$reset\n"
|
||||
# printf "$red> $INSTALL_DIRECTORY already exists, possibly from a past Wasmer install.$reset\n"
|
||||
# printf "$red> Remove it (rm -rf $INSTALL_DIRECTORY) and run this script again.$reset\n"
|
||||
# exit 0
|
||||
# fi
|
||||
# fi
|
||||
|
||||
wasmer_download # $1 $2
|
||||
wasmer_link
|
||||
wasmer_reset
|
||||
|
9
integration_tests/cowsay/README.md
Normal file
9
integration_tests/cowsay/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# `cowsay` integration test
|
||||
|
||||
|
||||
This starts Wasmer with the Cowsay WASI Wasm file. The test makes assertions on
|
||||
the output of Wasmer. Run test with:
|
||||
|
||||
```bash
|
||||
./integration_tests/cowsay/test.sh
|
||||
```
|
14
integration_tests/cowsay/test.sh
Executable file
14
integration_tests/cowsay/test.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#! /bin/bash
|
||||
|
||||
nohup ./target/release/wasmer run examples/cowsay.wasm --disable-cache -- "hello integration"
|
||||
|
||||
if grep "hello integration" ./nohup.out
|
||||
then
|
||||
echo "cowsay wasi integration test succeeded"
|
||||
rm ./nohup.out
|
||||
exit 0
|
||||
else
|
||||
echo "cowsay wasi integration test failed"
|
||||
rm ./nohup.out
|
||||
exit -1
|
||||
fi
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-clif-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime Cranelift compiler backend"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -8,14 +8,14 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
cranelift-native = "0.30.0"
|
||||
cranelift-codegen = "0.30.0"
|
||||
cranelift-entity = "0.30.0"
|
||||
cranelift-wasm = "0.30.0"
|
||||
hashbrown = "0.1"
|
||||
target-lexicon = "0.3.0"
|
||||
wasmparser = "0.23.0"
|
||||
wasmparser = "0.29.2"
|
||||
byteorder = "1"
|
||||
nix = "0.13.0"
|
||||
libc = "0.2.49"
|
||||
@ -33,7 +33,7 @@ version = "0.0.7"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.3.0" }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.4.1" }
|
||||
|
||||
[features]
|
||||
debug = ["wasmer-runtime-core/debug"]
|
||||
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
use wasmer_runtime_core::{
|
||||
backend::{sys::Memory, CacheGen},
|
||||
cache::{Artifact, Error},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
module::ModuleInfo,
|
||||
structures::Map,
|
||||
types::{LocalFuncIndex, SigIndex},
|
||||
};
|
||||
|
@ -107,7 +107,7 @@ pub fn call_protected<T>(
|
||||
Ok(SIGSEGV) => "segmentation violation",
|
||||
Ok(SIGBUS) => "bus error",
|
||||
Err(_) => "error while getting the Signal",
|
||||
_ => "unkown trapped signal",
|
||||
_ => "unknown trapped signal",
|
||||
};
|
||||
// When the trap-handler is fully implemented, this will return more information.
|
||||
let s = format!("unknown trap at {:p} - {}", faulting_addr, signal);
|
||||
|
@ -4,7 +4,6 @@ use crate::trampoline::Trampoline;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::{self, NonNull};
|
||||
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||
use wasmer_runtime_core::typed_func::WasmTrapInfo;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
use wasmer_runtime_core::vm::Func;
|
||||
@ -12,10 +11,14 @@ use wasmer_win_exception_handler::CallProtectedData;
|
||||
pub use wasmer_win_exception_handler::_call_protected;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::minwinbase::{
|
||||
EXCEPTION_ACCESS_VIOLATION, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO,
|
||||
EXCEPTION_ACCESS_VIOLATION, EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_BREAKPOINT,
|
||||
EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO,
|
||||
EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW,
|
||||
EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_ILLEGAL_INSTRUCTION,
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW, EXCEPTION_STACK_OVERFLOW,
|
||||
EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_GUARD_PAGE,
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW,
|
||||
EXCEPTION_INVALID_HANDLE, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_NONCONTINUABLE_EXCEPTION,
|
||||
EXCEPTION_POSSIBLE_DEADLOCK, EXCEPTION_PRIV_INSTRUCTION, EXCEPTION_SINGLE_STEP,
|
||||
EXCEPTION_STACK_OVERFLOW,
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
@ -43,7 +46,7 @@ pub fn call_protected(
|
||||
}
|
||||
|
||||
let CallProtectedData {
|
||||
code: signum,
|
||||
code,
|
||||
exception_address,
|
||||
instruction_pointer,
|
||||
} = result.unwrap_err();
|
||||
@ -53,7 +56,7 @@ pub fn call_protected(
|
||||
srcloc: _,
|
||||
}) = handler_data.lookup(instruction_pointer as _)
|
||||
{
|
||||
Err(CallProtError::Trap(match signum as DWORD {
|
||||
Err(CallProtError::Trap(match code as DWORD {
|
||||
EXCEPTION_ACCESS_VIOLATION => WasmTrapInfo::MemoryOutOfBounds,
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
|
||||
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
|
||||
@ -70,7 +73,7 @@ pub fn call_protected(
|
||||
_ => WasmTrapInfo::Unknown,
|
||||
}))
|
||||
} else {
|
||||
let signal = match signum as DWORD {
|
||||
let signal = match code as DWORD {
|
||||
EXCEPTION_FLT_DENORMAL_OPERAND
|
||||
| EXCEPTION_FLT_DIVIDE_BY_ZERO
|
||||
| EXCEPTION_FLT_INEXACT_RESULT
|
||||
@ -80,10 +83,26 @@ pub fn call_protected(
|
||||
| EXCEPTION_FLT_UNDERFLOW => "floating-point exception",
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => "illegal instruction",
|
||||
EXCEPTION_ACCESS_VIOLATION => "segmentation violation",
|
||||
_ => "unkown trapped signal",
|
||||
EXCEPTION_DATATYPE_MISALIGNMENT => "datatype misalignment",
|
||||
EXCEPTION_BREAKPOINT => "breakpoint",
|
||||
EXCEPTION_SINGLE_STEP => "single step",
|
||||
EXCEPTION_ARRAY_BOUNDS_EXCEEDED => "array bounds exceeded",
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO => "int div by zero",
|
||||
EXCEPTION_INT_OVERFLOW => "int overflow",
|
||||
EXCEPTION_PRIV_INSTRUCTION => "priv instruction",
|
||||
EXCEPTION_IN_PAGE_ERROR => "in page error",
|
||||
EXCEPTION_NONCONTINUABLE_EXCEPTION => "non continuable exception",
|
||||
EXCEPTION_STACK_OVERFLOW => "stack overflow",
|
||||
EXCEPTION_GUARD_PAGE => "guard page",
|
||||
EXCEPTION_INVALID_HANDLE => "invalid handle",
|
||||
EXCEPTION_POSSIBLE_DEADLOCK => "possible deadlock",
|
||||
_ => "unknown exception code",
|
||||
};
|
||||
|
||||
let s = format!("unknown trap at {} - {}", exception_address, signal);
|
||||
let s = format!(
|
||||
"unhandled trap at {:x} - code #{:x}: {}",
|
||||
exception_address, code, signal,
|
||||
);
|
||||
|
||||
Err(CallProtError::Error(Box::new(s)))
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-emscripten"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime emscripten implementation library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,14 +9,14 @@ edition = "2018"
|
||||
build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
lazy_static = "1.2.0"
|
||||
libc = "0.2.49"
|
||||
byteorder = "1"
|
||||
time = "0.1.41"
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.3.0" }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.3.0", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.3.0", optional = true }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.4.1" }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.1", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.4.1", optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
rand = "0.6"
|
||||
|
@ -15,6 +15,15 @@ pub fn getTempRet0(ctx: &mut Ctx) -> i32 {
|
||||
get_emscripten_data(ctx).temp_ret_0
|
||||
}
|
||||
|
||||
pub fn _atexit(_ctx: &mut Ctx, _func: i32) -> i32 {
|
||||
debug!("emscripten::_atexit");
|
||||
// TODO: implement atexit properly
|
||||
// __ATEXIT__.unshift({
|
||||
// func: func,
|
||||
// arg: arg
|
||||
// });
|
||||
0
|
||||
}
|
||||
pub fn __Unwind_Backtrace(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::__Unwind_Backtrace");
|
||||
0
|
||||
@ -45,14 +54,45 @@ pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_dladdr");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_attr_init({})", _a);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_attr_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_getstack(
|
||||
_ctx: &mut Ctx,
|
||||
_stackaddr: i32,
|
||||
_stacksize: i32,
|
||||
_other: i32,
|
||||
) -> i32 {
|
||||
debug!(
|
||||
"emscripten::_pthread_attr_getstack({}, {}, {})",
|
||||
_stackaddr, _stacksize, _other
|
||||
);
|
||||
// TODO: Translate from Emscripten
|
||||
// HEAP32[stackaddr >> 2] = STACK_BASE;
|
||||
// HEAP32[stacksize >> 2] = TOTAL_STACK;
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_timedwait(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_timedwait");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_getspecific");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_getattr_np(_ctx: &mut Ctx, _thread: i32, _attr: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_setspecific");
|
||||
0
|
||||
@ -69,6 +109,10 @@ pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i3
|
||||
debug!("emscripten::_pthread_create");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_detach");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_join");
|
||||
0
|
||||
@ -691,6 +735,10 @@ pub fn invoke_vj(ctx: &mut Ctx, index: i32, a1: i32, a2: i32) {
|
||||
panic!("dyn_call_vj is set to None");
|
||||
}
|
||||
}
|
||||
pub fn invoke_vjji(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) {
|
||||
debug!("emscripten::invoke_vjji");
|
||||
invoke_no_return!(ctx, dyn_call_vjji, index, a1, a2, a3, a4, a5)
|
||||
}
|
||||
pub fn invoke_vij(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32) {
|
||||
debug!("emscripten::invoke_vij");
|
||||
if let Some(dyn_call_vij) = &get_emscripten_data(ctx).dyn_call_vij {
|
||||
|
42
lib/emscripten/src/env/mod.rs
vendored
42
lib/emscripten/src/env/mod.rs
vendored
@ -60,21 +60,51 @@ pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) {
|
||||
const MAX_ENV_VALUES: u32 = 64;
|
||||
const TOTAL_ENV_SIZE: u32 = 1024;
|
||||
let environment = emscripten_memory_pointer!(ctx.memory(0), environ) as *mut c_int;
|
||||
unsafe {
|
||||
let (mut pool_offset, env_ptr, mut pool_ptr) = unsafe {
|
||||
let (pool_offset, _pool_slice): (u32, &mut [u8]) =
|
||||
allocate_on_stack(ctx, TOTAL_ENV_SIZE as u32);
|
||||
let (env_offset, _env_slice): (u32, &mut [u8]) =
|
||||
allocate_on_stack(ctx, (MAX_ENV_VALUES * 4) as u32);
|
||||
let env_ptr = emscripten_memory_pointer!(ctx.memory(0), env_offset) as *mut c_int;
|
||||
let mut _pool_ptr = emscripten_memory_pointer!(ctx.memory(0), pool_offset) as *mut c_int;
|
||||
let pool_ptr = emscripten_memory_pointer!(ctx.memory(0), pool_offset) as *mut u8;
|
||||
*env_ptr = pool_offset as i32;
|
||||
*environment = env_offset as i32;
|
||||
|
||||
// *env_ptr = 0;
|
||||
(pool_offset, env_ptr, pool_ptr)
|
||||
};
|
||||
// unsafe {
|
||||
// *env_ptr = 0;
|
||||
// };
|
||||
|
||||
// *env_ptr = 0;
|
||||
let default_vars = vec![
|
||||
["USER", "web_user"],
|
||||
["LOGNAME", "web_user"],
|
||||
["PATH", "/"],
|
||||
["PWD", "/"],
|
||||
["HOME", "/home/web_user"],
|
||||
["LANG", "C.UTF-8"],
|
||||
["_", "thisProgram"],
|
||||
];
|
||||
let mut strings = vec![];
|
||||
let mut total_size = 0;
|
||||
for [key, val] in &default_vars {
|
||||
let line = key.to_string() + "=" + val;
|
||||
total_size += line.len();
|
||||
strings.push(line);
|
||||
}
|
||||
if total_size as u32 > TOTAL_ENV_SIZE {
|
||||
panic!("Environment size exceeded TOTAL_ENV_SIZE!");
|
||||
}
|
||||
unsafe {
|
||||
for (i, s) in strings.iter().enumerate() {
|
||||
for (j, c) in s.chars().enumerate() {
|
||||
debug_assert!(c < u8::max_value() as char);
|
||||
*pool_ptr.add(j) = c as u8;
|
||||
}
|
||||
*env_ptr.add(i * 4) = pool_offset as i32;
|
||||
pool_offset += s.len() as u32 + 1;
|
||||
pool_ptr = pool_ptr.add(s.len() + 1);
|
||||
}
|
||||
*env_ptr.add(strings.len() * 4) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ___assert_fail(_ctx: &mut Ctx, _a: c_int, _b: c_int, _c: c_int, _d: c_int) {
|
||||
|
@ -28,3 +28,9 @@ pub fn ___cxa_uncaught_exception(_ctx: &mut Ctx) -> i32 {
|
||||
debug!("emscripten::___cxa_uncaught_exception");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___cxa_pure_virtual(_ctx: &mut Ctx) {
|
||||
debug!("emscripten::___cxa_pure_virtual");
|
||||
// ABORT = true
|
||||
panic!("Pure virtual function called!");
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use wasmer_runtime_core::vm::Ctx;
|
||||
/// setjmp
|
||||
pub fn __setjmp(ctx: &mut Ctx, _env_addr: u32) -> c_int {
|
||||
debug!("emscripten::__setjmp (setjmp)");
|
||||
abort_with_message(ctx, "missing function: _longjmp");
|
||||
abort_with_message(ctx, "missing function: _setjmp");
|
||||
unreachable!()
|
||||
// unsafe {
|
||||
// // Rather than using the env as the holder of the jump buffer pointer,
|
||||
|
@ -50,7 +50,7 @@ mod varargs;
|
||||
|
||||
pub use self::storage::{align_memory, static_alloc};
|
||||
pub use self::utils::{
|
||||
allocate_cstr_on_stack, allocate_on_stack, get_emscripten_memory_size,
|
||||
allocate_cstr_on_stack, allocate_on_stack, get_emscripten_memory_size, get_emscripten_metadata,
|
||||
get_emscripten_table_size, is_emscripten_module,
|
||||
};
|
||||
|
||||
@ -127,6 +127,7 @@ pub struct EmscriptenData<'a> {
|
||||
pub dyn_call_viijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32, i32)>>,
|
||||
pub dyn_call_viijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||
pub dyn_call_vj: Option<Func<'a, (i32, i32, i32)>>,
|
||||
pub dyn_call_vjji: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
|
||||
pub dyn_call_vij: Option<Func<'a, (i32, i32, i32, i32)>>,
|
||||
pub dyn_call_viji: Option<Func<'a, (i32, i32, i32, i32, i32)>>,
|
||||
pub dyn_call_vijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||
@ -146,11 +147,7 @@ impl<'a> EmscriptenData<'a> {
|
||||
pub fn new(instance: &'a mut Instance) -> EmscriptenData<'a> {
|
||||
let malloc = instance.func("_malloc").unwrap();
|
||||
let free = instance.func("_free").unwrap();
|
||||
let memalign = if let Ok(func) = instance.func("_memalign") {
|
||||
Some(func)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let memalign = instance.func("_memalign").ok();
|
||||
let memset = instance.func("_memset").unwrap();
|
||||
let stack_alloc = instance.func("stackAlloc").unwrap();
|
||||
|
||||
@ -198,6 +195,7 @@ impl<'a> EmscriptenData<'a> {
|
||||
let dyn_call_viijiii = instance.func("dynCall_viijiii").ok();
|
||||
let dyn_call_viijj = instance.func("dynCall_viijj").ok();
|
||||
let dyn_call_vj = instance.func("dynCall_vj").ok();
|
||||
let dyn_call_vjji = instance.func("dynCall_vjji").ok();
|
||||
let dyn_call_vij = instance.func("dynCall_vij").ok();
|
||||
let dyn_call_viji = instance.func("dynCall_viji").ok();
|
||||
let dyn_call_vijiii = instance.func("dynCall_vijiii").ok();
|
||||
@ -261,6 +259,7 @@ impl<'a> EmscriptenData<'a> {
|
||||
dyn_call_viijiii,
|
||||
dyn_call_viijj,
|
||||
dyn_call_vj,
|
||||
dyn_call_vjji,
|
||||
dyn_call_vij,
|
||||
dyn_call_viji,
|
||||
dyn_call_vijiii,
|
||||
@ -282,6 +281,7 @@ pub fn run_emscripten_instance(
|
||||
instance: &mut Instance,
|
||||
path: &str,
|
||||
args: Vec<&str>,
|
||||
entrypoint: Option<String>,
|
||||
) -> CallResult<()> {
|
||||
let mut data = EmscriptenData::new(instance);
|
||||
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||
@ -299,52 +299,58 @@ pub fn run_emscripten_instance(
|
||||
|
||||
// println!("running emscripten instance");
|
||||
|
||||
let main_func = instance.dyn_func("_main")?;
|
||||
let num_params = main_func.signature().params().len();
|
||||
let _result = match num_params {
|
||||
2 => {
|
||||
let (argc, argv) = store_module_arguments(instance.context_mut(), path, args);
|
||||
instance.call("_main", &[Value::I32(argc as i32), Value::I32(argv as i32)])?;
|
||||
}
|
||||
0 => {
|
||||
instance.call("_main", &[])?;
|
||||
}
|
||||
_ => panic!(
|
||||
"The emscripten main function has received an incorrect number of params {}",
|
||||
num_params
|
||||
),
|
||||
};
|
||||
if let Some(ep) = entrypoint {
|
||||
debug!("Running entry point: {}", &ep);
|
||||
let arg = unsafe { allocate_cstr_on_stack(instance.context_mut(), args[0]).0 };
|
||||
//let (argc, argv) = store_module_arguments(instance.context_mut(), args);
|
||||
instance.call(&ep, &[Value::I32(arg as i32)])?;
|
||||
} else {
|
||||
let main_func = instance.dyn_func("_main")?;
|
||||
let num_params = main_func.signature().params().len();
|
||||
let _result = match num_params {
|
||||
2 => {
|
||||
let mut new_args = vec![path];
|
||||
new_args.extend(args);
|
||||
let (argc, argv) = store_module_arguments(instance.context_mut(), new_args);
|
||||
instance.call("_main", &[Value::I32(argc as i32), Value::I32(argv as i32)])?;
|
||||
}
|
||||
0 => {
|
||||
instance.call("_main", &[])?;
|
||||
}
|
||||
_ => panic!(
|
||||
"The emscripten main function has received an incorrect number of params {}",
|
||||
num_params
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
// TODO atexit for emscripten
|
||||
// println!("{:?}", data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn store_module_arguments(ctx: &mut Ctx, path: &str, args: Vec<&str>) -> (u32, u32) {
|
||||
fn store_module_arguments(ctx: &mut Ctx, args: Vec<&str>) -> (u32, u32) {
|
||||
let argc = args.len() + 1;
|
||||
|
||||
let mut args_slice = vec![0; argc];
|
||||
args_slice[0] = unsafe { allocate_cstr_on_stack(ctx, path).0 };
|
||||
for (slot, arg) in args_slice[1..argc].iter_mut().zip(args.iter()) {
|
||||
for (slot, arg) in args_slice[0..argc].iter_mut().zip(args.iter()) {
|
||||
*slot = unsafe { allocate_cstr_on_stack(ctx, &arg).0 };
|
||||
}
|
||||
|
||||
let (argv_offset, argv_slice): (_, &mut [u32]) =
|
||||
unsafe { allocate_on_stack(ctx, ((argc + 1) * 4) as u32) };
|
||||
unsafe { allocate_on_stack(ctx, ((argc) * 4) as u32) };
|
||||
assert!(!argv_slice.is_empty());
|
||||
for (slot, arg) in argv_slice[0..argc].iter_mut().zip(args_slice.iter()) {
|
||||
*slot = *arg
|
||||
}
|
||||
argv_slice[argc] = 0;
|
||||
|
||||
(argc as u32, argv_offset)
|
||||
(argc as u32 - 1, argv_offset)
|
||||
}
|
||||
|
||||
pub fn emscripten_set_up_memory(memory: &Memory, globals: &EmscriptenGlobalsData) {
|
||||
let dynamictop_ptr = globals.dynamictop_ptr;
|
||||
let stack_max = globals.stack_max;
|
||||
|
||||
let dynamic_base = align_memory(stack_max);
|
||||
let dynamic_base = globals.dynamic_base;
|
||||
|
||||
memory.view::<u32>()[(dynamictop_ptr / 4) as usize].set(dynamic_base);
|
||||
}
|
||||
@ -355,6 +361,7 @@ pub struct EmscriptenGlobalsData {
|
||||
stacktop: u32,
|
||||
stack_max: u32,
|
||||
dynamictop_ptr: u32,
|
||||
dynamic_base: u32,
|
||||
memory_base: u32,
|
||||
table_base: u32,
|
||||
temp_double_ptr: u32,
|
||||
@ -424,7 +431,14 @@ impl EmscriptenGlobals {
|
||||
let temp_double_ptr = static_top;
|
||||
static_top += 16;
|
||||
|
||||
let dynamictop_ptr = static_alloc(&mut static_top, 4);
|
||||
let (dynamic_base, dynamictop_ptr) =
|
||||
get_emscripten_metadata(&module).unwrap_or_else(|| {
|
||||
let dynamictop_ptr = static_alloc(&mut static_top, 4);
|
||||
(
|
||||
align_memory(align_memory(static_top) + TOTAL_STACK),
|
||||
dynamictop_ptr,
|
||||
)
|
||||
});
|
||||
|
||||
let stacktop = align_memory(static_top);
|
||||
let stack_max = stacktop + TOTAL_STACK;
|
||||
@ -434,6 +448,7 @@ impl EmscriptenGlobals {
|
||||
stacktop,
|
||||
stack_max,
|
||||
dynamictop_ptr,
|
||||
dynamic_base,
|
||||
memory_base,
|
||||
table_base,
|
||||
temp_double_ptr,
|
||||
@ -597,6 +612,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"___syscall272" => func!(crate::syscalls::___syscall272),
|
||||
"___syscall295" => func!(crate::syscalls::___syscall295),
|
||||
"___syscall300" => func!(crate::syscalls::___syscall300),
|
||||
"___syscall320" => func!(crate::syscalls::___syscall320),
|
||||
"___syscall324" => func!(crate::syscalls::___syscall324),
|
||||
"___syscall330" => func!(crate::syscalls::___syscall330),
|
||||
"___syscall334" => func!(crate::syscalls::___syscall334),
|
||||
@ -619,6 +635,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"_llvm_eh_typeid_for" => func!(crate::process::_llvm_eh_typeid_for),
|
||||
"_raise" => func!(crate::process::_raise),
|
||||
"_sem_init" => func!(crate::process::_sem_init),
|
||||
"_sem_destroy" => func!(crate::process::_sem_destroy),
|
||||
"_sem_post" => func!(crate::process::_sem_post),
|
||||
"_sem_wait" => func!(crate::process::_sem_wait),
|
||||
"_getgrent" => func!(crate::process::_getgrent),
|
||||
@ -646,6 +663,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"_emscripten_get_heap_size" => func!(crate::memory::_emscripten_get_heap_size),
|
||||
"_emscripten_resize_heap" => func!(crate::memory::_emscripten_resize_heap),
|
||||
"enlargeMemory" => func!(crate::memory::enlarge_memory),
|
||||
"segfault" => func!(crate::memory::segfault),
|
||||
"alignfault" => func!(crate::memory::alignfault),
|
||||
"ftfault" => func!(crate::memory::ftfault),
|
||||
"getTotalMemory" => func!(crate::memory::get_total_memory),
|
||||
"___map_file" => func!(crate::memory::___map_file),
|
||||
|
||||
@ -655,6 +675,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"___cxa_begin_catch" => func!(crate::exception::___cxa_begin_catch),
|
||||
"___cxa_end_catch" => func!(crate::exception::___cxa_end_catch),
|
||||
"___cxa_uncaught_exception" => func!(crate::exception::___cxa_uncaught_exception),
|
||||
"___cxa_pure_virtual" => func!(crate::exception::___cxa_pure_virtual),
|
||||
|
||||
// Time
|
||||
"_gettimeofday" => func!(crate::time::_gettimeofday),
|
||||
@ -683,6 +704,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"_llvm_cos_f64" => func!(crate::math::_llvm_cos_f64),
|
||||
"_llvm_exp2_f32" => func!(crate::math::_llvm_exp2_f32),
|
||||
"_llvm_exp2_f64" => func!(crate::math::_llvm_exp2_f64),
|
||||
"_llvm_trunc_f64" => func!(crate::math::_llvm_trunc_f64),
|
||||
"_emscripten_random" => func!(crate::math::_emscripten_random),
|
||||
|
||||
// Jump
|
||||
@ -701,6 +723,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"_dlsym" => func!(crate::linking::_dlsym),
|
||||
|
||||
// wasm32-unknown-emscripten
|
||||
"_atexit" => func!(crate::emscripten_target::_atexit),
|
||||
"setTempRet0" => func!(crate::emscripten_target::setTempRet0),
|
||||
"getTempRet0" => func!(crate::emscripten_target::getTempRet0),
|
||||
"invoke_i" => func!(crate::emscripten_target::invoke_i),
|
||||
@ -711,6 +734,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"invoke_v" => func!(crate::emscripten_target::invoke_v),
|
||||
"invoke_vi" => func!(crate::emscripten_target::invoke_vi),
|
||||
"invoke_vj" => func!(crate::emscripten_target::invoke_vj),
|
||||
"invoke_vjji" => func!(crate::emscripten_target::invoke_vjji),
|
||||
"invoke_vii" => func!(crate::emscripten_target::invoke_vii),
|
||||
"invoke_viii" => func!(crate::emscripten_target::invoke_viii),
|
||||
"invoke_viiii" => func!(crate::emscripten_target::invoke_viiii),
|
||||
@ -723,10 +747,15 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"___resumeException" => func!(crate::emscripten_target::___resumeException),
|
||||
"_dladdr" => func!(crate::emscripten_target::_dladdr),
|
||||
"_pthread_create" => func!(crate::emscripten_target::_pthread_create),
|
||||
"_pthread_detach" => func!(crate::emscripten_target::_pthread_detach),
|
||||
"_pthread_join" => func!(crate::emscripten_target::_pthread_join),
|
||||
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
|
||||
"_pthread_attr_init" => func!(crate::emscripten_target::_pthread_attr_init),
|
||||
"_pthread_attr_destroy" => func!(crate::emscripten_target::_pthread_attr_destroy),
|
||||
"_pthread_attr_getstack" => func!(crate::emscripten_target::_pthread_attr_getstack),
|
||||
"_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init),
|
||||
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
|
||||
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
|
||||
"_pthread_cond_timedwait" => func!(crate::emscripten_target::_pthread_cond_timedwait),
|
||||
"_pthread_cond_wait" => func!(crate::emscripten_target::_pthread_cond_wait),
|
||||
"_pthread_condattr_destroy" => func!(crate::emscripten_target::_pthread_condattr_destroy),
|
||||
"_pthread_condattr_init" => func!(crate::emscripten_target::_pthread_condattr_init),
|
||||
@ -740,6 +769,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
|
||||
"_pthread_setcancelstate" => func!(crate::emscripten_target::_pthread_setcancelstate),
|
||||
"_pthread_getspecific" => func!(crate::emscripten_target::_pthread_getspecific),
|
||||
"_pthread_getattr_np" => func!(crate::emscripten_target::_pthread_getattr_np),
|
||||
"_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific),
|
||||
"_pthread_once" => func!(crate::emscripten_target::_pthread_once),
|
||||
"_pthread_key_create" => func!(crate::emscripten_target::_pthread_key_create),
|
||||
|
@ -44,6 +44,11 @@ pub fn _llvm_exp2_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||
2f64.powf(value)
|
||||
}
|
||||
|
||||
pub fn _llvm_trunc_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||
debug!("emscripten::_llvm_trunc_f64");
|
||||
value.trunc()
|
||||
}
|
||||
|
||||
pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 {
|
||||
debug!("emscripten::_emscripten_random");
|
||||
-1.0
|
||||
|
@ -21,8 +21,11 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u
|
||||
|
||||
/// emscripten: _emscripten_get_heap_size
|
||||
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
|
||||
debug!("emscripten::_emscripten_get_heap_size",);
|
||||
ctx.memory(0).size().bytes().0 as u32
|
||||
debug!("emscripten::_emscripten_get_heap_size");
|
||||
let result = ctx.memory(0).size().bytes().0 as u32;
|
||||
debug!("=> {}", result);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// From emscripten implementation
|
||||
@ -95,6 +98,24 @@ pub fn abort_on_cannot_grow_memory_old(ctx: &mut Ctx) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
/// emscripten: segfault
|
||||
pub fn segfault(ctx: &mut Ctx) {
|
||||
debug!("emscripten::segfault");
|
||||
abort_with_message(ctx, "segmentation fault");
|
||||
}
|
||||
|
||||
/// emscripten: alignfault
|
||||
pub fn alignfault(ctx: &mut Ctx) {
|
||||
debug!("emscripten::alignfault");
|
||||
abort_with_message(ctx, "alignment fault");
|
||||
}
|
||||
|
||||
/// emscripten: ftfault
|
||||
pub fn ftfault(ctx: &mut Ctx) {
|
||||
debug!("emscripten::ftfault");
|
||||
abort_with_message(ctx, "Function table mask error");
|
||||
}
|
||||
|
||||
/// emscripten: ___map_file
|
||||
pub fn ___map_file(_ctx: &mut Ctx, _one: u32, _two: u32) -> c_int {
|
||||
debug!("emscripten::___map_file");
|
||||
|
@ -82,8 +82,13 @@ pub fn _raise(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
}
|
||||
|
||||
pub fn _sem_init(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
debug!("emscripten::_sem_init");
|
||||
-1
|
||||
debug!("emscripten::_sem_init: {}, {}, {}", _one, _two, _three);
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _sem_destroy(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_sem_destroy");
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _sem_post(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
@ -159,7 +164,7 @@ pub fn _system(_ctx: &mut Ctx, _one: i32) -> c_int {
|
||||
debug!("emscripten::_system");
|
||||
// TODO: May need to change this Em impl to a working version
|
||||
eprintln!("Can't call external programs");
|
||||
return EAGAIN;
|
||||
EAGAIN
|
||||
}
|
||||
|
||||
pub fn _popen(_ctx: &mut Ctx, _one: i32, _two: i32) -> c_int {
|
||||
|
@ -31,12 +31,13 @@ use libc::{
|
||||
off_t,
|
||||
// open,
|
||||
read,
|
||||
rename,
|
||||
// sockaddr_in,
|
||||
// readv,
|
||||
rmdir,
|
||||
// writev,
|
||||
stat,
|
||||
write,
|
||||
// sockaddr_in,
|
||||
};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
@ -118,9 +119,21 @@ pub fn ___syscall20(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
unsafe { getpid() }
|
||||
}
|
||||
|
||||
pub fn ___syscall38(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall38");
|
||||
-1
|
||||
// rename
|
||||
pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
debug!("emscripten::___syscall38 (rename)");
|
||||
let old_path_addr: u32 = varargs.get(ctx);
|
||||
let new_path_addr: u32 = varargs.get(ctx);
|
||||
let old_path = emscripten_memory_pointer!(ctx.memory(0), old_path_addr) as *const i8;
|
||||
let new_path = emscripten_memory_pointer!(ctx.memory(0), new_path_addr) as *const i8;
|
||||
let result = unsafe { rename(old_path, new_path) };
|
||||
debug!(
|
||||
"=> old_path: {}, new_path: {}, result: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(old_path).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(new_path).to_str().unwrap() },
|
||||
result
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
// rmdir
|
||||
@ -246,12 +259,21 @@ pub fn ___syscall192(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
if fd == -1 {
|
||||
let ptr = env::call_memalign(ctx, 16384, len);
|
||||
if ptr == 0 {
|
||||
return -1;
|
||||
// ENOMEM
|
||||
return -12;
|
||||
}
|
||||
let real_ptr = emscripten_memory_pointer!(ctx.memory(0), ptr) as *const u8;
|
||||
env::call_memset(ctx, ptr, 0, len);
|
||||
ptr as _
|
||||
for i in 0..(len as usize) {
|
||||
unsafe {
|
||||
assert_eq!(*real_ptr.add(i), 0);
|
||||
}
|
||||
}
|
||||
debug!("=> ptr: {}", ptr);
|
||||
return ptr as i32;
|
||||
} else {
|
||||
-1
|
||||
// return ENODEV
|
||||
return -19;
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,6 +483,12 @@ pub fn ___syscall300(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
-1
|
||||
}
|
||||
|
||||
// utimensat
|
||||
pub fn ___syscall320(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall320 (utimensat), {}", _which);
|
||||
0
|
||||
}
|
||||
|
||||
pub fn ___syscall334(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall334");
|
||||
-1
|
||||
|
@ -251,8 +251,9 @@ pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8;
|
||||
let result = unsafe { access(path, amode) };
|
||||
debug!(
|
||||
"=> path: {}, result: {}",
|
||||
"=> path: {}, amode: {}, result: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() },
|
||||
amode,
|
||||
result
|
||||
);
|
||||
result
|
||||
@ -354,8 +355,13 @@ pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
debug!("emscripten::___syscall54 (ioctl) {}", _which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let request: u32 = varargs.get(ctx);
|
||||
debug!("fd: {}, op: {}", fd, request);
|
||||
debug!("=> fd: {}, op: {}", fd, request);
|
||||
// Got the equivalents here: https://code.woboq.org/linux/linux/include/uapi/asm-generic/ioctls.h.html
|
||||
// let argp: u32 = varargs.get(ctx);
|
||||
// let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void;
|
||||
// let ret = unsafe { ioctl(fd, request as _, argp_ptr) };
|
||||
// debug!("=> {}", ret);
|
||||
// ret
|
||||
match request as _ {
|
||||
21537 => {
|
||||
// FIONBIO
|
||||
|
@ -28,7 +28,9 @@ use wasmer_runtime_core::vm::Ctx;
|
||||
use libc::{CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_REALTIME};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use libc::{CLOCK_MONOTONIC, CLOCK_REALTIME};
|
||||
use libc::CLOCK_REALTIME;
|
||||
#[cfg(target_os = "macos")]
|
||||
const CLOCK_MONOTONIC: clockid_t = 1;
|
||||
#[cfg(target_os = "macos")]
|
||||
const CLOCK_MONOTONIC_COARSE: clockid_t = 6;
|
||||
|
||||
@ -345,7 +347,7 @@ pub fn _strftime(
|
||||
// pad for null?
|
||||
let bytes = result_str.chars().count();
|
||||
if bytes as u32 > maxsize {
|
||||
return 0;
|
||||
0
|
||||
} else {
|
||||
// write output string
|
||||
for (i, c) in result_str.chars().enumerate() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use super::env;
|
||||
use super::env::get_emscripten_data;
|
||||
use crate::storage::align_memory;
|
||||
use libc::stat;
|
||||
use std::ffi::CStr;
|
||||
use std::mem::size_of;
|
||||
@ -39,6 +40,43 @@ pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option<Pages>) {
|
||||
(memory.minimum, memory.maximum)
|
||||
}
|
||||
|
||||
/// Reads values written by `-s EMIT_EMSCRIPTEN_METADATA=1`
|
||||
/// Assumes values start from the end in this order:
|
||||
/// Last export: Dynamic Base
|
||||
/// Second-to-Last export: Dynamic top pointer
|
||||
pub fn get_emscripten_metadata(module: &Module) -> Option<(u32, u32)> {
|
||||
let max_idx = &module.info().globals.iter().map(|(k, _)| k).max()?;
|
||||
let snd_max_idx = &module
|
||||
.info()
|
||||
.globals
|
||||
.iter()
|
||||
.map(|(k, _)| k)
|
||||
.filter(|k| k != max_idx)
|
||||
.max()?;
|
||||
|
||||
use wasmer_runtime_core::types::{GlobalInit, Initializer::Const, Value::I32};
|
||||
if let (
|
||||
GlobalInit {
|
||||
init: Const(I32(dynamic_base)),
|
||||
..
|
||||
},
|
||||
GlobalInit {
|
||||
init: Const(I32(dynamictop_ptr)),
|
||||
..
|
||||
},
|
||||
) = (
|
||||
&module.info().globals[*max_idx],
|
||||
&module.info().globals[*snd_max_idx],
|
||||
) {
|
||||
Some((
|
||||
align_memory(*dynamic_base as u32 - 32),
|
||||
align_memory(*dynamictop_ptr as u32 - 32),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn write_to_buf(ctx: &mut Ctx, string: *const c_char, buf: u32, max: u32) -> u32 {
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_char;
|
||||
|
||||
|
@ -53,6 +53,7 @@ macro_rules! assert_emscripten_output {
|
||||
&mut instance,
|
||||
$name,
|
||||
$args,
|
||||
None,
|
||||
).expect("run_emscripten_instance finishes");
|
||||
|
||||
let output = capturer.end().unwrap().0;
|
||||
|
@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "wasmer-llvm-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
authors = ["Lachlan Sneff <lachlan.sneff@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm7-0" }
|
||||
wasmparser = "0.28.0"
|
||||
wasmparser = "0.29.2"
|
||||
hashbrown = "0.1.8"
|
||||
smallvec = "0.6.8"
|
||||
goblin = "0.0.20"
|
||||
|
@ -298,7 +298,7 @@ impl LLVMBackend {
|
||||
let callbacks = get_callbacks();
|
||||
let mut module: *mut LLVMModule = ptr::null_mut();
|
||||
|
||||
let slice = unsafe { memory.as_slice() };
|
||||
let slice = memory.as_slice();
|
||||
|
||||
let res = module_load(slice.as_ptr(), slice.len(), callbacks, &mut module);
|
||||
|
||||
@ -308,7 +308,7 @@ impl LLVMBackend {
|
||||
|
||||
static SIGNAL_HANDLER_INSTALLED: Once = Once::new();
|
||||
|
||||
SIGNAL_HANDLER_INSTALLED.call_once(|| unsafe {
|
||||
SIGNAL_HANDLER_INSTALLED.call_once(|| {
|
||||
crate::platform::install_signal_handler();
|
||||
});
|
||||
|
||||
|
@ -1468,7 +1468,7 @@ fn parse_function(
|
||||
context,
|
||||
&function,
|
||||
-2147483904.0,
|
||||
2147483648.0,
|
||||
2_147_483_648.0,
|
||||
v1,
|
||||
);
|
||||
let res =
|
||||
@ -1482,8 +1482,8 @@ fn parse_function(
|
||||
intrinsics,
|
||||
context,
|
||||
&function,
|
||||
-2147483649.0,
|
||||
2147483648.0,
|
||||
-2_147_483_649.0,
|
||||
2_147_483_648.0,
|
||||
v1,
|
||||
);
|
||||
let res =
|
||||
@ -1503,8 +1503,8 @@ fn parse_function(
|
||||
intrinsics,
|
||||
context,
|
||||
&function,
|
||||
-9223373136366403584.0,
|
||||
9223372036854775808.0,
|
||||
-9_223_373_136_366_403_584.0,
|
||||
9_223_372_036_854_775_808.0,
|
||||
v1,
|
||||
);
|
||||
let res =
|
||||
|
11
lib/middleware-common/Cargo.toml
Normal file
11
lib/middleware-common/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "wasmer-middleware-common"
|
||||
version = "0.4.1"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
description = "Wasmer runtime common middlewares"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
27
lib/middleware-common/src/call_trace.rs
Normal file
27
lib/middleware-common/src/call_trace.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use wasmer_runtime_core::{
|
||||
codegen::{Event, EventSink, FunctionMiddleware, InternalEvent},
|
||||
module::ModuleInfo,
|
||||
};
|
||||
|
||||
pub struct CallTrace;
|
||||
|
||||
impl FunctionMiddleware for CallTrace {
|
||||
type Error = String;
|
||||
fn feed_event<'a, 'b: 'a>(
|
||||
&mut self,
|
||||
op: Event<'a, 'b>,
|
||||
module_info: &ModuleInfo,
|
||||
sink: &mut EventSink<'a, 'b>,
|
||||
) -> Result<(), Self::Error> {
|
||||
match op {
|
||||
Event::Internal(InternalEvent::FunctionBegin(id)) => sink.push(Event::Internal(
|
||||
InternalEvent::Breakpoint(Box::new(move |_| {
|
||||
eprintln!("func ({})", id);
|
||||
})),
|
||||
)),
|
||||
_ => {}
|
||||
}
|
||||
sink.push(op);
|
||||
Ok(())
|
||||
}
|
||||
}
|
1
lib/middleware-common/src/lib.rs
Normal file
1
lib/middleware-common/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod call_trace;
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime-abi"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime core library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -13,7 +13,7 @@ wasmer-runtime-core = { path = "../runtime-core" }
|
||||
hashbrown = "0.1"
|
||||
failure = "0.1"
|
||||
tar = "0.4"
|
||||
wasmparser = "0.23.0"
|
||||
wasmparser = "0.29.2"
|
||||
zstd = "0.4"
|
||||
|
||||
[target.'cfg(unix)'.dependencies.zbox]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime-c-api"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer C API library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -16,11 +16,11 @@ libc = "0.2"
|
||||
|
||||
[dependencies.wasmer-runtime]
|
||||
path = "../runtime"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[dependencies.wasmer-runtime-core]
|
||||
path = "../runtime-core"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[features]
|
||||
debug = ["wasmer-runtime/debug"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime-core"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime core library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
|
255
lib/runtime-core/src/codegen.rs
Normal file
255
lib/runtime-core/src/codegen.rs
Normal file
@ -0,0 +1,255 @@
|
||||
use crate::{
|
||||
backend::RunnableModule,
|
||||
backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token},
|
||||
cache::{Artifact, Error as CacheError},
|
||||
error::{CompileError, CompileResult},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
structures::Map,
|
||||
types::{FuncIndex, FuncSig, SigIndex},
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use wasmparser::{Operator, Type as WpType};
|
||||
|
||||
pub enum Event<'a, 'b> {
|
||||
Internal(InternalEvent),
|
||||
Wasm(&'b Operator<'a>),
|
||||
}
|
||||
|
||||
pub enum InternalEvent {
|
||||
FunctionBegin(u32),
|
||||
FunctionEnd,
|
||||
Breakpoint(Box<Fn(BkptInfo) + Send + Sync + 'static>),
|
||||
SetInternal(u32),
|
||||
GetInternal(u32),
|
||||
}
|
||||
|
||||
pub struct BkptInfo {}
|
||||
|
||||
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
|
||||
fn new() -> Self;
|
||||
fn backend_id() -> Backend;
|
||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
||||
|
||||
/// Creates a new function and returns the function-scope code generator for it.
|
||||
fn next_function(&mut self) -> Result<&mut FCG, E>;
|
||||
fn finalize(self, module_info: &ModuleInfo) -> Result<RM, E>;
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||
|
||||
/// Sets function signatures.
|
||||
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
||||
|
||||
/// Adds an import function.
|
||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||
}
|
||||
|
||||
pub struct StreamingCompiler<
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
RM: RunnableModule + 'static,
|
||||
E: Debug,
|
||||
CGEN: Fn() -> MiddlewareChain,
|
||||
> {
|
||||
middleware_chain_generator: CGEN,
|
||||
_phantom_mcg: PhantomData<MCG>,
|
||||
_phantom_fcg: PhantomData<FCG>,
|
||||
_phantom_rm: PhantomData<RM>,
|
||||
_phantom_e: PhantomData<E>,
|
||||
}
|
||||
|
||||
pub struct SimpleStreamingCompilerGen<
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
RM: RunnableModule + 'static,
|
||||
E: Debug,
|
||||
> {
|
||||
_phantom_mcg: PhantomData<MCG>,
|
||||
_phantom_fcg: PhantomData<FCG>,
|
||||
_phantom_rm: PhantomData<RM>,
|
||||
_phantom_e: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
RM: RunnableModule + 'static,
|
||||
E: Debug,
|
||||
> SimpleStreamingCompilerGen<MCG, FCG, RM, E>
|
||||
{
|
||||
pub fn new() -> StreamingCompiler<MCG, FCG, RM, E, impl Fn() -> MiddlewareChain> {
|
||||
StreamingCompiler::new(|| MiddlewareChain::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
RM: RunnableModule + 'static,
|
||||
E: Debug,
|
||||
CGEN: Fn() -> MiddlewareChain,
|
||||
> StreamingCompiler<MCG, FCG, RM, E, CGEN>
|
||||
{
|
||||
pub fn new(chain_gen: CGEN) -> Self {
|
||||
Self {
|
||||
middleware_chain_generator: chain_gen,
|
||||
_phantom_mcg: PhantomData,
|
||||
_phantom_fcg: PhantomData,
|
||||
_phantom_rm: PhantomData,
|
||||
_phantom_e: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
RM: RunnableModule + 'static,
|
||||
E: Debug,
|
||||
CGEN: Fn() -> MiddlewareChain,
|
||||
> Compiler for StreamingCompiler<MCG, FCG, RM, E, CGEN>
|
||||
{
|
||||
fn compile(
|
||||
&self,
|
||||
wasm: &[u8],
|
||||
compiler_config: CompilerConfig,
|
||||
_: Token,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
struct Placeholder;
|
||||
impl CacheGen for Placeholder {
|
||||
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError> {
|
||||
Err(CacheError::Unknown(
|
||||
"the streaming compiler API doesn't support caching yet".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
let mut mcg = MCG::new();
|
||||
let mut chain = (self.middleware_chain_generator)();
|
||||
let info = crate::parse::read_module(
|
||||
wasm,
|
||||
MCG::backend_id(),
|
||||
&mut mcg,
|
||||
&mut chain,
|
||||
&compiler_config,
|
||||
)?;
|
||||
let exec_context = mcg
|
||||
.finalize(&info)
|
||||
.map_err(|x| CompileError::InternalError {
|
||||
msg: format!("{:?}", x),
|
||||
})?;
|
||||
Ok(ModuleInner {
|
||||
cache_gen: Box::new(Placeholder),
|
||||
runnable_module: Box::new(exec_context),
|
||||
info: info,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
Err(CacheError::Unknown(
|
||||
"the streaming compiler API doesn't support caching yet".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventSink<'a, 'b> {
|
||||
buffer: SmallVec<[Event<'a, 'b>; 2]>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> EventSink<'a, 'b> {
|
||||
pub fn push(&mut self, ev: Event<'a, 'b>) {
|
||||
self.buffer.push(ev);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MiddlewareChain {
|
||||
chain: Vec<Box<GenericFunctionMiddleware>>,
|
||||
}
|
||||
|
||||
impl MiddlewareChain {
|
||||
pub fn new() -> MiddlewareChain {
|
||||
MiddlewareChain { chain: vec![] }
|
||||
}
|
||||
|
||||
pub fn push<M: FunctionMiddleware + 'static>(&mut self, m: M) {
|
||||
self.chain.push(Box::new(m));
|
||||
}
|
||||
|
||||
pub(crate) fn run<E: Debug, FCG: FunctionCodeGenerator<E>>(
|
||||
&mut self,
|
||||
fcg: Option<&mut FCG>,
|
||||
ev: Event,
|
||||
module_info: &ModuleInfo,
|
||||
) -> Result<(), String> {
|
||||
let mut sink = EventSink {
|
||||
buffer: SmallVec::new(),
|
||||
};
|
||||
sink.push(ev);
|
||||
for m in &mut self.chain {
|
||||
let prev: SmallVec<[Event; 2]> = sink.buffer.drain().collect();
|
||||
for ev in prev {
|
||||
m.feed_event(ev, module_info, &mut sink)?;
|
||||
}
|
||||
}
|
||||
if let Some(fcg) = fcg {
|
||||
for ev in sink.buffer {
|
||||
fcg.feed_event(ev, module_info)
|
||||
.map_err(|x| format!("{:?}", x))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FunctionMiddleware {
|
||||
type Error: Debug;
|
||||
fn feed_event<'a, 'b: 'a>(
|
||||
&mut self,
|
||||
op: Event<'a, 'b>,
|
||||
module_info: &ModuleInfo,
|
||||
sink: &mut EventSink<'a, 'b>,
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
pub(crate) trait GenericFunctionMiddleware {
|
||||
fn feed_event<'a, 'b: 'a>(
|
||||
&mut self,
|
||||
op: Event<'a, 'b>,
|
||||
module_info: &ModuleInfo,
|
||||
sink: &mut EventSink<'a, 'b>,
|
||||
) -> Result<(), String>;
|
||||
}
|
||||
|
||||
impl<E: Debug, T: FunctionMiddleware<Error = E>> GenericFunctionMiddleware for T {
|
||||
fn feed_event<'a, 'b: 'a>(
|
||||
&mut self,
|
||||
op: Event<'a, 'b>,
|
||||
module_info: &ModuleInfo,
|
||||
sink: &mut EventSink<'a, 'b>,
|
||||
) -> Result<(), String> {
|
||||
<Self as FunctionMiddleware>::feed_event(self, op, module_info, sink)
|
||||
.map_err(|x| format!("{:?}", x))
|
||||
}
|
||||
}
|
||||
|
||||
/// The function-scope code generator trait.
|
||||
pub trait FunctionCodeGenerator<E: Debug> {
|
||||
/// Sets the return type.
|
||||
fn feed_return(&mut self, ty: WpType) -> Result<(), E>;
|
||||
|
||||
/// Adds a parameter to the function.
|
||||
fn feed_param(&mut self, ty: WpType) -> Result<(), E>;
|
||||
|
||||
/// Adds `n` locals to the function.
|
||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), E>;
|
||||
|
||||
/// Called before the first call to `feed_opcode`.
|
||||
fn begin_body(&mut self) -> Result<(), E>;
|
||||
|
||||
/// Called for each operator.
|
||||
fn feed_event(&mut self, op: Event, module_info: &ModuleInfo) -> Result<(), E>;
|
||||
|
||||
/// Finalizes the function.
|
||||
fn finalize(&mut self) -> Result<(), E>;
|
||||
}
|
@ -657,10 +657,3 @@ impl<'a> DynFunc<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl Instance {
|
||||
pub fn memory_offset_addr(&self, _: u32, _: usize) -> *const u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ pub mod backend;
|
||||
mod backing;
|
||||
|
||||
pub mod cache;
|
||||
pub mod codegen;
|
||||
pub mod error;
|
||||
pub mod export;
|
||||
pub mod global;
|
||||
@ -21,6 +22,7 @@ pub mod import;
|
||||
pub mod instance;
|
||||
pub mod memory;
|
||||
pub mod module;
|
||||
pub mod parse;
|
||||
mod sig_registry;
|
||||
pub mod structures;
|
||||
mod sys;
|
||||
|
@ -52,6 +52,7 @@ macro_rules! intcast {
|
||||
}
|
||||
intcast! { u8 i8 u16 i16 u32 i32 u64 i64 }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Atomic<T> {
|
||||
v: UnsafeCell<Wrapping<T>>,
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::codegen::{CodegenError, FunctionCodeGenerator, ModuleCodeGenerator};
|
||||
use hashbrown::HashMap;
|
||||
use wasmer_runtime_core::{
|
||||
use crate::codegen::*;
|
||||
use crate::{
|
||||
backend::{Backend, CompilerConfig, RunnableModule},
|
||||
error::CompileError,
|
||||
module::{
|
||||
DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder,
|
||||
TableInitializer,
|
||||
@ -14,16 +14,25 @@ use wasmer_runtime_core::{
|
||||
},
|
||||
units::Pages,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use wasmparser::{
|
||||
BinaryReaderError, Data, DataKind, Element, ElementKind, Export, ExternalKind, FuncType,
|
||||
Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, SectionCode, Type as WpType,
|
||||
BinaryReaderError, ExternalKind, FuncType, ImportSectionEntryType, Operator, Type as WpType,
|
||||
WasmDecoder,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoadError {
|
||||
Parse(BinaryReaderError),
|
||||
Codegen(CodegenError),
|
||||
Codegen(String),
|
||||
}
|
||||
|
||||
impl From<LoadError> for CompileError {
|
||||
fn from(other: LoadError) -> CompileError {
|
||||
CompileError::InternalError {
|
||||
msg: format!("{:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BinaryReaderError> for LoadError {
|
||||
@ -32,20 +41,16 @@ impl From<BinaryReaderError> for LoadError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodegenError> for LoadError {
|
||||
fn from(other: CodegenError) -> LoadError {
|
||||
LoadError::Codegen(other)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_module<
|
||||
MCG: ModuleCodeGenerator<FCG, RM>,
|
||||
FCG: FunctionCodeGenerator,
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
RM: RunnableModule,
|
||||
E: Debug,
|
||||
>(
|
||||
wasm: &[u8],
|
||||
backend: Backend,
|
||||
mcg: &mut MCG,
|
||||
middlewares: &mut MiddlewareChain,
|
||||
compiler_config: &CompilerConfig,
|
||||
) -> Result<ModuleInfo, LoadError> {
|
||||
let mut info = ModuleInfo {
|
||||
@ -116,7 +121,8 @@ pub fn read_module<
|
||||
let sigindex = SigIndex::new(sigindex as usize);
|
||||
info.imported_functions.push(import_name);
|
||||
info.func_assoc.push(sigindex);
|
||||
mcg.feed_import_function()?;
|
||||
mcg.feed_import_function()
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
ImportSectionEntryType::Table(table_ty) => {
|
||||
assert_eq!(table_ty.element_type, WpType::AnyFunc);
|
||||
@ -186,12 +192,25 @@ pub fn read_module<
|
||||
if func_count == 0 {
|
||||
info.namespace_table = namespace_builder.take().unwrap().finish();
|
||||
info.name_table = name_builder.take().unwrap().finish();
|
||||
mcg.feed_signatures(info.signatures.clone())?;
|
||||
mcg.feed_function_signatures(info.func_assoc.clone())?;
|
||||
mcg.check_precondition(&info)?;
|
||||
mcg.feed_signatures(info.signatures.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.feed_function_signatures(info.func_assoc.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.check_precondition(&info)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
|
||||
let fcg = mcg.next_function()?;
|
||||
let fcg = mcg
|
||||
.next_function()
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
middlewares
|
||||
.run(
|
||||
Some(fcg),
|
||||
Event::Internal(InternalEvent::FunctionBegin(id as u32)),
|
||||
&info,
|
||||
)
|
||||
.map_err(|x| LoadError::Codegen(x))?;
|
||||
|
||||
let sig = info
|
||||
.signatures
|
||||
.get(
|
||||
@ -202,10 +221,12 @@ pub fn read_module<
|
||||
)
|
||||
.unwrap();
|
||||
for ret in sig.returns() {
|
||||
fcg.feed_return(type_to_wp_type(*ret))?;
|
||||
fcg.feed_return(type_to_wp_type(*ret))
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
for param in sig.params() {
|
||||
fcg.feed_param(type_to_wp_type(*param))?;
|
||||
fcg.feed_param(type_to_wp_type(*param))
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
|
||||
let mut body_begun = false;
|
||||
@ -216,21 +237,33 @@ pub fn read_module<
|
||||
ParserState::Error(err) => return Err(LoadError::Parse(err)),
|
||||
ParserState::FunctionBodyLocals { ref locals } => {
|
||||
for &(count, ty) in locals.iter() {
|
||||
fcg.feed_local(ty, count as usize)?;
|
||||
fcg.feed_local(ty, count as usize)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
}
|
||||
ParserState::CodeOperator(ref op) => {
|
||||
if !body_begun {
|
||||
body_begun = true;
|
||||
fcg.begin_body()?;
|
||||
fcg.begin_body()
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
fcg.feed_opcode(op, &info)?;
|
||||
middlewares
|
||||
.run(Some(fcg), Event::Wasm(op), &info)
|
||||
.map_err(|x| LoadError::Codegen(x))?;
|
||||
}
|
||||
ParserState::EndFunctionBody => break,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fcg.finalize()?;
|
||||
middlewares
|
||||
.run(
|
||||
Some(fcg),
|
||||
Event::Internal(InternalEvent::FunctionEnd),
|
||||
&info,
|
||||
)
|
||||
.map_err(|x| LoadError::Codegen(x))?;
|
||||
fcg.finalize()
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
ParserState::BeginActiveElementSectionEntry(table_index) => {
|
||||
let table_index = TableIndex::new(table_index as usize);
|
||||
@ -281,7 +314,7 @@ pub fn read_module<
|
||||
base = Some(eval_init_expr(op)?)
|
||||
}
|
||||
ParserState::DataSectionEntryBodyChunk(chunk) => {
|
||||
data = chunk.to_vec();
|
||||
data.extend_from_slice(chunk);
|
||||
}
|
||||
ParserState::BeginInitExpressionBody
|
||||
| ParserState::EndInitExpressionBody => {}
|
@ -33,7 +33,13 @@ impl Memory {
|
||||
|
||||
let protect = protection.to_protect_const();
|
||||
|
||||
let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, protect) };
|
||||
let flags = if protection == Protect::None {
|
||||
MEM_RESERVE
|
||||
} else {
|
||||
MEM_RESERVE | MEM_COMMIT
|
||||
};
|
||||
|
||||
let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, flags, protect) };
|
||||
|
||||
if ptr.is_null() {
|
||||
Err("unable to allocate memory".to_string())
|
||||
@ -229,3 +235,25 @@ fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
|
||||
fn round_down_to_page_size(size: usize, page_size: usize) -> usize {
|
||||
size & !(page_size - 1)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn clone() {
|
||||
// these should work
|
||||
let _ = Memory::with_size_protect(200_000, Protect::Read)
|
||||
.unwrap()
|
||||
.clone();
|
||||
let _ = Memory::with_size_protect(200_000, Protect::ReadWrite)
|
||||
.unwrap()
|
||||
.clone();
|
||||
let _ = Memory::with_size_protect(200_000, Protect::ReadExec)
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
// this would cause segmentation fault as uncommited memory with no access
|
||||
//let _ = Memory::with_size_protect(200_000, Protect::None).unwrap().clone();
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ pub trait LocalImport {
|
||||
macro_rules! define_map_index {
|
||||
($ty:ident) => {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct $ty (u32);
|
||||
impl TypedIndex for $ty {
|
||||
#[doc(hidden)]
|
||||
|
@ -22,7 +22,7 @@ pub struct Ctx {
|
||||
|
||||
local_backing: *mut LocalBacking,
|
||||
import_backing: *mut ImportBacking,
|
||||
pub(crate) module: *const ModuleInner,
|
||||
pub module: *const ModuleInner,
|
||||
|
||||
pub data: *mut c_void,
|
||||
pub data_finalizer: Option<fn(data: *mut c_void)>,
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,17 +9,17 @@ edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.3.0", optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.1", optional = true }
|
||||
lazy_static = "1.2.0"
|
||||
memmap = "0.7.0"
|
||||
|
||||
[dependencies.wasmer-runtime-core]
|
||||
path = "../runtime-core"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[dependencies.wasmer-clif-backend]
|
||||
path = "../clif-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-singlepass-backend"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
description = "Wasmer runtime single pass compiler backend"
|
||||
license = "MIT"
|
||||
@ -8,8 +8,8 @@ authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmparser = "0.28.0"
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
wasmparser = "0.29.2"
|
||||
dynasm = "0.3.1"
|
||||
dynasmrt = "0.3.1"
|
||||
lazy_static = "1.2.0"
|
||||
|
@ -1,51 +0,0 @@
|
||||
use wasmer_runtime_core::{
|
||||
backend::RunnableModule,
|
||||
module::ModuleInfo,
|
||||
structures::Map,
|
||||
types::{FuncIndex, FuncSig, SigIndex},
|
||||
};
|
||||
use wasmparser::{Operator, Type as WpType};
|
||||
|
||||
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator, RM: RunnableModule> {
|
||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), CodegenError>;
|
||||
|
||||
/// Creates a new function and returns the function-scope code generator for it.
|
||||
fn next_function(&mut self) -> Result<&mut FCG, CodegenError>;
|
||||
fn finalize(self, module_info: &ModuleInfo) -> Result<RM, CodegenError>;
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), CodegenError>;
|
||||
|
||||
/// Sets function signatures.
|
||||
fn feed_function_signatures(
|
||||
&mut self,
|
||||
assoc: Map<FuncIndex, SigIndex>,
|
||||
) -> Result<(), CodegenError>;
|
||||
|
||||
/// Adds an import function.
|
||||
fn feed_import_function(&mut self) -> Result<(), CodegenError>;
|
||||
}
|
||||
|
||||
/// The function-scope code generator trait.
|
||||
pub trait FunctionCodeGenerator {
|
||||
/// Sets the return type.
|
||||
fn feed_return(&mut self, ty: WpType) -> Result<(), CodegenError>;
|
||||
|
||||
/// Adds a parameter to the function.
|
||||
fn feed_param(&mut self, ty: WpType) -> Result<(), CodegenError>;
|
||||
|
||||
/// Adds `n` locals to the function.
|
||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError>;
|
||||
|
||||
/// Called before the first call to `feed_opcode`.
|
||||
fn begin_body(&mut self) -> Result<(), CodegenError>;
|
||||
|
||||
/// Called for each operator.
|
||||
fn feed_opcode(&mut self, op: &Operator, module_info: &ModuleInfo) -> Result<(), CodegenError>;
|
||||
|
||||
/// Finalizes the function.
|
||||
fn finalize(&mut self) -> Result<(), CodegenError>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CodegenError {
|
||||
pub message: &'static str,
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
#![allow(clippy::forget_copy)] // Used by dynasm.
|
||||
|
||||
use super::codegen::*;
|
||||
use crate::emitter_x64::*;
|
||||
use crate::machine::*;
|
||||
use crate::protect_unix;
|
||||
@ -11,7 +10,8 @@ use smallvec::SmallVec;
|
||||
use std::ptr::NonNull;
|
||||
use std::{any::Any, collections::HashMap, sync::Arc};
|
||||
use wasmer_runtime_core::{
|
||||
backend::RunnableModule,
|
||||
backend::{Backend, RunnableModule},
|
||||
codegen::*,
|
||||
memory::MemoryType,
|
||||
module::ModuleInfo,
|
||||
structures::{Map, TypedIndex},
|
||||
@ -135,6 +135,7 @@ pub struct X64FunctionCode {
|
||||
assembler: Option<Assembler>,
|
||||
function_labels: Option<HashMap<usize, (DynamicLabel, Option<AssemblyOffset>)>>,
|
||||
br_table_data: Option<Vec<Vec<usize>>>,
|
||||
breakpoints: Option<HashMap<AssemblyOffset, Box<Fn(BkptInfo) + Send + Sync + 'static>>>,
|
||||
returns: SmallVec<[WpType; 1]>,
|
||||
locals: Vec<Location>,
|
||||
num_params: usize,
|
||||
@ -160,6 +161,7 @@ pub struct X64ExecutionContext {
|
||||
function_pointers: Vec<FuncPtr>,
|
||||
signatures: Arc<Map<SigIndex, FuncSig>>,
|
||||
_br_table_data: Vec<Vec<usize>>,
|
||||
breakpoints: Arc<HashMap<usize, Box<Fn(BkptInfo) + Send + Sync + 'static>>>,
|
||||
func_import_count: usize,
|
||||
}
|
||||
|
||||
@ -209,12 +211,18 @@ impl RunnableModule for X64ExecutionContext {
|
||||
user_error: *mut Option<Box<dyn Any>>,
|
||||
num_params_plus_one: Option<NonNull<c_void>>,
|
||||
) -> bool {
|
||||
let rm: &Box<dyn RunnableModule> = &unsafe { &*(*ctx).module }.runnable_module;
|
||||
let execution_context = unsafe {
|
||||
::std::mem::transmute_copy::<&dyn RunnableModule, &X64ExecutionContext>(&&**rm)
|
||||
};
|
||||
let args = ::std::slice::from_raw_parts(
|
||||
args,
|
||||
num_params_plus_one.unwrap().as_ptr() as usize - 1,
|
||||
);
|
||||
let args_reverse: SmallVec<[u64; 8]> = args.iter().cloned().rev().collect();
|
||||
match protect_unix::call_protected(|| {
|
||||
protect_unix::BKPT_MAP
|
||||
.with(|x| x.borrow_mut().push(execution_context.breakpoints.clone()));
|
||||
let ret = match protect_unix::call_protected(|| {
|
||||
CONSTRUCT_STACK_AND_CALL_WASM(
|
||||
args_reverse.as_ptr(),
|
||||
args_reverse.as_ptr().offset(args_reverse.len() as isize),
|
||||
@ -235,7 +243,9 @@ impl RunnableModule for X64ExecutionContext {
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
protect_unix::BKPT_MAP.with(|x| x.borrow_mut().pop().unwrap());
|
||||
ret
|
||||
}
|
||||
|
||||
unsafe extern "C" fn dummy_trampoline(
|
||||
@ -262,8 +272,15 @@ impl RunnableModule for X64ExecutionContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl X64ModuleCodeGenerator {
|
||||
pub fn new() -> X64ModuleCodeGenerator {
|
||||
#[derive(Debug)]
|
||||
pub struct CodegenError {
|
||||
pub message: &'static str,
|
||||
}
|
||||
|
||||
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
for X64ModuleCodeGenerator
|
||||
{
|
||||
fn new() -> X64ModuleCodeGenerator {
|
||||
X64ModuleCodeGenerator {
|
||||
functions: vec![],
|
||||
signatures: None,
|
||||
@ -273,26 +290,31 @@ impl X64ModuleCodeGenerator {
|
||||
func_import_count: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCodeGenerator {
|
||||
fn backend_id() -> Backend {
|
||||
Backend::Singlepass
|
||||
}
|
||||
|
||||
fn check_precondition(&mut self, _module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> {
|
||||
let (mut assembler, mut function_labels, br_table_data) = match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
x.assembler.take().unwrap(),
|
||||
x.function_labels.take().unwrap(),
|
||||
x.br_table_data.take().unwrap(),
|
||||
),
|
||||
None => (
|
||||
self.assembler.take().unwrap(),
|
||||
self.function_labels.take().unwrap(),
|
||||
vec![],
|
||||
),
|
||||
};
|
||||
let (mut assembler, mut function_labels, br_table_data, breakpoints) =
|
||||
match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
x.assembler.take().unwrap(),
|
||||
x.function_labels.take().unwrap(),
|
||||
x.br_table_data.take().unwrap(),
|
||||
x.breakpoints.take().unwrap(),
|
||||
),
|
||||
None => (
|
||||
self.assembler.take().unwrap(),
|
||||
self.function_labels.take().unwrap(),
|
||||
vec![],
|
||||
HashMap::new(),
|
||||
),
|
||||
};
|
||||
let begin_offset = assembler.offset();
|
||||
let begin_label_info = function_labels
|
||||
.entry(self.functions.len() + self.func_import_count)
|
||||
@ -313,6 +335,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
|
||||
assembler: Some(assembler),
|
||||
function_labels: Some(function_labels),
|
||||
br_table_data: Some(br_table_data),
|
||||
breakpoints: Some(breakpoints),
|
||||
returns: smallvec![],
|
||||
locals: vec![],
|
||||
num_params: 0,
|
||||
@ -327,8 +350,12 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
|
||||
}
|
||||
|
||||
fn finalize(mut self, _: &ModuleInfo) -> Result<X64ExecutionContext, CodegenError> {
|
||||
let (assembler, mut br_table_data) = match self.functions.last_mut() {
|
||||
Some(x) => (x.assembler.take().unwrap(), x.br_table_data.take().unwrap()),
|
||||
let (assembler, mut br_table_data, breakpoints) = match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
x.assembler.take().unwrap(),
|
||||
x.br_table_data.take().unwrap(),
|
||||
x.breakpoints.take().unwrap(),
|
||||
),
|
||||
None => {
|
||||
return Err(CodegenError {
|
||||
message: "no function",
|
||||
@ -370,11 +397,19 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
|
||||
out_labels.push(FuncPtr(output.ptr(*offset) as _));
|
||||
}
|
||||
|
||||
let breakpoints: Arc<HashMap<_, _>> = Arc::new(
|
||||
breakpoints
|
||||
.into_iter()
|
||||
.map(|(offset, f)| (output.ptr(offset) as usize, f))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
Ok(X64ExecutionContext {
|
||||
code: output,
|
||||
functions: self.functions,
|
||||
signatures: self.signatures.as_ref().unwrap().clone(),
|
||||
_br_table_data: br_table_data,
|
||||
breakpoints: breakpoints,
|
||||
func_import_count: self.func_import_count,
|
||||
function_pointers: out_labels,
|
||||
})
|
||||
@ -1028,7 +1063,7 @@ impl X64FunctionCode {
|
||||
let mut call_movs: Vec<(Location, GPR)> = vec![];
|
||||
|
||||
// Prepare register & stack parameters.
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
for (i, param) in params.iter().enumerate().rev() {
|
||||
let loc = Machine::get_param_location(1 + i);
|
||||
match loc {
|
||||
Location::GPR(x) => {
|
||||
@ -1335,7 +1370,7 @@ impl X64FunctionCode {
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionCodeGenerator for X64FunctionCode {
|
||||
impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
fn feed_return(&mut self, ty: WpType) -> Result<(), CodegenError> {
|
||||
self.returns.push(ty);
|
||||
Ok(())
|
||||
@ -1361,6 +1396,8 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
||||
.machine
|
||||
.init_locals(a, self.num_locals, self.num_params);
|
||||
|
||||
a.emit_sub(Size::S64, Location::Imm32(32), Location::GPR(GPR::RSP)); // simulate "red zone" if not supported by the platform
|
||||
|
||||
self.control_stack.push(ControlFrame {
|
||||
label: a.get_label(),
|
||||
loop_like: false,
|
||||
@ -1377,30 +1414,33 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_opcode(&mut self, op: &Operator, module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
fn feed_event(&mut self, ev: Event, module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
//println!("{:?} {}", op, self.value_stack.len());
|
||||
let was_unreachable;
|
||||
|
||||
if self.unreachable_depth > 0 {
|
||||
was_unreachable = true;
|
||||
match *op {
|
||||
Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => {
|
||||
self.unreachable_depth += 1;
|
||||
}
|
||||
Operator::End => {
|
||||
self.unreachable_depth -= 1;
|
||||
}
|
||||
Operator::Else => {
|
||||
// We are in a reachable true branch
|
||||
if self.unreachable_depth == 1 {
|
||||
if let Some(IfElseState::If(_)) =
|
||||
self.control_stack.last().map(|x| x.if_else)
|
||||
{
|
||||
self.unreachable_depth -= 1;
|
||||
|
||||
if let Event::Wasm(op) = ev {
|
||||
match *op {
|
||||
Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => {
|
||||
self.unreachable_depth += 1;
|
||||
}
|
||||
Operator::End => {
|
||||
self.unreachable_depth -= 1;
|
||||
}
|
||||
Operator::Else => {
|
||||
// We are in a reachable true branch
|
||||
if self.unreachable_depth == 1 {
|
||||
if let Some(IfElseState::If(_)) =
|
||||
self.control_stack.last().map(|x| x.if_else)
|
||||
{
|
||||
self.unreachable_depth -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if self.unreachable_depth > 0 {
|
||||
return Ok(());
|
||||
@ -1410,6 +1450,24 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
||||
}
|
||||
|
||||
let a = self.assembler.as_mut().unwrap();
|
||||
|
||||
let op = match ev {
|
||||
Event::Wasm(x) => x,
|
||||
Event::Internal(x) => {
|
||||
match x {
|
||||
InternalEvent::Breakpoint(callback) => {
|
||||
a.emit_bkpt();
|
||||
self.breakpoints
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(a.get_offset(), callback);
|
||||
}
|
||||
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
match *op {
|
||||
Operator::GetGlobal { global_index } => {
|
||||
let global_index = global_index as usize;
|
||||
|
@ -194,6 +194,8 @@ pub trait Emitter {
|
||||
fn emit_ret(&mut self);
|
||||
fn emit_call_label(&mut self, label: Self::Label);
|
||||
fn emit_call_location(&mut self, loc: Location);
|
||||
|
||||
fn emit_bkpt(&mut self);
|
||||
}
|
||||
|
||||
macro_rules! unop_gpr {
|
||||
@ -947,4 +949,8 @@ impl Emitter for Assembler {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_bkpt(&mut self) {
|
||||
dynasm!(self ; int 0x3);
|
||||
}
|
||||
}
|
||||
|
@ -18,74 +18,18 @@ extern crate byteorder;
|
||||
#[macro_use]
|
||||
extern crate smallvec;
|
||||
|
||||
mod codegen;
|
||||
mod codegen_x64;
|
||||
mod emitter_x64;
|
||||
mod machine;
|
||||
mod parse;
|
||||
mod protect_unix;
|
||||
|
||||
use crate::codegen::{CodegenError, ModuleCodeGenerator};
|
||||
use crate::parse::LoadError;
|
||||
use wasmer_runtime_core::{
|
||||
backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token},
|
||||
cache::{Artifact, Error as CacheError},
|
||||
error::{CompileError, CompileResult},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
};
|
||||
pub use codegen_x64::X64FunctionCode as FunctionCodeGenerator;
|
||||
pub use codegen_x64::X64ModuleCodeGenerator as ModuleCodeGenerator;
|
||||
|
||||
struct Placeholder;
|
||||
impl CacheGen for Placeholder {
|
||||
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError> {
|
||||
Err(CacheError::Unknown(
|
||||
"the singlepass backend doesn't support caching yet".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SinglePassCompiler {}
|
||||
impl SinglePassCompiler {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Compiler for SinglePassCompiler {
|
||||
fn compile(
|
||||
&self,
|
||||
wasm: &[u8],
|
||||
compiler_config: CompilerConfig,
|
||||
_: Token,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
let mut mcg = codegen_x64::X64ModuleCodeGenerator::new();
|
||||
let info = parse::read_module(wasm, Backend::Singlepass, &mut mcg, &compiler_config)?;
|
||||
let exec_context = mcg.finalize(&info)?;
|
||||
Ok(ModuleInner {
|
||||
cache_gen: Box::new(Placeholder),
|
||||
runnable_module: Box::new(exec_context),
|
||||
info: info,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
Err(CacheError::Unknown(
|
||||
"the singlepass backend doesn't support caching yet".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodegenError> for CompileError {
|
||||
fn from(other: CodegenError) -> CompileError {
|
||||
CompileError::InternalError {
|
||||
msg: other.message.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LoadError> for CompileError {
|
||||
fn from(other: LoadError) -> CompileError {
|
||||
CompileError::InternalError {
|
||||
msg: format!("{:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
||||
pub type SinglePassCompiler = SimpleStreamingCompilerGen<
|
||||
codegen_x64::X64ModuleCodeGenerator,
|
||||
codegen_x64::X64FunctionCode,
|
||||
codegen_x64::X64ExecutionContext,
|
||||
codegen_x64::CodegenError,
|
||||
>;
|
||||
|
@ -12,11 +12,15 @@
|
||||
use libc::{c_int, c_void, siginfo_t};
|
||||
use nix::sys::signal::{
|
||||
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
||||
SIGTRAP,
|
||||
};
|
||||
use std::any::Any;
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::cell::{Cell, RefCell, UnsafeCell};
|
||||
use std::collections::HashMap;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Once;
|
||||
use wasmer_runtime_core::codegen::BkptInfo;
|
||||
use wasmer_runtime_core::typed_func::WasmTrapInfo;
|
||||
|
||||
extern "C" fn signal_trap_handler(
|
||||
@ -25,6 +29,20 @@ extern "C" fn signal_trap_handler(
|
||||
ucontext: *mut c_void,
|
||||
) {
|
||||
unsafe {
|
||||
match Signal::from_c_int(signum) {
|
||||
Ok(SIGTRAP) => {
|
||||
let (_, ip) = get_faulting_addr_and_ip(siginfo as _, ucontext);
|
||||
let bkpt_map = BKPT_MAP.with(|x| x.borrow().last().map(|x| x.clone()));
|
||||
if let Some(bkpt_map) = bkpt_map {
|
||||
if let Some(ref x) = bkpt_map.get(&(ip as usize)) {
|
||||
(x)(BkptInfo {});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
do_unwind(signum, siginfo as _, ucontext);
|
||||
}
|
||||
}
|
||||
@ -44,6 +62,7 @@ pub unsafe fn install_sighandler() {
|
||||
sigaction(SIGILL, &sa).unwrap();
|
||||
sigaction(SIGSEGV, &sa).unwrap();
|
||||
sigaction(SIGBUS, &sa).unwrap();
|
||||
sigaction(SIGTRAP, &sa).unwrap();
|
||||
}
|
||||
|
||||
const SETJMP_BUFFER_LEN: usize = 27;
|
||||
@ -54,6 +73,7 @@ thread_local! {
|
||||
pub static CAUGHT_ADDRESSES: Cell<(*const c_void, *const c_void)> = Cell::new((ptr::null(), ptr::null()));
|
||||
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
|
||||
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
|
||||
pub static BKPT_MAP: RefCell<Vec<Arc<HashMap<usize, Box<Fn(BkptInfo) + Send + Sync + 'static>>>>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
pub unsafe fn trigger_trap() -> ! {
|
||||
@ -91,7 +111,7 @@ pub fn call_protected<T>(f: impl FnOnce() -> T) -> Result<T, CallProtError> {
|
||||
// Ok(SIGSEGV) => "segmentation violation",
|
||||
// Ok(SIGBUS) => "bus error",
|
||||
// Err(_) => "error while getting the Signal",
|
||||
// _ => "unkown trapped signal",
|
||||
// _ => "unknown trapped signal",
|
||||
// };
|
||||
// // When the trap-handler is fully implemented, this will return more information.
|
||||
// Err(RuntimeError::Trap {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-spectests"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer spectests library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,10 +9,10 @@ edition = "2018"
|
||||
build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.3.0" }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.3.0", optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.3.0", optional = true }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.4.1" }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.4.1", optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.1", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.7.2"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-wasi"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime WASI implementation library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -8,7 +8,7 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
libc = "0.2.50"
|
||||
rand = "0.6.5"
|
||||
# wasmer-runtime-abi = { path = "../runtime-abi" }
|
||||
@ -16,8 +16,3 @@ hashbrown = "0.1.8"
|
||||
generational-arena = "0.2.2"
|
||||
log = "0.4.6"
|
||||
byteorder = "1.3.1"
|
||||
|
||||
[dependencies.zbox]
|
||||
git = "https://github.com/wasmerio/zbox"
|
||||
branch = "bundle-libsodium"
|
||||
features = ["libsodium-bundled"]
|
||||
|
@ -13,42 +13,35 @@ use std::{
|
||||
time::SystemTime,
|
||||
};
|
||||
use wasmer_runtime_core::debug;
|
||||
//use zbox::init_env as zbox_init_env;
|
||||
|
||||
pub const MAX_SYMLINKS: usize = 100;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WasiFile {
|
||||
#[allow(dead_code)]
|
||||
ZboxFile(zbox::File),
|
||||
HostFile(fs::File),
|
||||
}
|
||||
|
||||
impl Write for WasiFile {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.write(buf),
|
||||
WasiFile::HostFile(hf) => hf.write(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.flush(),
|
||||
WasiFile::HostFile(hf) => hf.flush(),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.write_all(buf),
|
||||
WasiFile::HostFile(hf) => hf.write_all(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.write_fmt(fmt),
|
||||
WasiFile::HostFile(hf) => hf.write_fmt(fmt),
|
||||
}
|
||||
}
|
||||
@ -57,28 +50,24 @@ impl Write for WasiFile {
|
||||
impl Read for WasiFile {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.read(buf),
|
||||
WasiFile::HostFile(hf) => hf.read(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.read_to_end(buf),
|
||||
WasiFile::HostFile(hf) => hf.read_to_end(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.read_to_string(buf),
|
||||
WasiFile::HostFile(hf) => hf.read_to_string(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.read_exact(buf),
|
||||
WasiFile::HostFile(hf) => hf.read_exact(buf),
|
||||
}
|
||||
}
|
||||
@ -87,7 +76,6 @@ impl Read for WasiFile {
|
||||
impl Seek for WasiFile {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
match self {
|
||||
WasiFile::ZboxFile(zbf) => zbf.seek(pos),
|
||||
WasiFile::HostFile(hf) => hf.seek(pos),
|
||||
}
|
||||
}
|
||||
@ -151,9 +139,11 @@ pub enum Kind {
|
||||
handle: WasiFile,
|
||||
},
|
||||
Dir {
|
||||
// parent directory
|
||||
/// parent directory
|
||||
parent: Option<Inode>,
|
||||
handle: WasiFile,
|
||||
// TODO: wrap it like WasiFile
|
||||
/// The path on the host system where the directory is located
|
||||
path: PathBuf,
|
||||
/// The entries of a directory are lazily filled.
|
||||
entries: HashMap<String, Inode>,
|
||||
},
|
||||
@ -253,11 +243,11 @@ impl WasiFs {
|
||||
);
|
||||
// TODO: think about this
|
||||
let default_rights = 0x1FFFFFFF; // all rights
|
||||
let cur_file: fs::File = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&canonical_file)
|
||||
.expect("Could not find file");
|
||||
let cur_file_metadata = cur_file
|
||||
/*let cur_file: fs::File = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&canonical_file)
|
||||
.expect("Could not find file");*/
|
||||
let cur_file_metadata = canonical_file
|
||||
.metadata()
|
||||
.expect("Could not get metadata for file");
|
||||
// return how deep we had to go to find a parent
|
||||
@ -295,18 +285,15 @@ impl WasiFs {
|
||||
let mid_dir_name = comp.as_os_str().to_string_lossy().to_string();
|
||||
|
||||
let default_rights = 0x1FFFFFFF; // all rights
|
||||
let cur_file: fs::File = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&cumulative_path)
|
||||
.expect("Could not find file");
|
||||
let mid_dir_metadata = cur_file
|
||||
let cur_dir = cumulative_path.clone();
|
||||
let mid_dir_metadata = cur_dir
|
||||
.metadata()
|
||||
.expect("Could not get metadata for intermediate file");
|
||||
|
||||
let kind = if mid_dir_metadata.is_dir() {
|
||||
Kind::Dir {
|
||||
parent: Some(cur_parent),
|
||||
handle: WasiFile::HostFile(cur_file),
|
||||
path: cur_dir.clone(),
|
||||
entries: Default::default(),
|
||||
}
|
||||
} else {
|
||||
@ -362,7 +349,7 @@ impl WasiFs {
|
||||
let kind = if cur_file_metadata.is_dir() {
|
||||
Kind::Dir {
|
||||
parent,
|
||||
handle: WasiFile::HostFile(cur_file),
|
||||
path: cur_dir.clone(),
|
||||
entries: Default::default(),
|
||||
}
|
||||
} else {
|
||||
|
@ -1284,16 +1284,13 @@ pub fn path_open(
|
||||
};
|
||||
// TODO: handle __WASI_O_TRUNC on directories
|
||||
|
||||
let cur_dir = wasi_try!(open_options
|
||||
.open(&cumulative_path)
|
||||
.map_err(|_| __WASI_EINVAL));
|
||||
|
||||
// TODO: refactor and reuse
|
||||
let cur_file_metadata = cur_dir.metadata().unwrap();
|
||||
let cur_file_metadata =
|
||||
wasi_try!(cumulative_path.metadata().map_err(|_| __WASI_EINVAL));
|
||||
let kind = if cur_file_metadata.is_dir() {
|
||||
Kind::Dir {
|
||||
parent: Some(cur_dir_inode),
|
||||
handle: WasiFile::HostFile(cur_dir),
|
||||
path: cumulative_path.clone(),
|
||||
entries: Default::default(),
|
||||
}
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-win-exception-handler"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
description = "Wasmer runtime exception handling for Windows"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -8,7 +8,7 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
|
||||
winapi = { version = "0.3", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
libc = "0.2.49"
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use cmake::Config;
|
||||
|
||||
fn main() {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use cmake::Config;
|
||||
let project_name = "exception_handling";
|
||||
let dst = Config::new(project_name).build();
|
||||
println!("cargo:rustc-link-search=native={}", dst.display());
|
||||
|
@ -5,6 +5,7 @@
|
||||
#define CALL_FIRST 1
|
||||
|
||||
__declspec(thread) jmp_buf jmpBuf;
|
||||
__declspec(thread) DWORD caughtExceptionCode;
|
||||
__declspec(thread) PVOID caughtExceptionAddress;
|
||||
__declspec(thread) DWORD64 caughtInstructionPointer;
|
||||
__declspec(thread) PVOID savedStackPointer;
|
||||
@ -25,6 +26,7 @@ static LONG WINAPI
|
||||
exceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) {
|
||||
EXCEPTION_RECORD* pExceptionRecord = ExceptionInfo->ExceptionRecord;
|
||||
PCONTEXT pCONTEXT = ExceptionInfo->ContextRecord;
|
||||
caughtExceptionCode = pExceptionRecord->ExceptionCode;
|
||||
caughtExceptionAddress = pExceptionRecord->ExceptionAddress;
|
||||
caughtInstructionPointer = pCONTEXT->Rip;
|
||||
if (alreadyHandlingException == TRUE) {
|
||||
@ -61,8 +63,9 @@ uint8_t callProtected(trampoline_t trampoline,
|
||||
}
|
||||
|
||||
// jmp jmp jmp!
|
||||
int signum = setjmp(jmpBuf);
|
||||
if (signum == 0) {
|
||||
int status = setjmp(jmpBuf);
|
||||
if (status == 0) // 0 means the original call
|
||||
{
|
||||
// save the stack pointer
|
||||
savedStackPointer = get_callee_frame_address();
|
||||
trampoline(ctx, func, param_vec, return_vec);
|
||||
@ -74,7 +77,7 @@ uint8_t callProtected(trampoline_t trampoline,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
out_result->code = (uint64_t)signum;
|
||||
out_result->code = (uint64_t)caughtExceptionCode;
|
||||
out_result->exception_address = (uint64_t)caughtExceptionAddress;
|
||||
out_result->instruction_pointer = caughtInstructionPointer;
|
||||
|
||||
@ -83,4 +86,4 @@ uint8_t callProtected(trampoline_t trampoline,
|
||||
|
||||
removeExceptionHandler();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
BIN
media/wizard_logo.ico
Normal file
BIN
media/wizard_logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
BIN
media/wizard_logo_2.bmp
Normal file
BIN
media/wizard_logo_2.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 958 KiB |
BIN
media/wizard_logo_small.bmp
Normal file
BIN
media/wizard_logo_small.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
@ -11,12 +11,15 @@ use std::str::FromStr;
|
||||
use hashbrown::HashMap;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use wasmer::webassembly::InstanceABI;
|
||||
use wasmer::*;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
#[cfg(feature = "backend:llvm")]
|
||||
use wasmer_llvm_backend::LLVMCompiler;
|
||||
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
|
||||
use wasmer_runtime::{
|
||||
cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH},
|
||||
error::RuntimeError,
|
||||
Func, Value,
|
||||
};
|
||||
use wasmer_runtime_core::{
|
||||
self,
|
||||
backend::{Compiler, CompilerConfig},
|
||||
@ -83,6 +86,10 @@ struct Run {
|
||||
#[structopt(long = "em-symbol-map", parse(from_os_str), group = "emscripten")]
|
||||
em_symbol_map: Option<PathBuf>,
|
||||
|
||||
/// Begin execution at the specified symbol
|
||||
#[structopt(long = "em-entrypoint", group = "emscripten")]
|
||||
em_entrypoint: Option<String>,
|
||||
|
||||
/// WASI pre-opened directory
|
||||
#[structopt(long = "dir", multiple = true, group = "wasi")]
|
||||
pre_opened_directories: Vec<String>,
|
||||
@ -301,60 +308,82 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
};
|
||||
|
||||
// TODO: refactor this
|
||||
let (abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module);
|
||||
(
|
||||
InstanceABI::Emscripten,
|
||||
wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals),
|
||||
Some(emscripten_globals), // TODO Em Globals is here to extend, lifetime, find better solution
|
||||
let import_object = wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals);
|
||||
let mut instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
wasmer_emscripten::run_emscripten_instance(
|
||||
&module,
|
||||
&mut instance,
|
||||
if let Some(cn) = &options.command_name {
|
||||
cn
|
||||
} else {
|
||||
options.path.to_str().unwrap()
|
||||
},
|
||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||
options.em_entrypoint.clone(),
|
||||
)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
} else {
|
||||
if cfg!(feature = "wasi") && wasmer_wasi::is_wasi_module(&module) {
|
||||
(
|
||||
InstanceABI::WASI,
|
||||
wasmer_wasi::generate_import_object(
|
||||
if let Some(cn) = &options.command_name {
|
||||
[cn.clone()]
|
||||
} else {
|
||||
[options.path.to_str().unwrap().to_owned()]
|
||||
}
|
||||
.iter()
|
||||
.chain(options.args.iter())
|
||||
.cloned()
|
||||
.map(|arg| arg.into_bytes())
|
||||
let import_object = wasmer_wasi::generate_import_object(
|
||||
if let Some(cn) = &options.command_name {
|
||||
[cn.clone()]
|
||||
} else {
|
||||
[options.path.to_str().unwrap().to_owned()]
|
||||
}
|
||||
.iter()
|
||||
.chain(options.args.iter())
|
||||
.cloned()
|
||||
.map(|arg| arg.into_bytes())
|
||||
.collect(),
|
||||
env::vars()
|
||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||
.collect(),
|
||||
env::vars()
|
||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||
.collect(),
|
||||
options.pre_opened_directories.clone(),
|
||||
),
|
||||
None,
|
||||
)
|
||||
options.pre_opened_directories.clone(),
|
||||
);
|
||||
|
||||
let instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
let start: Func<(), ()> = instance.func("_start").map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
let result = start.call();
|
||||
|
||||
if let Err(ref err) = result {
|
||||
match err {
|
||||
RuntimeError::Trap { msg } => panic!("wasm trap occured: {}", msg),
|
||||
RuntimeError::Error { data } => {
|
||||
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
|
||||
std::process::exit(error_code.code as i32)
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("error: {:?}", err)
|
||||
}
|
||||
} else {
|
||||
(
|
||||
InstanceABI::None,
|
||||
wasmer_runtime_core::import::ImportObject::new(),
|
||||
None,
|
||||
)
|
||||
let import_object = wasmer_runtime_core::import::ImportObject::new();
|
||||
let instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
let args: Vec<Value> = options
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| arg.as_str())
|
||||
.map(|x| Value::I32(x.parse().unwrap()))
|
||||
.collect();
|
||||
instance
|
||||
.dyn_func("main")
|
||||
.map_err(|e| format!("{:?}", e))?
|
||||
.call(&args)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
};
|
||||
|
||||
let mut instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
webassembly::run_instance(
|
||||
&module,
|
||||
&mut instance,
|
||||
abi,
|
||||
if let Some(cn) = &options.command_name {
|
||||
cn
|
||||
} else {
|
||||
options.path.to_str().unwrap()
|
||||
},
|
||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||
)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[Setup]
|
||||
AppName=Wasmer
|
||||
AppVersion=1.5
|
||||
AppVersion=0.4.0
|
||||
DefaultDirName={pf}\Wasmer
|
||||
DefaultGroupName=Wasmer
|
||||
Compression=lzma2
|
||||
@ -9,9 +9,17 @@ OutputDir=.\
|
||||
DisableProgramGroupPage=yes
|
||||
ChangesEnvironment=yes
|
||||
OutputBaseFilename=WasmerInstaller
|
||||
WizardImageFile=..\..\media\wizard_logo_2.bmp
|
||||
WizardSmallImageFile=..\..\media\wizard_logo_small.bmp
|
||||
SetupIconFile=..\..\media\wizard_logo.ico
|
||||
DisableWelcomePage=no
|
||||
|
||||
[Files]
|
||||
Source: "..\..\target\release\wasmer.exe"; DestDir: "{app}\bin"
|
||||
Source: "..\..\wapm-cli\target\release\wapm.exe"; DestDir: "{app}\bin"
|
||||
|
||||
[Dirs]
|
||||
Name: "{%USERPROFILE}\.wasmer"
|
||||
|
||||
[Code]
|
||||
const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
|
||||
@ -61,11 +69,17 @@ end;
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if CurStep = ssPostInstall
|
||||
then EnvAddPath(ExpandConstant('{app}') +'\bin');
|
||||
then begin
|
||||
EnvAddPath(ExpandConstant('{app}') +'\bin');
|
||||
EnvAddPath(ExpandConstant('{%USERPROFILE}') +'\globals\wapm_packages\.bin');
|
||||
end
|
||||
end;
|
||||
|
||||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||
begin
|
||||
if CurUninstallStep = usPostUninstall
|
||||
then EnvRemovePath(ExpandConstant('{app}') +'\bin');
|
||||
then begin
|
||||
EnvRemovePath(ExpandConstant('{app}') +'\bin');
|
||||
EnvAddPath(ExpandConstant('{%USERPROFILE}') +'\globals\wapm_packages\.bin');
|
||||
end
|
||||
end;
|
@ -1,13 +1,6 @@
|
||||
use std::panic;
|
||||
pub use wasmer_runtime::compile_with_config_with;
|
||||
use wasmer_runtime::{
|
||||
self as runtime,
|
||||
error::{CallResult, Result},
|
||||
ImportObject, Instance, Module,
|
||||
};
|
||||
use wasmer_runtime_core::types::Value;
|
||||
|
||||
use wasmer_emscripten::run_emscripten_instance;
|
||||
use wasmer_runtime::{self as runtime, error::Result, ImportObject, Instance, Module};
|
||||
|
||||
pub struct ResultObject {
|
||||
/// A webassembly::Module object representing the compiled WebAssembly module.
|
||||
@ -77,40 +70,3 @@ pub fn compile(buffer_source: &[u8]) -> Result<Module> {
|
||||
let module = runtime::compile(buffer_source)?;
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
// /// The same as `compile` but takes a `CompilerConfig` for the purpose of
|
||||
// /// changing the compiler's behavior
|
||||
// pub fn compile_with_config_with(
|
||||
// buffer_source: &[u8],
|
||||
// compiler_config: CompilerConfig,
|
||||
// ) -> Result<Module> {
|
||||
// let module = runtime::compile_with_config(buffer_source, compiler_config)?;
|
||||
// Ok(module)
|
||||
// }
|
||||
|
||||
/// Performs common instance operations needed when an instance is first run
|
||||
/// including data setup, handling arguments and calling a main function
|
||||
pub fn run_instance(
|
||||
module: &Module,
|
||||
instance: &mut Instance,
|
||||
abi: InstanceABI,
|
||||
path: &str,
|
||||
args: Vec<&str>,
|
||||
) -> CallResult<()> {
|
||||
match abi {
|
||||
InstanceABI::Emscripten => {
|
||||
run_emscripten_instance(module, instance, path, args)?;
|
||||
}
|
||||
InstanceABI::WASI => {
|
||||
instance.call("_start", &[])?;
|
||||
}
|
||||
InstanceABI::None => {
|
||||
let args: Vec<Value> = args
|
||||
.into_iter()
|
||||
.map(|x| Value::I32(x.parse().unwrap()))
|
||||
.collect();
|
||||
instance.call("main", &args)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
PREVIOUS_VERSION='0.2.1'
|
||||
NEXT_VERSION='0.3.0'
|
||||
PREVIOUS_VERSION='0.4.0'
|
||||
NEXT_VERSION='0.4.1'
|
||||
|
||||
# quick hack
|
||||
fd Cargo.toml --exec sed -i '' "s/version = \"$PREVIOUS_VERSION\"/version = \"$NEXT_VERSION\"/"
|
||||
|
1
wapm-cli
Submodule
1
wapm-cli
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8286d0a4bcd771c2f5e622b40543143e25e096df
|
Loading…
Reference in New Issue
Block a user