mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-14 05:06:07 +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)
|
# VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
|
||||||
# echo "${VERSION}" >> artifacts/version
|
# echo "${VERSION}" >> artifacts/version
|
||||||
- run:
|
- run:
|
||||||
name: Dynamic library
|
name: Generate dynamic library for the runtime C API
|
||||||
command: |
|
command: |
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
export PATH="$HOME/.cargo/bin:$PATH"
|
||||||
cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml
|
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
|
cp target/release/libwasmer_runtime_c_api.dylib ./artifacts
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
@ -362,7 +363,7 @@ jobs:
|
|||||||
# VERSION_TAG=$(git describe --exact-match --tags)
|
# VERSION_TAG=$(git describe --exact-match --tags)
|
||||||
#if [ "$VERSION" == "$VERSION_TAG" ]; then
|
#if [ "$VERSION" == "$VERSION_TAG" ]; then
|
||||||
# echo "Versions match, publishing to Github"
|
# 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
|
#else
|
||||||
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
# echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}"
|
||||||
# exit 1
|
# exit 1
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Wasmer uses the following components:
|
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
|
- [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
|
- [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.
|
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.
|
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]**
|
## **[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
|
- [#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
|
- [#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
|
- [#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)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
@ -211,67 +211,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-bforest"
|
name = "cranelift-bforest"
|
||||||
version = "0.30.0"
|
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 = [
|
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]]
|
[[package]]
|
||||||
name = "cranelift-codegen"
|
name = "cranelift-codegen"
|
||||||
version = "0.30.0"
|
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 = [
|
dependencies = [
|
||||||
"cranelift-bforest 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 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-codegen-meta 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||||
"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)",
|
||||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "cranelift-codegen-meta"
|
name = "cranelift-codegen-meta"
|
||||||
version = "0.30.0"
|
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 = [
|
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]]
|
[[package]]
|
||||||
name = "cranelift-entity"
|
name = "cranelift-entity"
|
||||||
version = "0.30.0"
|
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]]
|
[[package]]
|
||||||
name = "cranelift-frontend"
|
name = "cranelift-frontend"
|
||||||
version = "0.30.0"
|
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 = [
|
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)",
|
"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]]
|
[[package]]
|
||||||
name = "cranelift-native"
|
name = "cranelift-native"
|
||||||
version = "0.30.0"
|
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 = [
|
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)",
|
"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]]
|
[[package]]
|
||||||
name = "cranelift-wasm"
|
name = "cranelift-wasm"
|
||||||
version = "0.30.0"
|
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 = [
|
dependencies = [
|
||||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||||
"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)",
|
||||||
"cranelift-frontend 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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 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)",
|
"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)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1002,7 +1002,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.14"
|
version = "0.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1125,16 +1125,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt"
|
name = "structopt"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "structopt-derive"
|
name = "structopt-derive"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-clif-backend 0.4.2",
|
"wasmer-clif-backend 0.4.2",
|
||||||
"wasmer-dev-utils 0.4.2",
|
"wasmer-dev-utils 0.4.2",
|
||||||
@ -1381,10 +1381,11 @@ name = "wasmer-clif-backend"
|
|||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||||
"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)",
|
||||||
"cranelift-native 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cranelift-frontend 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)",
|
||||||
"cranelift-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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-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_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)",
|
"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-runtime-core 0.4.2",
|
||||||
"wasmer-win-exception-handler 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)",
|
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1413,6 +1414,7 @@ version = "0.4.2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-runtime-core 0.4.2",
|
"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]]
|
[[package]]
|
||||||
@ -1508,7 +1510,7 @@ dependencies = [
|
|||||||
"serde_bytes 0.10.5 (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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wasmer-runtime-core 0.4.2",
|
"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]]
|
[[package]]
|
||||||
@ -1574,11 +1576,6 @@ name = "wasmparser"
|
|||||||
version = "0.29.2"
|
version = "0.29.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
version = "2.0.1"
|
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 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 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 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-bforest 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||||
"checksum cranelift-codegen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab00cb149a5bb0f7e6dd391357356a5d71c335a431e8eece94f32da2d5a043f7"
|
"checksum cranelift-codegen 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||||
"checksum cranelift-codegen-meta 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3797a2f450ac71297e083dd440d0cdd0d3bceabe4a3ca6bcb9e4077e9c0327d"
|
"checksum cranelift-codegen-meta 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||||
"checksum cranelift-entity 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b66e28877b75b3d2b31250f780bb5db8f68ae3df681cd56add803b2567ac4fd"
|
"checksum cranelift-entity 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||||
"checksum cranelift-frontend 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b72d55fd732b1f7a99d043a36c54a5679b6ec8bc777c8d954fb97c4fa0fce7eb"
|
"checksum cranelift-frontend 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||||
"checksum cranelift-native 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0239f34836621a127c2132980b2f5c32a1be1c40e2d1a9a1a9bd5af33c12aee"
|
"checksum cranelift-native 0.30.0 (git+https://github.com/wasmerio/cranelift.git?branch=wasmer)" = "<none>"
|
||||||
"checksum cranelift-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740ebfba28c8433f06750f84819f1eb663ea9f5e4b9a81c01f4e52262d868b56"
|
"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 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 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"
|
"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 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 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 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 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 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"
|
"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 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 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 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 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fa19a5a708e22bb5be31c1b6108a2a902f909c4b9ba85cba44c06632386bc0ff"
|
||||||
"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6"
|
"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.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 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 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 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 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 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 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"
|
"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 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 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.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 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.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"
|
"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)
|
* [**🐘 PHP**](https://github.com/wasmerio/php-ext-wasm)
|
||||||
* [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm)
|
* [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm)
|
||||||
* [**💎 Ruby**](https://github.com/wasmerio/ruby-ext-wasm)
|
* [**💎 Ruby**](https://github.com/wasmerio/ruby-ext-wasm)
|
||||||
|
* [**🐹 Go**](https://github.com/wasmerio/go-ext-wasm)
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
@ -9,13 +9,14 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||||
cranelift-native = "0.30.0"
|
cranelift-native = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||||
cranelift-codegen = "0.30.0"
|
cranelift-codegen = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||||
cranelift-entity = "0.30.0"
|
cranelift-entity = { git = "https://github.com/wasmerio/cranelift.git", branch = "wasmer" }
|
||||||
cranelift-wasm = "0.30.0"
|
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"
|
hashbrown = "0.1"
|
||||||
target-lexicon = "0.3.0"
|
target-lexicon = "0.4.0"
|
||||||
wasmparser = "0.30.0"
|
wasmparser = "0.29.2"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
nix = "0.13.0"
|
nix = "0.13.0"
|
||||||
libc = "0.2.49"
|
libc = "0.2.49"
|
||||||
|
@ -1,51 +1,405 @@
|
|||||||
use crate::{module::Converter, module_env::ModuleEnv, relocation::call_names};
|
// Parts of the following code are Copyright 2018 Cranelift Developers
|
||||||
use cranelift_codegen::{
|
// and subject to the license https://github.com/CraneStation/cranelift/blob/c47ca7bafc8fc48358f1baa72360e61fc1f7a0f2/cranelift-wasm/LICENSE
|
||||||
cursor::FuncCursor,
|
|
||||||
ir::{self, InstBuilder},
|
use crate::{
|
||||||
isa,
|
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::mem;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use wasmer_runtime_core::error::CompileError;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
|
backend::{Backend, CacheGen, Token},
|
||||||
|
cache::{Artifact, Error as CacheError},
|
||||||
|
codegen::*,
|
||||||
memory::MemoryType,
|
memory::MemoryType,
|
||||||
structures::TypedIndex,
|
module::{ModuleInfo, ModuleInner},
|
||||||
types::{FuncIndex, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex},
|
structures::{Map, TypedIndex},
|
||||||
|
types::{
|
||||||
|
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex,
|
||||||
|
TableIndex,
|
||||||
|
},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
|
use wasmparser::Type as WpType;
|
||||||
|
|
||||||
pub struct FuncEnv<'env, 'module, 'isa> {
|
pub struct CraneliftModuleCodeGenerator {
|
||||||
env: &'env ModuleEnv<'module, 'isa>,
|
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> {
|
impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
||||||
pub fn new(env: &'env ModuleEnv<'module, 'isa>) -> Self {
|
for CraneliftModuleCodeGenerator
|
||||||
Self { env }
|
{
|
||||||
|
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
|
fn backend_id() -> Backend {
|
||||||
pub fn generate_signature(
|
Backend::Cranelift
|
||||||
&self,
|
}
|
||||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
|
||||||
) -> ir::Signature {
|
|
||||||
// Get signature
|
|
||||||
let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone();
|
|
||||||
|
|
||||||
// Add the vmctx parameter type to it
|
fn check_precondition(&mut self, _module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||||
signature.params.insert(
|
Ok(())
|
||||||
0,
|
}
|
||||||
ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
|
||||||
|
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
|
let func = ir::Function::with_name_signature(name, sig);
|
||||||
signature
|
|
||||||
|
//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
|
/// Gets configuration information needed for compiling functions
|
||||||
fn target_config(&self) -> isa::TargetFrontendConfig {
|
fn target_config(&self) -> isa::TargetFrontendConfig {
|
||||||
self.env.target_config()
|
self.target_config
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets native pointers types.
|
/// Gets native pointers types.
|
||||||
@ -68,14 +422,16 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
clif_global_index: cranelift_wasm::GlobalIndex,
|
clif_global_index: cranelift_wasm::GlobalIndex,
|
||||||
) -> cranelift_wasm::GlobalVariable {
|
) -> cranelift_wasm::WasmResult<cranelift_wasm::GlobalVariable> {
|
||||||
let global_index: GlobalIndex = Converter(clif_global_index).into();
|
let global_index: GlobalIndex = Converter(clif_global_index).into();
|
||||||
|
|
||||||
// Create VMContext value.
|
// Create VMContext value.
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_type = self.pointer_type();
|
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) => {
|
LocalOrImport::Local(local_global_index) => {
|
||||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
@ -92,12 +448,19 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let ty = self.module_info.read().unwrap().globals[local_global_index]
|
||||||
|
.desc
|
||||||
|
.ty;
|
||||||
|
|
||||||
|
(
|
||||||
func.create_global_value(ir::GlobalValueData::Load {
|
func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: local_global_ptr_ptr,
|
base: local_global_ptr_ptr,
|
||||||
offset: 0.into(),
|
offset: 0.into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
})
|
}),
|
||||||
|
ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
LocalOrImport::Import(import_global_index) => {
|
LocalOrImport::Import(import_global_index) => {
|
||||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
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,
|
global_type: ptr_type,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let ty = self.module_info.read().unwrap().imported_globals[import_global_index]
|
||||||
|
.1
|
||||||
|
.ty;
|
||||||
|
|
||||||
|
(
|
||||||
func.create_global_value(ir::GlobalValueData::Load {
|
func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: local_global_ptr_ptr,
|
base: local_global_ptr_ptr,
|
||||||
offset: 0.into(),
|
offset: 0.into(),
|
||||||
global_type: ptr_type,
|
global_type: ptr_type,
|
||||||
readonly: true,
|
readonly: true,
|
||||||
})
|
}),
|
||||||
|
ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cranelift_wasm::GlobalVariable::Memory {
|
Ok(cranelift_wasm::GlobalVariable::Memory {
|
||||||
gv: local_global_addr,
|
gv: local_global_addr,
|
||||||
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
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
|
/// 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,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
clif_mem_index: cranelift_wasm::MemoryIndex,
|
clif_mem_index: cranelift_wasm::MemoryIndex,
|
||||||
) -> ir::Heap {
|
) -> cranelift_wasm::WasmResult<ir::Heap> {
|
||||||
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
let mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
// Create VMContext value.
|
// Create VMContext value.
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_type = self.pointer_type();
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
let (local_memory_ptr_ptr, description) =
|
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) => {
|
LocalOrImport::Local(local_mem_index) => {
|
||||||
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
let memories_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
@ -164,7 +534,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
offset: (local_memory_ptr_offset as i64).into(),
|
offset: (local_memory_ptr_offset as i64).into(),
|
||||||
global_type: ptr_type,
|
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) => {
|
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(),
|
offset: (local_memory_ptr_offset as i64).into(),
|
||||||
global_type: ptr_type,
|
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,
|
readonly: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
func.create_heap(ir::HeapData {
|
Ok(func.create_heap(ir::HeapData {
|
||||||
base: local_memory_base,
|
base: local_memory_base,
|
||||||
min_size: (description.minimum.bytes().0 as u64).into(),
|
min_size: (description.minimum.bytes().0 as u64).into(),
|
||||||
offset_guard_size: mem_type.guard_size().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,
|
bound_gv: local_memory_bound,
|
||||||
},
|
},
|
||||||
index_type: ir::types::I32,
|
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 {
|
.create_heap(ir::HeapData {
|
||||||
base: local_memory_base,
|
base: local_memory_base,
|
||||||
min_size: (description.minimum.bytes().0 as u64).into(),
|
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(),
|
bound: mem_type.bounds().unwrap().into(),
|
||||||
},
|
},
|
||||||
index_type: ir::types::I32,
|
index_type: ir::types::I32,
|
||||||
}),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,14 +618,14 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
clif_table_index: cranelift_wasm::TableIndex,
|
clif_table_index: cranelift_wasm::TableIndex,
|
||||||
) -> ir::Table {
|
) -> cranelift_wasm::WasmResult<ir::Table> {
|
||||||
let table_index: TableIndex = Converter(clif_table_index).into();
|
let table_index: TableIndex = Converter(clif_table_index).into();
|
||||||
// Create VMContext value.
|
// Create VMContext value.
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_type = self.pointer_type();
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
let (table_struct_ptr_ptr, description) = match table_index
|
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) => {
|
LocalOrImport::Local(local_table_index) => {
|
||||||
let tables_base = func.create_global_value(ir::GlobalValueData::Load {
|
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,
|
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) => {
|
LocalOrImport::Import(import_table_index) => {
|
||||||
@ -298,7 +668,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
|||||||
|
|
||||||
(
|
(
|
||||||
table_struct_ptr_ptr,
|
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,
|
readonly: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
func.create_table(ir::TableData {
|
Ok(func.create_table(ir::TableData {
|
||||||
base_gv: table_base,
|
base_gv: table_base,
|
||||||
min_size: (description.minimum as u64).into(),
|
min_size: (description.minimum as u64).into(),
|
||||||
bound_gv: table_count,
|
bound_gv: table_count,
|
||||||
element_size: (vm::Anyfunc::size() as u64).into(),
|
element_size: (vm::Anyfunc::size() as u64).into(),
|
||||||
index_type: ir::types::I32,
|
index_type: ir::types::I32,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up a signature definition in `func`'s preamble.
|
/// 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,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
clif_sig_index: cranelift_wasm::SignatureIndex,
|
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).
|
// 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
|
/// 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,
|
&mut self,
|
||||||
func: &mut ir::Function,
|
func: &mut ir::Function,
|
||||||
func_index: cranelift_wasm::FuncIndex,
|
func_index: cranelift_wasm::FuncIndex,
|
||||||
) -> ir::FuncRef {
|
) -> cranelift_wasm::WasmResult<ir::FuncRef> {
|
||||||
// Get signature of function.
|
// 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).
|
// Create a signature reference from specified signature (with VMContext param added).
|
||||||
let signature = func.import_signature(self.generate_signature(signature_index));
|
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());
|
let name = ir::ExternalName::user(0, func_index.as_u32());
|
||||||
|
|
||||||
// Create function reference from fuction data.
|
// Create function reference from fuction data.
|
||||||
func.import_function(ir::ExtFuncData {
|
Ok(func.import_function(ir::ExtFuncData {
|
||||||
name,
|
name,
|
||||||
signature,
|
signature,
|
||||||
// Make this colocated so all calls between local functions are relative.
|
// Make this colocated so all calls between local functions are relative.
|
||||||
colocated: true,
|
colocated: true,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an indirect call IR with `callee` and `call_args`.
|
/// 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 callee_index: FuncIndex = Converter(clif_callee_index).into();
|
||||||
let ptr_type = self.pointer_type();
|
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) => {
|
LocalOrImport::Local(local_function_index) => {
|
||||||
// this is an internal function
|
// this is an internal function
|
||||||
let vmctx = pos
|
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 mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
|
|
||||||
let (namespace, mem_index, description) =
|
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) => (
|
LocalOrImport::Local(local_mem_index) => (
|
||||||
call_names::LOCAL_NAMESPACE,
|
call_names::LOCAL_NAMESPACE,
|
||||||
local_mem_index.index(),
|
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) => (
|
LocalOrImport::Import(import_mem_index) => (
|
||||||
call_names::IMPORT_NAMESPACE,
|
call_names::IMPORT_NAMESPACE,
|
||||||
import_mem_index.index(),
|
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 mem_index: MemoryIndex = Converter(clif_mem_index).into();
|
||||||
|
|
||||||
let (namespace, mem_index, description) =
|
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) => (
|
LocalOrImport::Local(local_mem_index) => (
|
||||||
call_names::LOCAL_NAMESPACE,
|
call_names::LOCAL_NAMESPACE,
|
||||||
local_mem_index.index(),
|
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) => (
|
LocalOrImport::Import(import_mem_index) => (
|
||||||
call_names::IMPORT_NAMESPACE,
|
call_names::IMPORT_NAMESPACE,
|
||||||
import_mem_index.index(),
|
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())
|
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)]
|
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)]
|
||||||
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod func_env;
|
mod code;
|
||||||
mod libcalls;
|
mod libcalls;
|
||||||
mod module;
|
mod module;
|
||||||
mod module_env;
|
|
||||||
mod relocation;
|
mod relocation;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
mod signal;
|
mod signal;
|
||||||
@ -16,87 +15,12 @@ use cranelift_codegen::{
|
|||||||
};
|
};
|
||||||
use target_lexicon::Triple;
|
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]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
extern crate rayon;
|
extern crate rayon;
|
||||||
extern crate serde;
|
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> {
|
fn get_isa() -> Box<isa::TargetIsa> {
|
||||||
let flags = {
|
let flags = {
|
||||||
let mut builder = settings::builder();
|
let mut builder = settings::builder();
|
||||||
@ -113,19 +37,14 @@ fn get_isa() -> Box<isa::TargetIsa> {
|
|||||||
isa::lookup(Triple::host()).unwrap().finish(flags)
|
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
|
/// The current version of this crate
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
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::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_entity::EntityRef;
|
||||||
use cranelift_wasm;
|
use cranelift_wasm;
|
||||||
use hashbrown::HashMap;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
|
||||||
|
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{Backend, CompilerConfig},
|
module::{ModuleInfo, ModuleInner},
|
||||||
error::CompileResult,
|
structures::TypedIndex,
|
||||||
module::{ModuleInfo, ModuleInner, StringTable},
|
types::{FuncIndex, FuncSig, GlobalIndex, MemoryIndex, SigIndex, TableIndex, Type},
|
||||||
structures::{Map, TypedIndex},
|
|
||||||
types::{
|
|
||||||
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
|
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
|
||||||
@ -25,69 +20,6 @@ pub struct Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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> {
|
pub fn from_cache(cache: Artifact) -> Result<ModuleInner, CacheError> {
|
||||||
let (info, compiled_code, backend_cache) = BackendCache::from_cache(cache)?;
|
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"
|
build = "build/mod.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
byteorder = "1"
|
||||||
|
hashbrown = "0.1"
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.2.0"
|
||||||
libc = "0.2.49"
|
libc = "0.2.49"
|
||||||
byteorder = "1"
|
|
||||||
time = "0.1.41"
|
time = "0.1.41"
|
||||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.4.2" }
|
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-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]
|
[target.'cfg(windows)'.dependencies]
|
||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate wasmer_runtime_core;
|
extern crate wasmer_runtime_core;
|
||||||
|
|
||||||
|
use hashbrown::HashMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::{f64, ffi::c_void};
|
use std::{f64, ffi::c_void};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
error::CallResult,
|
error::CallResult,
|
||||||
@ -141,10 +143,14 @@ pub struct EmscriptenData<'a> {
|
|||||||
pub stack_save: Option<Func<'a, (), i32>>,
|
pub stack_save: Option<Func<'a, (), i32>>,
|
||||||
pub stack_restore: Option<Func<'a, (i32)>>,
|
pub stack_restore: Option<Func<'a, (i32)>>,
|
||||||
pub set_threw: Option<Func<'a, (i32, i32)>>,
|
pub set_threw: Option<Func<'a, (i32, i32)>>,
|
||||||
|
pub mapped_dirs: HashMap<String, PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EmscriptenData<'a> {
|
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 malloc = instance.func("_malloc").unwrap();
|
||||||
let free = instance.func("_free").unwrap();
|
let free = instance.func("_free").unwrap();
|
||||||
let memalign = instance.func("_memalign").ok();
|
let memalign = instance.func("_memalign").ok();
|
||||||
@ -272,6 +278,7 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
stack_save,
|
stack_save,
|
||||||
stack_restore,
|
stack_restore,
|
||||||
set_threw,
|
set_threw,
|
||||||
|
mapped_dirs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,8 +289,9 @@ pub fn run_emscripten_instance(
|
|||||||
path: &str,
|
path: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
entrypoint: Option<String>,
|
entrypoint: Option<String>,
|
||||||
|
mapped_dirs: Vec<(String, PathBuf)>,
|
||||||
) -> CallResult<()> {
|
) -> 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;
|
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||||
instance.context_mut().data = data_ptr;
|
instance.context_mut().data = data_ptr;
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ pub use self::unix::*;
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use self::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 super::varargs::VarArgs;
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
|
/// 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 {
|
pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall12 (chdir) {}", _which);
|
debug!("emscripten::___syscall12 (chdir) {}", _which);
|
||||||
let path_ptr = varargs.get_str(ctx);
|
let path_ptr = varargs.get_str(ctx);
|
||||||
unsafe {
|
let real_path_owned = get_cstr_path(ctx, path_ptr);
|
||||||
let _path = std::ffi::CStr::from_ptr(path_ptr);
|
let real_path = if let Some(ref rp) = real_path_owned {
|
||||||
let ret = chdir(path_ptr);
|
rp.as_c_str().as_ptr()
|
||||||
debug!("=> path: {:?}, ret: {}", _path, ret);
|
} else {
|
||||||
|
path_ptr
|
||||||
|
};
|
||||||
|
let ret = unsafe { chdir(real_path) };
|
||||||
|
debug!(
|
||||||
|
"=> path: {:?}, ret: {}",
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(real_path) },
|
||||||
|
ret
|
||||||
|
);
|
||||||
ret
|
ret
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
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)");
|
debug!("emscripten::___syscall38 (rename)");
|
||||||
let old_path = varargs.get_str(ctx);
|
let old_path = varargs.get_str(ctx);
|
||||||
let new_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!(
|
debug!(
|
||||||
"=> old_path: {}, new_path: {}, result: {}",
|
"=> old_path: {}, new_path: {}, result: {}",
|
||||||
unsafe { std::ffi::CStr::from_ptr(old_path).to_str().unwrap() },
|
unsafe { std::ffi::CStr::from_ptr(real_old_path).to_str().unwrap() },
|
||||||
unsafe { std::ffi::CStr::from_ptr(new_path).to_str().unwrap() },
|
unsafe { std::ffi::CStr::from_ptr(real_new_path).to_str().unwrap() },
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
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 {
|
pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall40 (rmdir)");
|
debug!("emscripten::___syscall40 (rmdir)");
|
||||||
let pathname_addr = varargs.get_str(ctx);
|
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
|
// pipe
|
||||||
@ -244,10 +270,9 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
// getcwd
|
// getcwd
|
||||||
pub fn ___syscall183(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall183(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||||
debug!("emscripten::___syscall183");
|
debug!("emscripten::___syscall183");
|
||||||
use std::env;
|
|
||||||
let buf_offset: c_int = varargs.get(ctx);
|
let buf_offset: c_int = varargs.get(ctx);
|
||||||
let _size: 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 path_string = path.unwrap().display().to_string();
|
||||||
let len = path_string.len();
|
let len = path_string.len();
|
||||||
unsafe {
|
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 pathname_addr = varargs.get_str(ctx);
|
||||||
let buf: u32 = varargs.get(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 {
|
unsafe {
|
||||||
let mut _stat: stat = std::mem::zeroed();
|
let mut _stat: stat = std::mem::zeroed();
|
||||||
let ret = stat(pathname_addr, &mut _stat);
|
let ret = stat(real_path, &mut _stat);
|
||||||
debug!(
|
debug!(
|
||||||
"=> pathname: {}, buf: {} = {}, last os error: {}",
|
"=> 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,
|
buf,
|
||||||
ret,
|
ret,
|
||||||
Error::last_os_error()
|
Error::last_os_error()
|
||||||
@ -457,11 +489,6 @@ pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|
||||||
debug!("emscripten::___syscall220");
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
|
|
||||||
// fcntl64
|
// fcntl64
|
||||||
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
|
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
|
// |FNONBLOCK - 0x04
|
||||||
debug!("=> fd: {}, cmd: {}", _fd, cmd);
|
debug!("=> fd: {}, cmd: {}", _fd, cmd);
|
||||||
match cmd {
|
match cmd {
|
||||||
2 => 0,
|
1 | 2 => 0,
|
||||||
13 | 14 => 0, // pretend file locking worked
|
13 | 14 => 0, // pretend file locking worked
|
||||||
_ => -1,
|
_ => -1,
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ use libc::{
|
|||||||
pid_t,
|
pid_t,
|
||||||
pread,
|
pread,
|
||||||
pwrite,
|
pwrite,
|
||||||
|
readdir,
|
||||||
// readv,
|
// readv,
|
||||||
recvfrom,
|
recvfrom,
|
||||||
recvmsg,
|
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 pathname_addr = varargs.get_str(ctx);
|
||||||
let flags: i32 = varargs.get(ctx);
|
let flags: i32 = varargs.get(ctx);
|
||||||
let mode: u32 = varargs.get(ctx);
|
let mode: u32 = varargs.get(ctx);
|
||||||
let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
|
let real_path_owned = utils::get_cstr_path(ctx, pathname_addr);
|
||||||
let fd = unsafe { open(pathname_addr, flags, mode) };
|
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!(
|
debug!(
|
||||||
"=> path: {}, flags: {}, mode: {} = fd: {}, last os error: {}",
|
"=> path: {}, flags: {}, mode: {} = fd: {}, last os error: {}",
|
||||||
_path_str,
|
_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 path1 = varargs.get_str(ctx);
|
||||||
let path2 = 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!(
|
debug!(
|
||||||
"=> path1: {}, path2: {}, result: {}",
|
"=> path1: {}, path2: {}, result: {}",
|
||||||
unsafe { std::ffi::CStr::from_ptr(path1).to_str().unwrap() },
|
unsafe { std::ffi::CStr::from_ptr(real_path1).to_str().unwrap() },
|
||||||
unsafe { std::ffi::CStr::from_ptr(path2).to_str().unwrap() },
|
unsafe { std::ffi::CStr::from_ptr(real_path2).to_str().unwrap() },
|
||||||
result,
|
result,
|
||||||
);
|
);
|
||||||
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 {
|
pub fn ___syscall198(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall198 (lchown) {}", _which);
|
debug!("emscripten::___syscall198 (lchown) {}", _which);
|
||||||
let path_ptr = varargs.get_str(ctx);
|
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 uid: uid_t = varargs.get(ctx);
|
||||||
let gid: gid_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!(
|
debug!(
|
||||||
"=> path: {}, uid: {}, gid: {}, result: {}",
|
"=> 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,
|
uid,
|
||||||
gid,
|
gid,
|
||||||
result,
|
result,
|
||||||
@ -216,10 +241,16 @@ pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
debug!("emscripten::___syscall212 (chown) {}", _which);
|
debug!("emscripten::___syscall212 (chown) {}", _which);
|
||||||
|
|
||||||
let pathname_addr = varargs.get_str(ctx);
|
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 owner: u32 = varargs.get(ctx);
|
||||||
let group: u32 = varargs.get(ctx);
|
let group: u32 = varargs.get(ctx);
|
||||||
|
|
||||||
unsafe { chown(pathname_addr, owner, group) }
|
unsafe { chown(real_path, owner, group) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// madvise
|
/// 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 {
|
pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall33 (access) {}", _which);
|
debug!("emscripten::___syscall33 (access) {}", _which);
|
||||||
let path = varargs.get_str(ctx);
|
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 amode: c_int = varargs.get(ctx);
|
||||||
let result = unsafe { access(path, amode) };
|
let result = unsafe { access(real_path, amode) };
|
||||||
debug!(
|
debug!(
|
||||||
"=> path: {}, amode: {}, result: {}",
|
"=> 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,
|
amode,
|
||||||
result
|
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 {
|
pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall39 (mkdir) {}", _which);
|
debug!("emscripten::___syscall39 (mkdir) {}", _which);
|
||||||
let pathname_addr = varargs.get_str(ctx);
|
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);
|
let mode: u32 = varargs.get(ctx);
|
||||||
unsafe { mkdir(pathname_addr, mode as _) }
|
unsafe { mkdir(real_path, mode as _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// dup
|
/// 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 {
|
pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
debug!("emscripten::___syscall196 (lstat64) {}", _which);
|
debug!("emscripten::___syscall196 (lstat64) {}", _which);
|
||||||
let path = varargs.get_str(ctx);
|
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);
|
let buf_ptr: u32 = varargs.get(ctx);
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut stat: stat = std::mem::zeroed();
|
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;
|
let stat_ptr = &mut stat as *mut stat;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let ret = lstat64(path, stat_ptr);
|
let ret = lstat64(real_path, stat_ptr);
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
let ret = lstat(path, stat_ptr);
|
let ret = lstat(real_path, stat_ptr);
|
||||||
|
|
||||||
debug!("ret: {}", ret);
|
debug!("ret: {}", ret);
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
@ -784,6 +833,45 @@ pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
|||||||
0
|
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
|
/// fallocate
|
||||||
pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall324 (fallocate) {}", _which);
|
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 crate::varargs::VarArgs;
|
||||||
use libc::mkdir;
|
use libc::mkdir;
|
||||||
use libc::open;
|
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"))]
|
#[cfg(not(feature = "debug"))]
|
||||||
let _ = which;
|
let _ = which;
|
||||||
let pathname_addr = varargs.get_str(ctx);
|
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 flags: i32 = varargs.get(ctx);
|
||||||
let mode: u32 = 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 {
|
match path_str {
|
||||||
"/dev/urandom" => {
|
"/dev/urandom" => {
|
||||||
// create a fake urandom file for windows, super hacky
|
// 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
|
fd
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let fd = unsafe { open(pathname_addr, flags, mode) };
|
let fd = unsafe { open(real_path, flags, mode) };
|
||||||
debug!(
|
debug!(
|
||||||
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
|
||||||
path_str, flags, mode, fd, path_str
|
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"))]
|
#[cfg(not(feature = "debug"))]
|
||||||
let _ = which;
|
let _ = which;
|
||||||
let pathname_addr = varargs.get_str(ctx);
|
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
|
/// dup
|
||||||
@ -249,6 +261,12 @@ pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getdents
|
||||||
|
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
|
debug!("emscripten::___syscall220");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
/// fchown
|
/// fchown
|
||||||
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall207 (fchown) {}", _which);
|
debug!("emscripten::___syscall207 (fchown) {}", _which);
|
||||||
|
@ -5,6 +5,7 @@ use libc::stat;
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use wasmer_runtime_core::memory::Memory;
|
use wasmer_runtime_core::memory::Memory;
|
||||||
use wasmer_runtime_core::{
|
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()
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::is_emscripten_module;
|
use super::is_emscripten_module;
|
||||||
|
@ -56,6 +56,7 @@ macro_rules! assert_emscripten_output {
|
|||||||
$name,
|
$name,
|
||||||
$args,
|
$args,
|
||||||
None,
|
None,
|
||||||
|
vec![],
|
||||||
).expect("run_emscripten_instance finishes");
|
).expect("run_emscripten_instance finishes");
|
||||||
|
|
||||||
let output = capturer.end().unwrap().0;
|
let output = capturer.end().unwrap().0;
|
||||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||||
inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm7-0" }
|
inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm7-0" }
|
||||||
wasmparser = "0.30.0"
|
wasmparser = "0.29.2"
|
||||||
hashbrown = "0.1.8"
|
hashbrown = "0.1.8"
|
||||||
smallvec = "0.6.8"
|
smallvec = "0.6.8"
|
||||||
goblin = "0.0.20"
|
goblin = "0.0.20"
|
||||||
|
@ -8,7 +8,7 @@ use inkwell::{
|
|||||||
AddressSpace, FloatPredicate, IntPredicate,
|
AddressSpace, FloatPredicate, IntPredicate,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, RwLock};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{Backend, CacheGen, Token},
|
backend::{Backend, CacheGen, Token},
|
||||||
cache::{Artifact, Error as CacheError},
|
cache::{Artifact, Error as CacheError},
|
||||||
@ -2551,7 +2551,10 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
|||||||
Ok(())
|
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.
|
// Creates a new function and returns the function-scope code generator for it.
|
||||||
let (context, builder, intrinsics, breakpoints) = match self.functions.last_mut() {
|
let (context, builder, intrinsics, breakpoints) = match self.functions.last_mut() {
|
||||||
Some(x) => (
|
Some(x) => (
|
||||||
|
@ -13,7 +13,7 @@ wasmer-runtime-core = { path = "../runtime-core" }
|
|||||||
hashbrown = "0.1"
|
hashbrown = "0.1"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
tar = "0.4"
|
tar = "0.4"
|
||||||
wasmparser = "0.30.0"
|
wasmparser = "0.29.2"
|
||||||
zstd = "0.4"
|
zstd = "0.4"
|
||||||
|
|
||||||
# [target.'cfg(unix)'.dependencies.zbox]
|
# [target.'cfg(unix)'.dependencies.zbox]
|
||||||
|
@ -10,7 +10,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
nix = "0.12.0"
|
nix = "0.12.0"
|
||||||
page_size = "0.4.1"
|
page_size = "0.4.1"
|
||||||
wasmparser = "0.30.0"
|
wasmparser = "0.29.2"
|
||||||
parking_lot = "0.7.1"
|
parking_lot = "0.7.1"
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.2.0"
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
|
@ -11,6 +11,8 @@ use smallvec::SmallVec;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use wasmparser::{self, WasmDecoder};
|
||||||
use wasmparser::{Operator, Type as WpType};
|
use wasmparser::{Operator, Type as WpType};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -57,13 +59,14 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
|
|||||||
}
|
}
|
||||||
/// Adds an import function.
|
/// Adds an import function.
|
||||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||||
|
|
||||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||||
/// Sets function signatures.
|
/// Sets function signatures.
|
||||||
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
||||||
/// Checks the precondition for a module.
|
/// Checks the precondition for a module.
|
||||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
||||||
/// Creates a new function and returns the function-scope code generator for it.
|
/// 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.
|
/// Finalizes this module.
|
||||||
fn finalize(self, module_info: &ModuleInfo) -> Result<(RM, Box<dyn CacheGen>), E>;
|
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<
|
impl<
|
||||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||||
FCG: FunctionCodeGenerator<E>,
|
FCG: FunctionCodeGenerator<E>,
|
||||||
@ -142,6 +159,10 @@ impl<
|
|||||||
compiler_config: CompilerConfig,
|
compiler_config: CompilerConfig,
|
||||||
_: Token,
|
_: Token,
|
||||||
) -> CompileResult<ModuleInner> {
|
) -> CompileResult<ModuleInner> {
|
||||||
|
if requires_pre_validation(MCG::backend_id()) {
|
||||||
|
validate(wasm)?;
|
||||||
|
}
|
||||||
|
|
||||||
let mut mcg = MCG::new();
|
let mut mcg = MCG::new();
|
||||||
let mut chain = (self.middleware_chain_generator)();
|
let mut chain = (self.middleware_chain_generator)();
|
||||||
let info = crate::parse::read_module(
|
let info = crate::parse::read_module(
|
||||||
@ -152,14 +173,14 @@ impl<
|
|||||||
&compiler_config,
|
&compiler_config,
|
||||||
)?;
|
)?;
|
||||||
let (exec_context, cache_gen) =
|
let (exec_context, cache_gen) =
|
||||||
mcg.finalize(&info)
|
mcg.finalize(&info.read().unwrap())
|
||||||
.map_err(|x| CompileError::InternalError {
|
.map_err(|x| CompileError::InternalError {
|
||||||
msg: format!("{:?}", x),
|
msg: format!("{:?}", x),
|
||||||
})?;
|
})?;
|
||||||
Ok(ModuleInner {
|
Ok(ModuleInner {
|
||||||
cache_gen,
|
cache_gen,
|
||||||
runnable_module: Box::new(exec_context),
|
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> {
|
pub struct EventSink<'a, 'b> {
|
||||||
buffer: SmallVec<[Event<'a, 'b>; 2]>,
|
buffer: SmallVec<[Event<'a, 'b>; 2]>,
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ pub struct ModuleInner {
|
|||||||
pub info: ModuleInfo,
|
pub info: ModuleInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct ModuleInfo {
|
pub struct ModuleInfo {
|
||||||
// This are strictly local and the typsystem ensures that.
|
// This are strictly local and the typsystem ensures that.
|
||||||
pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
|
pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
|
||||||
|
@ -16,6 +16,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
BinaryReaderError, ExternalKind, FuncType, ImportSectionEntryType, Operator, Type as WpType,
|
BinaryReaderError, ExternalKind, FuncType, ImportSectionEntryType, Operator, Type as WpType,
|
||||||
WasmDecoder,
|
WasmDecoder,
|
||||||
@ -52,10 +53,10 @@ pub fn read_module<
|
|||||||
mcg: &mut MCG,
|
mcg: &mut MCG,
|
||||||
middlewares: &mut MiddlewareChain,
|
middlewares: &mut MiddlewareChain,
|
||||||
compiler_config: &CompilerConfig,
|
compiler_config: &CompilerConfig,
|
||||||
) -> Result<ModuleInfo, LoadError> {
|
) -> Result<Arc<RwLock<ModuleInfo>>, LoadError> {
|
||||||
mcg.feed_compiler_config(compiler_config)
|
mcg.feed_compiler_config(compiler_config)
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
let mut info = ModuleInfo {
|
let info = Arc::new(RwLock::new(ModuleInfo {
|
||||||
memories: Map::new(),
|
memories: Map::new(),
|
||||||
globals: Map::new(),
|
globals: Map::new(),
|
||||||
tables: Map::new(),
|
tables: Map::new(),
|
||||||
@ -82,7 +83,7 @@ pub fn read_module<
|
|||||||
em_symbol_map: compiler_config.symbol_map.clone(),
|
em_symbol_map: compiler_config.symbol_map.clone(),
|
||||||
|
|
||||||
custom_sections: HashMap::new(),
|
custom_sections: HashMap::new(),
|
||||||
};
|
}));
|
||||||
|
|
||||||
let mut parser = wasmparser::ValidatingParser::new(
|
let mut parser = wasmparser::ValidatingParser::new(
|
||||||
wasm,
|
wasm,
|
||||||
@ -105,10 +106,13 @@ pub fn read_module<
|
|||||||
use wasmparser::ParserState;
|
use wasmparser::ParserState;
|
||||||
let state = parser.read();
|
let state = parser.read();
|
||||||
match *state {
|
match *state {
|
||||||
ParserState::EndWasm => break Ok(info),
|
ParserState::EndWasm => break,
|
||||||
ParserState::Error(err) => Err(LoadError::Parse(err))?,
|
ParserState::Error(err) => Err(LoadError::Parse(err))?,
|
||||||
ParserState::TypeSectionEntry(ref ty) => {
|
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 } => {
|
ParserState::ImportSectionEntry { module, field, ty } => {
|
||||||
let namespace_index = namespace_builder.as_mut().unwrap().register(module);
|
let namespace_index = namespace_builder.as_mut().unwrap().register(module);
|
||||||
@ -121,8 +125,8 @@ pub fn read_module<
|
|||||||
match ty {
|
match ty {
|
||||||
ImportSectionEntryType::Function(sigindex) => {
|
ImportSectionEntryType::Function(sigindex) => {
|
||||||
let sigindex = SigIndex::new(sigindex as usize);
|
let sigindex = SigIndex::new(sigindex as usize);
|
||||||
info.imported_functions.push(import_name);
|
info.write().unwrap().imported_functions.push(import_name);
|
||||||
info.func_assoc.push(sigindex);
|
info.write().unwrap().func_assoc.push(sigindex);
|
||||||
mcg.feed_import_function()
|
mcg.feed_import_function()
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
@ -134,7 +138,10 @@ pub fn read_module<
|
|||||||
maximum: table_ty.limits.maximum,
|
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) => {
|
ImportSectionEntryType::Memory(memory_ty) => {
|
||||||
let mem_desc = MemoryDescriptor {
|
let mem_desc = MemoryDescriptor {
|
||||||
@ -142,20 +149,26 @@ pub fn read_module<
|
|||||||
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
maximum: memory_ty.limits.maximum.map(|max| Pages(max)),
|
||||||
shared: memory_ty.shared,
|
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) => {
|
ImportSectionEntryType::Global(global_ty) => {
|
||||||
let global_desc = GlobalDescriptor {
|
let global_desc = GlobalDescriptor {
|
||||||
mutable: global_ty.mutable,
|
mutable: global_ty.mutable,
|
||||||
ty: wp_type_to_type(global_ty.content_type)?,
|
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) => {
|
ParserState::FunctionSectionEntry(sigindex) => {
|
||||||
let sigindex = SigIndex::new(sigindex as usize);
|
let sigindex = SigIndex::new(sigindex as usize);
|
||||||
info.func_assoc.push(sigindex);
|
info.write().unwrap().func_assoc.push(sigindex);
|
||||||
}
|
}
|
||||||
ParserState::TableSectionEntry(table_ty) => {
|
ParserState::TableSectionEntry(table_ty) => {
|
||||||
let table_desc = TableDescriptor {
|
let table_desc = TableDescriptor {
|
||||||
@ -164,7 +177,7 @@ pub fn read_module<
|
|||||||
maximum: table_ty.limits.maximum,
|
maximum: table_ty.limits.maximum,
|
||||||
};
|
};
|
||||||
|
|
||||||
info.tables.push(table_desc);
|
info.write().unwrap().tables.push(table_desc);
|
||||||
}
|
}
|
||||||
ParserState::MemorySectionEntry(memory_ty) => {
|
ParserState::MemorySectionEntry(memory_ty) => {
|
||||||
let mem_desc = MemoryDescriptor {
|
let mem_desc = MemoryDescriptor {
|
||||||
@ -173,7 +186,7 @@ pub fn read_module<
|
|||||||
shared: memory_ty.shared,
|
shared: memory_ty.shared,
|
||||||
};
|
};
|
||||||
|
|
||||||
info.memories.push(mem_desc);
|
info.write().unwrap().memories.push(mem_desc);
|
||||||
}
|
}
|
||||||
ParserState::ExportSectionEntry { field, kind, index } => {
|
ParserState::ExportSectionEntry { field, kind, index } => {
|
||||||
let export_index = match kind {
|
let export_index = match kind {
|
||||||
@ -183,42 +196,51 @@ pub fn read_module<
|
|||||||
ExternalKind::Global => ExportIndex::Global(GlobalIndex::new(index as usize)),
|
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) => {
|
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 { .. } => {
|
ParserState::BeginFunctionBody { .. } => {
|
||||||
let id = func_count.wrapping_add(1);
|
let id = func_count.wrapping_add(1);
|
||||||
func_count = id;
|
func_count = id;
|
||||||
if func_count == 0 {
|
if func_count == 0 {
|
||||||
info.namespace_table = namespace_builder.take().unwrap().finish();
|
info.write().unwrap().namespace_table =
|
||||||
info.name_table = name_builder.take().unwrap().finish();
|
namespace_builder.take().unwrap().finish();
|
||||||
mcg.feed_signatures(info.signatures.clone())
|
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)))?;
|
.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)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
mcg.check_precondition(&info)
|
mcg.check_precondition(&info.read().unwrap())
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fcg = mcg
|
let fcg = mcg
|
||||||
.next_function()
|
.next_function(Arc::clone(&info))
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
middlewares
|
middlewares
|
||||||
.run(
|
.run(
|
||||||
Some(fcg),
|
Some(fcg),
|
||||||
Event::Internal(InternalEvent::FunctionBegin(id as u32)),
|
Event::Internal(InternalEvent::FunctionBegin(id as u32)),
|
||||||
&info,
|
&info.read().unwrap(),
|
||||||
)
|
)
|
||||||
.map_err(|x| LoadError::Codegen(x))?;
|
.map_err(|x| LoadError::Codegen(x))?;
|
||||||
|
|
||||||
let sig = info
|
let info_read = info.read().unwrap();
|
||||||
|
let sig = info_read
|
||||||
.signatures
|
.signatures
|
||||||
.get(
|
.get(
|
||||||
*info
|
*info
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
.func_assoc
|
.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(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -235,22 +257,22 @@ pub fn read_module<
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
let state = parser.read();
|
let state = parser.read();
|
||||||
match *state {
|
match state {
|
||||||
ParserState::Error(err) => return Err(LoadError::Parse(err)),
|
ParserState::Error(err) => return Err(LoadError::Parse(*err)),
|
||||||
ParserState::FunctionBodyLocals { ref locals } => {
|
ParserState::FunctionBodyLocals { ref locals } => {
|
||||||
for &(count, ty) in locals.iter() {
|
for &(count, ty) in locals.iter() {
|
||||||
fcg.feed_local(ty, count as usize)
|
fcg.feed_local(ty, count as usize)
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserState::CodeOperator(ref op) => {
|
ParserState::CodeOperator(op) => {
|
||||||
if !body_begun {
|
if !body_begun {
|
||||||
body_begun = true;
|
body_begun = true;
|
||||||
fcg.begin_body(&info)
|
fcg.begin_body(&info.read().unwrap())
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
middlewares
|
middlewares
|
||||||
.run(Some(fcg), Event::Wasm(op), &info)
|
.run(Some(fcg), Event::Wasm(op), &info.read().unwrap())
|
||||||
.map_err(|x| LoadError::Codegen(x))?;
|
.map_err(|x| LoadError::Codegen(x))?;
|
||||||
}
|
}
|
||||||
ParserState::EndFunctionBody => break,
|
ParserState::EndFunctionBody => break,
|
||||||
@ -261,7 +283,7 @@ pub fn read_module<
|
|||||||
.run(
|
.run(
|
||||||
Some(fcg),
|
Some(fcg),
|
||||||
Event::Internal(InternalEvent::FunctionEnd),
|
Event::Internal(InternalEvent::FunctionEnd),
|
||||||
&info,
|
&info.read().unwrap(),
|
||||||
)
|
)
|
||||||
.map_err(|x| LoadError::Codegen(x))?;
|
.map_err(|x| LoadError::Codegen(x))?;
|
||||||
fcg.finalize()
|
fcg.finalize()
|
||||||
@ -301,7 +323,7 @@ pub fn read_module<
|
|||||||
elements: elements.unwrap(),
|
elements: elements.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
info.elem_initializers.push(table_init);
|
info.write().unwrap().elem_initializers.push(table_init);
|
||||||
}
|
}
|
||||||
ParserState::BeginActiveDataSectionEntry(memory_index) => {
|
ParserState::BeginActiveDataSectionEntry(memory_index) => {
|
||||||
let memory_index = MemoryIndex::new(memory_index as usize);
|
let memory_index = MemoryIndex::new(memory_index as usize);
|
||||||
@ -332,7 +354,7 @@ pub fn read_module<
|
|||||||
base: base.unwrap(),
|
base: base.unwrap(),
|
||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
info.data_initializers.push(data_init);
|
info.write().unwrap().data_initializers.push(data_init);
|
||||||
}
|
}
|
||||||
ParserState::BeginGlobalSectionEntry(ty) => {
|
ParserState::BeginGlobalSectionEntry(ty) => {
|
||||||
let init = loop {
|
let init = loop {
|
||||||
@ -353,12 +375,13 @@ pub fn read_module<
|
|||||||
|
|
||||||
let global_init = GlobalInit { desc, init };
|
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> {
|
pub fn wp_type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
|
||||||
|
@ -9,7 +9,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" }
|
||||||
wasmparser = "0.30.0"
|
wasmparser = "0.29.2"
|
||||||
dynasm = "0.3.2"
|
dynasm = "0.3.2"
|
||||||
dynasmrt = "0.3.1"
|
dynasmrt = "0.3.1"
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.2.0"
|
||||||
|
@ -8,7 +8,11 @@ use dynasmrt::{
|
|||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::ptr::NonNull;
|
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::{
|
use wasmer_runtime_core::{
|
||||||
backend::{
|
backend::{
|
||||||
sys::Memory, Backend, CacheGen, CompilerConfig, MemoryBoundCheckMode, RunnableModule, Token,
|
sys::Memory, Backend, CacheGen, CompilerConfig, MemoryBoundCheckMode, RunnableModule, Token,
|
||||||
@ -319,7 +323,10 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
|||||||
Ok(())
|
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() {
|
let (mut assembler, mut function_labels, breakpoints) = match self.functions.last_mut() {
|
||||||
Some(x) => (
|
Some(x) => (
|
||||||
x.assembler.take().unwrap(),
|
x.assembler.take().unwrap(),
|
||||||
@ -332,6 +339,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
|||||||
HashMap::new(),
|
HashMap::new(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let begin_offset = assembler.offset();
|
let begin_offset = assembler.offset();
|
||||||
let begin_label_info = function_labels
|
let begin_label_info = function_labels
|
||||||
.entry(self.functions.len() + self.func_import_count)
|
.entry(self.functions.len() + self.func_import_count)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use wabt::wat2wasm;
|
use wabt::wat2wasm;
|
||||||
use wasmer_clif_backend::CraneliftCompiler;
|
use wasmer_clif_backend::CraneliftCompiler;
|
||||||
use wasmer_runtime_core::{import::ImportObject, Instance};
|
use wasmer_runtime_core::{backend::Compiler, import::ImportObject, Instance};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let instance = create_module_1();
|
let instance = create_module_1();
|
||||||
@ -24,13 +24,38 @@ fn create_module_1() -> Instance {
|
|||||||
(elem (;1;) (i32.const 9) 1))
|
(elem (;1;) (i32.const 9) 1))
|
||||||
"#;
|
"#;
|
||||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
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");
|
.expect("WASM can't be compiled");
|
||||||
module
|
module
|
||||||
.instantiate(&generate_imports())
|
.instantiate(&generate_imports())
|
||||||
.expect("WASM can't be instantiated")
|
.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#"
|
static IMPORT_MODULE: &str = r#"
|
||||||
(module
|
(module
|
||||||
(type $t0 (func (param i32)))
|
(type $t0 (func (param i32)))
|
||||||
@ -44,7 +69,7 @@ static IMPORT_MODULE: &str = r#"
|
|||||||
|
|
||||||
pub fn generate_imports() -> ImportObject {
|
pub fn generate_imports() -> ImportObject {
|
||||||
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
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");
|
.expect("WASM can't be compiled");
|
||||||
let instance = module
|
let instance = module
|
||||||
.instantiate(&ImportObject::new())
|
.instantiate(&ImportObject::new())
|
||||||
|
@ -471,9 +471,6 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
.instantiate(&import_object)
|
.instantiate(&import_object)
|
||||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
.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(
|
wasmer_emscripten::run_emscripten_instance(
|
||||||
&module,
|
&module,
|
||||||
&mut instance,
|
&mut instance,
|
||||||
@ -484,6 +481,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
},
|
},
|
||||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||||
options.em_entrypoint.clone(),
|
options.em_entrypoint.clone(),
|
||||||
|
mapped_dirs,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("{:?}", e))?;
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user