mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 13:41:32 +00:00
Merge branch 'master'
Conflicts: Cargo.lock Cargo.toml lib/emscripten/Cargo.toml lib/emscripten/src/syscalls/unix.rs lib/runtime-core/Cargo.toml
This commit is contained in:
@ -31,8 +31,10 @@ jobs:
|
||||
- run:
|
||||
name: Install lint deps
|
||||
command: |
|
||||
git config --global --unset url."ssh://git@github.com".insteadOf || true
|
||||
rustup toolchain install nightly
|
||||
rustup component add rustfmt
|
||||
rustup component add clippy
|
||||
rustup component add clippy --toolchain=nightly || cargo +nightly install --git https://github.com/rust-lang/rust-clippy/ --force clippy
|
||||
- run:
|
||||
name: Execute lints
|
||||
command: |
|
||||
@ -205,6 +207,10 @@ jobs:
|
||||
echo "${VERSION}" >> artifacts/version
|
||||
echo "${CIRCLE_TAG}" >> artifacts/git_version
|
||||
cp ./target/release/wasmer ./artifacts/$(./binary-name.sh)
|
||||
- run:
|
||||
name: Debug flag checked
|
||||
command: |
|
||||
cargo check --features "debug"
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
@ -322,6 +328,9 @@ jobs:
|
||||
export SODIUM_LIB_DIR=/usr/local/lib
|
||||
export SODIUM_STATIC=true
|
||||
make test
|
||||
make test-nightly
|
||||
make test-emscripten
|
||||
make test-emscripten-nightly
|
||||
- save_cache:
|
||||
paths:
|
||||
- /usr/local/cargo/registry
|
||||
@ -355,6 +364,22 @@ jobs:
|
||||
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
||||
# exit 1
|
||||
#fi
|
||||
trigger-benchmark-build:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
steps:
|
||||
- run:
|
||||
name: "Trigger Benchmark Build"
|
||||
command: |
|
||||
if [[ -z "${CIRCLE_API_USER_TOKEN}" ]]; then
|
||||
echo "CIRCLE_API_USER_TOKEN environment variable not set"
|
||||
exit 1
|
||||
else
|
||||
echo "Triggering benchmark build"
|
||||
curl -u ${CIRCLE_API_USER_TOKEN} \
|
||||
-d build_parameters[CIRCLE_JOB]=bench \
|
||||
https://circleci.com/api/v1.1/project/github/wasmerio/wasmer-bench/tree/master
|
||||
fi
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@ -397,3 +422,10 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- trigger-benchmark-build:
|
||||
requires:
|
||||
- test-and-build
|
||||
- lint
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
|
119
Cargo.lock
generated
119
Cargo.lock
generated
@ -60,7 +60,7 @@ name = "backtrace-sys"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -78,7 +78,7 @@ version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -155,7 +155,7 @@ name = "capstone-sys"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -194,7 +194,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.30"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -202,7 +202,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.3.4"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -250,7 +250,7 @@ name = "cmake"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -418,6 +418,30 @@ dependencies = [
|
||||
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynasm"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynasmrt"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.1"
|
||||
@ -590,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
[[package]]
|
||||
name = "inkwell"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/wasmerio/inkwell?branch=llvm7-0#b541566a0ac18a0f52bef54596d00c740c8b0597"
|
||||
source = "git+https://github.com/wasmerio/inkwell?branch=llvm7-0#a14e62977504ef574dc2e933edc559cc79781ca7"
|
||||
dependencies = [
|
||||
"either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -602,7 +626,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "inkwell_internal_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/wasmerio/inkwell?branch=llvm7-0#b541566a0ac18a0f52bef54596d00c740c8b0597"
|
||||
source = "git+https://github.com/wasmerio/inkwell?branch=llvm7-0#a14e62977504ef574dc2e933edc559cc79781ca7"
|
||||
dependencies = [
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -654,13 +678,13 @@ name = "libloading"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -672,7 +696,7 @@ name = "llvm-sys"
|
||||
version = "70.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -711,7 +735,7 @@ name = "lz4-sys"
|
||||
version = "1.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -723,6 +747,15 @@ dependencies = [
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
version = "0.7.0"
|
||||
@ -743,7 +776,7 @@ version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -755,7 +788,7 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -796,6 +829,14 @@ dependencies = [
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owning_ref"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owning_ref"
|
||||
version = "0.4.0"
|
||||
@ -1007,7 +1048,7 @@ version = "6.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1306,9 +1347,14 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "take_mut"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.21"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1476,7 +1522,7 @@ name = "wabt-sys"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1500,6 +1546,7 @@ dependencies = [
|
||||
"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.2.0",
|
||||
"wasmer-dynasm-backend 0.1.0",
|
||||
"wasmer-emscripten 0.2.1",
|
||||
"wasmer-llvm-backend 0.1.0",
|
||||
"wasmer-runtime 0.2.1",
|
||||
@ -1531,6 +1578,20 @@ dependencies = [
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-dynasm-backend"
|
||||
version = "0.1.0"
|
||||
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)",
|
||||
"dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.2.1",
|
||||
"wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-emscripten"
|
||||
version = "0.2.1"
|
||||
@ -1545,6 +1606,7 @@ dependencies = [
|
||||
"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.2.0",
|
||||
"wasmer-dynasm-backend 0.1.0",
|
||||
"wasmer-llvm-backend 0.1.0",
|
||||
"wasmer-runtime-abi 0.2.1",
|
||||
"wasmer-runtime-core 0.2.1",
|
||||
@ -1555,7 +1617,7 @@ name = "wasmer-llvm-backend"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"goblin 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inkwell 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm7-0)",
|
||||
@ -1581,6 +1643,7 @@ dependencies = [
|
||||
"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.2.0",
|
||||
"wasmer-dynasm-backend 0.1.0",
|
||||
"wasmer-llvm-backend 0.1.0",
|
||||
"wasmer-runtime-core 0.2.1",
|
||||
]
|
||||
@ -1591,7 +1654,7 @@ version = "0.2.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)",
|
||||
"tar 0.4.21 (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.2.1",
|
||||
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1639,6 +1702,7 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-clif-backend 0.2.0",
|
||||
"wasmer-dynasm-backend 0.1.0",
|
||||
"wasmer-llvm-backend 0.1.0",
|
||||
"wasmer-runtime-core 0.2.1",
|
||||
]
|
||||
@ -1740,7 +1804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1772,7 +1836,7 @@ version = "1.4.8+zstd.1.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"blob 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1800,8 +1864,8 @@ dependencies = [
|
||||
"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe"
|
||||
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
||||
"checksum cbindgen 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f61c5411fe3ac196fae7ea397dd13959b1323edda046eec50d648a8e92015a53"
|
||||
"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92"
|
||||
"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da"
|
||||
"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d"
|
||||
"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af"
|
||||
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
|
||||
"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4"
|
||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||
@ -1823,6 +1887,8 @@ dependencies = [
|
||||
"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04"
|
||||
"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
|
||||
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
|
||||
"checksum dynasm 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b77e128faecc4d16cff7cae96c0c9e809f687f748a0dbc4d017996e48240a991"
|
||||
"checksum dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c408a211e7f5762829f5e46bdff0c14bc3b1517a21a4bb781c716bf88b0c68"
|
||||
"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac"
|
||||
"checksum enum-methods 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7798e7da2d4cb0d6d6fc467e8d6b5bf247e9e989f786dde1732d79899c32bb10"
|
||||
"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
|
||||
@ -1853,13 +1919,14 @@ dependencies = [
|
||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||
"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
|
||||
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
|
||||
"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
|
||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||
"checksum llvm-sys 70.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60a9ee82fe0fa72ae6ef6d018b407296085863836451c7a97384f84ed7e26b9f"
|
||||
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
|
||||
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||
"checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5"
|
||||
"checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe"
|
||||
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
|
||||
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
|
||||
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "921f61dc817b379d0834e45d5ec45beaacfae97082090a49c2cf30dcbc30206f"
|
||||
@ -1869,6 +1936,7 @@ dependencies = [
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
|
||||
"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242"
|
||||
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
|
||||
@ -1929,7 +1997,8 @@ dependencies = [
|
||||
"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
"checksum tar 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)" = "904b43da53c99b929c4484fa281e5535f2eb86b3040de3e3e5b69708e2a8bd65"
|
||||
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
|
||||
"checksum tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2167ff53da2a661702b3299f71a91b61b1dffef36b4b2884b1f9c67254c0133"
|
||||
"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9"
|
||||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a"
|
||||
|
10
Cargo.toml
10
Cargo.toml
@ -19,20 +19,19 @@ include = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
errno = "0.2.4"
|
||||
structopt = "0.2.11"
|
||||
wabt = "0.7.2"
|
||||
wasmer-clif-backend = { path = "lib/clif-backend" }
|
||||
wasmer-dynasm-backend = { path = "lib/dynasm-backend", optional = true }
|
||||
wasmer-runtime = { path = "lib/runtime" }
|
||||
wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
|
||||
wasmer-runtime-core = { path = "lib/runtime-core" }
|
||||
wasmer-emscripten = { path = "lib/emscripten" }
|
||||
wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
|
||||
errno = "0.2.4"
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
|
||||
|
||||
[workspace]
|
||||
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/runtime-abi"]
|
||||
members = ["lib/clif-backend", "lib/dynasm-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"]
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.7.2"
|
||||
@ -44,4 +43,5 @@ debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
# This feature will allow cargo test to run much faster
|
||||
fast-tests = []
|
||||
llvm = ["wasmer-llvm-backend"]
|
||||
dynasm = ["wasmer-dynasm-backend"]
|
||||
vfs = ["wasmer-runtime-abi", "wasmer-emscripten/vfs"]
|
||||
|
13
Makefile
13
Makefile
@ -28,33 +28,36 @@ integration-tests: release
|
||||
|
||||
lint:
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all
|
||||
cargo +nightly clippy --all
|
||||
|
||||
precommit: lint test
|
||||
|
||||
test:
|
||||
# We use one thread so the emscripten stdouts doesn't collide
|
||||
cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests -- $(runargs)
|
||||
cargo test --all --exclude wasmer-runtime-c-api --exclude wasmer-emscripten --exclude wasmer-spectests --exclude wasmer-dynasm-backend -- $(runargs)
|
||||
# cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
|
||||
cargo test --manifest-path lib/spectests/Cargo.toml --features clif
|
||||
cargo test --manifest-path lib/spectests/Cargo.toml --features llvm
|
||||
cargo build -p wasmer-runtime-c-api
|
||||
cargo test -p wasmer-runtime-c-api -- --nocapture
|
||||
|
||||
test-nightly:
|
||||
cargo test --manifest-path lib/spectests/Cargo.toml --features dynasm
|
||||
|
||||
test-emscripten:
|
||||
cargo test --manifest-path lib/emscripten/Cargo.toml --features clif -- --test-threads=1 $(runargs)
|
||||
cargo test --manifest-path lib/emscripten/Cargo.toml --features llvm -- --test-threads=1 $(runargs)
|
||||
cargo test --manifest-path lib/emscripten/Cargo.toml _vfs --features clif,vfs -- --test-threads=1 $(runargs)
|
||||
cargo test --manifest-path lib/emscripten/Cargo.toml _vfs --features llvm,vfs -- --test-threads=1 $(runargs)
|
||||
|
||||
test-emscripten-nightly:
|
||||
cargo test --manifest-path lib/emscripten/Cargo.toml --features dynasm -- --test-threads=1 $(runargs)
|
||||
|
||||
release:
|
||||
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
|
||||
# brew install mingw-w64
|
||||
cargo build --release
|
||||
|
||||
debug-release:
|
||||
cargo build --release --features debug
|
||||
|
||||
debug-release:
|
||||
cargo build --release --features "debug"
|
||||
|
||||
|
37
examples/single_pass_tests/br_table.wat
Normal file
37
examples/single_pass_tests/br_table.wat
Normal file
@ -0,0 +1,37 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(i32.eq (call $test (i32.const 0)) (i32.const 2))
|
||||
(i32.eq (call $test (i32.const 1)) (i32.const 0))
|
||||
(i32.eq (call $test (i32.const 2)) (i32.const 1))
|
||||
(i32.eq (call $test (i32.const 3)) (i32.const 3))
|
||||
(i32.eq (call $test (i32.const 4)) (i32.const 3))
|
||||
(i32.and)
|
||||
(i32.and)
|
||||
(i32.and)
|
||||
(i32.and)
|
||||
(i32.const 1)
|
||||
(i32.eq)
|
||||
(br_if 0)
|
||||
(unreachable)
|
||||
)
|
||||
|
||||
(func $test (param $p i32) (result i32)
|
||||
(block
|
||||
(block
|
||||
(block
|
||||
(block
|
||||
(block
|
||||
(get_local $p)
|
||||
(br_table 2 0 1 3)
|
||||
)
|
||||
(return (i32.const 0))
|
||||
)
|
||||
(return (i32.const 1))
|
||||
)
|
||||
(return (i32.const 2))
|
||||
)
|
||||
(return (i32.const 3))
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
23
examples/single_pass_tests/call.wat
Normal file
23
examples/single_pass_tests/call.wat
Normal file
@ -0,0 +1,23 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(local $a i32)
|
||||
(block
|
||||
(set_local $a (i32.const 33))
|
||||
(i32.const 11)
|
||||
(call $foo (get_local $a))
|
||||
(i32.add)
|
||||
(i32.const 86)
|
||||
(i32.eq)
|
||||
(br_if 0)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
|
||||
(func $foo (param $input i32) (result i32)
|
||||
(local $a i32)
|
||||
(set_local $a (i32.const 42))
|
||||
(get_local $a)
|
||||
(get_local $input)
|
||||
(i32.add)
|
||||
)
|
||||
)
|
25
examples/single_pass_tests/call_indirect.wat
Normal file
25
examples/single_pass_tests/call_indirect.wat
Normal file
@ -0,0 +1,25 @@
|
||||
(module
|
||||
(type $binop (func (param i32 i32) (result i32)))
|
||||
(table 1 100 anyfunc)
|
||||
(elem (i32.const 5) $sub)
|
||||
(elem (i32.const 10) $add)
|
||||
|
||||
(func $main (export "main")
|
||||
(if (i32.eq (call_indirect (type $binop) (i32.const 42) (i32.const 1) (i32.const 10)) (i32.const 43))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
(if (i32.eq (call_indirect (type $binop) (i32.const 42) (i32.const 1) (i32.const 5)) (i32.const 41))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
)
|
||||
|
||||
(func $add (param i32) (param i32) (result i32)
|
||||
(i32.add (get_local 0) (get_local 1))
|
||||
)
|
||||
|
||||
(func $sub (param i32) (param i32) (result i32)
|
||||
(i32.sub (get_local 0) (get_local 1))
|
||||
)
|
||||
)
|
36
examples/single_pass_tests/div.wat
Normal file
36
examples/single_pass_tests/div.wat
Normal file
@ -0,0 +1,36 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(i32.const 1)
|
||||
(if (i32.ne (i32.div_s (i32.const 2) (i32.const -1)) (i32.const -2))
|
||||
(then unreachable)
|
||||
)
|
||||
(i32.const 2)
|
||||
(if (i32.ne (i32.div_u (i32.const 2) (i32.const -1)) (i32.const 0))
|
||||
(then unreachable)
|
||||
)
|
||||
(i32.const 3)
|
||||
(if (i32.ne (i32.div_u (i32.const 10) (i32.const 5)) (i32.const 2))
|
||||
(then unreachable)
|
||||
)
|
||||
(i32.const 4)
|
||||
(if (i64.ne (i64.div_s (i64.const 300000000000) (i64.const -1)) (i64.const -300000000000))
|
||||
(then unreachable)
|
||||
)
|
||||
(i32.const 5)
|
||||
(if (i64.ne (i64.div_u (i64.const 300000000000) (i64.const -1)) (i64.const 0))
|
||||
(then unreachable)
|
||||
)
|
||||
(i32.const 6)
|
||||
(if (i64.ne (i64.div_u (i64.const 300000000000) (i64.const 2)) (i64.const 150000000000))
|
||||
(then unreachable)
|
||||
)
|
||||
(i32.add)
|
||||
(i32.add)
|
||||
(i32.add)
|
||||
(i32.add)
|
||||
(i32.add)
|
||||
(if (i32.ne (i32.const 21))
|
||||
(then unreachable)
|
||||
)
|
||||
)
|
||||
)
|
26
examples/single_pass_tests/global.wat
Normal file
26
examples/single_pass_tests/global.wat
Normal file
@ -0,0 +1,26 @@
|
||||
(module
|
||||
(global $g1 (mut i32) (i32.const 0))
|
||||
(global $g2 (mut i32) (i32.const 99))
|
||||
(func $main (export "main")
|
||||
(if (i32.eq (get_global $g1) (i32.const 0))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
(if (i32.eq (get_global $g2) (i32.const 99))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
|
||||
(set_global $g1 (i32.add (get_global $g1) (i32.const 1)))
|
||||
(set_global $g2 (i32.sub (get_global $g2) (i32.const 1)))
|
||||
|
||||
(if (i32.eq (get_global $g1) (i32.const 1))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
(if (i32.eq (get_global $g2) (i32.const 98))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
)
|
||||
)
|
44
examples/single_pass_tests/i32.wat
Normal file
44
examples/single_pass_tests/i32.wat
Normal file
@ -0,0 +1,44 @@
|
||||
(module
|
||||
(func $main (export "main") (result i32)
|
||||
(local $v1 i32)
|
||||
(block
|
||||
(i32.const 10)
|
||||
(set_local $v1)
|
||||
|
||||
(i32.const 42)
|
||||
(get_local $v1)
|
||||
(i32.add)
|
||||
(i32.const 53)
|
||||
(i32.eq)
|
||||
(br_if 0)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.const -100)
|
||||
(i32.const 41)
|
||||
(i32.lt_s)
|
||||
(i32.sub)
|
||||
(br_if 0)
|
||||
|
||||
(i32.const -100)
|
||||
(i32.const 41)
|
||||
(i32.lt_u)
|
||||
(br_if 0)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.const 100)
|
||||
(i32.const -41)
|
||||
(i32.gt_s)
|
||||
(i32.sub)
|
||||
(br_if 0)
|
||||
|
||||
(i32.const 100)
|
||||
(i32.const -41)
|
||||
(i32.gt_u)
|
||||
(br_if 0)
|
||||
|
||||
(i32.const 0)
|
||||
(return)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
48
examples/single_pass_tests/i64.wat
Normal file
48
examples/single_pass_tests/i64.wat
Normal file
@ -0,0 +1,48 @@
|
||||
(module
|
||||
(func $main (export "main") (result i64)
|
||||
(local $v1 i64)
|
||||
(block
|
||||
(i64.const 10)
|
||||
(set_local $v1)
|
||||
|
||||
(i64.const 42)
|
||||
(get_local $v1)
|
||||
(i64.add)
|
||||
(i64.const 53)
|
||||
(i64.eq)
|
||||
(br_if 0)
|
||||
|
||||
(i64.const 1)
|
||||
(i64.const -100)
|
||||
(i64.const 41)
|
||||
(i64.lt_s)
|
||||
(i64.extend_u/i32)
|
||||
(i64.sub)
|
||||
(i32.wrap/i64)
|
||||
(br_if 0)
|
||||
|
||||
(i64.const -100)
|
||||
(i64.const 41)
|
||||
(i64.lt_u)
|
||||
(br_if 0)
|
||||
|
||||
(i64.const 1)
|
||||
(i64.const 100)
|
||||
(i64.const -41)
|
||||
(i64.gt_s)
|
||||
(i64.extend_u/i32)
|
||||
(i64.sub)
|
||||
(i32.wrap/i64)
|
||||
(br_if 0)
|
||||
|
||||
(i64.const 100)
|
||||
(i64.const -41)
|
||||
(i64.gt_u)
|
||||
(br_if 0)
|
||||
|
||||
(i64.const 0)
|
||||
(return)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
33
examples/single_pass_tests/if_else.wat
Normal file
33
examples/single_pass_tests/if_else.wat
Normal file
@ -0,0 +1,33 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(local $a i32)
|
||||
(set_local $a (i32.const 33))
|
||||
|
||||
(block
|
||||
(call $foo (if (result i32) (i32.eq (get_local $a) (i32.const 33))
|
||||
(then (i32.const 1))
|
||||
(else (i32.const 2))
|
||||
))
|
||||
(i32.eq (i32.const 43))
|
||||
(br_if 0)
|
||||
(unreachable)
|
||||
)
|
||||
(block
|
||||
(call $foo (if (result i32) (i32.eq (get_local $a) (i32.const 30))
|
||||
(then (i32.const 1))
|
||||
(else (i32.const 2))
|
||||
))
|
||||
(i32.eq (i32.const 44))
|
||||
(br_if 0)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
|
||||
(func $foo (param $input i32) (result i32)
|
||||
(local $a i32)
|
||||
(set_local $a (i32.const 42))
|
||||
(get_local $a)
|
||||
(get_local $input)
|
||||
(i32.add)
|
||||
)
|
||||
)
|
16
examples/single_pass_tests/loop.wat
Normal file
16
examples/single_pass_tests/loop.wat
Normal file
@ -0,0 +1,16 @@
|
||||
(module
|
||||
(func $main (export "main") (result i32)
|
||||
(local $count i32)
|
||||
(local $sum i32)
|
||||
(loop (result i32)
|
||||
(set_local $count (i32.add (get_local $count) (i32.const 1)))
|
||||
(set_local $sum (i32.add (get_local $sum) (get_local $count)))
|
||||
(i32.sub (i32.const 1) (i32.eq
|
||||
(get_local $count)
|
||||
(i32.const 100000)
|
||||
))
|
||||
(br_if 0)
|
||||
(get_local $sum)
|
||||
)
|
||||
)
|
||||
)
|
90
examples/single_pass_tests/memory.wat
Normal file
90
examples/single_pass_tests/memory.wat
Normal file
@ -0,0 +1,90 @@
|
||||
(module
|
||||
(memory 1)
|
||||
(func $main (export "main")
|
||||
(call $test_stack_layout)
|
||||
)
|
||||
|
||||
(func $test_stack_layout
|
||||
(local $addr i32)
|
||||
(set_local $addr (i32.const 16))
|
||||
|
||||
(i32.store (get_local $addr) (i32.const 10))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 655360))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 11))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 720896))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 12))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 786432))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 13))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 851968))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 14))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 917504))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 15))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 983040))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 16))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1048576))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 17))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1114112))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 18))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1179648))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(i32.const 1)
|
||||
(i32.store (get_local $addr) (i32.const 19))
|
||||
(if (i32.eq (i32.load (i32.const 14)) (i32.const 1245184))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
(drop)
|
||||
)
|
||||
)
|
20
examples/single_pass_tests/select.wat
Normal file
20
examples/single_pass_tests/select.wat
Normal file
@ -0,0 +1,20 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(if (i32.eq (select
|
||||
(i32.const 10)
|
||||
(i32.const 20)
|
||||
(i32.const 1)
|
||||
) (i32.const 10))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
(if (i32.eq (select
|
||||
(i32.const 10)
|
||||
(i32.const 20)
|
||||
(i32.const 0)
|
||||
) (i32.const 20))
|
||||
(then)
|
||||
(else (unreachable))
|
||||
)
|
||||
)
|
||||
)
|
11
examples/single_pass_tests/tee_local.wat
Normal file
11
examples/single_pass_tests/tee_local.wat
Normal file
@ -0,0 +1,11 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(local $x i32)
|
||||
(tee_local $x (i32.const 3))
|
||||
(i32.add (i32.const 4))
|
||||
(if (i32.eq (i32.const 7))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
)
|
||||
)
|
38
examples/single_pass_tests/unwinding.wat
Normal file
38
examples/single_pass_tests/unwinding.wat
Normal file
@ -0,0 +1,38 @@
|
||||
(module
|
||||
(func $main (export "main")
|
||||
(i32.const 5)
|
||||
(block (result i32)
|
||||
(i32.const 10)
|
||||
(block
|
||||
(i32.const 20)
|
||||
(block
|
||||
(i32.const 50)
|
||||
(br 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(i32.add)
|
||||
(if (i32.eq (i32.const 15))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
|
||||
(block (result i32)
|
||||
(i32.const 10)
|
||||
(block (result i32)
|
||||
(i32.const 20)
|
||||
(block
|
||||
(i32.const 50)
|
||||
(br 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(i32.add)
|
||||
)
|
||||
(if (i32.eq (i32.const 60))
|
||||
(then)
|
||||
(else unreachable)
|
||||
)
|
||||
)
|
||||
)
|
@ -33,5 +33,6 @@ to tune the codegen properties (compile speed, performance, etc) to best fit the
|
||||
|
||||
Currently, we support multiple backends for compiling WebAssembly to machine code:
|
||||
|
||||
- [clif-backend](./clif-backend/): Cranelift backend
|
||||
- [llvm-backend](./llvm-backend/): LLVM backend
|
||||
- [dynasm-backend](./dynasm-backend/): Dynasm backend - super fast compilation, slower runtime speed
|
||||
- [clif-backend](./clif-backend/): Cranelift backend - slower compilation, normal runtime speed
|
||||
- [llvm-backend](./llvm-backend/): LLVM backend - slow compilation, native runtime speed
|
||||
|
18
lib/dynasm-backend/Cargo.toml
Normal file
18
lib/dynasm-backend/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "wasmer-dynasm-backend"
|
||||
version = "0.1.0"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
description = "Wasmer runtime Dynasm compiler backend"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core" }
|
||||
wasmparser = "0.28.0"
|
||||
dynasm = "0.3.1"
|
||||
dynasmrt = "0.3.1"
|
||||
lazy_static = "1.2.0"
|
||||
byteorder = "1"
|
||||
nix = "0.13.0"
|
||||
libc = "0.2.49"
|
33
lib/dynasm-backend/src/codegen.rs
Normal file
33
lib/dynasm-backend/src/codegen.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use wasmer_runtime_core::{
|
||||
backend::{FuncResolver, ProtectedCaller},
|
||||
module::ModuleInfo,
|
||||
structures::Map,
|
||||
types::{FuncIndex, FuncSig, SigIndex},
|
||||
};
|
||||
use wasmparser::{Operator, Type as WpType};
|
||||
|
||||
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator, PC: ProtectedCaller, FR: FuncResolver> {
|
||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), CodegenError>;
|
||||
fn next_function(&mut self) -> Result<&mut FCG, CodegenError>;
|
||||
fn finalize(self, module_info: &ModuleInfo) -> Result<(PC, FR), CodegenError>;
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), CodegenError>;
|
||||
fn feed_function_signatures(
|
||||
&mut self,
|
||||
assoc: Map<FuncIndex, SigIndex>,
|
||||
) -> Result<(), CodegenError>;
|
||||
fn feed_import_function(&mut self) -> Result<(), CodegenError>;
|
||||
}
|
||||
|
||||
pub trait FunctionCodeGenerator {
|
||||
fn feed_return(&mut self, ty: WpType) -> Result<(), CodegenError>;
|
||||
fn feed_param(&mut self, ty: WpType) -> Result<(), CodegenError>;
|
||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError>;
|
||||
fn begin_body(&mut self) -> Result<(), CodegenError>;
|
||||
fn feed_opcode(&mut self, op: Operator, module_info: &ModuleInfo) -> Result<(), CodegenError>;
|
||||
fn finalize(&mut self) -> Result<(), CodegenError>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CodegenError {
|
||||
pub message: &'static str,
|
||||
}
|
5261
lib/dynasm-backend/src/codegen_x64.rs
Normal file
5261
lib/dynasm-backend/src/codegen_x64.rs
Normal file
File diff suppressed because it is too large
Load Diff
87
lib/dynasm-backend/src/lib.rs
Normal file
87
lib/dynasm-backend/src/lib.rs
Normal file
@ -0,0 +1,87 @@
|
||||
#![feature(proc_macro_hygiene)]
|
||||
|
||||
#[cfg(not(any(
|
||||
all(target_os = "macos", target_arch = "x86_64"),
|
||||
all(target_os = "linux", target_arch = "x86_64"),
|
||||
)))]
|
||||
compile_error!("This crate doesn't yet support compiling on operating systems other than linux and macos and architectures other than x86_64");
|
||||
|
||||
extern crate dynasmrt;
|
||||
|
||||
#[macro_use]
|
||||
extern crate dynasm;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
extern crate byteorder;
|
||||
|
||||
mod codegen;
|
||||
mod codegen_x64;
|
||||
mod parse;
|
||||
mod protect_unix;
|
||||
mod stack;
|
||||
|
||||
use crate::codegen::{CodegenError, ModuleCodeGenerator};
|
||||
use crate::parse::LoadError;
|
||||
use wasmer_runtime_core::{
|
||||
backend::{sys::Memory, Backend, CacheGen, Compiler, Token},
|
||||
cache::{Artifact, Error as CacheError},
|
||||
error::{CompileError, CompileResult},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
};
|
||||
|
||||
struct Placeholder;
|
||||
impl CacheGen for Placeholder {
|
||||
fn generate_cache(
|
||||
&self,
|
||||
_module: &ModuleInner,
|
||||
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError> {
|
||||
Err(CacheError::Unknown(
|
||||
"the dynasm 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], _: Token) -> CompileResult<ModuleInner> {
|
||||
let mut mcg = codegen_x64::X64ModuleCodeGenerator::new();
|
||||
let info = parse::read_module(wasm, Backend::Dynasm, &mut mcg)?;
|
||||
let (ec, resolver) = mcg.finalize(&info)?;
|
||||
Ok(ModuleInner {
|
||||
cache_gen: Box::new(Placeholder),
|
||||
func_resolver: Box::new(resolver),
|
||||
protected_caller: Box::new(ec),
|
||||
info: info,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
Err(CacheError::Unknown(
|
||||
"the dynasm 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),
|
||||
}
|
||||
}
|
||||
}
|
441
lib/dynasm-backend/src/parse.rs
Normal file
441
lib/dynasm-backend/src/parse.rs
Normal file
@ -0,0 +1,441 @@
|
||||
use crate::codegen::{CodegenError, FunctionCodeGenerator, ModuleCodeGenerator};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, FuncResolver, ProtectedCaller},
|
||||
module::{
|
||||
DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder,
|
||||
TableInitializer,
|
||||
},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
ElementType, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit,
|
||||
ImportedGlobalIndex, Initializer, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor,
|
||||
TableIndex, Type, Value,
|
||||
},
|
||||
units::Pages,
|
||||
};
|
||||
use wasmparser::{
|
||||
BinaryReaderError, Data, DataKind, Element, ElementKind, Export, ExternalKind, FuncType,
|
||||
Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, SectionCode, Type as WpType,
|
||||
WasmDecoder,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoadError {
|
||||
Parse(BinaryReaderError),
|
||||
Codegen(CodegenError),
|
||||
}
|
||||
|
||||
impl From<BinaryReaderError> for LoadError {
|
||||
fn from(other: BinaryReaderError) -> LoadError {
|
||||
LoadError::Parse(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CodegenError> for LoadError {
|
||||
fn from(other: CodegenError) -> LoadError {
|
||||
LoadError::Codegen(other)
|
||||
}
|
||||
}
|
||||
|
||||
fn validate(bytes: &[u8]) -> Result<(), LoadError> {
|
||||
let mut parser = wasmparser::ValidatingParser::new(
|
||||
bytes,
|
||||
Some(wasmparser::ValidatingParserConfig {
|
||||
operator_config: wasmparser::OperatorValidatorConfig {
|
||||
enable_threads: false,
|
||||
enable_reference_types: false,
|
||||
enable_simd: false,
|
||||
enable_bulk_memory: false,
|
||||
},
|
||||
mutable_global_imports: false,
|
||||
}),
|
||||
);
|
||||
|
||||
loop {
|
||||
let state = parser.read();
|
||||
match *state {
|
||||
wasmparser::ParserState::EndWasm => break Ok(()),
|
||||
wasmparser::ParserState::Error(err) => Err(LoadError::Parse(err))?,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_module<
|
||||
MCG: ModuleCodeGenerator<FCG, PC, FR>,
|
||||
FCG: FunctionCodeGenerator,
|
||||
PC: ProtectedCaller,
|
||||
FR: FuncResolver,
|
||||
>(
|
||||
wasm: &[u8],
|
||||
backend: Backend,
|
||||
mcg: &mut MCG,
|
||||
) -> Result<ModuleInfo, LoadError> {
|
||||
validate(wasm)?;
|
||||
let mut info = ModuleInfo {
|
||||
memories: Map::new(),
|
||||
globals: Map::new(),
|
||||
tables: Map::new(),
|
||||
|
||||
imported_functions: Map::new(),
|
||||
imported_memories: Map::new(),
|
||||
imported_tables: Map::new(),
|
||||
imported_globals: Map::new(),
|
||||
|
||||
exports: Default::default(),
|
||||
|
||||
data_initializers: Vec::new(),
|
||||
elem_initializers: Vec::new(),
|
||||
|
||||
start_func: None,
|
||||
|
||||
func_assoc: Map::new(),
|
||||
signatures: Map::new(),
|
||||
backend: backend,
|
||||
|
||||
namespace_table: StringTable::new(),
|
||||
name_table: StringTable::new(),
|
||||
};
|
||||
|
||||
let mut reader = ModuleReader::new(wasm)?;
|
||||
|
||||
loop {
|
||||
if reader.eof() {
|
||||
return Ok(info);
|
||||
}
|
||||
|
||||
let section = reader.read()?;
|
||||
|
||||
match section.code {
|
||||
SectionCode::Type => {
|
||||
let type_reader = section.get_type_section_reader()?;
|
||||
|
||||
for ty in type_reader {
|
||||
let ty = ty?;
|
||||
info.signatures.push(func_type_to_func_sig(ty)?);
|
||||
}
|
||||
|
||||
mcg.feed_signatures(info.signatures.clone())?;
|
||||
}
|
||||
SectionCode::Import => {
|
||||
let import_reader = section.get_import_section_reader()?;
|
||||
let mut namespace_builder = StringTableBuilder::new();
|
||||
let mut name_builder = StringTableBuilder::new();
|
||||
|
||||
for import in import_reader {
|
||||
let Import { module, field, ty } = import?;
|
||||
|
||||
let namespace_index = namespace_builder.register(module);
|
||||
let name_index = name_builder.register(field);
|
||||
let import_name = ImportName {
|
||||
namespace_index,
|
||||
name_index,
|
||||
};
|
||||
|
||||
match ty {
|
||||
ImportSectionEntryType::Function(sigindex) => {
|
||||
let sigindex = SigIndex::new(sigindex as usize);
|
||||
info.imported_functions.push(import_name);
|
||||
info.func_assoc.push(sigindex);
|
||||
mcg.feed_import_function()?;
|
||||
}
|
||||
ImportSectionEntryType::Table(table_ty) => {
|
||||
assert_eq!(table_ty.element_type, WpType::AnyFunc);
|
||||
let table_desc = TableDescriptor {
|
||||
element: ElementType::Anyfunc,
|
||||
minimum: table_ty.limits.initial,
|
||||
maximum: table_ty.limits.maximum,
|
||||
};
|
||||
|
||||
info.imported_tables.push((import_name, table_desc));
|
||||
}
|
||||
ImportSectionEntryType::Memory(memory_ty) => {
|
||||
let mem_desc = MemoryDescriptor {
|
||||
minimum: Pages(memory_ty.limits.initial),
|
||||
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
||||
shared: memory_ty.shared,
|
||||
};
|
||||
info.imported_memories.push((import_name, mem_desc));
|
||||
}
|
||||
ImportSectionEntryType::Global(global_ty) => {
|
||||
let global_desc = GlobalDescriptor {
|
||||
mutable: global_ty.mutable,
|
||||
ty: wp_type_to_type(global_ty.content_type)?,
|
||||
};
|
||||
info.imported_globals.push((import_name, global_desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info.namespace_table = namespace_builder.finish();
|
||||
info.name_table = name_builder.finish();
|
||||
}
|
||||
SectionCode::Function => {
|
||||
let func_decl_reader = section.get_function_section_reader()?;
|
||||
|
||||
for sigindex in func_decl_reader {
|
||||
let sigindex = sigindex?;
|
||||
|
||||
let sigindex = SigIndex::new(sigindex as usize);
|
||||
info.func_assoc.push(sigindex);
|
||||
}
|
||||
|
||||
mcg.feed_function_signatures(info.func_assoc.clone())?;
|
||||
}
|
||||
SectionCode::Table => {
|
||||
let table_decl_reader = section.get_table_section_reader()?;
|
||||
|
||||
for table_ty in table_decl_reader {
|
||||
let table_ty = table_ty?;
|
||||
|
||||
let table_desc = TableDescriptor {
|
||||
element: ElementType::Anyfunc,
|
||||
minimum: table_ty.limits.initial,
|
||||
maximum: table_ty.limits.maximum,
|
||||
};
|
||||
|
||||
info.tables.push(table_desc);
|
||||
}
|
||||
}
|
||||
SectionCode::Memory => {
|
||||
let mem_decl_reader = section.get_memory_section_reader()?;
|
||||
|
||||
for memory_ty in mem_decl_reader {
|
||||
let memory_ty = memory_ty?;
|
||||
|
||||
let mem_desc = MemoryDescriptor {
|
||||
minimum: Pages(memory_ty.limits.initial),
|
||||
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
||||
shared: memory_ty.shared,
|
||||
};
|
||||
|
||||
info.memories.push(mem_desc);
|
||||
}
|
||||
}
|
||||
SectionCode::Global => {
|
||||
let global_decl_reader = section.get_global_section_reader()?;
|
||||
|
||||
for global in global_decl_reader {
|
||||
let global = global?;
|
||||
|
||||
let desc = GlobalDescriptor {
|
||||
mutable: global.ty.mutable,
|
||||
ty: wp_type_to_type(global.ty.content_type)?,
|
||||
};
|
||||
|
||||
let global_init = GlobalInit {
|
||||
desc,
|
||||
init: eval_init_expr(&global.init_expr)?,
|
||||
};
|
||||
|
||||
info.globals.push(global_init);
|
||||
}
|
||||
}
|
||||
SectionCode::Export => {
|
||||
let export_reader = section.get_export_section_reader()?;
|
||||
|
||||
for export in export_reader {
|
||||
let Export { field, kind, index } = export?;
|
||||
|
||||
let export_index = match kind {
|
||||
ExternalKind::Function => ExportIndex::Func(FuncIndex::new(index as usize)),
|
||||
ExternalKind::Table => ExportIndex::Table(TableIndex::new(index as usize)),
|
||||
ExternalKind::Memory => {
|
||||
ExportIndex::Memory(MemoryIndex::new(index as usize))
|
||||
}
|
||||
ExternalKind::Global => {
|
||||
ExportIndex::Global(GlobalIndex::new(index as usize))
|
||||
}
|
||||
};
|
||||
|
||||
info.exports.insert(field.to_string(), export_index);
|
||||
}
|
||||
}
|
||||
SectionCode::Start => {
|
||||
let start_index = section.get_start_section_content()?;
|
||||
|
||||
info.start_func = Some(FuncIndex::new(start_index as usize));
|
||||
}
|
||||
SectionCode::Element => {
|
||||
let element_reader = section.get_element_section_reader()?;
|
||||
|
||||
for element in element_reader {
|
||||
let Element { kind, items } = element?;
|
||||
|
||||
match kind {
|
||||
ElementKind::Active {
|
||||
table_index,
|
||||
init_expr,
|
||||
} => {
|
||||
let table_index = TableIndex::new(table_index as usize);
|
||||
let base = eval_init_expr(&init_expr)?;
|
||||
let items_reader = items.get_items_reader()?;
|
||||
|
||||
let elements: Vec<_> = items_reader
|
||||
.into_iter()
|
||||
.map(|res| res.map(|index| FuncIndex::new(index as usize)))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
let table_init = TableInitializer {
|
||||
table_index,
|
||||
base,
|
||||
elements,
|
||||
};
|
||||
|
||||
info.elem_initializers.push(table_init);
|
||||
}
|
||||
ElementKind::Passive(_ty) => {
|
||||
return Err(BinaryReaderError {
|
||||
message: "passive tables are not yet supported",
|
||||
offset: -1isize as usize,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionCode::Code => {
|
||||
let mut code_reader = section.get_code_section_reader()?;
|
||||
if code_reader.get_count() as usize > info.func_assoc.len() {
|
||||
return Err(BinaryReaderError {
|
||||
message: "code_reader.get_count() > info.func_assoc.len()",
|
||||
offset: ::std::usize::MAX,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
mcg.check_precondition(&info)?;
|
||||
for i in 0..code_reader.get_count() {
|
||||
let item = code_reader.read()?;
|
||||
let fcg = mcg.next_function()?;
|
||||
let sig = info
|
||||
.signatures
|
||||
.get(
|
||||
*info
|
||||
.func_assoc
|
||||
.get(FuncIndex::new(i as usize + info.imported_functions.len()))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
for ret in sig.returns() {
|
||||
fcg.feed_return(type_to_wp_type(*ret))?;
|
||||
}
|
||||
for param in sig.params() {
|
||||
fcg.feed_param(type_to_wp_type(*param))?;
|
||||
}
|
||||
for local in item.get_locals_reader()? {
|
||||
let (count, ty) = local?;
|
||||
fcg.feed_local(ty, count as usize)?;
|
||||
}
|
||||
fcg.begin_body()?;
|
||||
for op in item.get_operators_reader()? {
|
||||
let op = op?;
|
||||
fcg.feed_opcode(op, &info)?;
|
||||
}
|
||||
fcg.finalize()?;
|
||||
}
|
||||
}
|
||||
SectionCode::Data => {
|
||||
let data_reader = section.get_data_section_reader()?;
|
||||
|
||||
for data in data_reader {
|
||||
let Data { kind, data } = data?;
|
||||
|
||||
match kind {
|
||||
DataKind::Active {
|
||||
memory_index,
|
||||
init_expr,
|
||||
} => {
|
||||
let memory_index = MemoryIndex::new(memory_index as usize);
|
||||
let base = eval_init_expr(&init_expr)?;
|
||||
|
||||
let data_init = DataInitializer {
|
||||
memory_index,
|
||||
base,
|
||||
data: data.to_vec(),
|
||||
};
|
||||
|
||||
info.data_initializers.push(data_init);
|
||||
}
|
||||
DataKind::Passive => {
|
||||
return Err(BinaryReaderError {
|
||||
message: "passive memories are not yet supported",
|
||||
offset: -1isize as usize,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionCode::DataCount => {}
|
||||
SectionCode::Custom { .. } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wp_type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
|
||||
Ok(match ty {
|
||||
WpType::I32 => Type::I32,
|
||||
WpType::I64 => Type::I64,
|
||||
WpType::F32 => Type::F32,
|
||||
WpType::F64 => Type::F64,
|
||||
WpType::V128 => {
|
||||
return Err(BinaryReaderError {
|
||||
message: "the wasmer llvm backend does not yet support the simd extension",
|
||||
offset: -1isize as usize,
|
||||
});
|
||||
}
|
||||
_ => panic!("broken invariant, invalid type"),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn type_to_wp_type(ty: Type) -> WpType {
|
||||
match ty {
|
||||
Type::I32 => WpType::I32,
|
||||
Type::I64 => WpType::I64,
|
||||
Type::F32 => WpType::F32,
|
||||
Type::F64 => WpType::F64,
|
||||
}
|
||||
}
|
||||
|
||||
fn func_type_to_func_sig(func_ty: FuncType) -> Result<FuncSig, BinaryReaderError> {
|
||||
assert_eq!(func_ty.form, WpType::Func);
|
||||
|
||||
Ok(FuncSig::new(
|
||||
func_ty
|
||||
.params
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(wp_type_to_type)
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
func_ty
|
||||
.returns
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(wp_type_to_type)
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
))
|
||||
}
|
||||
|
||||
fn eval_init_expr(expr: &InitExpr) -> Result<Initializer, BinaryReaderError> {
|
||||
let mut reader = expr.get_operators_reader();
|
||||
let (op, offset) = reader.read_with_offset()?;
|
||||
Ok(match op {
|
||||
Operator::GetGlobal { global_index } => {
|
||||
Initializer::GetGlobal(ImportedGlobalIndex::new(global_index as usize))
|
||||
}
|
||||
Operator::I32Const { value } => Initializer::Const(Value::I32(value)),
|
||||
Operator::I64Const { value } => Initializer::Const(Value::I64(value)),
|
||||
Operator::F32Const { value } => {
|
||||
Initializer::Const(Value::F32(f32::from_bits(value.bits())))
|
||||
}
|
||||
Operator::F64Const { value } => {
|
||||
Initializer::Const(Value::F64(f64::from_bits(value.bits())))
|
||||
}
|
||||
_ => {
|
||||
return Err(BinaryReaderError {
|
||||
message: "init expr evaluation failed: unsupported opcode",
|
||||
offset,
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
202
lib/dynasm-backend/src/protect_unix.rs
Normal file
202
lib/dynasm-backend/src/protect_unix.rs
Normal file
@ -0,0 +1,202 @@
|
||||
//! Installing signal handlers allows us to handle traps and out-of-bounds memory
|
||||
//! accesses that occur when runniing webassembly.
|
||||
//!
|
||||
//! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622
|
||||
//!
|
||||
//! When a WebAssembly module triggers any traps, we perform recovery here.
|
||||
//!
|
||||
//! This module uses TLS (thread-local storage) to track recovery information. Since the four signals we're handling
|
||||
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
|
||||
//! unless you have memory unsafety elsewhere in your code.
|
||||
//!
|
||||
use libc::{c_int, c_void, siginfo_t};
|
||||
use nix::sys::signal::{
|
||||
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
||||
};
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::ptr;
|
||||
use std::sync::Once;
|
||||
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||
|
||||
extern "C" fn signal_trap_handler(
|
||||
signum: ::nix::libc::c_int,
|
||||
siginfo: *mut siginfo_t,
|
||||
ucontext: *mut c_void,
|
||||
) {
|
||||
unsafe {
|
||||
do_unwind(signum, siginfo as _, ucontext);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn setjmp(env: *mut c_void) -> c_int;
|
||||
fn longjmp(env: *mut c_void, val: c_int) -> !;
|
||||
}
|
||||
|
||||
pub unsafe fn install_sighandler() {
|
||||
let sa = SigAction::new(
|
||||
SigHandler::SigAction(signal_trap_handler),
|
||||
SaFlags::SA_ONSTACK,
|
||||
SigSet::empty(),
|
||||
);
|
||||
sigaction(SIGFPE, &sa).unwrap();
|
||||
sigaction(SIGILL, &sa).unwrap();
|
||||
sigaction(SIGSEGV, &sa).unwrap();
|
||||
sigaction(SIGBUS, &sa).unwrap();
|
||||
}
|
||||
|
||||
const SETJMP_BUFFER_LEN: usize = 27;
|
||||
pub static SIGHANDLER_INIT: Once = Once::new();
|
||||
|
||||
thread_local! {
|
||||
pub static SETJMP_BUFFER: UnsafeCell<[c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]);
|
||||
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 unsafe fn trigger_trap() -> ! {
|
||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
||||
|
||||
longjmp(jmp_buf as *mut c_void, 0)
|
||||
}
|
||||
|
||||
pub fn call_protected<T>(f: impl FnOnce() -> T) -> RuntimeResult<T> {
|
||||
unsafe {
|
||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
||||
let prev_jmp_buf = *jmp_buf;
|
||||
|
||||
SIGHANDLER_INIT.call_once(|| {
|
||||
install_sighandler();
|
||||
});
|
||||
|
||||
let signum = setjmp(jmp_buf as *mut _);
|
||||
if signum != 0 {
|
||||
*jmp_buf = prev_jmp_buf;
|
||||
|
||||
let (faulting_addr, _inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
|
||||
|
||||
let signal = match Signal::from_c_int(signum) {
|
||||
Ok(SIGFPE) => "floating-point exception",
|
||||
Ok(SIGILL) => "illegal instruction",
|
||||
Ok(SIGSEGV) => "segmentation violation",
|
||||
Ok(SIGBUS) => "bus error",
|
||||
Err(_) => "error while getting the Signal",
|
||||
_ => "unkown trapped signal",
|
||||
};
|
||||
// When the trap-handler is fully implemented, this will return more information.
|
||||
Err(RuntimeError::Trap {
|
||||
msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
|
||||
}
|
||||
.into())
|
||||
} else {
|
||||
let ret = f(); // TODO: Switch stack?
|
||||
*jmp_buf = prev_jmp_buf;
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwinds to last protected_call.
|
||||
pub unsafe fn do_unwind(signum: i32, siginfo: *const c_void, ucontext: *const c_void) -> ! {
|
||||
// Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.)
|
||||
// itself, accessing TLS here is safe. In case any other code calls this, it often indicates a memory safety bug and you should
|
||||
// temporarily disable the signal handlers to debug it.
|
||||
|
||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
||||
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
|
||||
::std::process::abort();
|
||||
}
|
||||
|
||||
CAUGHT_ADDRESSES.with(|cell| cell.set(get_faulting_addr_and_ip(siginfo, ucontext)));
|
||||
|
||||
longjmp(jmp_buf as *mut ::nix::libc::c_void, signum)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||
unsafe fn get_faulting_addr_and_ip(
|
||||
siginfo: *const c_void,
|
||||
ucontext: *const c_void,
|
||||
) -> (*const c_void, *const c_void) {
|
||||
use libc::{ucontext_t, RIP};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
struct siginfo_t {
|
||||
si_signo: i32,
|
||||
si_errno: i32,
|
||||
si_code: i32,
|
||||
si_addr: u64,
|
||||
// ...
|
||||
}
|
||||
|
||||
let siginfo = siginfo as *const siginfo_t;
|
||||
let si_addr = (*siginfo).si_addr;
|
||||
|
||||
let ucontext = ucontext as *const ucontext_t;
|
||||
let rip = (*ucontext).uc_mcontext.gregs[RIP as usize];
|
||||
|
||||
(si_addr as _, rip as _)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||
unsafe fn get_faulting_addr_and_ip(
|
||||
siginfo: *const c_void,
|
||||
ucontext: *const c_void,
|
||||
) -> (*const c_void, *const c_void) {
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
struct ucontext_t {
|
||||
uc_onstack: u32,
|
||||
uc_sigmask: u32,
|
||||
uc_stack: libc::stack_t,
|
||||
uc_link: *const ucontext_t,
|
||||
uc_mcsize: u64,
|
||||
uc_mcontext: *const mcontext_t,
|
||||
}
|
||||
#[repr(C)]
|
||||
struct exception_state {
|
||||
trapno: u16,
|
||||
cpu: u16,
|
||||
err: u32,
|
||||
faultvaddr: u64,
|
||||
}
|
||||
#[repr(C)]
|
||||
struct regs {
|
||||
rax: u64,
|
||||
rbx: u64,
|
||||
rcx: u64,
|
||||
rdx: u64,
|
||||
rdi: u64,
|
||||
rsi: u64,
|
||||
rbp: u64,
|
||||
rsp: u64,
|
||||
r8: u64,
|
||||
r9: u64,
|
||||
r10: u64,
|
||||
r11: u64,
|
||||
r12: u64,
|
||||
r13: u64,
|
||||
r14: u64,
|
||||
r15: u64,
|
||||
rip: u64,
|
||||
rflags: u64,
|
||||
cs: u64,
|
||||
fs: u64,
|
||||
gs: u64,
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[repr(C)]
|
||||
struct mcontext_t {
|
||||
es: exception_state,
|
||||
ss: regs,
|
||||
// ...
|
||||
}
|
||||
|
||||
let siginfo = siginfo as *const siginfo_t;
|
||||
let si_addr = (*siginfo).si_addr;
|
||||
|
||||
let ucontext = ucontext as *const ucontext_t;
|
||||
let rip = (*(*ucontext).uc_mcontext).ss.rip;
|
||||
|
||||
(si_addr, rip as _)
|
||||
}
|
164
lib/dynasm-backend/src/stack.rs
Normal file
164
lib/dynasm-backend/src/stack.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use crate::codegen::CodegenError;
|
||||
use dynasmrt::DynamicLabel;
|
||||
use wasmparser::Type as WpType;
|
||||
|
||||
/*#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RegisterName {
|
||||
RDI,
|
||||
RSI,
|
||||
RDX,
|
||||
RCX,
|
||||
R8,
|
||||
R9,
|
||||
R10,
|
||||
R11,
|
||||
RBX,
|
||||
R12,
|
||||
R13,
|
||||
R14,
|
||||
R15,
|
||||
Invalid,
|
||||
}*/
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum IfElseState {
|
||||
None,
|
||||
If(DynamicLabel),
|
||||
Else,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ControlFrame {
|
||||
pub label: DynamicLabel,
|
||||
pub loop_like: bool,
|
||||
pub if_else: IfElseState,
|
||||
pub returns: Vec<WpType>,
|
||||
pub value_stack_depth_before: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ControlStack {
|
||||
pub frames: Vec<ControlFrame>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ValueStack {
|
||||
pub num_regs: u8,
|
||||
pub values: Vec<ValueInfo>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ValueInfo {
|
||||
pub ty: WpType,
|
||||
pub location: ValueLocation,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ValueLocation {
|
||||
Register(ScratchRegister),
|
||||
Stack,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ScratchRegister(u8);
|
||||
|
||||
impl ScratchRegister {
|
||||
pub fn raw_id(&self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueLocation {
|
||||
pub fn is_register(&self) -> bool {
|
||||
if let ValueLocation::Register(_) = *self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_register(&self) -> Result<ScratchRegister, CodegenError> {
|
||||
if let ValueLocation::Register(id) = *self {
|
||||
Ok(id)
|
||||
} else {
|
||||
Err(CodegenError {
|
||||
message: "not a register location",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueStack {
|
||||
pub fn new(num_regs: u8) -> ValueStack {
|
||||
ValueStack {
|
||||
num_regs: num_regs,
|
||||
values: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn next_location(&self, loc: &ValueLocation) -> ValueLocation {
|
||||
match *loc {
|
||||
ValueLocation::Register(ScratchRegister(x)) => {
|
||||
if x >= self.num_regs - 1 {
|
||||
ValueLocation::Stack
|
||||
} else {
|
||||
ValueLocation::Register(ScratchRegister(x + 1))
|
||||
}
|
||||
}
|
||||
ValueLocation::Stack => ValueLocation::Stack,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, ty: WpType) -> ValueLocation {
|
||||
let loc = self
|
||||
.values
|
||||
.last()
|
||||
.map(|x| self.next_location(&x.location))
|
||||
.unwrap_or(ValueLocation::Register(ScratchRegister(0)));
|
||||
self.values.push(ValueInfo {
|
||||
ty: ty,
|
||||
location: loc,
|
||||
});
|
||||
loc
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Result<ValueInfo, CodegenError> {
|
||||
match self.values.pop() {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(CodegenError {
|
||||
message: "no value on top of stack",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop2(&mut self) -> Result<(ValueInfo, ValueInfo), CodegenError> {
|
||||
if self.values.len() < 2 {
|
||||
Err(CodegenError {
|
||||
message: "less than 2 values on top of stack",
|
||||
})
|
||||
} else {
|
||||
let v2 = self.values.pop().unwrap();
|
||||
let v1 = self.values.pop().unwrap();
|
||||
Ok((v1, v2))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_depth(&mut self, target_depth: usize) {
|
||||
self.values.truncate(target_depth);
|
||||
}
|
||||
}
|
||||
|
||||
impl ControlStack {
|
||||
pub fn new(label: DynamicLabel, returns: Vec<WpType>) -> ControlStack {
|
||||
ControlStack {
|
||||
frames: vec![ControlFrame {
|
||||
label: label,
|
||||
loop_like: false,
|
||||
if_else: IfElseState::None,
|
||||
returns: returns,
|
||||
value_stack_depth_before: 0,
|
||||
}],
|
||||
}
|
||||
}
|
||||
}
|
@ -9,17 +9,16 @@ edition = "2018"
|
||||
build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
||||
wasmer-runtime-abi = { path = "../runtime-abi", optional = true }
|
||||
bit_field = "0.9.0"
|
||||
byteorder = "1"
|
||||
errno = "0.2.4"
|
||||
lazy_static = "1.2.0"
|
||||
libc = "0.2.49"
|
||||
byteorder = "1"
|
||||
time = "0.1.41"
|
||||
errno = "0.2.4"
|
||||
bit_field = "0.9.0"
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0", optional = true }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
||||
wasmer-runtime-abi = { path = "../runtime-abi", optional = true }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
|
||||
wasmer-dynasm-backend = { path = "../dynasm-backend", version = "0.1.0", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0", optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
@ -32,6 +31,7 @@ wabt = "0.7.2"
|
||||
glob = "0.2.11"
|
||||
|
||||
[features]
|
||||
clif = ["wasmer-clif-backend"]
|
||||
clif = []
|
||||
llvm = ["wasmer-llvm-backend"]
|
||||
dynasm = ["wasmer-dynasm-backend"]
|
||||
vfs = ["wasmer-runtime-abi"]
|
||||
|
@ -168,7 +168,13 @@ mod tests {
|
||||
LLVMCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif")))]
|
||||
#[cfg(feature = "dynasm")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_dynasm_backend::SinglePassCompiler;
|
||||
SinglePassCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "dynasm")))]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
panic!("compiler not specified, activate a compiler via features")
|
||||
}
|
||||
|
@ -20,7 +20,13 @@ macro_rules! assert_emscripten_output {
|
||||
LLVMCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif")))]
|
||||
#[cfg(feature = "dynasm")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_dynasm_backend::SinglePassCompiler;
|
||||
SinglePassCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "dynasm")))]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
panic!("compiler not specified, activate a compiler via features");
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
|
@ -8,13 +8,23 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime = { path = "../runtime", version = "0.2.1" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
||||
libc = "0.2"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[dependencies.wasmer-runtime]
|
||||
path = "../runtime"
|
||||
version = "0.2.1"
|
||||
|
||||
[dependencies.wasmer-runtime-core]
|
||||
path = "../runtime-core"
|
||||
version = "0.2.1"
|
||||
|
||||
[features]
|
||||
debug = ["wasmer-runtime/debug"]
|
||||
llvm = ["wasmer-runtime/llvm"]
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.8"
|
@ -10,9 +10,13 @@ use std::fmt;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
use std::{ffi::c_void, ptr};
|
||||
use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value};
|
||||
use wasmer_runtime::{
|
||||
default_compiler, Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value,
|
||||
};
|
||||
use wasmer_runtime_core::cache::Artifact;
|
||||
use wasmer_runtime_core::export::{Context, Export, FuncPointer};
|
||||
use wasmer_runtime_core::import::Namespace;
|
||||
use wasmer_runtime_core::load_cache_with;
|
||||
use wasmer_runtime_core::module::{ExportIndex, ImportName};
|
||||
use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type};
|
||||
use wasmer_runtime_core::units::{Bytes, Pages};
|
||||
@ -20,6 +24,9 @@ use wasmer_runtime_core::units::{Bytes, Pages};
|
||||
#[repr(C)]
|
||||
pub struct wasmer_module_t;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmer_serialized_module_t;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasmer_instance_t;
|
||||
|
||||
@ -165,7 +172,7 @@ pub unsafe extern "C" fn wasmer_validate(
|
||||
if wasm_bytes.is_null() {
|
||||
return false;
|
||||
}
|
||||
let bytes: &[u8] = ::std::slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize);
|
||||
let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize);
|
||||
|
||||
wasmer_runtime_core::validate(bytes)
|
||||
}
|
||||
@ -310,7 +317,7 @@ pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) {
|
||||
if !table.is_null() {
|
||||
drop(unsafe { Box::from_raw(table as *mut Table) });
|
||||
unsafe { Box::from_raw(table as *mut Table) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,7 +372,7 @@ pub extern "C" fn wasmer_global_get_descriptor(
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) {
|
||||
if !global.is_null() {
|
||||
drop(unsafe { Box::from_raw(global as *mut Global) });
|
||||
unsafe { Box::from_raw(global as *mut Global) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,7 +381,7 @@ pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) {
|
||||
if !memory.is_null() {
|
||||
drop(unsafe { Box::from_raw(memory as *mut Memory) });
|
||||
unsafe { Box::from_raw(memory as *mut Memory) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +398,7 @@ pub unsafe extern "C" fn wasmer_compile(
|
||||
wasm_bytes: *mut uint8_t,
|
||||
wasm_bytes_len: uint32_t,
|
||||
) -> wasmer_result_t {
|
||||
let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
|
||||
let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
|
||||
let result = wasmer_runtime::compile(bytes);
|
||||
let new_module = match result {
|
||||
Ok(instance) => instance,
|
||||
@ -509,13 +516,11 @@ pub struct NamedExportDescriptors(Vec<NamedExportDescriptor>);
|
||||
/// Frees the memory for the given export descriptors
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_export_descriptors_destroy(
|
||||
pub extern "C" fn wasmer_export_descriptors_destroy(
|
||||
export_descriptors: *mut wasmer_export_descriptors_t,
|
||||
) {
|
||||
if !export_descriptors.is_null() {
|
||||
drop(Box::from_raw(
|
||||
export_descriptors as *mut NamedExportDescriptors,
|
||||
));
|
||||
unsafe { Box::from_raw(export_descriptors as *mut NamedExportDescriptors) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,12 +574,150 @@ pub unsafe extern "C" fn wasmer_export_descriptor_kind(
|
||||
named_export_descriptor.kind.clone()
|
||||
}
|
||||
|
||||
/// Serialize the given Module.
|
||||
///
|
||||
/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
|
||||
///
|
||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
///
|
||||
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_module_serialize(
|
||||
serialized_module: *mut *mut wasmer_serialized_module_t,
|
||||
module: *const wasmer_module_t,
|
||||
) -> wasmer_result_t {
|
||||
let module = &*(module as *const Module);
|
||||
|
||||
match module.cache() {
|
||||
Ok(artifact) => match artifact.serialize() {
|
||||
Ok(serialized_artifact) => {
|
||||
*serialized_module = Box::into_raw(Box::new(serialized_artifact)) as _;
|
||||
|
||||
wasmer_result_t::WASMER_OK
|
||||
}
|
||||
Err(_) => {
|
||||
update_last_error(CApiError {
|
||||
msg: "Failed to serialize the module artifact".to_string(),
|
||||
});
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
update_last_error(CApiError {
|
||||
msg: "Failed to serialize the module".to_string(),
|
||||
});
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get bytes of the serialized module.
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_serialized_module_bytes(
|
||||
serialized_module: *const wasmer_serialized_module_t,
|
||||
) -> wasmer_byte_array {
|
||||
let serialized_module = &*(serialized_module as *const &[u8]);
|
||||
|
||||
wasmer_byte_array {
|
||||
bytes: serialized_module.as_ptr(),
|
||||
bytes_len: serialized_module.len() as u32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transform a sequence of bytes into a serialized module.
|
||||
///
|
||||
/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
|
||||
///
|
||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
///
|
||||
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_serialized_module_from_bytes(
|
||||
serialized_module: *mut *mut wasmer_serialized_module_t,
|
||||
serialized_module_bytes: *const uint8_t,
|
||||
serialized_module_bytes_length: uint32_t,
|
||||
) -> wasmer_result_t {
|
||||
if serialized_module.is_null() {
|
||||
update_last_error(CApiError {
|
||||
msg: "`serialized_module_bytes` pointer is null".to_string(),
|
||||
});
|
||||
return wasmer_result_t::WASMER_ERROR;
|
||||
}
|
||||
|
||||
let serialized_module_bytes: &[u8] = slice::from_raw_parts(
|
||||
serialized_module_bytes,
|
||||
serialized_module_bytes_length as usize,
|
||||
);
|
||||
|
||||
*serialized_module = Box::into_raw(Box::new(serialized_module_bytes)) as _;
|
||||
wasmer_result_t::WASMER_OK
|
||||
}
|
||||
|
||||
/// Deserialize the given serialized module.
|
||||
///
|
||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
///
|
||||
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_module_deserialize(
|
||||
module: *mut *mut wasmer_module_t,
|
||||
serialized_module: *const wasmer_serialized_module_t,
|
||||
) -> wasmer_result_t {
|
||||
if serialized_module.is_null() {
|
||||
update_last_error(CApiError {
|
||||
msg: "`serialized_module` pointer is null".to_string(),
|
||||
});
|
||||
return wasmer_result_t::WASMER_ERROR;
|
||||
}
|
||||
|
||||
let serialized_module: &[u8] = &*(serialized_module as *const &[u8]);
|
||||
|
||||
match Artifact::deserialize(serialized_module) {
|
||||
Ok(artifact) => match load_cache_with(artifact, default_compiler()) {
|
||||
Ok(deserialized_module) => {
|
||||
*module = Box::into_raw(Box::new(deserialized_module)) as _;
|
||||
wasmer_result_t::WASMER_OK
|
||||
}
|
||||
Err(_) => {
|
||||
update_last_error(CApiError {
|
||||
msg: "Failed to compile the serialized module".to_string(),
|
||||
});
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
update_last_error(CApiError {
|
||||
msg: "Failed to deserialize the module".to_string(),
|
||||
});
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees memory for the given serialized Module.
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_serialized_module_destroy(
|
||||
serialized_module: *mut wasmer_serialized_module_t,
|
||||
) {
|
||||
if !serialized_module.is_null() {
|
||||
unsafe { Box::from_raw(serialized_module as *mut &[u8]) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees memory for the given Module
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) {
|
||||
if !module.is_null() {
|
||||
drop(unsafe { Box::from_raw(module as *mut Module) });
|
||||
unsafe { Box::from_raw(module as *mut Module) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -682,13 +825,11 @@ pub struct NamedImportDescriptors(Vec<NamedImportDescriptor>);
|
||||
/// Frees the memory for the given import descriptors
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_import_descriptors_destroy(
|
||||
pub extern "C" fn wasmer_import_descriptors_destroy(
|
||||
import_descriptors: *mut wasmer_import_descriptors_t,
|
||||
) {
|
||||
if !import_descriptors.is_null() {
|
||||
drop(Box::from_raw(
|
||||
import_descriptors as *mut NamedImportDescriptors,
|
||||
));
|
||||
unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,7 +972,7 @@ pub unsafe extern "C" fn wasmer_instantiate(
|
||||
import_object.register(module_name, namespace);
|
||||
}
|
||||
|
||||
let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
|
||||
let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize);
|
||||
let result = wasmer_runtime::instantiate(bytes, &import_object);
|
||||
let new_instance = match result {
|
||||
Ok(instance) => instance,
|
||||
@ -964,9 +1105,9 @@ pub struct NamedExports(Vec<NamedExport>);
|
||||
/// Frees the memory for the given exports
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) {
|
||||
pub extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) {
|
||||
if !exports.is_null() {
|
||||
drop(Box::from_raw(exports as *mut NamedExports));
|
||||
unsafe { Box::from_raw(exports as *mut NamedExports) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1255,7 +1396,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity(
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) {
|
||||
if !func.is_null() {
|
||||
drop(unsafe { Box::from_raw(func as *mut Export) });
|
||||
unsafe { Box::from_raw(func as *mut Export) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1395,7 +1536,7 @@ pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) {
|
||||
if !instance.is_null() {
|
||||
drop(unsafe { Box::from_raw(instance as *mut Instance) });
|
||||
unsafe { Box::from_raw(instance as *mut Instance) };
|
||||
}
|
||||
}
|
||||
|
||||
|
11
lib/runtime-c-api/tests/.gitignore
vendored
11
lib/runtime-c-api/tests/.gitignore
vendored
@ -9,15 +9,16 @@ install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
test-globals
|
||||
rust-build
|
||||
test-exports
|
||||
test-instantiate
|
||||
test-imports
|
||||
test-globals
|
||||
test-import-function
|
||||
test-imports
|
||||
test-instantiate
|
||||
test-memory
|
||||
test-module-imports
|
||||
test-module
|
||||
test-module-exports
|
||||
test-module-imports
|
||||
test-module-serialize
|
||||
test-tables
|
||||
test-validate
|
||||
rust-build
|
@ -1,17 +1,18 @@
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (WasmerRuntimeCApiTests)
|
||||
|
||||
add_executable(test-imports test-imports.c)
|
||||
add_executable(test-exports test-exports.c)
|
||||
add_executable(test-globals test-globals.c)
|
||||
add_executable(test-instantiate test-instantiate.c)
|
||||
add_executable(test-import-function test-import-function.c)
|
||||
add_executable(test-imports test-imports.c)
|
||||
add_executable(test-instantiate test-instantiate.c)
|
||||
add_executable(test-memory test-memory.c)
|
||||
add_executable(test-module-imports test-module-imports.c)
|
||||
add_executable(test-module test-module.c)
|
||||
add_executable(test-module-exports test-module-exports.c)
|
||||
add_executable(test-validate test-validate.c)
|
||||
add_executable(test-module-imports test-module-imports.c)
|
||||
add_executable(test-module-serialize test-module-serialize.c)
|
||||
add_executable(test-tables test-tables.c)
|
||||
add_executable(test-validate test-validate.c)
|
||||
|
||||
find_library(
|
||||
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll
|
||||
@ -34,10 +35,6 @@ set(
|
||||
"/WX" >
|
||||
)
|
||||
|
||||
target_link_libraries(test-imports general ${WASMER_LIB})
|
||||
target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-imports test-imports)
|
||||
|
||||
target_link_libraries(test-exports general ${WASMER_LIB})
|
||||
target_compile_options(test-exports PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-exports test-exports)
|
||||
@ -46,22 +43,22 @@ target_link_libraries(test-globals general ${WASMER_LIB})
|
||||
target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-globals test-globals)
|
||||
|
||||
target_link_libraries(test-instantiate general ${WASMER_LIB})
|
||||
target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-instantiate test-instantiate)
|
||||
|
||||
target_link_libraries(test-import-function general ${WASMER_LIB})
|
||||
target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-import-function test-import-function)
|
||||
|
||||
target_link_libraries(test-imports general ${WASMER_LIB})
|
||||
target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-imports test-imports)
|
||||
|
||||
target_link_libraries(test-instantiate general ${WASMER_LIB})
|
||||
target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-instantiate test-instantiate)
|
||||
|
||||
target_link_libraries(test-memory general ${WASMER_LIB})
|
||||
target_compile_options(test-memory PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-memory test-memory)
|
||||
|
||||
target_link_libraries(test-module-imports general ${WASMER_LIB})
|
||||
target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-module-imports test-module-imports)
|
||||
|
||||
target_link_libraries(test-module general ${WASMER_LIB})
|
||||
target_compile_options(test-module PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-module test-module)
|
||||
@ -70,10 +67,18 @@ target_link_libraries(test-module-exports general ${WASMER_LIB})
|
||||
target_compile_options(test-module-exports PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-module-exports test-module-exports)
|
||||
|
||||
target_link_libraries(test-validate general ${WASMER_LIB})
|
||||
target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-validate test-validate)
|
||||
target_link_libraries(test-module-imports general ${WASMER_LIB})
|
||||
target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-module-imports test-module-imports)
|
||||
|
||||
target_link_libraries(test-module-serialize general ${WASMER_LIB})
|
||||
target_compile_options(test-module-serialize PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-module-serialize test-module-serialize)
|
||||
|
||||
target_link_libraries(test-tables general ${WASMER_LIB})
|
||||
target_compile_options(test-tables PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-tables test-tables)
|
||||
|
||||
target_link_libraries(test-validate general ${WASMER_LIB})
|
||||
target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-validate test-validate)
|
||||
|
93
lib/runtime-c-api/tests/test-module-serialize.c
Normal file
93
lib/runtime-c-api/tests/test-module-serialize.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
#include "../wasmer.h"
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Read the wasm file bytes
|
||||
FILE *file = fopen("sum.wasm", "r");
|
||||
fseek(file, 0, SEEK_END);
|
||||
long len = ftell(file);
|
||||
uint8_t *bytes = malloc(len);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fread(bytes, 1, len, file);
|
||||
fclose(file);
|
||||
|
||||
wasmer_module_t *module_one = NULL;
|
||||
wasmer_result_t compile_result = wasmer_compile(&module_one, bytes, len);
|
||||
printf("Compile result: %d\n", compile_result);
|
||||
assert(compile_result == WASMER_OK);
|
||||
|
||||
wasmer_serialized_module_t *serialized_module = NULL;
|
||||
wasmer_result_t serialize_result = wasmer_module_serialize(&serialized_module, module_one);
|
||||
printf("Serialize result: %d\n", serialize_result);
|
||||
assert(serialize_result == WASMER_OK);
|
||||
|
||||
wasmer_byte_array serialized_module_bytes = wasmer_serialized_module_bytes(serialized_module);
|
||||
printf("Serialized module pointer: %p\n", serialized_module_bytes.bytes);
|
||||
printf("Serialized module length: %d\n", serialized_module_bytes.bytes_len);
|
||||
assert(serialized_module_bytes.bytes != NULL);
|
||||
assert(serialized_module_bytes.bytes_len > 8);
|
||||
assert(serialized_module_bytes.bytes[0] == 'W');
|
||||
assert(serialized_module_bytes.bytes[1] == 'A');
|
||||
assert(serialized_module_bytes.bytes[2] == 'S');
|
||||
assert(serialized_module_bytes.bytes[3] == 'M');
|
||||
assert(serialized_module_bytes.bytes[4] == 'E');
|
||||
assert(serialized_module_bytes.bytes[5] == 'R');
|
||||
|
||||
wasmer_module_t *module_two = NULL;
|
||||
wasmer_result_t unserialize_result = wasmer_module_deserialize(&module_two, serialized_module);
|
||||
assert(unserialize_result == WASMER_OK);
|
||||
|
||||
wasmer_import_t imports[] = {};
|
||||
wasmer_instance_t *instance = NULL;
|
||||
wasmer_result_t instantiate_result = wasmer_module_instantiate(module_two, &instance, imports, 0);
|
||||
printf("Instantiate result: %d\n", compile_result);
|
||||
assert(instantiate_result == WASMER_OK);
|
||||
|
||||
wasmer_value_t param_one;
|
||||
param_one.tag = WASM_I32;
|
||||
param_one.value.I32 = 7;
|
||||
wasmer_value_t param_two;
|
||||
param_two.tag = WASM_I32;
|
||||
param_two.value.I32 = 8;
|
||||
wasmer_value_t params[] = {param_one, param_two};
|
||||
|
||||
wasmer_value_t result_one;
|
||||
wasmer_value_t results[] = {result_one};
|
||||
|
||||
wasmer_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1);
|
||||
printf("Call result: %d\n", call_result);
|
||||
printf("Result: %d\n", results[0].value.I32);
|
||||
assert(results[0].value.I32 == 15);
|
||||
assert(call_result == WASMER_OK);
|
||||
|
||||
wasmer_serialized_module_t *serialized_module_two = NULL;
|
||||
wasmer_result_t serialized_module_from_bytes_result = wasmer_serialized_module_from_bytes(
|
||||
&serialized_module_two,
|
||||
serialized_module_bytes.bytes,
|
||||
serialized_module_bytes.bytes_len
|
||||
);
|
||||
assert(serialized_module_from_bytes_result == WASMER_OK);
|
||||
|
||||
wasmer_module_t *module_three = NULL;
|
||||
wasmer_result_t unserialized_result_two = wasmer_module_deserialize(&module_three, serialized_module_two);
|
||||
assert(unserialized_result_two == WASMER_OK);
|
||||
|
||||
wasmer_instance_t *instance_two = NULL;
|
||||
wasmer_result_t instantiate_result_two = wasmer_module_instantiate(module_three, &instance, imports, 0);
|
||||
assert(instantiate_result_two == WASMER_OK);
|
||||
|
||||
printf("Destroy the serialized module\n");
|
||||
wasmer_serialized_module_destroy(serialized_module);
|
||||
wasmer_serialized_module_destroy(serialized_module_two);
|
||||
|
||||
printf("Destroy instance\n");
|
||||
wasmer_instance_destroy(instance);
|
||||
|
||||
printf("Destroy modules\n");
|
||||
wasmer_module_destroy(module_one);
|
||||
wasmer_module_destroy(module_two);
|
||||
return 0;
|
||||
}
|
@ -129,6 +129,10 @@ typedef struct {
|
||||
wasmer_limit_option_t max;
|
||||
} wasmer_limits_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} wasmer_serialized_module_t;
|
||||
|
||||
/**
|
||||
* Creates a new Module from the given wasm bytes.
|
||||
* Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
@ -488,6 +492,15 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory);
|
||||
*/
|
||||
wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits);
|
||||
|
||||
/**
|
||||
* Deserialize the given serialized module.
|
||||
* Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
* Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
* and `wasmer_last_error_message` to get an error message.
|
||||
*/
|
||||
wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module,
|
||||
const wasmer_serialized_module_t *serialized_module);
|
||||
|
||||
/**
|
||||
* Frees memory for the given Module
|
||||
*/
|
||||
@ -504,6 +517,37 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module,
|
||||
wasmer_import_t *imports,
|
||||
int imports_len);
|
||||
|
||||
/**
|
||||
* Serialize the given Module.
|
||||
* The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
|
||||
* Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
* Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
* and `wasmer_last_error_message` to get an error message.
|
||||
*/
|
||||
wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module,
|
||||
const wasmer_module_t *module);
|
||||
|
||||
/**
|
||||
* Get bytes of the serialized module.
|
||||
*/
|
||||
wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module);
|
||||
|
||||
/**
|
||||
* Frees memory for the given serialized Module.
|
||||
*/
|
||||
void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module);
|
||||
|
||||
/**
|
||||
* Transform a sequence of bytes into a serialized module.
|
||||
* The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
|
||||
* Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
* Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
* and `wasmer_last_error_message` to get an error message.
|
||||
*/
|
||||
wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module,
|
||||
const uint8_t *serialized_module_bytes,
|
||||
uint32_t serialized_module_bytes_length);
|
||||
|
||||
/**
|
||||
* Frees memory for the given Table
|
||||
*/
|
||||
|
@ -126,6 +126,10 @@ struct wasmer_limits_t {
|
||||
wasmer_limit_option_t max;
|
||||
};
|
||||
|
||||
struct wasmer_serialized_module_t {
|
||||
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
/// Creates a new Module from the given wasm bytes.
|
||||
@ -385,6 +389,13 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory);
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits);
|
||||
|
||||
/// Deserialize the given serialized module.
|
||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module,
|
||||
const wasmer_serialized_module_t *serialized_module);
|
||||
|
||||
/// Frees memory for the given Module
|
||||
void wasmer_module_destroy(wasmer_module_t *module);
|
||||
|
||||
@ -397,6 +408,29 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module,
|
||||
wasmer_import_t *imports,
|
||||
int imports_len);
|
||||
|
||||
/// Serialize the given Module.
|
||||
/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
|
||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module,
|
||||
const wasmer_module_t *module);
|
||||
|
||||
/// Get bytes of the serialized module.
|
||||
wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module);
|
||||
|
||||
/// Frees memory for the given serialized Module.
|
||||
void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module);
|
||||
|
||||
/// Transform a sequence of bytes into a serialized module.
|
||||
/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
|
||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
|
||||
/// and `wasmer_last_error_message` to get an error message.
|
||||
wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module,
|
||||
const uint8_t *serialized_module_bytes,
|
||||
uint32_t serialized_module_bytes_length);
|
||||
|
||||
/// Frees memory for the given Table
|
||||
void wasmer_table_destroy(wasmer_table_t *table);
|
||||
|
||||
|
@ -43,5 +43,8 @@ winapi = { version = "0.3", features = ["memoryapi"] }
|
||||
[dev-dependencies]
|
||||
field-offset = "0.1.1"
|
||||
|
||||
[build-dependencies]
|
||||
blake2b_simd = "0.4.1"
|
||||
|
||||
[features]
|
||||
debug = []
|
||||
|
26
lib/runtime-core/build.rs
Normal file
26
lib/runtime-core/build.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use blake2b_simd::blake2bp;
|
||||
use std::{env, fs, io::Write, path::PathBuf};
|
||||
|
||||
const WASMER_VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
fn main() {
|
||||
let mut state = blake2bp::State::new();
|
||||
state.update(WASMER_VERSION.as_bytes());
|
||||
|
||||
let hasher = state.finalize();
|
||||
let hash_string = hasher.to_hex().as_str().to_owned();
|
||||
|
||||
let crate_dir = env::var("OUT_DIR").unwrap();
|
||||
let wasmer_version_hash_file = {
|
||||
let mut path = PathBuf::from(&crate_dir);
|
||||
path.push("wasmer_version_hash.txt");
|
||||
path
|
||||
};
|
||||
|
||||
let mut f_out = fs::File::create(wasmer_version_hash_file)
|
||||
.expect("Could not create file for wasmer hash value");
|
||||
|
||||
f_out
|
||||
.write_all(hash_string.as_bytes())
|
||||
.expect("Could not write to file for wasmer hash value");
|
||||
}
|
@ -22,6 +22,7 @@ pub use crate::sig_registry::SigRegistry;
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Backend {
|
||||
Cranelift,
|
||||
Dynasm,
|
||||
LLVM,
|
||||
}
|
||||
|
||||
|
@ -207,3 +207,7 @@ pub trait Cache {
|
||||
fn load(&self, key: WasmHash) -> Result<Module, Self::LoadError>;
|
||||
fn store(&mut self, key: WasmHash, module: Module) -> Result<(), Self::StoreError>;
|
||||
}
|
||||
|
||||
/// A unique ID generated from the version of Wasmer for use with cache versioning
|
||||
pub const WASMER_VERSION_HASH: &'static str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/wasmer_version_hash.txt"));
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::types::{FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, Value};
|
||||
use crate::types::{
|
||||
FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type,
|
||||
Value,
|
||||
};
|
||||
use core::borrow::Borrow;
|
||||
use std::any::Any;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
pub type CompileResult<T> = std::result::Result<T, CompileError>;
|
||||
|
@ -1,4 +1,8 @@
|
||||
use crate::{memory::MemoryType, module::ModuleInfo, structures::TypedIndex, units::Pages};
|
||||
use crate::error::{CompileError, CompileResult};
|
||||
use crate::{
|
||||
memory::MemoryType, module::ModuleInfo, module::ModuleInner, structures::TypedIndex,
|
||||
units::Pages,
|
||||
};
|
||||
use std::{borrow::Cow, mem};
|
||||
|
||||
/// Represents a WebAssembly type.
|
||||
|
@ -13,32 +13,8 @@ use std::{ffi::c_void, mem, ptr};
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Ctx {
|
||||
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
|
||||
pub(crate) memories: *mut *mut LocalMemory,
|
||||
|
||||
/// A pointer to an array of locally-defined tables, indexed by `TableIndex`.
|
||||
pub(crate) tables: *mut *mut LocalTable,
|
||||
|
||||
/// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`.
|
||||
pub(crate) globals: *mut *mut LocalGlobal,
|
||||
|
||||
/// A pointer to an array of imported memories, indexed by `MemoryIndex,
|
||||
pub(crate) imported_memories: *mut *mut LocalMemory,
|
||||
|
||||
/// A pointer to an array of imported tables, indexed by `TableIndex`.
|
||||
pub(crate) imported_tables: *mut *mut LocalTable,
|
||||
|
||||
/// A pointer to an array of imported globals, indexed by `GlobalIndex`.
|
||||
pub(crate) imported_globals: *mut *mut LocalGlobal,
|
||||
|
||||
/// A pointer to an array of imported functions, indexed by `FuncIndex`.
|
||||
pub(crate) imported_funcs: *mut ImportedFunc,
|
||||
|
||||
/// A pointer to an array of signature ids. Conceptually, this maps
|
||||
/// from a static, module-local signature id to a runtime-global
|
||||
/// signature id. This is used to allow call-indirect to other
|
||||
/// modules safely.
|
||||
pub(crate) dynamic_sigindices: *const SigId,
|
||||
// `internal` must be the first field of `Ctx`.
|
||||
pub(crate) internal: InternalCtx,
|
||||
|
||||
pub(crate) local_functions: *const *const Func,
|
||||
|
||||
@ -50,6 +26,41 @@ pub struct Ctx {
|
||||
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
|
||||
}
|
||||
|
||||
/// The internal context of the currently running WebAssembly instance.
|
||||
///
|
||||
///
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct InternalCtx {
|
||||
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
|
||||
pub memories: *mut *mut LocalMemory,
|
||||
|
||||
/// A pointer to an array of locally-defined tables, indexed by `TableIndex`.
|
||||
pub tables: *mut *mut LocalTable,
|
||||
|
||||
/// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`.
|
||||
pub globals: *mut *mut LocalGlobal,
|
||||
|
||||
/// A pointer to an array of imported memories, indexed by `MemoryIndex,
|
||||
pub imported_memories: *mut *mut LocalMemory,
|
||||
|
||||
/// A pointer to an array of imported tables, indexed by `TableIndex`.
|
||||
pub imported_tables: *mut *mut LocalTable,
|
||||
|
||||
/// A pointer to an array of imported globals, indexed by `GlobalIndex`.
|
||||
pub imported_globals: *mut *mut LocalGlobal,
|
||||
|
||||
/// A pointer to an array of imported functions, indexed by `FuncIndex`.
|
||||
pub imported_funcs: *mut ImportedFunc,
|
||||
|
||||
/// A pointer to an array of signature ids. Conceptually, this maps
|
||||
/// from a static, module-local signature id to a runtime-global
|
||||
/// signature id. This is used to allow call-indirect to other
|
||||
/// modules safely.
|
||||
pub dynamic_sigindices: *const SigId,
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
#[doc(hidden)]
|
||||
pub unsafe fn new(
|
||||
@ -58,6 +69,7 @@ impl Ctx {
|
||||
module: &ModuleInner,
|
||||
) -> Self {
|
||||
Self {
|
||||
internal: InternalCtx {
|
||||
memories: local_backing.vm_memories.as_mut_ptr(),
|
||||
tables: local_backing.vm_tables.as_mut_ptr(),
|
||||
globals: local_backing.vm_globals.as_mut_ptr(),
|
||||
@ -68,6 +80,7 @@ impl Ctx {
|
||||
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
|
||||
|
||||
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
|
||||
},
|
||||
local_functions: local_backing.local_functions.as_ptr(),
|
||||
|
||||
local_backing,
|
||||
@ -88,6 +101,7 @@ impl Ctx {
|
||||
data_finalizer: extern "C" fn(*mut c_void),
|
||||
) -> Self {
|
||||
Self {
|
||||
internal: InternalCtx {
|
||||
memories: local_backing.vm_memories.as_mut_ptr(),
|
||||
tables: local_backing.vm_tables.as_mut_ptr(),
|
||||
globals: local_backing.vm_globals.as_mut_ptr(),
|
||||
@ -98,6 +112,7 @@ impl Ctx {
|
||||
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
|
||||
|
||||
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
|
||||
},
|
||||
local_functions: local_backing.local_functions.as_ptr(),
|
||||
|
||||
local_backing,
|
||||
@ -333,43 +348,45 @@ impl Anyfunc {
|
||||
|
||||
#[cfg(test)]
|
||||
mod vm_offset_tests {
|
||||
use super::{Anyfunc, Ctx, ImportedFunc, LocalGlobal, LocalMemory, LocalTable};
|
||||
use super::{Anyfunc, Ctx, ImportedFunc, InternalCtx, LocalGlobal, LocalMemory, LocalTable};
|
||||
|
||||
#[test]
|
||||
fn vmctx() {
|
||||
assert_eq!(0usize, offset_of!(Ctx => internal).get_byte_offset(),);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_memories() as usize,
|
||||
offset_of!(Ctx => memories).get_byte_offset(),
|
||||
offset_of!(InternalCtx => memories).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_tables() as usize,
|
||||
offset_of!(Ctx => tables).get_byte_offset(),
|
||||
offset_of!(InternalCtx => tables).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_globals() as usize,
|
||||
offset_of!(Ctx => globals).get_byte_offset(),
|
||||
offset_of!(InternalCtx => globals).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_imported_memories() as usize,
|
||||
offset_of!(Ctx => imported_memories).get_byte_offset(),
|
||||
offset_of!(InternalCtx => imported_memories).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_imported_tables() as usize,
|
||||
offset_of!(Ctx => imported_tables).get_byte_offset(),
|
||||
offset_of!(InternalCtx => imported_tables).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_imported_globals() as usize,
|
||||
offset_of!(Ctx => imported_globals).get_byte_offset(),
|
||||
offset_of!(InternalCtx => imported_globals).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_imported_funcs() as usize,
|
||||
offset_of!(Ctx => imported_funcs).get_byte_offset(),
|
||||
offset_of!(InternalCtx => imported_funcs).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -17,7 +17,7 @@ pub unsafe extern "C" fn local_static_memory_grow(
|
||||
memory_index: LocalMemoryIndex,
|
||||
delta: Pages,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let local_memory = *ctx.internal.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
@ -30,7 +30,7 @@ pub unsafe extern "C" fn local_static_memory_size(
|
||||
ctx: &vm::Ctx,
|
||||
memory_index: LocalMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let local_memory = *ctx.internal.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
(*memory).size()
|
||||
@ -41,7 +41,7 @@ pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||
memory_index: LocalMemoryIndex,
|
||||
delta: Pages,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let local_memory = *ctx.internal.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
@ -54,7 +54,7 @@ pub unsafe extern "C" fn local_dynamic_memory_size(
|
||||
ctx: &vm::Ctx,
|
||||
memory_index: LocalMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let local_memory = *ctx.internal.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
(*memory).size()
|
||||
@ -69,7 +69,10 @@ pub unsafe extern "C" fn imported_static_memory_grow(
|
||||
import_memory_index: ImportedMemoryIndex,
|
||||
delta: Pages,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||
let local_memory = *ctx
|
||||
.internal
|
||||
.imported_memories
|
||||
.add(import_memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
@ -82,7 +85,10 @@ pub unsafe extern "C" fn imported_static_memory_size(
|
||||
ctx: &vm::Ctx,
|
||||
import_memory_index: ImportedMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||
let local_memory = *ctx
|
||||
.internal
|
||||
.imported_memories
|
||||
.add(import_memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
(*memory).size()
|
||||
@ -93,7 +99,7 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow(
|
||||
memory_index: ImportedMemoryIndex,
|
||||
delta: Pages,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||
let local_memory = *ctx.internal.imported_memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
@ -106,7 +112,7 @@ pub unsafe extern "C" fn imported_dynamic_memory_size(
|
||||
ctx: &vm::Ctx,
|
||||
memory_index: ImportedMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||
let local_memory = *ctx.internal.imported_memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
(*memory).size()
|
||||
|
@ -9,6 +9,7 @@ edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-dynasm-backend = { path = "../dynasm-backend", optional = true }
|
||||
lazy_static = "1.2.0"
|
||||
memmap = "0.7.0"
|
||||
|
||||
@ -19,6 +20,7 @@ version = "0.2.1"
|
||||
[dependencies.wasmer-clif-backend]
|
||||
path = "../clif-backend"
|
||||
version = "0.2.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.0.7"
|
||||
@ -30,8 +32,12 @@ path = "../llvm-backend"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = ["default-compiler"]
|
||||
default-compiler = ["wasmer-clif-backend"]
|
||||
cache = ["default-compiler"]
|
||||
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
llvm = ["wasmer-llvm-backend"]
|
||||
dynasm = ["wasmer-dynasm-backend"]
|
||||
|
||||
[[bench]]
|
||||
name = "nginx"
|
||||
|
@ -7,7 +7,7 @@ use std::{
|
||||
};
|
||||
|
||||
use wasmer_runtime_core::cache::Error as CacheError;
|
||||
pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash};
|
||||
pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash, WASMER_VERSION_HASH};
|
||||
|
||||
/// Representation of a directory that contains compiled wasm artifacts.
|
||||
///
|
||||
@ -40,12 +40,17 @@ pub struct FileSystemCache {
|
||||
|
||||
impl FileSystemCache {
|
||||
/// Construct a new `FileSystemCache` around the specified directory.
|
||||
/// The contents of the cache are stored in sub-versioned directories.
|
||||
///
|
||||
/// # Note:
|
||||
/// This method is unsafe because there's no way to ensure the artifacts
|
||||
/// stored in this cache haven't been corrupted or tampered with.
|
||||
pub unsafe fn new<P: Into<PathBuf>>(path: P) -> io::Result<Self> {
|
||||
let path: PathBuf = path.into();
|
||||
let path: PathBuf = {
|
||||
let mut path = path.into();
|
||||
path.push(WASMER_VERSION_HASH);
|
||||
path
|
||||
};
|
||||
|
||||
if path.exists() {
|
||||
let metadata = path.metadata()?;
|
||||
|
@ -152,13 +152,17 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result<I
|
||||
module.instantiate(import_object)
|
||||
}
|
||||
|
||||
fn default_compiler() -> &'static dyn Compiler {
|
||||
/// Get a single instance of the default compiler to use.
|
||||
pub fn default_compiler() -> &'static dyn Compiler {
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
use wasmer_llvm_backend::LLVMCompiler as DefaultCompiler;
|
||||
|
||||
#[cfg(not(feature = "llvm"))]
|
||||
#[cfg(feature = "dynasm")]
|
||||
use wasmer_dynasm_backend::SinglePassCompiler as DefaultCompiler;
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "dynasm")))]
|
||||
use wasmer_clif_backend::CraneliftCompiler as DefaultCompiler;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -10,19 +10,19 @@ build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.0" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0", optional = true }
|
||||
wasmer-dynasm-backend = { path = "../dynasm-backend", version = "0.1.0", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.7.2"
|
||||
|
||||
[dev-dependencies]
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
|
||||
wabt = "0.7.2"
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.1.0", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["fast-tests"]
|
||||
fast-tests = []
|
||||
clif = []
|
||||
llvm = ["wasmer-llvm-backend"]
|
||||
dynasm = ["wasmer-dynasm-backend"]
|
@ -107,7 +107,13 @@ fn get_compiler() -> impl Compiler {
|
||||
LLVMCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif")))]
|
||||
#[cfg(feature = "dynasm")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_dynasm_backend::SinglePassCompiler;
|
||||
SinglePassCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "dynasm")))]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
panic!("compiler not specified, activate a compiler via features");
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
|
@ -22,7 +22,13 @@ fn get_compiler() -> impl Compiler {
|
||||
LLVMCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif")))]
|
||||
#[cfg(feature = "dynasm")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_dynasm_backend::SinglePassCompiler;
|
||||
SinglePassCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "dynasm")))]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
panic!("compiler not specified, activate a compiler via features");
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
|
@ -12,7 +12,7 @@ use structopt::StructOpt;
|
||||
use wasmer::webassembly::InstanceABI;
|
||||
use wasmer::*;
|
||||
use wasmer_emscripten;
|
||||
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash};
|
||||
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "wasmer", about = "Wasm execution runtime.")]
|
||||
@ -48,9 +48,11 @@ struct Run {
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
enum Cache {
|
||||
/// Clear the cache
|
||||
#[structopt(name = "clean")]
|
||||
Clean,
|
||||
|
||||
/// Display the location of the cache
|
||||
#[structopt(name = "dir")]
|
||||
Dir,
|
||||
}
|
||||
@ -72,6 +74,7 @@ fn get_cache_dir() -> PathBuf {
|
||||
// We use a temporal directory for saving cache files
|
||||
let mut temp_dir = env::temp_dir();
|
||||
temp_dir.push("wasmer");
|
||||
temp_dir.push(WASMER_VERSION_HASH);
|
||||
temp_dir
|
||||
}
|
||||
}
|
||||
@ -128,8 +131,9 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
let module = webassembly::compile(&wasm_binary[..])
|
||||
.map_err(|e| format!("Can't compile module: {:?}", e))?;
|
||||
|
||||
// We save the module into a cache file
|
||||
cache.store(hash, module.clone()).unwrap();
|
||||
// We try to save the module into a cache file
|
||||
cache.store(hash, module.clone()).unwrap_or_default();
|
||||
|
||||
module
|
||||
}
|
||||
};
|
||||
@ -194,8 +198,10 @@ fn main() {
|
||||
Cache::Clean => {
|
||||
use std::fs;
|
||||
let cache_dir = get_cache_dir();
|
||||
if cache_dir.exists() {
|
||||
fs::remove_dir_all(cache_dir.clone()).expect("Can't remove cache dir");
|
||||
fs::create_dir(cache_dir.clone()).expect("Can't create cache dir");
|
||||
}
|
||||
fs::create_dir_all(cache_dir.clone()).expect("Can't create cache dir");
|
||||
}
|
||||
Cache::Dir => {
|
||||
println!("{}", get_cache_dir().to_string_lossy());
|
||||
|
@ -4,6 +4,7 @@ use wasmer_runtime::{
|
||||
error::{CallResult, Result},
|
||||
ImportObject, Instance, Module,
|
||||
};
|
||||
use wasmer_runtime_core::types::Value;
|
||||
|
||||
use wasmer_emscripten::{is_emscripten_module, run_emscripten_instance};
|
||||
|
||||
@ -86,7 +87,11 @@ pub fn run_instance(
|
||||
if is_emscripten_module(module) {
|
||||
run_emscripten_instance(module, instance, path, args)?;
|
||||
} else {
|
||||
instance.call("main", &[])?;
|
||||
let args: Vec<Value> = args
|
||||
.into_iter()
|
||||
.map(|x| Value::I32(x.parse().unwrap()))
|
||||
.collect();
|
||||
instance.call("main", &args)?;
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
Reference in New Issue
Block a user