mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05:33 +00:00
Merge remote-tracking branch 'origin/feature/clif-cgapi' into feature/metering
This commit is contained in:
commit
8019505e65
@ -284,10 +284,11 @@ jobs:
|
||||
# VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||
# echo "${VERSION}" >> artifacts/version
|
||||
- run:
|
||||
name: Dynamic library
|
||||
name: Generate dynamic library for the runtime C API
|
||||
command: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml
|
||||
install_name_tool -id "@rpath/libwasmer_runtime_c_api.dylib" target/release/libwasmer_runtime_c_api.dylib
|
||||
cp target/release/libwasmer_runtime_c_api.dylib ./artifacts
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
@ -362,7 +363,7 @@ jobs:
|
||||
# VERSION_TAG=$(git describe --exact-match --tags)
|
||||
#if [ "$VERSION" == "$VERSION_TAG" ]; then
|
||||
# echo "Versions match, publishing to Github"
|
||||
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} ./artifacts/
|
||||
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} ./artifacts/ || true
|
||||
#else
|
||||
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
||||
# exit 1
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Wasmer uses the following components:
|
||||
|
||||
- [Cranelift](https://github.com/cranestation/cranelift): for compiling Wasm binaries to machine code
|
||||
- Compiler backends: for compiling Wasm binaries to machine code ([more info here](https://github.com/wasmerio/wasmer/tree/master/lib#backends))
|
||||
- [wabt](https://github.com/pepyakin/wabt-rs): for transforming `.wast` files to `.wasm` and running WebAssembly spec tests
|
||||
- [wasmparser](https://github.com/yurydelendik/wasmparser.rs): for parsing the `.wasm` files and translating them into WebAssembly modules
|
||||
|
||||
@ -67,3 +67,8 @@ Once that's finished, we will have a `Instance` function that will be ready to e
|
||||
|
||||
Wasmer's Emscripten integration tries to wrap (and emulate) all the different syscalls that Emscripten needs.
|
||||
We provide this integration by filling the `import_object` with the Emscripten functions, while instantiating the WebAssembly Instance.
|
||||
|
||||
## WASI
|
||||
|
||||
Wasmer's WASI integration implements all the different syscalls that WASI needs.
|
||||
We provide this integration by filling the `import_object` with the WASI functions, while instantiating the WebAssembly Instance.
|
||||
|
@ -6,6 +6,7 @@ Blocks of changes will separated by version increments.
|
||||
|
||||
## **[Unreleased]**
|
||||
|
||||
- [#470](https://github.com/wasmerio/wasmer/pull/470) Add mapdir support to Emscripten, implement getdents for Unix
|
||||
- [#467](https://github.com/wasmerio/wasmer/pull/467) `wasmer_instantiate` returns better error messages in the runtime C API
|
||||
- [#463](https://github.com/wasmerio/wasmer/pull/463) Fix bug in WASI path_open allowing one level above preopened dir to be accessed
|
||||
- [#461](https://github.com/wasmerio/wasmer/pull/461) Prevent passing negative lengths in various places in the runtime C API
|
||||
|
102
Cargo.lock
generated
102
Cargo.lock
generated
@ -53,7 +53,7 @@ dependencies = [
|
||||
"backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -211,67 +211,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
dependencies = [
|
||||
"cranelift-bforest 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen-meta 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-bforest 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-codegen-meta 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
dependencies = [
|
||||
"cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
dependencies = [
|
||||
"cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-wasm"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/wasmerio/cranelift.git?branch=wasmer#84ec31b0fdfc10db491ef950815ee2961db057cb"
|
||||
dependencies = [
|
||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-frontend 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-frontend 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1002,7 +1002,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.14"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -1125,16 +1125,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt-derive 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1189,7 +1189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1362,7 +1362,7 @@ dependencies = [
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.2.16 (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.4.2",
|
||||
"wasmer-dev-utils 0.4.2",
|
||||
@ -1381,10 +1381,11 @@ name = "wasmer-clif-backend"
|
||||
version = "0.4.2"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-native 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-frontend 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-native 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"cranelift-wasm 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1393,10 +1394,10 @@ dependencies = [
|
||||
"serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.2",
|
||||
"wasmer-win-exception-handler 0.4.2",
|
||||
"wasmparser 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1413,6 +1414,7 @@ version = "0.4.2"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.1.8 (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.55 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1451,7 +1453,7 @@ dependencies = [
|
||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.2",
|
||||
"wasmparser 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1508,7 +1510,7 @@ dependencies = [
|
||||
"serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmparser 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1525,7 +1527,7 @@ dependencies = [
|
||||
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime-core 0.4.2",
|
||||
"wasmparser 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1574,11 +1576,6 @@ name = "wasmparser"
|
||||
version = "0.29.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "2.0.1"
|
||||
@ -1659,13 +1656,13 @@ dependencies = [
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum cmake 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "2ca4386c8954b76a8415b63959337d940d724b336cabd3afe189c2b51a7e1ff0"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum cranelift-bforest 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5a357d20666bf4a8c2d626a19f1b59dbca66cd844fb1e66c5612254fd0f7505"
|
||||
"checksum cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab00cb149a5bb0f7e6dd391357356a5d71c335a431e8eece94f32da2d5a043f7"
|
||||
"checksum cranelift-codegen-meta 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3797a2f450ac71297e083dd440d0cdd0d3bceabe4a3ca6bcb9e4077e9c0327d"
|
||||
"checksum cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b66e28877b75b3d2b31250f780bb5db8f68ae3df681cd56add803b2567ac4fd"
|
||||
"checksum cranelift-frontend 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b72d55fd732b1f7a99d043a36c54a5679b6ec8bc777c8d954fb97c4fa0fce7eb"
|
||||
"checksum cranelift-native 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0239f34836621a127c2132980b2f5c32a1be1c40e2d1a9a1a9bd5af33c12aee"
|
||||
"checksum cranelift-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740ebfba28c8433f06750f84819f1eb663ea9f5e4b9a81c01f4e52262d868b56"
|
||||
"checksum cranelift-bforest 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum cranelift-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum cranelift-codegen-meta 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum cranelift-frontend 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum cranelift-native 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum cranelift-wasm 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||
"checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394"
|
||||
"checksum criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
@ -1748,7 +1745,7 @@ dependencies = [
|
||||
"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
|
||||
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||
"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
|
||||
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
|
||||
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
|
||||
@ -1765,14 +1762,14 @@ dependencies = [
|
||||
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1"
|
||||
"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6"
|
||||
"checksum structopt 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fa19a5a708e22bb5be31c1b6108a2a902f909c4b9ba85cba44c06632386bc0ff"
|
||||
"checksum structopt-derive 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d59d0ae8ef8de16e49e3ca7afa16024a3e0dfd974a75ef93fdc5464e34523f"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
|
||||
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
|
||||
"checksum target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6923974ce4eb5bd28814756256d8ab71c28dd6e7483313fe7ab6614306bf633"
|
||||
"checksum target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0ab4982b8945c35cc1c46a83a9094c414f6828a099ce5dcaa8ee2b04642dcb"
|
||||
"checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef"
|
||||
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
||||
@ -1795,7 +1792,6 @@ dependencies = [
|
||||
"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c"
|
||||
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
|
||||
"checksum wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)" = "981a8797cf89762e0233ec45fae731cb79a4dfaee12d9f0fe6cee01e4ac58d00"
|
||||
"checksum wasmparser 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "566a9eefa2267a1a32af59807326e84191cdff41c3fc2efda0a790d821615b31"
|
||||
"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||
|
@ -33,6 +33,7 @@ Wasmer runtime can also be embedded in different languages, so you can use WebAs
|
||||
* [**🐘 PHP**](https://github.com/wasmerio/php-ext-wasm)
|
||||
* [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm)
|
||||
* [**💎 Ruby**](https://github.com/wasmerio/ruby-ext-wasm)
|
||||
* [**🐹 Go**](https://github.com/wasmerio/go-ext-wasm)
|
||||
|
||||
### Usage
|
||||
|
||||
|
@ -9,13 +9,14 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||
cranelift-native = "0.30.0"
|
||||
cranelift-codegen = "0.30.0"
|
||||
cranelift-entity = "0.30.0"
|
||||
cranelift-wasm = "0.30.0"
|
||||
cranelift-native = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||
cranelift-codegen = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||
cranelift-entity = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||
cranelift-frontend = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||
cranelift-wasm = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||
hashbrown = "0.1"
|
||||
target-lexicon = "0.3.0"
|
||||
wasmparser = "0.30.0"
|
||||
target-lexicon = "0.4.0"
|
||||
wasmparser = "0.29.2"
|
||||
byteorder = "1"
|
||||
nix = "0.13.0"
|
||||
libc = "0.2.49"
|
||||
|
@ -1,51 +1,405 @@
|
||||
use crate::{module::Converter, module_env::ModuleEnv, relocation::call_names};
|
||||
use cranelift_codegen::{
|
||||
cursor::FuncCursor,
|
||||
ir::{self, InstBuilder},
|
||||
isa,
|
||||
// Parts of the following code are Copyright 2018 Cranelift Developers
|
||||
// and subject to the license https://github.com/CraneStation/cranelift/blob/c47ca7bafc8fc48358f1baa72360e61fc1f7a0f2/cranelift-wasm/LICENSE
|
||||
|
||||
use crate::{
|
||||
cache::CacheGenerator, get_isa, module, module::Converter, relocation::call_names,
|
||||
resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines,
|
||||
};
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_wasm::{self, FuncEnvironment, ModuleEnvironment};
|
||||
|
||||
use cranelift_codegen::entity::EntityRef;
|
||||
use cranelift_codegen::ir::{self, Ebb, Function, InstBuilder};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_codegen::{cursor::FuncCursor, isa};
|
||||
use cranelift_frontend::{FunctionBuilder, Position, Variable};
|
||||
use cranelift_wasm::{self, FuncTranslator};
|
||||
use cranelift_wasm::{get_vmctx_value_label, translate_operator};
|
||||
use cranelift_wasm::{FuncEnvironment, ReturnMode, WasmError};
|
||||
use std::mem;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use wasmer_runtime_core::error::CompileError;
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, CacheGen, Token},
|
||||
cache::{Artifact, Error as CacheError},
|
||||
codegen::*,
|
||||
memory::MemoryType,
|
||||
structures::TypedIndex,
|
||||
types::{FuncIndex, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex,
|
||||
TableIndex,
|
||||
},
|
||||
vm,
|
||||
};
|
||||
use wasmparser::Type as WpType;
|
||||
|
||||
pub struct FuncEnv<'env, 'module, 'isa> {
|
||||
env: &'env ModuleEnv<'module, 'isa>,
|
||||
pub struct CraneliftModuleCodeGenerator {
|
||||
isa: Box<isa::TargetIsa>,
|
||||
signatures: Option<Arc<Map<SigIndex, FuncSig>>>,
|
||||
pub clif_signatures: Map<SigIndex, ir::Signature>,
|
||||
function_signatures: Option<Arc<Map<FuncIndex, SigIndex>>>,
|
||||
functions: Vec<CraneliftFunctionCodeGenerator>,
|
||||
}
|
||||
|
||||
impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> {
|
||||
pub fn new(env: &'env ModuleEnv<'module, 'isa>) -> Self {
|
||||
Self { env }
|
||||
impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
||||
for CraneliftModuleCodeGenerator
|
||||
{
|
||||
fn new() -> Self {
|
||||
let isa = get_isa();
|
||||
CraneliftModuleCodeGenerator {
|
||||
isa,
|
||||
clif_signatures: Map::new(),
|
||||
functions: vec![],
|
||||
function_signatures: None,
|
||||
signatures: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a signature with VMContext as the last param
|
||||
pub fn generate_signature(
|
||||
&self,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
) -> ir::Signature {
|
||||
// Get signature
|
||||
let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone();
|
||||
fn backend_id() -> Backend {
|
||||
Backend::Cranelift
|
||||
}
|
||||
|
||||
// Add the vmctx parameter type to it
|
||||
signature.params.insert(
|
||||
0,
|
||||
ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
||||
fn check_precondition(&mut self, _module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_function(
|
||||
&mut self,
|
||||
module_info: Arc<RwLock<ModuleInfo>>,
|
||||
) -> Result<&mut CraneliftFunctionCodeGenerator, CodegenError> {
|
||||
// define_function_body(
|
||||
|
||||
let func_translator = FuncTranslator::new();
|
||||
|
||||
let func_index = LocalFuncIndex::new(self.functions.len());
|
||||
let name = ir::ExternalName::user(0, func_index.index() as u32);
|
||||
|
||||
let sig = generate_signature(
|
||||
self,
|
||||
self.get_func_type(
|
||||
&module_info.read().unwrap(),
|
||||
Converter(func_index.convert_up(&module_info.read().unwrap())).into(),
|
||||
),
|
||||
);
|
||||
|
||||
// Return signature
|
||||
signature
|
||||
let func = ir::Function::with_name_signature(name, sig);
|
||||
|
||||
//func_translator.translate(body_bytes, body_offset, &mut func, &mut func_env)?;
|
||||
|
||||
let mut func_env = CraneliftFunctionCodeGenerator {
|
||||
func,
|
||||
func_translator,
|
||||
next_local: 0,
|
||||
clif_signatures: self.clif_signatures.clone(),
|
||||
module_info: Arc::clone(&module_info),
|
||||
target_config: self.isa.frontend_config().clone(),
|
||||
position: Position::default(),
|
||||
};
|
||||
|
||||
debug_assert_eq!(func_env.func.dfg.num_ebbs(), 0, "Function must be empty");
|
||||
debug_assert_eq!(func_env.func.dfg.num_insts(), 0, "Function must be empty");
|
||||
|
||||
let mut builder = FunctionBuilder::new(
|
||||
&mut func_env.func,
|
||||
&mut func_env.func_translator.func_ctx,
|
||||
&mut func_env.position,
|
||||
);
|
||||
|
||||
// TODO srcloc
|
||||
//builder.set_srcloc(cur_srcloc(&reader));
|
||||
|
||||
let entry_block = builder.create_ebb();
|
||||
builder.append_ebb_params_for_function_params(entry_block);
|
||||
builder.switch_to_block(entry_block); // This also creates values for the arguments.
|
||||
builder.seal_block(entry_block);
|
||||
// Make sure the entry block is inserted in the layout before we make any callbacks to
|
||||
// `environ`. The callback functions may need to insert things in the entry block.
|
||||
builder.ensure_inserted_ebb();
|
||||
|
||||
declare_wasm_parameters(&mut builder, entry_block);
|
||||
|
||||
// Set up the translation state with a single pushed control block representing the whole
|
||||
// function and its return values.
|
||||
let exit_block = builder.create_ebb();
|
||||
builder.append_ebb_params_for_function_returns(exit_block);
|
||||
func_env
|
||||
.func_translator
|
||||
.state
|
||||
.initialize(&builder.func.signature, exit_block);
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
{
|
||||
use cranelift_codegen::cursor::{Cursor, FuncCursor};
|
||||
use cranelift_codegen::ir::InstBuilder;
|
||||
let entry_ebb = func.layout.entry_block().unwrap();
|
||||
let ebb = func.dfg.make_ebb();
|
||||
func.layout.insert_ebb(ebb, entry_ebb);
|
||||
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(ebb);
|
||||
let params = pos.func.dfg.ebb_params(entry_ebb).to_vec();
|
||||
|
||||
let new_ebb_params: Vec<_> = params
|
||||
.iter()
|
||||
.map(|¶m| {
|
||||
pos.func
|
||||
.dfg
|
||||
.append_ebb_param(ebb, pos.func.dfg.value_type(param))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let start_debug = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("strtdbug");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let end_debug = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![ir::AbiParam::special(
|
||||
ir::types::I64,
|
||||
ir::ArgumentPurpose::VMContext,
|
||||
)],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("enddbug");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let i32_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("i32print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let i64_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I64),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("i64print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let f32_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::F32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("f32print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let f64_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::F64),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("f64print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let vmctx = pos
|
||||
.func
|
||||
.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.expect("missing vmctx parameter");
|
||||
|
||||
let func_index = pos.ins().iconst(
|
||||
ir::types::I32,
|
||||
func_index.index() as i64 + self.module.info.imported_functions.len() as i64,
|
||||
);
|
||||
|
||||
pos.ins().call(start_debug, &[vmctx, func_index]);
|
||||
|
||||
for param in new_ebb_params.iter().cloned() {
|
||||
match pos.func.dfg.value_type(param) {
|
||||
ir::types::I32 => pos.ins().call(i32_print, &[vmctx, param]),
|
||||
ir::types::I64 => pos.ins().call(i64_print, &[vmctx, param]),
|
||||
ir::types::F32 => pos.ins().call(f32_print, &[vmctx, param]),
|
||||
ir::types::F64 => pos.ins().call(f64_print, &[vmctx, param]),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
}
|
||||
|
||||
pos.ins().call(end_debug, &[vmctx]);
|
||||
|
||||
pos.ins().jump(entry_ebb, new_ebb_params.as_slice());
|
||||
}
|
||||
|
||||
self.functions.push(func_env);
|
||||
Ok(self.functions.last_mut().unwrap())
|
||||
}
|
||||
|
||||
fn finalize(
|
||||
self,
|
||||
module_info: &ModuleInfo,
|
||||
) -> Result<(Caller, Box<dyn CacheGen>), CodegenError> {
|
||||
let mut func_bodies: Map<LocalFuncIndex, ir::Function> = Map::new();
|
||||
for f in self.functions.into_iter() {
|
||||
func_bodies.push(f.func);
|
||||
}
|
||||
|
||||
let (func_resolver_builder, handler_data) =
|
||||
FuncResolverBuilder::new(&*self.isa, func_bodies, module_info)?;
|
||||
|
||||
let trampolines = Arc::new(Trampolines::new(&*self.isa, module_info));
|
||||
|
||||
let (func_resolver, backend_cache) = func_resolver_builder.finalize(
|
||||
&self.signatures.as_ref().unwrap(),
|
||||
Arc::clone(&trampolines),
|
||||
handler_data.clone(),
|
||||
)?;
|
||||
|
||||
let cache_gen = Box::new(CacheGenerator::new(
|
||||
backend_cache,
|
||||
Arc::clone(&func_resolver.memory),
|
||||
));
|
||||
|
||||
Ok((
|
||||
Caller::new(handler_data, trampolines, func_resolver),
|
||||
cache_gen,
|
||||
))
|
||||
}
|
||||
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), CodegenError> {
|
||||
self.signatures = Some(Arc::new(signatures));
|
||||
let call_conv = self.isa.frontend_config().default_call_conv;
|
||||
for (_sig_idx, func_sig) in self.signatures.as_ref().unwrap().iter() {
|
||||
self.clif_signatures
|
||||
.push(convert_func_sig(func_sig, call_conv));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_function_signatures(
|
||||
&mut self,
|
||||
assoc: Map<FuncIndex, SigIndex>,
|
||||
) -> Result<(), CodegenError> {
|
||||
self.function_signatures = Some(Arc::new(assoc));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_import_function(&mut self) -> Result<(), CodegenError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn from_cache(cache: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
module::Module::from_cache(cache)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
fn convert_func_sig(sig: &FuncSig, call_conv: CallConv) -> ir::Signature {
|
||||
ir::Signature {
|
||||
params: sig
|
||||
.params()
|
||||
.iter()
|
||||
.map(|params| Converter(*params).into())
|
||||
.collect::<Vec<_>>(),
|
||||
returns: sig
|
||||
.returns()
|
||||
.iter()
|
||||
.map(|returns| Converter(*returns).into())
|
||||
.collect::<Vec<_>>(),
|
||||
call_conv,
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompileError> for CodegenError {
|
||||
fn from(other: CompileError) -> CodegenError {
|
||||
CodegenError {
|
||||
message: format!("{:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WasmError> for CodegenError {
|
||||
fn from(other: WasmError) -> CodegenError {
|
||||
CodegenError {
|
||||
message: format!("{:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CraneliftFunctionCodeGenerator {
|
||||
func: Function,
|
||||
func_translator: FuncTranslator,
|
||||
next_local: usize,
|
||||
pub clif_signatures: Map<SigIndex, ir::Signature>,
|
||||
module_info: Arc<RwLock<ModuleInfo>>,
|
||||
target_config: isa::TargetFrontendConfig,
|
||||
position: Position,
|
||||
}
|
||||
|
||||
pub struct FunctionEnvironment {
|
||||
module_info: Arc<RwLock<ModuleInfo>>,
|
||||
target_config: isa::TargetFrontendConfig,
|
||||
clif_signatures: Map<SigIndex, ir::Signature>,
|
||||
}
|
||||
|
||||
impl FuncEnvironment for FunctionEnvironment {
|
||||
/// Gets configuration information needed for compiling functions
|
||||
fn target_config(&self) -> isa::TargetFrontendConfig {
|
||||
self.env.target_config()
|
||||
self.target_config
|
||||
}
|
||||
|
||||
/// Gets native pointers types.
|
||||
@ -68,14 +422,16 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
clif_global_index: cranelift_wasm::GlobalIndex,
|
||||
) -> cranelift_wasm::GlobalVariable {
|
||||
) -> cranelift_wasm::WasmResult<cranelift_wasm::GlobalVariable> {
|
||||
let global_index: GlobalIndex = Converter(clif_global_index).into();
|
||||
|
||||
// Create VMContext value.
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
let ptr_type = self.pointer_type();
|
||||
|
||||
let local_global_addr = match global_index.local_or_import(&self.env.module.info) {
|
||||
let (local_global_addr, ty) = match global_index
|
||||
.local_or_import(&self.module_info.read().unwrap())
|
||||
{
|
||||
LocalOrImport::Local(local_global_index) => {
|
||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
@ -92,12 +448,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
global_type: ptr_type,
|
||||
});
|
||||
|
||||
func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: local_global_ptr_ptr,
|
||||
offset: 0.into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
})
|
||||
let ty = self.module_info.read().unwrap().globals[local_global_index]
|
||||
.desc
|
||||
.ty;
|
||||
|
||||
(
|
||||
func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: local_global_ptr_ptr,
|
||||
offset: 0.into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
}),
|
||||
ty,
|
||||
)
|
||||
}
|
||||
LocalOrImport::Import(import_global_index) => {
|
||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
@ -115,20 +478,27 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
global_type: ptr_type,
|
||||
});
|
||||
|
||||
func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: local_global_ptr_ptr,
|
||||
offset: 0.into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
})
|
||||
let ty = self.module_info.read().unwrap().imported_globals[import_global_index]
|
||||
.1
|
||||
.ty;
|
||||
|
||||
(
|
||||
func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: local_global_ptr_ptr,
|
||||
offset: 0.into(),
|
||||
global_type: ptr_type,
|
||||
readonly: true,
|
||||
}),
|
||||
ty,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
cranelift_wasm::GlobalVariable::Memory {
|
||||
Ok(cranelift_wasm::GlobalVariable::Memory {
|
||||
gv: local_global_addr,
|
||||
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
||||
ty: self.env.get_global(clif_global_index).ty,
|
||||
}
|
||||
ty: Converter(ty).into(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets up the necessary preamble definitions in `func` to access the linear memory identified
|
||||
@ -139,14 +509,14 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||
) -> ir::Heap {
|
||||
) -> cranelift_wasm::WasmResult<ir::Heap> {
|
||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||
// Create VMContext value.
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
let ptr_type = self.pointer_type();
|
||||
|
||||
let (local_memory_ptr_ptr, description) =
|
||||
match mem_index.local_or_import(&self.env.module.info) {
|
||||
match mem_index.local_or_import(&self.module_info.read().unwrap()) {
|
||||
LocalOrImport::Local(local_mem_index) => {
|
||||
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
@ -164,7 +534,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
offset: (local_memory_ptr_offset as i64).into(),
|
||||
global_type: ptr_type,
|
||||
}),
|
||||
self.env.module.info.memories[local_mem_index],
|
||||
self.module_info.read().unwrap().memories[local_mem_index],
|
||||
)
|
||||
}
|
||||
LocalOrImport::Import(import_mem_index) => {
|
||||
@ -184,7 +554,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
offset: (local_memory_ptr_offset as i64).into(),
|
||||
global_type: ptr_type,
|
||||
}),
|
||||
self.env.module.info.imported_memories[import_mem_index].1,
|
||||
self.module_info.read().unwrap().imported_memories[import_mem_index].1,
|
||||
)
|
||||
}
|
||||
};
|
||||
@ -217,7 +587,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
func.create_heap(ir::HeapData {
|
||||
Ok(func.create_heap(ir::HeapData {
|
||||
base: local_memory_base,
|
||||
min_size: (description.minimum.bytes().0 as u64).into(),
|
||||
offset_guard_size: mem_type.guard_size().into(),
|
||||
@ -225,9 +595,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
bound_gv: local_memory_bound,
|
||||
},
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
}))
|
||||
}
|
||||
mem_type @ MemoryType::Static | mem_type @ MemoryType::SharedStatic => func
|
||||
mem_type @ MemoryType::Static | mem_type @ MemoryType::SharedStatic => Ok(func
|
||||
.create_heap(ir::HeapData {
|
||||
base: local_memory_base,
|
||||
min_size: (description.minimum.bytes().0 as u64).into(),
|
||||
@ -236,7 +606,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
bound: mem_type.bounds().unwrap().into(),
|
||||
},
|
||||
index_type: ir::types::I32,
|
||||
}),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,14 +618,14 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
clif_table_index: cranelift_wasm::TableIndex,
|
||||
) -> ir::Table {
|
||||
) -> cranelift_wasm::WasmResult<ir::Table> {
|
||||
let table_index: TableIndex = Converter(clif_table_index).into();
|
||||
// Create VMContext value.
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
let ptr_type = self.pointer_type();
|
||||
|
||||
let (table_struct_ptr_ptr, description) = match table_index
|
||||
.local_or_import(&self.env.module.info)
|
||||
.local_or_import(&self.module_info.read().unwrap())
|
||||
{
|
||||
LocalOrImport::Local(local_table_index) => {
|
||||
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
@ -276,7 +646,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
|
||||
(
|
||||
table_struct_ptr_ptr,
|
||||
self.env.module.info.tables[local_table_index],
|
||||
self.module_info.read().unwrap().tables[local_table_index],
|
||||
)
|
||||
}
|
||||
LocalOrImport::Import(import_table_index) => {
|
||||
@ -298,7 +668,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
|
||||
(
|
||||
table_struct_ptr_ptr,
|
||||
self.env.module.info.imported_tables[import_table_index].1,
|
||||
self.module_info.read().unwrap().imported_tables[import_table_index].1,
|
||||
)
|
||||
}
|
||||
};
|
||||
@ -326,13 +696,13 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
func.create_table(ir::TableData {
|
||||
Ok(func.create_table(ir::TableData {
|
||||
base_gv: table_base,
|
||||
min_size: (description.minimum as u64).into(),
|
||||
bound_gv: table_count,
|
||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
||||
index_type: ir::types::I32,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
/// Sets up a signature definition in `func`'s preamble.
|
||||
@ -343,9 +713,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
) -> ir::SigRef {
|
||||
) -> cranelift_wasm::WasmResult<ir::SigRef> {
|
||||
// Create a signature reference out of specified signature (with VMContext param added).
|
||||
func.import_signature(self.generate_signature(clif_sig_index))
|
||||
Ok(func.import_signature(self.generate_signature(clif_sig_index)))
|
||||
}
|
||||
|
||||
/// Sets up an external function definition in the preamble of `func` that can be used to
|
||||
@ -356,9 +726,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
func_index: cranelift_wasm::FuncIndex,
|
||||
) -> ir::FuncRef {
|
||||
) -> cranelift_wasm::WasmResult<ir::FuncRef> {
|
||||
// Get signature of function.
|
||||
let signature_index = self.env.get_func_type(func_index);
|
||||
let signature_index = self.get_func_type(func_index);
|
||||
|
||||
// Create a signature reference from specified signature (with VMContext param added).
|
||||
let signature = func.import_signature(self.generate_signature(signature_index));
|
||||
@ -367,12 +737,12 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let name = ir::ExternalName::user(0, func_index.as_u32());
|
||||
|
||||
// Create function reference from fuction data.
|
||||
func.import_function(ir::ExtFuncData {
|
||||
Ok(func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
// Make this colocated so all calls between local functions are relative.
|
||||
colocated: true,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
/// Generates an indirect call IR with `callee` and `call_args`.
|
||||
@ -485,7 +855,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let callee_index: FuncIndex = Converter(clif_callee_index).into();
|
||||
let ptr_type = self.pointer_type();
|
||||
|
||||
match callee_index.local_or_import(&self.env.module.info) {
|
||||
match callee_index.local_or_import(&self.module_info.read().unwrap()) {
|
||||
LocalOrImport::Local(local_function_index) => {
|
||||
// this is an internal function
|
||||
let vmctx = pos
|
||||
@ -596,16 +966,16 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||
|
||||
let (namespace, mem_index, description) =
|
||||
match mem_index.local_or_import(&self.env.module.info) {
|
||||
match mem_index.local_or_import(&self.module_info.read().unwrap()) {
|
||||
LocalOrImport::Local(local_mem_index) => (
|
||||
call_names::LOCAL_NAMESPACE,
|
||||
local_mem_index.index(),
|
||||
self.env.module.info.memories[local_mem_index],
|
||||
self.module_info.read().unwrap().memories[local_mem_index],
|
||||
),
|
||||
LocalOrImport::Import(import_mem_index) => (
|
||||
call_names::IMPORT_NAMESPACE,
|
||||
import_mem_index.index(),
|
||||
self.env.module.info.imported_memories[import_mem_index].1,
|
||||
self.module_info.read().unwrap().imported_memories[import_mem_index].1,
|
||||
),
|
||||
};
|
||||
|
||||
@ -660,16 +1030,16 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||
|
||||
let (namespace, mem_index, description) =
|
||||
match mem_index.local_or_import(&self.env.module.info) {
|
||||
match mem_index.local_or_import(&self.module_info.read().unwrap()) {
|
||||
LocalOrImport::Local(local_mem_index) => (
|
||||
call_names::LOCAL_NAMESPACE,
|
||||
local_mem_index.index(),
|
||||
self.env.module.info.memories[local_mem_index],
|
||||
self.module_info.read().unwrap().memories[local_mem_index],
|
||||
),
|
||||
LocalOrImport::Import(import_mem_index) => (
|
||||
call_names::IMPORT_NAMESPACE,
|
||||
import_mem_index.index(),
|
||||
self.env.module.info.imported_memories[import_mem_index].1,
|
||||
self.module_info.read().unwrap().imported_memories[import_mem_index].1,
|
||||
),
|
||||
};
|
||||
|
||||
@ -698,3 +1068,200 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionEnvironment {
|
||||
pub fn get_func_type(
|
||||
&self,
|
||||
func_index: cranelift_wasm::FuncIndex,
|
||||
) -> cranelift_wasm::SignatureIndex {
|
||||
let sig_index: SigIndex =
|
||||
self.module_info.read().unwrap().func_assoc[Converter(func_index).into()];
|
||||
Converter(sig_index).into()
|
||||
}
|
||||
|
||||
/// Creates a signature with VMContext as the last param
|
||||
pub fn generate_signature(
|
||||
&self,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
) -> ir::Signature {
|
||||
// Get signature
|
||||
let mut signature = self.clif_signatures[Converter(clif_sig_index).into()].clone();
|
||||
|
||||
// Add the vmctx parameter type to it
|
||||
signature.params.insert(
|
||||
0,
|
||||
ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
||||
);
|
||||
|
||||
// Return signature
|
||||
signature
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionCodeGenerator<CodegenError> for CraneliftFunctionCodeGenerator {
|
||||
fn feed_return(&mut self, _ty: WpType) -> Result<(), CodegenError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_param(&mut self, _ty: WpType) -> Result<(), CodegenError> {
|
||||
self.next_local += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
|
||||
let mut next_local = self.next_local;
|
||||
cranelift_wasm::declare_locals(&mut self.builder(), n as u32, ty, &mut next_local)?;
|
||||
self.next_local = next_local;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn begin_body(&mut self, _module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_event(&mut self, event: Event, _module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||
let op = match event {
|
||||
Event::Wasm(x) => x,
|
||||
Event::WasmOwned(ref x) => x,
|
||||
Event::Internal(_x) => {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
//let builder = self.builder.as_mut().unwrap();
|
||||
//let func_environment = FuncEnv::new();
|
||||
//let state = TranslationState::new();
|
||||
let mut function_environment = FunctionEnvironment {
|
||||
module_info: Arc::clone(&self.module_info),
|
||||
target_config: self.target_config.clone(),
|
||||
clif_signatures: self.clif_signatures.clone(),
|
||||
};
|
||||
|
||||
if self.func_translator.state.control_stack.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut builder = FunctionBuilder::new(
|
||||
&mut self.func,
|
||||
&mut self.func_translator.func_ctx,
|
||||
&mut self.position,
|
||||
);
|
||||
let state = &mut self.func_translator.state;
|
||||
translate_operator(op, &mut builder, state, &mut function_environment)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize(&mut self) -> Result<(), CodegenError> {
|
||||
let return_mode = self.return_mode();
|
||||
|
||||
let mut builder = FunctionBuilder::new(
|
||||
&mut self.func,
|
||||
&mut self.func_translator.func_ctx,
|
||||
&mut self.position,
|
||||
);
|
||||
let state = &mut self.func_translator.state;
|
||||
|
||||
// The final `End` operator left us in the exit block where we need to manually add a return
|
||||
// instruction.
|
||||
//
|
||||
// If the exit block is unreachable, it may not have the correct arguments, so we would
|
||||
// generate a return instruction that doesn't match the signature.
|
||||
if state.reachable {
|
||||
debug_assert!(builder.is_pristine());
|
||||
if !builder.is_unreachable() {
|
||||
match return_mode {
|
||||
ReturnMode::NormalReturns => builder.ins().return_(&state.stack),
|
||||
ReturnMode::FallthroughReturn => builder.ins().fallthrough_return(&state.stack),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Discard any remaining values on the stack. Either we just returned them,
|
||||
// or the end of the function is unreachable.
|
||||
state.stack.clear();
|
||||
|
||||
self.builder().finalize();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CodegenError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl CraneliftModuleCodeGenerator {
|
||||
/// Return the signature index for the given function index.
|
||||
pub fn get_func_type(
|
||||
&self,
|
||||
module_info: &ModuleInfo,
|
||||
func_index: cranelift_wasm::FuncIndex,
|
||||
) -> cranelift_wasm::SignatureIndex {
|
||||
let sig_index: SigIndex = module_info.func_assoc[Converter(func_index).into()];
|
||||
Converter(sig_index).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl CraneliftFunctionCodeGenerator {
|
||||
pub fn builder(&mut self) -> FunctionBuilder {
|
||||
FunctionBuilder::new(
|
||||
&mut self.func,
|
||||
&mut self.func_translator.func_ctx,
|
||||
&mut self.position,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn return_mode(&self) -> ReturnMode {
|
||||
ReturnMode::NormalReturns
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a signature with VMContext as the last param
|
||||
fn generate_signature(
|
||||
env: &CraneliftModuleCodeGenerator,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
) -> ir::Signature {
|
||||
// Get signature
|
||||
let mut signature = env.clif_signatures[Converter(clif_sig_index).into()].clone();
|
||||
|
||||
// Add the vmctx parameter type to it
|
||||
signature.params.insert(
|
||||
0,
|
||||
ir::AbiParam::special(pointer_type(env), ir::ArgumentPurpose::VMContext),
|
||||
);
|
||||
|
||||
// Return signature
|
||||
signature
|
||||
}
|
||||
|
||||
fn pointer_type(mcg: &CraneliftModuleCodeGenerator) -> ir::Type {
|
||||
ir::Type::int(u16::from(mcg.isa.frontend_config().pointer_bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Declare local variables for the signature parameters that correspond to WebAssembly locals.
|
||||
///
|
||||
/// Return the number of local variables declared.
|
||||
fn declare_wasm_parameters(builder: &mut FunctionBuilder, entry_block: Ebb) -> usize {
|
||||
let sig_len = builder.func.signature.params.len();
|
||||
let mut next_local = 0;
|
||||
for i in 0..sig_len {
|
||||
let param_type = builder.func.signature.params[i];
|
||||
// There may be additional special-purpose parameters following the normal WebAssembly
|
||||
// signature parameters. For example, a `vmctx` pointer.
|
||||
if param_type.purpose == ir::ArgumentPurpose::Normal {
|
||||
// This is a normal WebAssembly signature parameter, so create a local for it.
|
||||
let local = Variable::new(next_local);
|
||||
builder.declare_var(local, param_type.value_type);
|
||||
next_local += 1;
|
||||
|
||||
let param_value = builder.ebb_params(entry_block)[i];
|
||||
builder.def_var(local, param_value);
|
||||
}
|
||||
if param_type.purpose == ir::ArgumentPurpose::VMContext {
|
||||
let param_value = builder.ebb_params(entry_block)[i];
|
||||
builder.set_val_label(param_value, get_vmctx_value_label());
|
||||
}
|
||||
}
|
||||
|
||||
next_local
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)]
|
||||
|
||||
mod cache;
|
||||
mod func_env;
|
||||
mod code;
|
||||
mod libcalls;
|
||||
mod module;
|
||||
mod module_env;
|
||||
mod relocation;
|
||||
mod resolver;
|
||||
mod signal;
|
||||
@ -16,87 +15,12 @@ use cranelift_codegen::{
|
||||
};
|
||||
use target_lexicon::Triple;
|
||||
|
||||
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Compiler, CompilerConfig, Token},
|
||||
error::{CompileError, CompileResult},
|
||||
module::ModuleInner,
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate rayon;
|
||||
extern crate serde;
|
||||
|
||||
use wasmparser::{self, WasmDecoder};
|
||||
|
||||
pub struct CraneliftCompiler {}
|
||||
|
||||
impl CraneliftCompiler {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Compiler for CraneliftCompiler {
|
||||
/// Compiles wasm binary to a wasmer module.
|
||||
fn compile(
|
||||
&self,
|
||||
wasm: &[u8],
|
||||
compiler_config: CompilerConfig,
|
||||
_: Token,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
validate(wasm)?;
|
||||
|
||||
let isa = get_isa();
|
||||
|
||||
let mut module = module::Module::new(&compiler_config);
|
||||
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
||||
|
||||
let func_bodies = module_env.translate(wasm)?;
|
||||
|
||||
module.compile(&*isa, func_bodies)
|
||||
}
|
||||
|
||||
/// Create a wasmer Module from an already-compiled cache.
|
||||
|
||||
unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
||||
module::Module::from_cache(cache)
|
||||
}
|
||||
|
||||
//
|
||||
// fn compile_to_backend_cache_data(
|
||||
// &self,
|
||||
// wasm: &[u8],
|
||||
// _: Token,
|
||||
// ) -> CompileResult<(Box<ModuleInfo>, Vec<u8>, Memory)> {
|
||||
// validate(wasm)?;
|
||||
|
||||
// let isa = get_isa();
|
||||
|
||||
// let mut module = module::Module::new(wasm);
|
||||
// let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
|
||||
|
||||
// let func_bodies = module_env.translate(wasm)?;
|
||||
|
||||
// let (info, backend_cache, compiled_code) = module
|
||||
// .compile_to_backend_cache(&*isa, func_bodies)
|
||||
// .map_err(|e| CompileError::InternalError {
|
||||
// msg: format!("{:?}", e),
|
||||
// })?;
|
||||
|
||||
// let buffer =
|
||||
// backend_cache
|
||||
// .into_backend_data()
|
||||
// .map_err(|e| CompileError::InternalError {
|
||||
// msg: format!("{:?}", e),
|
||||
// })?;
|
||||
|
||||
// Ok((Box::new(info), buffer, compiled_code))
|
||||
// }
|
||||
}
|
||||
|
||||
fn get_isa() -> Box<isa::TargetIsa> {
|
||||
let flags = {
|
||||
let mut builder = settings::builder();
|
||||
@ -113,19 +37,14 @@ fn get_isa() -> Box<isa::TargetIsa> {
|
||||
isa::lookup(Triple::host()).unwrap().finish(flags)
|
||||
}
|
||||
|
||||
fn validate(bytes: &[u8]) -> CompileResult<()> {
|
||||
let mut parser = wasmparser::ValidatingParser::new(bytes, None);
|
||||
loop {
|
||||
let state = parser.read();
|
||||
match *state {
|
||||
wasmparser::ParserState::EndWasm => break Ok(()),
|
||||
wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
|
||||
msg: err.message.to_string(),
|
||||
})?,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The current version of this crate
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
||||
|
||||
pub type CraneliftCompiler = SimpleStreamingCompilerGen<
|
||||
code::CraneliftModuleCodeGenerator,
|
||||
code::CraneliftFunctionCodeGenerator,
|
||||
signal::Caller,
|
||||
code::CodegenError,
|
||||
>;
|
||||
|
@ -1,22 +1,17 @@
|
||||
use crate::cache::{BackendCache, CacheGenerator};
|
||||
use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines};
|
||||
use crate::{resolver::FuncResolverBuilder, signal::Caller};
|
||||
|
||||
use cranelift_codegen::{ir, isa};
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_wasm;
|
||||
use hashbrown::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, CompilerConfig},
|
||||
error::CompileResult,
|
||||
module::{ModuleInfo, ModuleInner, StringTable},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type,
|
||||
},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
structures::TypedIndex,
|
||||
types::{FuncIndex, FuncSig, GlobalIndex, MemoryIndex, SigIndex, TableIndex, Type},
|
||||
};
|
||||
|
||||
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
|
||||
@ -25,69 +20,6 @@ pub struct Module {
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub fn new(compiler_config: &CompilerConfig) -> Self {
|
||||
Self {
|
||||
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: HashMap::new(),
|
||||
|
||||
data_initializers: Vec::new(),
|
||||
elem_initializers: Vec::new(),
|
||||
|
||||
start_func: None,
|
||||
|
||||
func_assoc: Map::new(),
|
||||
signatures: Map::new(),
|
||||
backend: Backend::Cranelift,
|
||||
|
||||
namespace_table: StringTable::new(),
|
||||
name_table: StringTable::new(),
|
||||
em_symbol_map: compiler_config.symbol_map.clone(),
|
||||
|
||||
custom_sections: HashMap::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile(
|
||||
self,
|
||||
isa: &isa::TargetIsa,
|
||||
functions: Map<LocalFuncIndex, ir::Function>,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
let (func_resolver_builder, handler_data) =
|
||||
FuncResolverBuilder::new(isa, functions, &self.info)?;
|
||||
|
||||
let trampolines = Arc::new(Trampolines::new(isa, &self.info));
|
||||
|
||||
let (func_resolver, backend_cache) = func_resolver_builder.finalize(
|
||||
&self.info.signatures,
|
||||
Arc::clone(&trampolines),
|
||||
handler_data.clone(),
|
||||
)?;
|
||||
|
||||
let cache_gen = Box::new(CacheGenerator::new(
|
||||
backend_cache,
|
||||
Arc::clone(&func_resolver.memory),
|
||||
));
|
||||
|
||||
let runnable_module = Caller::new(handler_data, trampolines, func_resolver);
|
||||
|
||||
Ok(ModuleInner {
|
||||
runnable_module: Box::new(runnable_module),
|
||||
cache_gen,
|
||||
|
||||
info: self.info,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_cache(cache: Artifact) -> Result<ModuleInner, CacheError> {
|
||||
let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?;
|
||||
|
||||
@ -179,3 +111,25 @@ impl From<Converter<ir::Type>> for Type {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Converter<Type>> for ir::Type {
|
||||
fn from(ty: Converter<Type>) -> Self {
|
||||
match ty.0 {
|
||||
Type::I32 => ir::types::I32,
|
||||
Type::I64 => ir::types::I64,
|
||||
Type::F32 => ir::types::F32,
|
||||
Type::F64 => ir::types::F64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Converter<Type>> for ir::AbiParam {
|
||||
fn from(ty: Converter<Type>) -> Self {
|
||||
match ty.0 {
|
||||
Type::I32 => ir::AbiParam::new(ir::types::I32),
|
||||
Type::I64 => ir::AbiParam::new(ir::types::I64),
|
||||
Type::F32 => ir::AbiParam::new(ir::types::F32),
|
||||
Type::F64 => ir::AbiParam::new(ir::types::F64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,557 +0,0 @@
|
||||
use crate::{
|
||||
func_env::FuncEnv,
|
||||
module::{Converter, Module},
|
||||
};
|
||||
use cranelift_codegen::{ir, isa};
|
||||
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
|
||||
use wasmer_runtime_core::{
|
||||
error::{CompileError, CompileResult},
|
||||
module::{
|
||||
DataInitializer, ExportIndex, ImportName, NameIndex, NamespaceIndex, StringTableBuilder,
|
||||
TableInitializer,
|
||||
},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
ElementType, GlobalDescriptor, GlobalIndex, GlobalInit, Initializer, LocalFuncIndex,
|
||||
LocalOrImport, MemoryDescriptor, SigIndex, TableDescriptor, Value,
|
||||
},
|
||||
units::Pages,
|
||||
};
|
||||
|
||||
pub struct ModuleEnv<'module, 'isa> {
|
||||
pub module: &'module mut Module,
|
||||
isa: &'isa isa::TargetIsa,
|
||||
pub signatures: Map<SigIndex, ir::Signature>,
|
||||
globals: Map<GlobalIndex, cranelift_wasm::Global>,
|
||||
func_bodies: Map<LocalFuncIndex, ir::Function>,
|
||||
namespace_table_builder: StringTableBuilder<NamespaceIndex>,
|
||||
name_table_builder: StringTableBuilder<NameIndex>,
|
||||
}
|
||||
|
||||
impl<'module, 'isa> ModuleEnv<'module, 'isa> {
|
||||
pub fn new(module: &'module mut Module, isa: &'isa isa::TargetIsa) -> Self {
|
||||
Self {
|
||||
module,
|
||||
isa,
|
||||
signatures: Map::new(),
|
||||
globals: Map::new(),
|
||||
func_bodies: Map::new(),
|
||||
namespace_table_builder: StringTableBuilder::new(),
|
||||
name_table_builder: StringTableBuilder::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn translate(mut self, wasm: &[u8]) -> CompileResult<Map<LocalFuncIndex, ir::Function>> {
|
||||
translate_module(wasm, &mut self)
|
||||
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
|
||||
|
||||
self.module.info.namespace_table = self.namespace_table_builder.finish();
|
||||
self.module.info.name_table = self.name_table_builder.finish();
|
||||
|
||||
Ok(self.func_bodies)
|
||||
}
|
||||
|
||||
/// Return the global for the given global index.
|
||||
pub fn get_global(&self, global_index: cranelift_wasm::GlobalIndex) -> &cranelift_wasm::Global {
|
||||
&self.globals[Converter(global_index).into()]
|
||||
}
|
||||
|
||||
/// Return the signature index for the given function index.
|
||||
pub fn get_func_type(
|
||||
&self,
|
||||
func_index: cranelift_wasm::FuncIndex,
|
||||
) -> cranelift_wasm::SignatureIndex {
|
||||
let sig_index: SigIndex = self.module.info.func_assoc[Converter(func_index).into()];
|
||||
Converter(sig_index).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> {
|
||||
/// Get the information needed to produce Cranelift IR for the current target.
|
||||
fn target_config(&self) -> isa::TargetFrontendConfig {
|
||||
self.isa.frontend_config()
|
||||
}
|
||||
|
||||
/// Declares a function signature to the environment.
|
||||
fn declare_signature(&mut self, sig: ir::Signature) {
|
||||
self.signatures.push(sig.clone());
|
||||
self.module.info.signatures.push(Converter(sig).into());
|
||||
}
|
||||
|
||||
/// Declares a function import to the environment.
|
||||
fn declare_func_import(
|
||||
&mut self,
|
||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
||||
namespace: &'data str,
|
||||
name: &'data str,
|
||||
) {
|
||||
// We convert the cranelift signature index to
|
||||
// a wasmer signature index without deduplicating
|
||||
// because we'll deduplicate later.
|
||||
let sig_index = Converter(clif_sig_index).into();
|
||||
self.module.info.func_assoc.push(sig_index);
|
||||
|
||||
let namespace_index = self.namespace_table_builder.register(namespace);
|
||||
let name_index = self.name_table_builder.register(name);
|
||||
|
||||
// Add import names to list of imported functions
|
||||
self.module.info.imported_functions.push(ImportName {
|
||||
namespace_index,
|
||||
name_index,
|
||||
});
|
||||
}
|
||||
|
||||
/// Declares the type (signature) of a local function in the module.
|
||||
fn declare_func_type(&mut self, clif_sig_index: cranelift_wasm::SignatureIndex) {
|
||||
// We convert the cranelift signature index to
|
||||
// a wasmer signature index without deduplicating
|
||||
// because we'll deduplicate later.
|
||||
let sig_index = Converter(clif_sig_index).into();
|
||||
self.module.info.func_assoc.push(sig_index);
|
||||
}
|
||||
|
||||
/// Declares a global to the environment.
|
||||
fn declare_global(&mut self, global: cranelift_wasm::Global) {
|
||||
let desc = GlobalDescriptor {
|
||||
mutable: global.mutability,
|
||||
ty: Converter(global.ty).into(),
|
||||
};
|
||||
|
||||
let init = match global.initializer {
|
||||
cranelift_wasm::GlobalInit::I32Const(x) => Initializer::Const(Value::I32(x)),
|
||||
cranelift_wasm::GlobalInit::I64Const(x) => Initializer::Const(Value::I64(x)),
|
||||
cranelift_wasm::GlobalInit::F32Const(x) => {
|
||||
Initializer::Const(Value::F32(f32::from_bits(x)))
|
||||
}
|
||||
cranelift_wasm::GlobalInit::F64Const(x) => {
|
||||
Initializer::Const(Value::F64(f64::from_bits(x)))
|
||||
}
|
||||
cranelift_wasm::GlobalInit::GetGlobal(global_index) => {
|
||||
// assert!(!desc.mutable);
|
||||
let global_index: GlobalIndex = Converter(global_index).into();
|
||||
let imported_global_index = global_index
|
||||
.local_or_import(&self.module.info)
|
||||
.import()
|
||||
.expect("invalid global initializer when declaring an imported global");
|
||||
Initializer::GetGlobal(imported_global_index)
|
||||
}
|
||||
_ => panic!("invalid global initializer when declaring a local global"),
|
||||
};
|
||||
|
||||
// Add global ir to the list of globals
|
||||
self.module.info.globals.push(GlobalInit { desc, init });
|
||||
|
||||
self.globals.push(global);
|
||||
}
|
||||
|
||||
/// Declares a global import to the environment.
|
||||
fn declare_global_import(
|
||||
&mut self,
|
||||
global: cranelift_wasm::Global,
|
||||
namespace: &'data str,
|
||||
name: &'data str,
|
||||
) {
|
||||
assert!(match global.initializer {
|
||||
cranelift_wasm::GlobalInit::Import => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let namespace_index = self.namespace_table_builder.register(namespace);
|
||||
let name_index = self.name_table_builder.register(name);
|
||||
|
||||
let import_name = ImportName {
|
||||
namespace_index,
|
||||
name_index,
|
||||
};
|
||||
|
||||
let desc = GlobalDescriptor {
|
||||
mutable: global.mutability,
|
||||
ty: Converter(global.ty).into(),
|
||||
};
|
||||
|
||||
// Add global ir to the list of globals
|
||||
self.module.info.imported_globals.push((import_name, desc));
|
||||
|
||||
self.globals.push(global);
|
||||
}
|
||||
|
||||
/// Declares a table to the environment.
|
||||
fn declare_table(&mut self, table: cranelift_wasm::Table) {
|
||||
use cranelift_wasm::TableElementType;
|
||||
// Add table ir to the list of tables
|
||||
self.module.info.tables.push(TableDescriptor {
|
||||
element: match table.ty {
|
||||
TableElementType::Func => ElementType::Anyfunc,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
minimum: table.minimum,
|
||||
maximum: table.maximum,
|
||||
});
|
||||
}
|
||||
|
||||
/// Declares a table import to the environment.
|
||||
fn declare_table_import(
|
||||
&mut self,
|
||||
table: cranelift_wasm::Table,
|
||||
namespace: &'data str,
|
||||
name: &'data str,
|
||||
) {
|
||||
use cranelift_wasm::TableElementType;
|
||||
|
||||
let namespace_index = self.namespace_table_builder.register(namespace);
|
||||
let name_index = self.name_table_builder.register(name);
|
||||
|
||||
let import_name = ImportName {
|
||||
namespace_index,
|
||||
name_index,
|
||||
};
|
||||
|
||||
let imported_table = TableDescriptor {
|
||||
element: match table.ty {
|
||||
TableElementType::Func => ElementType::Anyfunc,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
minimum: table.minimum,
|
||||
maximum: table.maximum,
|
||||
};
|
||||
|
||||
// Add import names to list of imported tables
|
||||
self.module
|
||||
.info
|
||||
.imported_tables
|
||||
.push((import_name, imported_table));
|
||||
}
|
||||
|
||||
/// Fills a declared table with references to functions in the module.
|
||||
fn declare_table_elements(
|
||||
&mut self,
|
||||
table_index: cranelift_wasm::TableIndex,
|
||||
base: Option<cranelift_wasm::GlobalIndex>,
|
||||
offset: usize,
|
||||
elements: Box<[cranelift_wasm::FuncIndex]>,
|
||||
) {
|
||||
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
||||
// let base = base.map(|index| WasmerGlobalIndex::new(index.index()));
|
||||
let base = match base {
|
||||
Some(global_index) => {
|
||||
let global_index: GlobalIndex = Converter(global_index).into();
|
||||
Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) {
|
||||
LocalOrImport::Import(imported_global_index) => imported_global_index,
|
||||
LocalOrImport::Local(_) => {
|
||||
panic!("invalid global initializer when declaring an imported global")
|
||||
}
|
||||
})
|
||||
}
|
||||
None => Initializer::Const((offset as i32).into()),
|
||||
};
|
||||
|
||||
// Add table initializer to list of table initializers
|
||||
self.module.info.elem_initializers.push(TableInitializer {
|
||||
table_index: Converter(table_index).into(),
|
||||
base,
|
||||
elements: elements
|
||||
.iter()
|
||||
.map(|&func_index| Converter(func_index).into())
|
||||
.collect(),
|
||||
});
|
||||
}
|
||||
|
||||
/// Declares a memory to the environment
|
||||
fn declare_memory(&mut self, memory: cranelift_wasm::Memory) {
|
||||
self.module.info.memories.push(MemoryDescriptor {
|
||||
minimum: Pages(memory.minimum),
|
||||
maximum: memory.maximum.map(|max| Pages(max)),
|
||||
shared: memory.shared,
|
||||
});
|
||||
}
|
||||
|
||||
/// Declares a memory import to the environment.
|
||||
fn declare_memory_import(
|
||||
&mut self,
|
||||
memory: cranelift_wasm::Memory,
|
||||
namespace: &'data str,
|
||||
name: &'data str,
|
||||
) {
|
||||
let namespace_index = self.namespace_table_builder.register(namespace);
|
||||
let name_index = self.name_table_builder.register(name);
|
||||
|
||||
let import_name = ImportName {
|
||||
namespace_index,
|
||||
name_index,
|
||||
};
|
||||
|
||||
let memory = MemoryDescriptor {
|
||||
minimum: Pages(memory.minimum),
|
||||
maximum: memory.maximum.map(|max| Pages(max)),
|
||||
shared: memory.shared,
|
||||
};
|
||||
|
||||
// Add import names to list of imported memories
|
||||
self.module
|
||||
.info
|
||||
.imported_memories
|
||||
.push((import_name, memory));
|
||||
}
|
||||
|
||||
/// Fills a declared memory with bytes at module instantiation.
|
||||
fn declare_data_initialization(
|
||||
&mut self,
|
||||
memory_index: cranelift_wasm::MemoryIndex,
|
||||
base: Option<cranelift_wasm::GlobalIndex>,
|
||||
offset: usize,
|
||||
data: &'data [u8],
|
||||
) {
|
||||
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
||||
let base = match base {
|
||||
Some(global_index) => {
|
||||
let global_index: GlobalIndex = Converter(global_index).into();
|
||||
Initializer::GetGlobal(match global_index.local_or_import(&self.module.info) {
|
||||
LocalOrImport::Import(imported_global_index) => imported_global_index,
|
||||
LocalOrImport::Local(_) => {
|
||||
panic!("invalid global initializer when declaring an imported global")
|
||||
}
|
||||
})
|
||||
}
|
||||
None => Initializer::Const((offset as i32).into()),
|
||||
};
|
||||
|
||||
// Add data initializer to list of data initializers
|
||||
self.module.info.data_initializers.push(DataInitializer {
|
||||
memory_index: Converter(memory_index).into(),
|
||||
base,
|
||||
data: data.to_vec(),
|
||||
});
|
||||
}
|
||||
|
||||
/// Declares a function export to the environment.
|
||||
fn declare_func_export(&mut self, func_index: cranelift_wasm::FuncIndex, name: &'data str) {
|
||||
self.module.info.exports.insert(
|
||||
name.to_string(),
|
||||
ExportIndex::Func(Converter(func_index).into()),
|
||||
);
|
||||
}
|
||||
/// Declares a table export to the environment.
|
||||
fn declare_table_export(&mut self, table_index: cranelift_wasm::TableIndex, name: &'data str) {
|
||||
self.module.info.exports.insert(
|
||||
name.to_string(),
|
||||
ExportIndex::Table(Converter(table_index).into()),
|
||||
);
|
||||
}
|
||||
/// Declares a memory export to the environment.
|
||||
fn declare_memory_export(
|
||||
&mut self,
|
||||
memory_index: cranelift_wasm::MemoryIndex,
|
||||
name: &'data str,
|
||||
) {
|
||||
self.module.info.exports.insert(
|
||||
name.to_string(),
|
||||
ExportIndex::Memory(Converter(memory_index).into()),
|
||||
);
|
||||
}
|
||||
/// Declares a global export to the environment.
|
||||
fn declare_global_export(
|
||||
&mut self,
|
||||
global_index: cranelift_wasm::GlobalIndex,
|
||||
name: &'data str,
|
||||
) {
|
||||
self.module.info.exports.insert(
|
||||
name.to_string(),
|
||||
ExportIndex::Global(Converter(global_index).into()),
|
||||
);
|
||||
}
|
||||
|
||||
/// Declares a start function.
|
||||
fn declare_start_func(&mut self, func_index: cranelift_wasm::FuncIndex) {
|
||||
self.module.info.start_func = Some(Converter(func_index).into());
|
||||
}
|
||||
|
||||
/// Provides the contents of a function body.
|
||||
fn define_function_body(
|
||||
&mut self,
|
||||
body_bytes: &'data [u8],
|
||||
body_offset: usize,
|
||||
) -> cranelift_wasm::WasmResult<()> {
|
||||
let mut func_translator = FuncTranslator::new();
|
||||
|
||||
let func_body = {
|
||||
let mut func_env = FuncEnv::new(self);
|
||||
let func_index = self.func_bodies.next_index();
|
||||
let name = ir::ExternalName::user(0, func_index.index() as u32);
|
||||
|
||||
let sig = func_env.generate_signature(
|
||||
self.get_func_type(Converter(func_index.convert_up(&self.module.info)).into()),
|
||||
);
|
||||
|
||||
let mut func = ir::Function::with_name_signature(name, sig);
|
||||
|
||||
func_translator.translate(body_bytes, body_offset, &mut func, &mut func_env)?;
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
{
|
||||
use cranelift_codegen::cursor::{Cursor, FuncCursor};
|
||||
use cranelift_codegen::ir::InstBuilder;
|
||||
let entry_ebb = func.layout.entry_block().unwrap();
|
||||
let ebb = func.dfg.make_ebb();
|
||||
func.layout.insert_ebb(ebb, entry_ebb);
|
||||
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(ebb);
|
||||
let params = pos.func.dfg.ebb_params(entry_ebb).to_vec();
|
||||
|
||||
let new_ebb_params: Vec<_> = params
|
||||
.iter()
|
||||
.map(|¶m| {
|
||||
pos.func
|
||||
.dfg
|
||||
.append_ebb_param(ebb, pos.func.dfg.value_type(param))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let start_debug = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("strtdbug");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let end_debug = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![ir::AbiParam::special(
|
||||
ir::types::I64,
|
||||
ir::ArgumentPurpose::VMContext,
|
||||
)],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("enddbug");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let i32_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("i32print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let i64_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I64),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("i64print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let f32_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::F32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("f32print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let f64_print = {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::F64),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let name = ir::ExternalName::testcase("f64print");
|
||||
|
||||
pos.func.import_function(ir::ExtFuncData {
|
||||
name,
|
||||
signature,
|
||||
colocated: false,
|
||||
})
|
||||
};
|
||||
|
||||
let vmctx = pos
|
||||
.func
|
||||
.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.expect("missing vmctx parameter");
|
||||
|
||||
let func_index = pos.ins().iconst(
|
||||
ir::types::I32,
|
||||
func_index.index() as i64 + self.module.info.imported_functions.len() as i64,
|
||||
);
|
||||
|
||||
pos.ins().call(start_debug, &[vmctx, func_index]);
|
||||
|
||||
for param in new_ebb_params.iter().cloned() {
|
||||
match pos.func.dfg.value_type(param) {
|
||||
ir::types::I32 => pos.ins().call(i32_print, &[vmctx, param]),
|
||||
ir::types::I64 => pos.ins().call(i64_print, &[vmctx, param]),
|
||||
ir::types::F32 => pos.ins().call(f32_print, &[vmctx, param]),
|
||||
ir::types::F64 => pos.ins().call(f64_print, &[vmctx, param]),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
}
|
||||
|
||||
pos.ins().call(end_debug, &[vmctx]);
|
||||
|
||||
pos.ins().jump(entry_ebb, new_ebb_params.as_slice());
|
||||
}
|
||||
|
||||
func
|
||||
};
|
||||
|
||||
// Add function body to list of function bodies.
|
||||
self.func_bodies.push(func_body);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -9,14 +9,15 @@ edition = "2018"
|
||||
build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||
byteorder = "1"
|
||||
hashbrown = "0.1"
|
||||
lazy_static = "1.2.0"
|
||||
libc = "0.2.49"
|
||||
byteorder = "1"
|
||||
time = "0.1.41"
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.4.2" }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.2", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.4.2", optional = true }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.2", optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
rand = "0.6"
|
||||
|
@ -3,8 +3,10 @@
|
||||
#[macro_use]
|
||||
extern crate wasmer_runtime_core;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use lazy_static::lazy_static;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::path::PathBuf;
|
||||
use std::{f64, ffi::c_void};
|
||||
use wasmer_runtime_core::{
|
||||
error::CallResult,
|
||||
@ -141,10 +143,14 @@ pub struct EmscriptenData<'a> {
|
||||
pub stack_save: Option<Func<'a, (), i32>>,
|
||||
pub stack_restore: Option<Func<'a, (i32)>>,
|
||||
pub set_threw: Option<Func<'a, (i32, i32)>>,
|
||||
pub mapped_dirs: HashMap<String, PathBuf>,
|
||||
}
|
||||
|
||||
impl<'a> EmscriptenData<'a> {
|
||||
pub fn new(instance: &'a mut Instance) -> EmscriptenData<'a> {
|
||||
pub fn new(
|
||||
instance: &'a mut Instance,
|
||||
mapped_dirs: HashMap<String, PathBuf>,
|
||||
) -> EmscriptenData<'a> {
|
||||
let malloc = instance.func("_malloc").unwrap();
|
||||
let free = instance.func("_free").unwrap();
|
||||
let memalign = instance.func("_memalign").ok();
|
||||
@ -272,6 +278,7 @@ impl<'a> EmscriptenData<'a> {
|
||||
stack_save,
|
||||
stack_restore,
|
||||
set_threw,
|
||||
mapped_dirs,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -282,8 +289,9 @@ pub fn run_emscripten_instance(
|
||||
path: &str,
|
||||
args: Vec<&str>,
|
||||
entrypoint: Option<String>,
|
||||
mapped_dirs: Vec<(String, PathBuf)>,
|
||||
) -> CallResult<()> {
|
||||
let mut data = EmscriptenData::new(instance);
|
||||
let mut data = EmscriptenData::new(instance, mapped_dirs.into_iter().collect());
|
||||
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||
instance.context_mut().data = data_ptr;
|
||||
|
||||
|
@ -10,7 +10,8 @@ pub use self::unix::*;
|
||||
#[cfg(windows)]
|
||||
pub use self::windows::*;
|
||||
|
||||
use super::utils::copy_stat_into_wasm;
|
||||
use crate::utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory};
|
||||
|
||||
use super::varargs::VarArgs;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
|
||||
@ -95,12 +96,19 @@ pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall12 (chdir) {}", _which);
|
||||
let path_ptr = varargs.get_str(ctx);
|
||||
unsafe {
|
||||
let _path = std::ffi::CStr::from_ptr(path_ptr);
|
||||
let ret = chdir(path_ptr);
|
||||
debug!("=> path: {:?}, ret: {}", _path, ret);
|
||||
let real_path_owned = get_cstr_path(ctx, path_ptr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
path_ptr
|
||||
};
|
||||
let ret = unsafe { chdir(real_path) };
|
||||
debug!(
|
||||
"=> path: {:?}, ret: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(real_path) },
|
||||
ret
|
||||
}
|
||||
);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
@ -124,11 +132,23 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
debug!("emscripten::___syscall38 (rename)");
|
||||
let old_path = varargs.get_str(ctx);
|
||||
let new_path = varargs.get_str(ctx);
|
||||
let result = unsafe { rename(old_path, new_path) };
|
||||
let real_old_path_owned = get_cstr_path(ctx, old_path);
|
||||
let real_old_path = if let Some(ref rp) = real_old_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
old_path
|
||||
};
|
||||
let real_new_path_owned = get_cstr_path(ctx, new_path);
|
||||
let real_new_path = if let Some(ref rp) = real_new_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
new_path
|
||||
};
|
||||
let result = unsafe { rename(real_old_path, real_new_path) };
|
||||
debug!(
|
||||
"=> old_path: {}, new_path: {}, result: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(old_path).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(new_path).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(real_old_path).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(real_new_path).to_str().unwrap() },
|
||||
result
|
||||
);
|
||||
result
|
||||
@ -138,7 +158,13 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall40 (rmdir)");
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
unsafe { rmdir(pathname_addr) }
|
||||
let real_path_owned = get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
unsafe { rmdir(real_path) }
|
||||
}
|
||||
|
||||
// pipe
|
||||
@ -244,10 +270,9 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
// getcwd
|
||||
pub fn ___syscall183(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
debug!("emscripten::___syscall183");
|
||||
use std::env;
|
||||
let buf_offset: c_int = varargs.get(ctx);
|
||||
let _size: c_int = varargs.get(ctx);
|
||||
let path = env::current_dir();
|
||||
let path = get_current_directory(ctx);
|
||||
let path_string = path.unwrap().display().to_string();
|
||||
let len = path_string.len();
|
||||
unsafe {
|
||||
@ -420,12 +445,19 @@ pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
|
||||
let real_path_owned = get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let mut _stat: stat = std::mem::zeroed();
|
||||
let ret = stat(pathname_addr, &mut _stat);
|
||||
let ret = stat(real_path, &mut _stat);
|
||||
debug!(
|
||||
"=> pathname: {}, buf: {} = {}, last os error: {}",
|
||||
std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap(),
|
||||
std::ffi::CStr::from_ptr(real_path).to_str().unwrap(),
|
||||
buf,
|
||||
ret,
|
||||
Error::last_os_error()
|
||||
@ -457,11 +489,6 @@ pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
0
|
||||
}
|
||||
|
||||
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall220");
|
||||
-1
|
||||
}
|
||||
|
||||
// fcntl64
|
||||
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
|
||||
@ -474,7 +501,7 @@ pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
// |FNONBLOCK - 0x04
|
||||
debug!("=> fd: {}, cmd: {}", _fd, cmd);
|
||||
match cmd {
|
||||
2 => 0,
|
||||
1 | 2 => 0,
|
||||
13 | 14 => 0, // pretend file locking worked
|
||||
_ => -1,
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ use libc::{
|
||||
pid_t,
|
||||
pread,
|
||||
pwrite,
|
||||
readdir,
|
||||
// readv,
|
||||
recvfrom,
|
||||
recvmsg,
|
||||
@ -107,8 +108,14 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
let flags: i32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
||||
let fd = unsafe { open(pathname_addr, flags, mode) };
|
||||
let real_path_owned = utils::get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
let _path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() };
|
||||
let fd = unsafe { open(real_path, flags, mode) };
|
||||
debug!(
|
||||
"=> path: {}, flags: {}, mode: {} = fd: {}, last os error: {}",
|
||||
_path_str,
|
||||
@ -154,11 +161,23 @@ pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
|
||||
let path1 = varargs.get_str(ctx);
|
||||
let path2 = varargs.get_str(ctx);
|
||||
let result = unsafe { symlink(path1, path2) };
|
||||
let real_path1_owned = utils::get_cstr_path(ctx, path1);
|
||||
let real_path1 = if let Some(ref rp) = real_path1_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
path1
|
||||
};
|
||||
let real_path2_owned = utils::get_cstr_path(ctx, path2);
|
||||
let real_path2 = if let Some(ref rp) = real_path2_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
path2
|
||||
};
|
||||
let result = unsafe { symlink(real_path1, real_path2) };
|
||||
debug!(
|
||||
"=> path1: {}, path2: {}, result: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(path1).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(path2).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(real_path1).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(real_path2).to_str().unwrap() },
|
||||
result,
|
||||
);
|
||||
result
|
||||
@ -181,12 +200,18 @@ pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
pub fn ___syscall198(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall198 (lchown) {}", _which);
|
||||
let path_ptr = varargs.get_str(ctx);
|
||||
let real_path_owned = utils::get_cstr_path(ctx, path_ptr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
path_ptr
|
||||
};
|
||||
let uid: uid_t = varargs.get(ctx);
|
||||
let gid: gid_t = varargs.get(ctx);
|
||||
let result = unsafe { lchown(path_ptr, uid, gid) };
|
||||
let result = unsafe { lchown(real_path, uid, gid) };
|
||||
debug!(
|
||||
"=> path: {}, uid: {}, gid: {}, result: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(path_ptr).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() },
|
||||
uid,
|
||||
gid,
|
||||
result,
|
||||
@ -216,10 +241,16 @@ pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
debug!("emscripten::___syscall212 (chown) {}", _which);
|
||||
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
let real_path_owned = utils::get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
let owner: u32 = varargs.get(ctx);
|
||||
let group: u32 = varargs.get(ctx);
|
||||
|
||||
unsafe { chown(pathname_addr, owner, group) }
|
||||
unsafe { chown(real_path, owner, group) }
|
||||
}
|
||||
|
||||
/// madvise
|
||||
@ -239,11 +270,17 @@ pub fn ___syscall219(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall33 (access) {}", _which);
|
||||
let path = varargs.get_str(ctx);
|
||||
let real_path_owned = utils::get_cstr_path(ctx, path);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
path
|
||||
};
|
||||
let amode: c_int = varargs.get(ctx);
|
||||
let result = unsafe { access(path, amode) };
|
||||
let result = unsafe { access(real_path, amode) };
|
||||
debug!(
|
||||
"=> path: {}, amode: {}, result: {}",
|
||||
unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() },
|
||||
unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() },
|
||||
amode,
|
||||
result
|
||||
);
|
||||
@ -261,8 +298,14 @@ pub fn ___syscall34(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall39 (mkdir) {}", _which);
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
let real_path_owned = utils::get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
unsafe { mkdir(pathname_addr, mode as _) }
|
||||
unsafe { mkdir(real_path, mode as _) }
|
||||
}
|
||||
|
||||
/// dup
|
||||
@ -761,6 +804,12 @@ pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
debug!("emscripten::___syscall196 (lstat64) {}", _which);
|
||||
let path = varargs.get_str(ctx);
|
||||
let real_path_owned = utils::get_cstr_path(ctx, path);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
path
|
||||
};
|
||||
let buf_ptr: u32 = varargs.get(ctx);
|
||||
unsafe {
|
||||
let mut stat: stat = std::mem::zeroed();
|
||||
@ -771,9 +820,9 @@ pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
let stat_ptr = &mut stat as *mut stat;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let ret = lstat64(path, stat_ptr);
|
||||
let ret = lstat64(real_path, stat_ptr);
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let ret = lstat(path, stat_ptr);
|
||||
let ret = lstat(real_path, stat_ptr);
|
||||
|
||||
debug!("ret: {}", ret);
|
||||
if ret != 0 {
|
||||
@ -784,6 +833,45 @@ pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
// getdents
|
||||
// dirent structure is
|
||||
// i64, i64, u16 (280), i8, [i8; 256]
|
||||
pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
debug!("emscripten::___syscall220");
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let dirp_addr: i32 = varargs.get(ctx);
|
||||
let count: u32 = varargs.get(ctx);
|
||||
|
||||
let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8;
|
||||
// need to persist stream across calls?
|
||||
let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
|
||||
|
||||
let mut pos = 0;
|
||||
let offset = 280;
|
||||
while pos + offset <= count as usize {
|
||||
let dirent = unsafe { readdir(dir) };
|
||||
if dirent.is_null() {
|
||||
break;
|
||||
}
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe {
|
||||
*(dirp.add(pos) as *mut u64) = (*dirent).d_ino;
|
||||
*(dirp.add(pos + 8) as *mut u64) = pos as u64 + offset as u64;
|
||||
*(dirp.add(pos + 16) as *mut u16) = offset as u16;
|
||||
*(dirp.add(pos + 18) as *mut u8) = (*dirent).d_type;
|
||||
let upper_bound = std::cmp::min((*dirent).d_reclen, 254) as usize;
|
||||
let mut i = 0;
|
||||
while i < upper_bound {
|
||||
*(dirp.add(pos + 19 + i) as *mut i8) = (*dirent).d_name[i];
|
||||
i += 1;
|
||||
}
|
||||
*(dirp.add(pos + 19 + i) as *mut i8) = 0 as i8;
|
||||
}
|
||||
pos += offset;
|
||||
}
|
||||
pos as i32
|
||||
}
|
||||
|
||||
/// fallocate
|
||||
pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall324 (fallocate) {}", _which);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::utils::copy_cstr_into_wasm;
|
||||
use crate::utils::{copy_cstr_into_wasm, get_cstr_path};
|
||||
use crate::varargs::VarArgs;
|
||||
use libc::mkdir;
|
||||
use libc::open;
|
||||
@ -19,9 +19,15 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
let real_path_owned = get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
let flags: i32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
||||
let path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() };
|
||||
match path_str {
|
||||
"/dev/urandom" => {
|
||||
// create a fake urandom file for windows, super hacky
|
||||
@ -47,7 +53,7 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
fd
|
||||
}
|
||||
_ => {
|
||||
let fd = unsafe { open(pathname_addr, flags, mode) };
|
||||
let fd = unsafe { open(real_path, flags, mode) };
|
||||
debug!(
|
||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
||||
path_str, flags, mode, fd, path_str
|
||||
@ -95,7 +101,13 @@ pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = which;
|
||||
let pathname_addr = varargs.get_str(ctx);
|
||||
unsafe { mkdir(pathname_addr) }
|
||||
let real_path_owned = get_cstr_path(ctx, pathname_addr);
|
||||
let real_path = if let Some(ref rp) = real_path_owned {
|
||||
rp.as_c_str().as_ptr()
|
||||
} else {
|
||||
pathname_addr
|
||||
};
|
||||
unsafe { mkdir(real_path) }
|
||||
}
|
||||
|
||||
/// dup
|
||||
@ -249,6 +261,12 @@ pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
-1
|
||||
}
|
||||
|
||||
// getdents
|
||||
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall220");
|
||||
-1
|
||||
}
|
||||
|
||||
/// fchown
|
||||
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall207 (fchown) {}", _which);
|
||||
|
@ -5,6 +5,7 @@ use libc::stat;
|
||||
use std::ffi::CStr;
|
||||
use std::mem::size_of;
|
||||
use std::os::raw::c_char;
|
||||
use std::path::PathBuf;
|
||||
use std::slice;
|
||||
use wasmer_runtime_core::memory::Memory;
|
||||
use wasmer_runtime_core::{
|
||||
@ -204,6 +205,61 @@ pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String {
|
||||
String::from_utf8_lossy(&v).to_owned().to_string()
|
||||
}
|
||||
|
||||
/// This function trys to find an entry in mapdir
|
||||
/// translating paths into their correct value
|
||||
pub fn get_cstr_path(ctx: &mut Ctx, path: *const i8) -> Option<std::ffi::CString> {
|
||||
use std::collections::VecDeque;
|
||||
|
||||
let path_str = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string();
|
||||
let data = get_emscripten_data(ctx);
|
||||
let path = PathBuf::from(path_str);
|
||||
let mut prefix_added = false;
|
||||
let mut components = path.components().collect::<VecDeque<_>>();
|
||||
// TODO(mark): handle absolute/non-canonical/non-relative paths too (this
|
||||
// functionality should be shared among the abis)
|
||||
if components.len() == 1 {
|
||||
components.push_front(std::path::Component::CurDir);
|
||||
prefix_added = true;
|
||||
}
|
||||
let mut cumulative_path = PathBuf::new();
|
||||
for c in components.into_iter() {
|
||||
cumulative_path.push(c);
|
||||
if let Some(val) = data
|
||||
.mapped_dirs
|
||||
.get(&cumulative_path.to_string_lossy().to_string())
|
||||
{
|
||||
let rest_of_path = if !prefix_added {
|
||||
path.strip_prefix(cumulative_path).ok()?
|
||||
} else {
|
||||
&path
|
||||
};
|
||||
let rebased_path = val.join(rest_of_path);
|
||||
return std::ffi::CString::new(rebased_path.to_string_lossy().as_bytes()).ok();
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// gets the current directory
|
||||
/// handles mapdir logic
|
||||
pub fn get_current_directory(ctx: &mut Ctx) -> Option<PathBuf> {
|
||||
if let Some(val) = get_emscripten_data(ctx).mapped_dirs.get(".") {
|
||||
return Some(val.clone());
|
||||
}
|
||||
std::env::current_dir()
|
||||
.map(|cwd| {
|
||||
if let Some(val) = get_emscripten_data(ctx)
|
||||
.mapped_dirs
|
||||
.get(&cwd.to_string_lossy().to_string())
|
||||
{
|
||||
val.clone()
|
||||
} else {
|
||||
cwd
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::is_emscripten_module;
|
||||
|
@ -56,6 +56,7 @@ macro_rules! assert_emscripten_output {
|
||||
$name,
|
||||
$args,
|
||||
None,
|
||||
vec![],
|
||||
).expect("run_emscripten_instance finishes");
|
||||
|
||||
let output = capturer.end().unwrap().0;
|
||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||
inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm7-0" }
|
||||
wasmparser = "0.30.0"
|
||||
wasmparser = "0.29.2"
|
||||
hashbrown = "0.1.8"
|
||||
smallvec = "0.6.8"
|
||||
goblin = "0.0.20"
|
||||
|
@ -8,7 +8,7 @@ use inkwell::{
|
||||
AddressSpace, FloatPredicate, IntPredicate,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, CacheGen, Token},
|
||||
cache::{Artifact, Error as CacheError},
|
||||
@ -2551,7 +2551,10 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_function(&mut self) -> Result<&mut LLVMFunctionCodeGenerator, CodegenError> {
|
||||
fn next_function(
|
||||
&mut self,
|
||||
_module_info: Arc<RwLock<ModuleInfo>>,
|
||||
) -> Result<&mut LLVMFunctionCodeGenerator, CodegenError> {
|
||||
// Creates a new function and returns the function-scope code generator for it.
|
||||
let (context, builder, intrinsics, breakpoints) = match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
|
@ -13,7 +13,7 @@ wasmer-runtime-core = { path = "../runtime-core" }
|
||||
hashbrown = "0.1"
|
||||
failure = "0.1"
|
||||
tar = "0.4"
|
||||
wasmparser = "0.30.0"
|
||||
wasmparser = "0.29.2"
|
||||
zstd = "0.4"
|
||||
|
||||
# [target.'cfg(unix)'.dependencies.zbox]
|
||||
|
@ -10,7 +10,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
nix = "0.12.0"
|
||||
page_size = "0.4.1"
|
||||
wasmparser = "0.30.0"
|
||||
wasmparser = "0.29.2"
|
||||
parking_lot = "0.7.1"
|
||||
lazy_static = "1.2.0"
|
||||
indexmap = "1.0.2"
|
||||
|
@ -11,6 +11,8 @@ use smallvec::SmallVec;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use wasmparser::{self, WasmDecoder};
|
||||
use wasmparser::{Operator, Type as WpType};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -57,13 +59,14 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
|
||||
}
|
||||
/// Adds an import function.
|
||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||
/// Sets function signatures.
|
||||
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
||||
/// Checks the precondition for a module.
|
||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
||||
/// Creates a new function and returns the function-scope code generator for it.
|
||||
fn next_function(&mut self) -> Result<&mut FCG, E>;
|
||||
fn next_function(&mut self, module_info: Arc<RwLock<ModuleInfo>>) -> Result<&mut FCG, E>;
|
||||
/// Finalizes this module.
|
||||
fn finalize(self, module_info: &ModuleInfo) -> Result<(RM, Box<dyn CacheGen>), E>;
|
||||
|
||||
@ -128,6 +131,20 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn validate(bytes: &[u8]) -> CompileResult<()> {
|
||||
let mut parser = wasmparser::ValidatingParser::new(bytes, None);
|
||||
loop {
|
||||
let state = parser.read();
|
||||
match *state {
|
||||
wasmparser::ParserState::EndWasm => break Ok(()),
|
||||
wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
|
||||
msg: err.message.to_string(),
|
||||
})?,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||
FCG: FunctionCodeGenerator<E>,
|
||||
@ -142,6 +159,10 @@ impl<
|
||||
compiler_config: CompilerConfig,
|
||||
_: Token,
|
||||
) -> CompileResult<ModuleInner> {
|
||||
if requires_pre_validation(MCG::backend_id()) {
|
||||
validate(wasm)?;
|
||||
}
|
||||
|
||||
let mut mcg = MCG::new();
|
||||
let mut chain = (self.middleware_chain_generator)();
|
||||
let info = crate::parse::read_module(
|
||||
@ -152,14 +173,14 @@ impl<
|
||||
&compiler_config,
|
||||
)?;
|
||||
let (exec_context, cache_gen) =
|
||||
mcg.finalize(&info)
|
||||
mcg.finalize(&info.read().unwrap())
|
||||
.map_err(|x| CompileError::InternalError {
|
||||
msg: format!("{:?}", x),
|
||||
})?;
|
||||
Ok(ModuleInner {
|
||||
cache_gen,
|
||||
runnable_module: Box::new(exec_context),
|
||||
info,
|
||||
info: Arc::try_unwrap(info).unwrap().into_inner().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -172,6 +193,14 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn requires_pre_validation(backend: Backend) -> bool {
|
||||
match backend {
|
||||
Backend::Cranelift => true,
|
||||
Backend::LLVM => false,
|
||||
Backend::Singlepass => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventSink<'a, 'b> {
|
||||
buffer: SmallVec<[Event<'a, 'b>; 2]>,
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub struct ModuleInner {
|
||||
pub info: ModuleInfo,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ModuleInfo {
|
||||
// This are strictly local and the typsystem ensures that.
|
||||
pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
|
||||
|
@ -16,6 +16,7 @@ use crate::{
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use wasmparser::{
|
||||
BinaryReaderError, ExternalKind, FuncType, ImportSectionEntryType, Operator, Type as WpType,
|
||||
WasmDecoder,
|
||||
@ -52,10 +53,10 @@ pub fn read_module<
|
||||
mcg: &mut MCG,
|
||||
middlewares: &mut MiddlewareChain,
|
||||
compiler_config: &CompilerConfig,
|
||||
) -> Result<ModuleInfo, LoadError> {
|
||||
) -> Result<Arc<RwLock<ModuleInfo>>, LoadError> {
|
||||
mcg.feed_compiler_config(compiler_config)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
let mut info = ModuleInfo {
|
||||
let info = Arc::new(RwLock::new(ModuleInfo {
|
||||
memories: Map::new(),
|
||||
globals: Map::new(),
|
||||
tables: Map::new(),
|
||||
@ -82,7 +83,7 @@ pub fn read_module<
|
||||
em_symbol_map: compiler_config.symbol_map.clone(),
|
||||
|
||||
custom_sections: HashMap::new(),
|
||||
};
|
||||
}));
|
||||
|
||||
let mut parser = wasmparser::ValidatingParser::new(
|
||||
wasm,
|
||||
@ -105,10 +106,13 @@ pub fn read_module<
|
||||
use wasmparser::ParserState;
|
||||
let state = parser.read();
|
||||
match *state {
|
||||
ParserState::EndWasm => break Ok(info),
|
||||
ParserState::EndWasm => break,
|
||||
ParserState::Error(err) => Err(LoadError::Parse(err))?,
|
||||
ParserState::TypeSectionEntry(ref ty) => {
|
||||
info.signatures.push(func_type_to_func_sig(ty)?);
|
||||
info.write()
|
||||
.unwrap()
|
||||
.signatures
|
||||
.push(func_type_to_func_sig(ty)?);
|
||||
}
|
||||
ParserState::ImportSectionEntry { module, field, ty } => {
|
||||
let namespace_index = namespace_builder.as_mut().unwrap().register(module);
|
||||
@ -121,8 +125,8 @@ pub fn read_module<
|
||||
match ty {
|
||||
ImportSectionEntryType::Function(sigindex) => {
|
||||
let sigindex = SigIndex::new(sigindex as usize);
|
||||
info.imported_functions.push(import_name);
|
||||
info.func_assoc.push(sigindex);
|
||||
info.write().unwrap().imported_functions.push(import_name);
|
||||
info.write().unwrap().func_assoc.push(sigindex);
|
||||
mcg.feed_import_function()
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
@ -134,7 +138,10 @@ pub fn read_module<
|
||||
maximum: table_ty.limits.maximum,
|
||||
};
|
||||
|
||||
info.imported_tables.push((import_name, table_desc));
|
||||
info.write()
|
||||
.unwrap()
|
||||
.imported_tables
|
||||
.push((import_name, table_desc));
|
||||
}
|
||||
ImportSectionEntryType::Memory(memory_ty) => {
|
||||
let mem_desc = MemoryDescriptor {
|
||||
@ -142,20 +149,26 @@ pub fn read_module<
|
||||
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
||||
shared: memory_ty.shared,
|
||||
};
|
||||
info.imported_memories.push((import_name, mem_desc));
|
||||
info.write()
|
||||
.unwrap()
|
||||
.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.write()
|
||||
.unwrap()
|
||||
.imported_globals
|
||||
.push((import_name, global_desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
ParserState::FunctionSectionEntry(sigindex) => {
|
||||
let sigindex = SigIndex::new(sigindex as usize);
|
||||
info.func_assoc.push(sigindex);
|
||||
info.write().unwrap().func_assoc.push(sigindex);
|
||||
}
|
||||
ParserState::TableSectionEntry(table_ty) => {
|
||||
let table_desc = TableDescriptor {
|
||||
@ -164,7 +177,7 @@ pub fn read_module<
|
||||
maximum: table_ty.limits.maximum,
|
||||
};
|
||||
|
||||
info.tables.push(table_desc);
|
||||
info.write().unwrap().tables.push(table_desc);
|
||||
}
|
||||
ParserState::MemorySectionEntry(memory_ty) => {
|
||||
let mem_desc = MemoryDescriptor {
|
||||
@ -173,7 +186,7 @@ pub fn read_module<
|
||||
shared: memory_ty.shared,
|
||||
};
|
||||
|
||||
info.memories.push(mem_desc);
|
||||
info.write().unwrap().memories.push(mem_desc);
|
||||
}
|
||||
ParserState::ExportSectionEntry { field, kind, index } => {
|
||||
let export_index = match kind {
|
||||
@ -183,42 +196,51 @@ pub fn read_module<
|
||||
ExternalKind::Global => ExportIndex::Global(GlobalIndex::new(index as usize)),
|
||||
};
|
||||
|
||||
info.exports.insert(field.to_string(), export_index);
|
||||
info.write()
|
||||
.unwrap()
|
||||
.exports
|
||||
.insert(field.to_string(), export_index);
|
||||
}
|
||||
ParserState::StartSectionEntry(start_index) => {
|
||||
info.start_func = Some(FuncIndex::new(start_index as usize));
|
||||
info.write().unwrap().start_func = Some(FuncIndex::new(start_index as usize));
|
||||
}
|
||||
ParserState::BeginFunctionBody { .. } => {
|
||||
let id = func_count.wrapping_add(1);
|
||||
func_count = id;
|
||||
if func_count == 0 {
|
||||
info.namespace_table = namespace_builder.take().unwrap().finish();
|
||||
info.name_table = name_builder.take().unwrap().finish();
|
||||
mcg.feed_signatures(info.signatures.clone())
|
||||
info.write().unwrap().namespace_table =
|
||||
namespace_builder.take().unwrap().finish();
|
||||
info.write().unwrap().name_table = name_builder.take().unwrap().finish();
|
||||
mcg.feed_signatures(info.read().unwrap().signatures.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.feed_function_signatures(info.func_assoc.clone())
|
||||
mcg.feed_function_signatures(info.read().unwrap().func_assoc.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.check_precondition(&info)
|
||||
mcg.check_precondition(&info.read().unwrap())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
|
||||
let fcg = mcg
|
||||
.next_function()
|
||||
.next_function(Arc::clone(&info))
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
middlewares
|
||||
.run(
|
||||
Some(fcg),
|
||||
Event::Internal(InternalEvent::FunctionBegin(id as u32)),
|
||||
&info,
|
||||
&info.read().unwrap(),
|
||||
)
|
||||
.map_err(|x| LoadError::Codegen(x))?;
|
||||
|
||||
let sig = info
|
||||
let info_read = info.read().unwrap();
|
||||
let sig = info_read
|
||||
.signatures
|
||||
.get(
|
||||
*info
|
||||
.read()
|
||||
.unwrap()
|
||||
.func_assoc
|
||||
.get(FuncIndex::new(id as usize + info.imported_functions.len()))
|
||||
.get(FuncIndex::new(
|
||||
id as usize + info.read().unwrap().imported_functions.len(),
|
||||
))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
@ -235,22 +257,22 @@ pub fn read_module<
|
||||
|
||||
loop {
|
||||
let state = parser.read();
|
||||
match *state {
|
||||
ParserState::Error(err) => return Err(LoadError::Parse(err)),
|
||||
match state {
|
||||
ParserState::Error(err) => return Err(LoadError::Parse(*err)),
|
||||
ParserState::FunctionBodyLocals { ref locals } => {
|
||||
for &(count, ty) in locals.iter() {
|
||||
fcg.feed_local(ty, count as usize)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
}
|
||||
ParserState::CodeOperator(ref op) => {
|
||||
ParserState::CodeOperator(op) => {
|
||||
if !body_begun {
|
||||
body_begun = true;
|
||||
fcg.begin_body(&info)
|
||||
fcg.begin_body(&info.read().unwrap())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
middlewares
|
||||
.run(Some(fcg), Event::Wasm(op), &info)
|
||||
.run(Some(fcg), Event::Wasm(op), &info.read().unwrap())
|
||||
.map_err(|x| LoadError::Codegen(x))?;
|
||||
}
|
||||
ParserState::EndFunctionBody => break,
|
||||
@ -261,7 +283,7 @@ pub fn read_module<
|
||||
.run(
|
||||
Some(fcg),
|
||||
Event::Internal(InternalEvent::FunctionEnd),
|
||||
&info,
|
||||
&info.read().unwrap(),
|
||||
)
|
||||
.map_err(|x| LoadError::Codegen(x))?;
|
||||
fcg.finalize()
|
||||
@ -301,7 +323,7 @@ pub fn read_module<
|
||||
elements: elements.unwrap(),
|
||||
};
|
||||
|
||||
info.elem_initializers.push(table_init);
|
||||
info.write().unwrap().elem_initializers.push(table_init);
|
||||
}
|
||||
ParserState::BeginActiveDataSectionEntry(memory_index) => {
|
||||
let memory_index = MemoryIndex::new(memory_index as usize);
|
||||
@ -332,7 +354,7 @@ pub fn read_module<
|
||||
base: base.unwrap(),
|
||||
data,
|
||||
};
|
||||
info.data_initializers.push(data_init);
|
||||
info.write().unwrap().data_initializers.push(data_init);
|
||||
}
|
||||
ParserState::BeginGlobalSectionEntry(ty) => {
|
||||
let init = loop {
|
||||
@ -353,12 +375,13 @@ pub fn read_module<
|
||||
|
||||
let global_init = GlobalInit { desc, init };
|
||||
|
||||
info.globals.push(global_init);
|
||||
info.write().unwrap().globals.push(global_init);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
pub fn wp_type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
|
||||
|
@ -9,7 +9,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||
wasmparser = "0.30.0"
|
||||
wasmparser = "0.29.2"
|
||||
dynasm = "0.3.2"
|
||||
dynasmrt = "0.3.1"
|
||||
lazy_static = "1.2.0"
|
||||
|
@ -8,7 +8,11 @@ use dynasmrt::{
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::ptr::NonNull;
|
||||
use std::{any::Any, collections::HashMap, sync::Arc};
|
||||
use std::{
|
||||
any::Any,
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{
|
||||
sys::Memory, Backend, CacheGen, CompilerConfig, MemoryBoundCheckMode, RunnableModule, Token,
|
||||
@ -319,7 +323,10 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> {
|
||||
fn next_function(
|
||||
&mut self,
|
||||
_module_info: Arc<RwLock<ModuleInfo>>,
|
||||
) -> Result<&mut X64FunctionCode, CodegenError> {
|
||||
let (mut assembler, mut function_labels, breakpoints) = match self.functions.last_mut() {
|
||||
Some(x) => (
|
||||
x.assembler.take().unwrap(),
|
||||
@ -332,6 +339,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
HashMap::new(),
|
||||
),
|
||||
};
|
||||
|
||||
let begin_offset = assembler.offset();
|
||||
let begin_label_info = function_labels
|
||||
.entry(self.functions.len() + self.func_import_count)
|
||||
|
@ -1,6 +1,6 @@
|
||||
use wabt::wat2wasm;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
use wasmer_runtime_core::{import::ImportObject, Instance};
|
||||
use wasmer_runtime_core::{backend::Compiler, import::ImportObject, Instance};
|
||||
|
||||
fn main() {
|
||||
let instance = create_module_1();
|
||||
@ -24,13 +24,38 @@ fn create_module_1() -> Instance {
|
||||
(elem (;1;) (i32.const 9) 1))
|
||||
"#;
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
||||
let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler())
|
||||
.expect("WASM can't be compiled");
|
||||
module
|
||||
.instantiate(&generate_imports())
|
||||
.expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
#[cfg(feature = "clif")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
CraneliftCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_llvm_backend::LLVMCompiler;
|
||||
LLVMCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(feature = "singlepass")]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
use wasmer_singlepass_backend::SinglePassCompiler;
|
||||
SinglePassCompiler::new()
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "llvm", feature = "clif", feature = "singlepass")))]
|
||||
fn get_compiler() -> impl Compiler {
|
||||
panic!("compiler not specified, activate a compiler via features");
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
CraneliftCompiler::new()
|
||||
}
|
||||
|
||||
static IMPORT_MODULE: &str = r#"
|
||||
(module
|
||||
(type $t0 (func (param i32)))
|
||||
@ -44,7 +69,7 @@ static IMPORT_MODULE: &str = r#"
|
||||
|
||||
pub fn generate_imports() -> ImportObject {
|
||||
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
||||
let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new())
|
||||
let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler())
|
||||
.expect("WASM can't be compiled");
|
||||
let instance = module
|
||||
.instantiate(&ImportObject::new())
|
||||
|
@ -471,9 +471,6 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
if !mapped_dirs.is_empty() {
|
||||
eprintln!("WARN: mapdir is not implemented for emscripten targets");
|
||||
}
|
||||
wasmer_emscripten::run_emscripten_instance(
|
||||
&module,
|
||||
&mut instance,
|
||||
@ -484,6 +481,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
},
|
||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||
options.em_entrypoint.clone(),
|
||||
mapped_dirs,
|
||||
)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user