mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-24 18:02:13 +00:00
Merge branch 'master' into feat-interface-types-better-error
This commit is contained in:
commit
03910a51fb
13
CHANGELOG.md
13
CHANGELOG.md
@ -3,6 +3,19 @@
|
||||
## **[Unreleased]**
|
||||
|
||||
- [#1285](https://github.com/wasmerio/wasmer/pull/1285) Greatly improve errors in `wasmer-interface-types`
|
||||
- [#1283](https://github.com/wasmerio/wasmer/pull/1283) Workaround for floating point arguments and return values in `DynamicFunc`s.
|
||||
|
||||
## 0.16.2 - 2020-03-11
|
||||
|
||||
- [#1294](https://github.com/wasmerio/wasmer/pull/1294) Fix bug related to system calls in WASI that rely on reading from WasmPtrs as arrays of length 0. `WasmPtr` will now succeed on length 0 arrays again.
|
||||
|
||||
## 0.16.1 - 2020-03-11
|
||||
|
||||
- [#1291](https://github.com/wasmerio/wasmer/pull/1291) Fix installation packaging script to package the `wax` command.
|
||||
|
||||
## 0.16.0 - 2020-03-11
|
||||
|
||||
- [#1286](https://github.com/wasmerio/wasmer/pull/1286) Updated Windows Wasmer icons. Add wax
|
||||
- [#1284](https://github.com/wasmerio/wasmer/pull/1284) Implement string and memory instructions in `wasmer-interface-types`
|
||||
- [#1272](https://github.com/wasmerio/wasmer/pull/1272) Fix off-by-one error bug when accessing memory with a `WasmPtr` that contains the last valid byte of memory. Also changes the behavior of `WasmPtr<T, Array>` with a length of 0 and `WasmPtr<T>` where `std::mem::size_of::<T>()` is 0 to always return `None`
|
||||
|
||||
|
38
Cargo.lock
generated
38
Cargo.lock
generated
@ -1820,7 +1820,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"byteorder",
|
||||
@ -1851,7 +1851,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-clif-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cranelift-codegen",
|
||||
@ -1902,14 +1902,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-dev-utils"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-emscripten"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"getrandom",
|
||||
@ -1922,7 +1922,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-emscripten-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"glob 0.3.0",
|
||||
"wabt",
|
||||
@ -1936,7 +1936,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-interface-types"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"wast",
|
||||
@ -1952,7 +1952,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-llvm-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cc",
|
||||
@ -1983,14 +1983,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-middleware-common"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"wasmer-runtime-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-middleware-common-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"wabt",
|
||||
@ -2003,7 +2003,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"lazy_static",
|
||||
@ -2020,7 +2020,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime-c-api"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"cbindgen",
|
||||
"libc",
|
||||
@ -2032,7 +2032,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime-core"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"blake3",
|
||||
@ -2060,7 +2060,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-runtime-core-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"wabt",
|
||||
"wasmer-clif-backend",
|
||||
@ -2071,7 +2071,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-singlepass-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"byteorder",
|
||||
@ -2088,7 +2088,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-spectests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"glob 0.3.0",
|
||||
"wabt",
|
||||
@ -2100,7 +2100,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-wasi"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"byteorder",
|
||||
@ -2117,7 +2117,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-wasi-experimental-io-devices"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"minifb",
|
||||
@ -2130,7 +2130,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-wasi-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"glob 0.3.0",
|
||||
"wasmer-clif-backend",
|
||||
@ -2143,7 +2143,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-win-exception-handler"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
dependencies = [
|
||||
"cmake",
|
||||
"libc",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
|
6
Makefile
6
Makefile
@ -287,7 +287,9 @@ build-install-package:
|
||||
mkdir -p ./install/bin
|
||||
cp ./wapm-cli/target/release/wapm ./install/bin/
|
||||
cp ./target/release/wasmer ./install/bin/
|
||||
tar -C ./install -zcvf wasmer.tar.gz bin/wapm bin/wasmer
|
||||
# Create the wax binary as symlink to wapm
|
||||
cd ./install/bin/ && ln -sf wapm wax && chmod +x wax
|
||||
tar -C ./install -zcvf wasmer.tar.gz bin
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
@ -315,7 +317,7 @@ endif
|
||||
cp lib/runtime-c-api/doc/index.md ./capi/README.md
|
||||
tar -C ./capi -zcvf wasmer-c-api.tar.gz lib include README.md LICENSE
|
||||
|
||||
WAPM_VERSION = 0.4.3
|
||||
WAPM_VERSION = v0.5.0
|
||||
build-wapm:
|
||||
git clone --branch $(WAPM_VERSION) https://github.com/wasmerio/wapm-cli.git
|
||||
cargo build --release --manifest-path wapm-cli/Cargo.toml --features "telemetry update-notifications"
|
||||
|
@ -300,6 +300,7 @@ jobs:
|
||||
isDraft: false
|
||||
isPreRelease: false
|
||||
assets: '$(Build.ArtifactStagingDirectory)/**'
|
||||
assetUploadMode: 'replace' # Don't delete previously uploaded assets (default)
|
||||
|
||||
- job: Publish_Docs
|
||||
dependsOn:
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-clif-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime Cranelift compiler backend"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -11,7 +11,7 @@ edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
cranelift-native = "0.59.0"
|
||||
cranelift-codegen = "0.59.0"
|
||||
cranelift-entity = "0.59.0"
|
||||
@ -38,7 +38,7 @@ version = "0.0.7"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.15.0" }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.16.2" }
|
||||
|
||||
[features]
|
||||
generate-debug-information = ["wasm-debug"]
|
||||
|
@ -209,7 +209,7 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_import_function(&mut self) -> Result<(), CodegenError> {
|
||||
fn feed_import_function(&mut self, _sigindex: SigIndex) -> Result<(), CodegenError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-dev-utils"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime core library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-emscripten-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Tests for our Emscripten implementation"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,15 +9,15 @@ publish = false
|
||||
build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
wasmer-emscripten = { path = "../emscripten", version = "0.15.0" }
|
||||
wasmer-runtime = { path = "../runtime", version = "0.15.0", default-features = false }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.15.0", optional = true}
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.15.0", optional = true, features = ["test"] }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.15.0", optional = true }
|
||||
wasmer-emscripten = { path = "../emscripten", version = "0.16.2" }
|
||||
wasmer-runtime = { path = "../runtime", version = "0.16.2", default-features = false }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.16.2", optional = true}
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.16.2", optional = true, features = ["test"] }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.16.2", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
wabt = "0.9.1"
|
||||
wasmer-dev-utils = { path = "../dev-utils", version = "0.15.0"}
|
||||
wasmer-dev-utils = { path = "../dev-utils", version = "0.16.2"}
|
||||
|
||||
[build-dependencies]
|
||||
glob = "0.3"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-emscripten"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime emscripten implementation library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -15,7 +15,7 @@ lazy_static = "1.4"
|
||||
libc = "0.2.60"
|
||||
log = "0.4"
|
||||
time = "0.1"
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
getrandom = "0.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-interface-types"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "WebAssembly Interface Types library for Wasmer"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
|
@ -9,8 +9,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wabt = "0.9.1"
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime = { path = "../runtime", version = "0.15.0" }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.15.0", features = ["test"] }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
wasmer-runtime = { path = "../runtime", version = "0.16.2" }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.16.2", features = ["test"] }
|
||||
|
||||
[features]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-llvm-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
@ -10,7 +10,7 @@ edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0", features = ["generate-debug-information-no-export-symbols"] }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2", features = ["generate-debug-information-no-export-symbols"] }
|
||||
wasmparser = "0.51.3"
|
||||
smallvec = "0.6"
|
||||
goblin = "0.0.24"
|
||||
|
@ -8984,7 +8984,7 @@ impl<'ctx> ModuleCodeGenerator<LLVMFunctionCodeGenerator<'ctx>, LLVMBackend, Cod
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_import_function(&mut self) -> Result<(), CodegenError> {
|
||||
fn feed_import_function(&mut self, _sigindex: SigIndex) -> Result<(), CodegenError> {
|
||||
self.func_import_count += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-middleware-common-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
@ -8,11 +8,11 @@ license = "MIT"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-middleware-common = { path = "../middleware-common", version = "0.15.0" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.15.0", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.15.0", features = ["test"], optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.15.0", optional = true }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
wasmer-middleware-common = { path = "../middleware-common", version = "0.16.2" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.16.2", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.16.2", features = ["test"], optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.16.2", optional = true }
|
||||
|
||||
[features]
|
||||
clif = ["wasmer-clif-backend"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-middleware-common"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
description = "Wasmer runtime common middlewares"
|
||||
license = "MIT"
|
||||
@ -10,4 +10,4 @@ categories = ["wasm"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime-c-api"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer C API library"
|
||||
documentation = "https://wasmerio.github.io/wasmer/c/runtime-c-api/"
|
||||
license = "MIT"
|
||||
@ -20,22 +20,22 @@ libc = "0.2.60"
|
||||
[dependencies.wasmer-runtime]
|
||||
default-features = false
|
||||
path = "../runtime"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
|
||||
[dependencies.wasmer-runtime-core]
|
||||
default-features = false
|
||||
path = "../runtime-core"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
|
||||
[dependencies.wasmer-wasi]
|
||||
default-features = false
|
||||
path = "../wasi"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.wasmer-emscripten]
|
||||
path = "../emscripten"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
|
@ -34,6 +34,8 @@ pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_context_trampoline
|
||||
}
|
||||
|
||||
/// Adds a callinfo trampoline to the builder.
|
||||
///
|
||||
/// Deprecated. In a future version `DynamicFunc::new` will be exposed to the C API and should be used instead of this function.
|
||||
#[no_mangle]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_callinfo_trampoline(
|
||||
@ -42,8 +44,14 @@ pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_callinfo_trampolin
|
||||
ctx: *const c_void,
|
||||
num_params: u32,
|
||||
) -> usize {
|
||||
use wasmer_runtime_core::types::Type;
|
||||
let builder = &mut *(builder as *mut TrampolineBufferBuilder);
|
||||
builder.add_callinfo_trampoline(mem::transmute(func), ctx as *const CallContext, num_params)
|
||||
builder.add_callinfo_trampoline(
|
||||
mem::transmute(func),
|
||||
ctx as *const CallContext,
|
||||
&vec![Type::I64; num_params as usize],
|
||||
&[Type::I64],
|
||||
)
|
||||
}
|
||||
|
||||
/// Finalizes the trampoline builder into an executable buffer.
|
||||
|
@ -1386,6 +1386,8 @@ wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits)
|
||||
#if (!defined(_WIN32) && defined(ARCH_X86_64))
|
||||
/**
|
||||
* Adds a callinfo trampoline to the builder.
|
||||
*
|
||||
* Deprecated. In a future version `DynamicFunc::new` will be exposed to the C API and should be used instead of this function.
|
||||
*/
|
||||
uintptr_t wasmer_trampoline_buffer_builder_add_callinfo_trampoline(wasmer_trampoline_buffer_builder_t *builder,
|
||||
const wasmer_trampoline_callable_t *func,
|
||||
|
@ -1146,6 +1146,8 @@ wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits)
|
||||
|
||||
#if (!defined(_WIN32) && defined(ARCH_X86_64))
|
||||
/// Adds a callinfo trampoline to the builder.
|
||||
///
|
||||
/// Deprecated. In a future version `DynamicFunc::new` will be exposed to the C API and should be used instead of this function.
|
||||
uintptr_t wasmer_trampoline_buffer_builder_add_callinfo_trampoline(wasmer_trampoline_buffer_builder_t *builder,
|
||||
const wasmer_trampoline_callable_t *func,
|
||||
const void *ctx,
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime-core-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Tests for the Wasmer runtime core crate"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,10 +9,10 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
wabt = "0.9.1"
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.15.0", optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.15.0", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.15.0", features = ["test"], optional = true }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.16.2", optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.16.2", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.16.2", features = ["test"], optional = true }
|
||||
|
||||
[features]
|
||||
default = ["backend-cranelift"]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
use wasmer_runtime_core::{
|
||||
compile_with,
|
||||
error::RuntimeError,
|
||||
@ -12,10 +12,11 @@ use wasmer_runtime_core::{
|
||||
use wasmer_runtime_core_tests::{get_compiler, wat2wasm};
|
||||
|
||||
macro_rules! call_and_assert {
|
||||
($instance:ident, $function:ident, $expected_value:expr) => {
|
||||
let $function: Func<i32, i32> = $instance.func(stringify!($function)).unwrap();
|
||||
($instance:ident, $function:ident( $( $inputs:ty ),* ) -> $output:ty, ( $( $arguments:expr ),* ) == $expected_value:expr) => {
|
||||
#[allow(unused_parens)]
|
||||
let $function: Func<( $( $inputs ),* ), $output> = $instance.func(stringify!($function)).expect(concat!("Failed to get the `", stringify!($function), "` export function."));
|
||||
|
||||
let result = $function.call(1);
|
||||
let result = $function.call( $( $arguments ),* );
|
||||
|
||||
match (result, $expected_value) {
|
||||
(Ok(value), expected_value) => assert_eq!(
|
||||
@ -75,7 +76,12 @@ fn imported_functions_forms(test: &dyn Fn(&Instance)) {
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(import "env" "callback_fn" (func $callback_fn (type $type)))
|
||||
(import "env" "callback_closure" (func $callback_closure (type $type)))
|
||||
(import "env" "callback_closure_dynamic" (func $callback_closure_dynamic (type $type)))
|
||||
(import "env" "callback_fn_dynamic" (func $callback_fn_dynamic (type $type)))
|
||||
(import "env" "callback_closure_dynamic_0" (func $callback_closure_dynamic_0))
|
||||
(import "env" "callback_closure_dynamic_1" (func $callback_closure_dynamic_1 (param i32) (result i32)))
|
||||
(import "env" "callback_closure_dynamic_2" (func $callback_closure_dynamic_2 (param i32 i64) (result i64)))
|
||||
(import "env" "callback_closure_dynamic_3" (func $callback_closure_dynamic_3 (param i32 i64 f32) (result f32)))
|
||||
(import "env" "callback_closure_dynamic_4" (func $callback_closure_dynamic_4 (param i32 i64 f32 f64) (result f64)))
|
||||
(import "env" "callback_closure_with_env" (func $callback_closure_with_env (type $type)))
|
||||
(import "env" "callback_fn_with_vmctx" (func $callback_fn_with_vmctx (type $type)))
|
||||
(import "env" "callback_closure_with_vmctx" (func $callback_closure_with_vmctx (type $type)))
|
||||
@ -94,9 +100,34 @@ fn imported_functions_forms(test: &dyn Fn(&Instance)) {
|
||||
get_local 0
|
||||
call $callback_closure)
|
||||
|
||||
(func (export "function_closure_dynamic") (type $type)
|
||||
(func (export "function_fn_dynamic") (type $type)
|
||||
get_local 0
|
||||
call $callback_closure_dynamic)
|
||||
call $callback_fn_dynamic)
|
||||
|
||||
(func (export "function_closure_dynamic_0")
|
||||
call $callback_closure_dynamic_0)
|
||||
|
||||
(func (export "function_closure_dynamic_1") (param i32) (result i32)
|
||||
get_local 0
|
||||
call $callback_closure_dynamic_1)
|
||||
|
||||
(func (export "function_closure_dynamic_2") (param i32 i64) (result i64)
|
||||
get_local 0
|
||||
get_local 1
|
||||
call $callback_closure_dynamic_2)
|
||||
|
||||
(func (export "function_closure_dynamic_3") (param i32 i64 f32) (result f32)
|
||||
get_local 0
|
||||
get_local 1
|
||||
get_local 2
|
||||
call $callback_closure_dynamic_3)
|
||||
|
||||
(func (export "function_closure_dynamic_4") (param i32 i64 f32 f64) (result f64)
|
||||
get_local 0
|
||||
get_local 1
|
||||
get_local 2
|
||||
get_local 3
|
||||
call $callback_closure_dynamic_4)
|
||||
|
||||
(func (export "function_closure_with_env") (type $type)
|
||||
get_local 0
|
||||
@ -154,13 +185,73 @@ fn imported_functions_forms(test: &dyn Fn(&Instance)) {
|
||||
Ok(n + 1)
|
||||
}),
|
||||
|
||||
"callback_closure_dynamic" => DynamicFunc::new(
|
||||
// Regular polymorphic function.
|
||||
"callback_fn_dynamic" => DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(vec![Type::I32], vec![Type::I32])),
|
||||
|_, params| -> Vec<Value> {
|
||||
match params[0] {
|
||||
Value::I32(x) => vec![Value::I32(x + 1)],
|
||||
_ => unreachable!()
|
||||
}
|
||||
callback_fn_dynamic,
|
||||
),
|
||||
|
||||
// Polymorphic closure “closures”.
|
||||
"callback_closure_dynamic_0" => DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(vec![], vec![])),
|
||||
|_, inputs: &[Value]| -> Vec<Value> {
|
||||
assert!(inputs.is_empty());
|
||||
|
||||
vec![]
|
||||
}
|
||||
),
|
||||
"callback_closure_dynamic_1" => DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(vec![Type::I32], vec![Type::I32])),
|
||||
move |vmctx: &mut vm::Ctx, inputs: &[Value]| -> Vec<Value> {
|
||||
assert_eq!(inputs.len(), 1);
|
||||
|
||||
let memory = vmctx.memory(0);
|
||||
let shift_ = shift + memory.view::<i32>()[0].get();
|
||||
let n: i32 = (&inputs[0]).try_into().unwrap();
|
||||
|
||||
vec![Value::I32(shift_ + n)]
|
||||
}
|
||||
),
|
||||
"callback_closure_dynamic_2" => DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(vec![Type::I32, Type::I64], vec![Type::I64])),
|
||||
move |vmctx: &mut vm::Ctx, inputs: &[Value]| -> Vec<Value> {
|
||||
assert_eq!(inputs.len(), 2);
|
||||
|
||||
let memory = vmctx.memory(0);
|
||||
let shift_ = shift + memory.view::<i32>()[0].get();
|
||||
let i: i32 = (&inputs[0]).try_into().unwrap();
|
||||
let j: i64 = (&inputs[1]).try_into().unwrap();
|
||||
|
||||
vec![Value::I64(shift_ as i64 + i as i64 + j)]
|
||||
}
|
||||
),
|
||||
"callback_closure_dynamic_3" => DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(vec![Type::I32, Type::I64, Type::F32], vec![Type::F32])),
|
||||
move |vmctx: &mut vm::Ctx, inputs: &[Value]| -> Vec<Value> {
|
||||
assert_eq!(inputs.len(), 3);
|
||||
|
||||
let memory = vmctx.memory(0);
|
||||
let shift_ = shift + memory.view::<i32>()[0].get();
|
||||
let i: i32 = (&inputs[0]).try_into().unwrap();
|
||||
let j: i64 = (&inputs[1]).try_into().unwrap();
|
||||
let k: f32 = (&inputs[2]).try_into().unwrap();
|
||||
|
||||
vec![Value::F32(shift_ as f32 + i as f32 + j as f32 + k)]
|
||||
}
|
||||
),
|
||||
"callback_closure_dynamic_4" => DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![Type::F64])),
|
||||
move |vmctx: &mut vm::Ctx, inputs: &[Value]| -> Vec<Value> {
|
||||
assert_eq!(inputs.len(), 4);
|
||||
|
||||
let memory = vmctx.memory(0);
|
||||
let shift_ = shift + memory.view::<i32>()[0].get();
|
||||
let i: i32 = (&inputs[0]).try_into().unwrap();
|
||||
let j: i64 = (&inputs[1]).try_into().unwrap();
|
||||
let k: f32 = (&inputs[2]).try_into().unwrap();
|
||||
let l: f64 = (&inputs[3]).try_into().unwrap();
|
||||
|
||||
vec![Value::F64(shift_ as f64 + i as f64 + j as f64 + k as f64 + l)]
|
||||
}
|
||||
),
|
||||
|
||||
@ -227,6 +318,13 @@ fn callback_fn(n: i32) -> Result<i32, ()> {
|
||||
Ok(n + 1)
|
||||
}
|
||||
|
||||
fn callback_fn_dynamic(_: &mut vm::Ctx, inputs: &[Value]) -> Vec<Value> {
|
||||
match inputs[0] {
|
||||
Value::I32(x) => vec![Value::I32(x + 1)],
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn callback_fn_with_vmctx(vmctx: &mut vm::Ctx, n: i32) -> Result<i32, ()> {
|
||||
let memory = vmctx.memory(0);
|
||||
let shift_: i32 = memory.view()[0].get();
|
||||
@ -246,57 +344,82 @@ fn callback_fn_trap_with_vmctx(vmctx: &mut vm::Ctx, n: i32) -> Result<i32, Strin
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
($test_name:ident, $function:ident, $expected_value:expr) => {
|
||||
($test_name:ident, $function:ident( $( $inputs:ty ),* ) -> $output:ty, ( $( $arguments:expr ),* ) == $expected_value:expr) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
imported_functions_forms(&|instance| {
|
||||
call_and_assert!(instance, $function, $expected_value);
|
||||
call_and_assert!(instance, $function( $( $inputs ),* ) -> $output, ( $( $arguments ),* ) == $expected_value);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test!(test_fn, function_fn, Ok(2));
|
||||
test!(test_closure, function_closure, Ok(2));
|
||||
test!(test_closure_dynamic, function_closure_dynamic, Ok(2));
|
||||
test!(test_fn, function_fn(i32) -> i32, (1) == Ok(2));
|
||||
test!(test_closure, function_closure(i32) -> i32, (1) == Ok(2));
|
||||
test!(test_fn_dynamic, function_fn_dynamic(i32) -> i32, (1) == Ok(2));
|
||||
test!(
|
||||
test_closure_dynamic_0,
|
||||
function_closure_dynamic_0(()) -> (),
|
||||
() == Ok(())
|
||||
);
|
||||
test!(
|
||||
test_closure_dynamic_1,
|
||||
function_closure_dynamic_1(i32) -> i32,
|
||||
(1) == Ok(1 + shift + SHIFT)
|
||||
);
|
||||
test!(
|
||||
test_closure_dynamic_2,
|
||||
function_closure_dynamic_2(i32, i64) -> i64,
|
||||
(1, 2) == Ok(1 + 2 + shift as i64 + SHIFT as i64)
|
||||
);
|
||||
test!(
|
||||
test_closure_dynamic_3,
|
||||
function_closure_dynamic_3(i32, i64, f32) -> f32,
|
||||
(1, 2, 3.) == Ok(1. + 2. + 3. + shift as f32 + SHIFT as f32)
|
||||
);
|
||||
test!(
|
||||
test_closure_dynamic_4,
|
||||
function_closure_dynamic_4(i32, i64, f32, f64) -> f64,
|
||||
(1, 2, 3., 4.) == Ok(1. + 2. + 3. + 4. + shift as f64 + SHIFT as f64)
|
||||
);
|
||||
test!(
|
||||
test_closure_with_env,
|
||||
function_closure_with_env,
|
||||
Ok(2 + shift + SHIFT)
|
||||
function_closure_with_env(i32) -> i32,
|
||||
(1) == Ok(2 + shift + SHIFT)
|
||||
);
|
||||
test!(test_fn_with_vmctx, function_fn_with_vmctx, Ok(2 + SHIFT));
|
||||
test!(test_fn_with_vmctx, function_fn_with_vmctx(i32) -> i32, (1) == Ok(2 + SHIFT));
|
||||
test!(
|
||||
test_closure_with_vmctx,
|
||||
function_closure_with_vmctx,
|
||||
Ok(2 + SHIFT)
|
||||
function_closure_with_vmctx(i32) -> i32,
|
||||
(1) == Ok(2 + SHIFT)
|
||||
);
|
||||
test!(
|
||||
test_closure_with_vmctx_and_env,
|
||||
function_closure_with_vmctx_and_env,
|
||||
Ok(2 + shift + SHIFT)
|
||||
function_closure_with_vmctx_and_env(i32) -> i32,
|
||||
(1) == Ok(2 + shift + SHIFT)
|
||||
);
|
||||
test!(
|
||||
test_fn_trap,
|
||||
function_fn_trap,
|
||||
Err(RuntimeError(Box::new(format!("foo {}", 2))))
|
||||
function_fn_trap(i32) -> i32,
|
||||
(1) == Err(RuntimeError(Box::new(format!("foo {}", 2))))
|
||||
);
|
||||
test!(
|
||||
test_closure_trap,
|
||||
function_closure_trap,
|
||||
Err(RuntimeError(Box::new(format!("bar {}", 2))))
|
||||
function_closure_trap(i32) -> i32,
|
||||
(1) == Err(RuntimeError(Box::new(format!("bar {}", 2))))
|
||||
);
|
||||
test!(
|
||||
test_fn_trap_with_vmctx,
|
||||
function_fn_trap_with_vmctx,
|
||||
Err(RuntimeError(Box::new(format!("baz {}", 2 + SHIFT))))
|
||||
function_fn_trap_with_vmctx(i32) -> i32,
|
||||
(1) == Err(RuntimeError(Box::new(format!("baz {}", 2 + SHIFT))))
|
||||
);
|
||||
test!(
|
||||
test_closure_trap_with_vmctx,
|
||||
function_closure_trap_with_vmctx,
|
||||
Err(RuntimeError(Box::new(format!("qux {}", 2 + SHIFT))))
|
||||
function_closure_trap_with_vmctx(i32) -> i32,
|
||||
(1) == Err(RuntimeError(Box::new(format!("qux {}", 2 + SHIFT))))
|
||||
);
|
||||
test!(
|
||||
test_closure_trap_with_vmctx_and_env,
|
||||
function_closure_trap_with_vmctx_and_env,
|
||||
Err(RuntimeError(Box::new(format!("! {}", 2 + shift + SHIFT))))
|
||||
function_closure_trap_with_vmctx_and_env(i32) -> i32,
|
||||
(1) == Err(RuntimeError(Box::new(format!("! {}", 2 + shift + SHIFT))))
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime-core"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime core library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -59,3 +59,5 @@ generate-debug-information = ["wasm-debug"]
|
||||
# don't export symbols related to the GDB JIT interafce, LLVM or some other native
|
||||
# code will be providing them
|
||||
generate-debug-information-no-export-symbols = []
|
||||
# enable DynamicFunc's for closures with captured environment.
|
||||
dynamicfunc-fat-closures = []
|
||||
|
@ -143,7 +143,7 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
|
||||
Ok(())
|
||||
}
|
||||
/// Adds an import function.
|
||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||
fn feed_import_function(&mut self, _sigindex: SigIndex) -> Result<(), E>;
|
||||
/// Sets the signatures.
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||
/// Sets function signatures.
|
||||
|
@ -130,9 +130,10 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
// for any index, we will always result an aligned memory access
|
||||
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
||||
let slice_full_len = index as usize + length as usize;
|
||||
let memory_size = memory.size().bytes().0;
|
||||
|
||||
if (self.offset as usize) + (item_size * slice_full_len) > memory.size().bytes().0
|
||||
|| length == 0
|
||||
if (self.offset as usize) + (item_size * slice_full_len) > memory_size
|
||||
|| self.offset as usize >= memory_size
|
||||
|| mem::size_of::<T>() == 0
|
||||
{
|
||||
return None;
|
||||
@ -167,9 +168,10 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
// for any index, we will always result an aligned memory access
|
||||
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
||||
let slice_full_len = index as usize + length as usize;
|
||||
let memory_size = memory.size().bytes().0;
|
||||
|
||||
if (self.offset as usize) + (item_size * slice_full_len) > memory.size().bytes().0
|
||||
|| length == 0
|
||||
|| self.offset as usize >= memory_size
|
||||
|| mem::size_of::<T>() == 0
|
||||
{
|
||||
return None;
|
||||
@ -190,7 +192,11 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
/// underlying data can be mutated if the Wasm is allowed to execute or
|
||||
/// an aliasing `WasmPtr` is used to mutate memory.
|
||||
pub fn get_utf8_string(self, memory: &Memory, str_len: u32) -> Option<&str> {
|
||||
if self.offset as usize + str_len as usize > memory.size().bytes().0 || str_len == 0 {
|
||||
let memory_size = memory.size().bytes().0;
|
||||
|
||||
if self.offset as usize + str_len as usize > memory.size().bytes().0
|
||||
|| self.offset as usize >= memory_size
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let ptr = unsafe { memory.view::<u8>().as_ptr().add(self.offset as usize) as *const u8 };
|
||||
@ -271,15 +277,15 @@ mod test {
|
||||
memory::MemoryDescriptor::new(Pages(1), Some(Pages(1)), false).unwrap();
|
||||
let memory = memory::Memory::new(memory_descriptor).unwrap();
|
||||
|
||||
// test that basic access works and that len = 0 is caught correctly
|
||||
// test that basic access works and that len = 0 works, but oob does not
|
||||
let start_wasm_ptr: WasmPtr<u8> = WasmPtr::new(0);
|
||||
let start_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(0);
|
||||
|
||||
assert!(start_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { start_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 0).is_none());
|
||||
assert!(start_wasm_ptr_array.get_utf8_string(&memory, 0).is_none());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 0).is_none() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 0).is_some());
|
||||
assert!(start_wasm_ptr_array.get_utf8_string(&memory, 0).is_some());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 0).is_some() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
|
||||
@ -293,7 +299,8 @@ mod test {
|
||||
|
||||
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
let invalid_idx_len_combos: [(u32, u32); 3] = [(0, 0), (0, 2), (1, 1)];
|
||||
let invalid_idx_len_combos: [(u32, u32); 3] =
|
||||
[(last_valid_address_for_u8 + 1, 0), (0, 2), (1, 1)];
|
||||
for &(idx, len) in invalid_idx_len_combos.into_iter() {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||
@ -323,7 +330,8 @@ mod test {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
|
||||
let invalid_idx_len_combos: [(u32, u32); 4] = [(0, 0), (1, 0), (0, 2), (1, 1)];
|
||||
let invalid_idx_len_combos: [(u32, u32); 3] =
|
||||
[(last_valid_address_for_u32 + 1, 0), (0, 2), (1, 1)];
|
||||
for &(idx, len) in invalid_idx_len_combos.into_iter() {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||
@ -339,8 +347,6 @@ mod test {
|
||||
for oob_end_array_ptr in end_wasm_ptr_array_oob_array.into_iter() {
|
||||
assert!(oob_end_array_ptr.deref(&memory, 0, 1).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 1).is_none() });
|
||||
assert!(oob_end_array_ptr.deref(&memory, 0, 0).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 0).is_none() });
|
||||
assert!(oob_end_array_ptr.deref(&memory, 1, 0).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 1, 0).is_none() });
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ use crate::{
|
||||
backend::{CompilerConfig, RunnableModule},
|
||||
error::CompileError,
|
||||
module::{
|
||||
DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder,
|
||||
TableInitializer,
|
||||
DataInitializer, ExportIndex, ImportName, ModuleInfo, NameIndex, NamespaceIndex,
|
||||
StringTable, StringTableBuilder, TableInitializer,
|
||||
},
|
||||
structures::{Map, TypedIndex},
|
||||
types::{
|
||||
@ -110,11 +110,36 @@ pub fn read_module<
|
||||
let mut namespace_builder = Some(StringTableBuilder::new());
|
||||
let mut name_builder = Some(StringTableBuilder::new());
|
||||
let mut func_count: usize = 0;
|
||||
let mut mcg_info_fed = false;
|
||||
|
||||
let mut feed_mcg_signatures: Option<_> = Some(|mcg: &mut MCG| -> Result<(), LoadError> {
|
||||
let info_read = info.read().unwrap();
|
||||
mcg.feed_signatures(info_read.signatures.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
Ok(())
|
||||
});
|
||||
let mut feed_mcg_info: Option<_> = Some(
|
||||
|mcg: &mut MCG,
|
||||
ns_builder: StringTableBuilder<NamespaceIndex>,
|
||||
name_builder: StringTableBuilder<NameIndex>|
|
||||
-> Result<(), LoadError> {
|
||||
{
|
||||
let mut info_write = info.write().unwrap();
|
||||
info_write.namespace_table = ns_builder.finish();
|
||||
info_write.name_table = name_builder.finish();
|
||||
}
|
||||
let info_read = info.read().unwrap();
|
||||
mcg.feed_function_signatures(info_read.func_assoc.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.check_precondition(&info_read)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
||||
loop {
|
||||
use wasmparser::ParserState;
|
||||
let state = parser.read();
|
||||
|
||||
match *state {
|
||||
ParserState::Error(ref err) => return Err(err.clone().into()),
|
||||
ParserState::TypeSectionEntry(ref ty) => {
|
||||
@ -124,6 +149,10 @@ pub fn read_module<
|
||||
.push(func_type_to_func_sig(ty)?);
|
||||
}
|
||||
ParserState::ImportSectionEntry { module, field, ty } => {
|
||||
if let Some(f) = feed_mcg_signatures.take() {
|
||||
f(mcg)?;
|
||||
}
|
||||
|
||||
let namespace_index = namespace_builder.as_mut().unwrap().register(module);
|
||||
let name_index = name_builder.as_mut().unwrap().register(field);
|
||||
let import_name = ImportName {
|
||||
@ -136,7 +165,7 @@ pub fn read_module<
|
||||
let sigindex = SigIndex::new(sigindex as usize);
|
||||
info.write().unwrap().imported_functions.push(import_name);
|
||||
info.write().unwrap().func_assoc.push(sigindex);
|
||||
mcg.feed_import_function()
|
||||
mcg.feed_import_function(sigindex)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
}
|
||||
ImportSectionEntryType::Table(table_ty) => {
|
||||
@ -217,23 +246,17 @@ pub fn read_module<
|
||||
info.write().unwrap().start_func = Some(FuncIndex::new(start_index as usize));
|
||||
}
|
||||
ParserState::BeginFunctionBody { range } => {
|
||||
let id = func_count;
|
||||
if !mcg_info_fed {
|
||||
mcg_info_fed = true;
|
||||
{
|
||||
let mut info_write = info.write().unwrap();
|
||||
info_write.namespace_table = namespace_builder.take().unwrap().finish();
|
||||
info_write.name_table = name_builder.take().unwrap().finish();
|
||||
}
|
||||
let info_read = info.read().unwrap();
|
||||
mcg.feed_signatures(info_read.signatures.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.feed_function_signatures(info_read.func_assoc.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.check_precondition(&info_read)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
if let Some(f) = feed_mcg_signatures.take() {
|
||||
f(mcg)?;
|
||||
}
|
||||
|
||||
if let Some(f) = feed_mcg_info.take() {
|
||||
f(
|
||||
mcg,
|
||||
namespace_builder.take().unwrap(),
|
||||
name_builder.take().unwrap(),
|
||||
)?;
|
||||
}
|
||||
let id = func_count;
|
||||
let fcg = mcg
|
||||
.next_function(
|
||||
Arc::clone(&info),
|
||||
@ -432,17 +455,15 @@ pub fn read_module<
|
||||
info.write().unwrap().globals.push(global_init);
|
||||
}
|
||||
ParserState::EndWasm => {
|
||||
// TODO Consolidate with BeginFunction body if possible
|
||||
if !mcg_info_fed {
|
||||
info.write().unwrap().namespace_table =
|
||||
namespace_builder.take().unwrap().finish();
|
||||
info.write().unwrap().name_table = name_builder.take().unwrap().finish();
|
||||
mcg.feed_signatures(info.read().unwrap().signatures.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.feed_function_signatures(info.read().unwrap().func_assoc.clone())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
mcg.check_precondition(&info.read().unwrap())
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
if let Some(f) = feed_mcg_signatures.take() {
|
||||
f(mcg)?;
|
||||
}
|
||||
if let Some(f) = feed_mcg_info.take() {
|
||||
f(
|
||||
mcg,
|
||||
namespace_builder.take().unwrap(),
|
||||
name_builder.take().unwrap(),
|
||||
)?;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -480,10 +480,11 @@ impl InstanceImage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Declarations for x86-64 registers.
|
||||
/// X64-specific structures and methods that do not depend on an x64 machine to run.
|
||||
#[cfg(unix)]
|
||||
pub mod x64_decl {
|
||||
use super::*;
|
||||
use crate::types::Type;
|
||||
|
||||
/// General-purpose registers.
|
||||
#[repr(u8)]
|
||||
@ -610,9 +611,88 @@ pub mod x64_decl {
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the instruction prefix for `movq %this_reg, ?(%rsp)`.
|
||||
///
|
||||
/// To build an instruction, append the memory location as a 32-bit
|
||||
/// offset to the stack pointer to this prefix.
|
||||
pub fn prefix_mov_to_stack(&self) -> Option<&'static [u8]> {
|
||||
Some(match *self {
|
||||
X64Register::GPR(gpr) => match gpr {
|
||||
GPR::RDI => &[0x48, 0x89, 0xbc, 0x24],
|
||||
GPR::RSI => &[0x48, 0x89, 0xb4, 0x24],
|
||||
GPR::RDX => &[0x48, 0x89, 0x94, 0x24],
|
||||
GPR::RCX => &[0x48, 0x89, 0x8c, 0x24],
|
||||
GPR::R8 => &[0x4c, 0x89, 0x84, 0x24],
|
||||
GPR::R9 => &[0x4c, 0x89, 0x8c, 0x24],
|
||||
_ => return None,
|
||||
},
|
||||
X64Register::XMM(xmm) => match xmm {
|
||||
XMM::XMM0 => &[0x66, 0x0f, 0xd6, 0x84, 0x24],
|
||||
XMM::XMM1 => &[0x66, 0x0f, 0xd6, 0x8c, 0x24],
|
||||
XMM::XMM2 => &[0x66, 0x0f, 0xd6, 0x94, 0x24],
|
||||
XMM::XMM3 => &[0x66, 0x0f, 0xd6, 0x9c, 0x24],
|
||||
XMM::XMM4 => &[0x66, 0x0f, 0xd6, 0xa4, 0x24],
|
||||
XMM::XMM5 => &[0x66, 0x0f, 0xd6, 0xac, 0x24],
|
||||
XMM::XMM6 => &[0x66, 0x0f, 0xd6, 0xb4, 0x24],
|
||||
XMM::XMM7 => &[0x66, 0x0f, 0xd6, 0xbc, 0x24],
|
||||
_ => return None,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An allocator that allocates registers for function arguments according to the System V ABI.
|
||||
#[derive(Default)]
|
||||
pub struct ArgumentRegisterAllocator {
|
||||
n_gprs: usize,
|
||||
n_xmms: usize,
|
||||
}
|
||||
|
||||
impl ArgumentRegisterAllocator {
|
||||
/// Allocates a register for argument type `ty`. Returns `None` if no register is available for this type.
|
||||
pub fn next(&mut self, ty: Type) -> Option<X64Register> {
|
||||
static GPR_SEQ: &'static [GPR] =
|
||||
&[GPR::RDI, GPR::RSI, GPR::RDX, GPR::RCX, GPR::R8, GPR::R9];
|
||||
static XMM_SEQ: &'static [XMM] = &[
|
||||
XMM::XMM0,
|
||||
XMM::XMM1,
|
||||
XMM::XMM2,
|
||||
XMM::XMM3,
|
||||
XMM::XMM4,
|
||||
XMM::XMM5,
|
||||
XMM::XMM6,
|
||||
XMM::XMM7,
|
||||
];
|
||||
match ty {
|
||||
Type::I32 | Type::I64 => {
|
||||
if self.n_gprs < GPR_SEQ.len() {
|
||||
let gpr = GPR_SEQ[self.n_gprs];
|
||||
self.n_gprs += 1;
|
||||
Some(X64Register::GPR(gpr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Type::F32 | Type::F64 => {
|
||||
if self.n_xmms < XMM_SEQ.len() {
|
||||
let xmm = XMM_SEQ[self.n_xmms];
|
||||
self.n_xmms += 1;
|
||||
Some(X64Register::XMM(xmm))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => todo!(
|
||||
"ArgumentRegisterAllocator::next: Unsupported type: {:?}",
|
||||
ty
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// X64-specific structures and methods that only work on an x64 machine.
|
||||
#[cfg(unix)]
|
||||
pub mod x64 {
|
||||
//! The x64 state module contains functions to generate state and code for x64 targets.
|
||||
|
@ -7,6 +7,8 @@
|
||||
//! Variadic functions are not supported because `rax` is used by the trampoline code.
|
||||
|
||||
use crate::loader::CodeMemory;
|
||||
use crate::state::x64_decl::ArgumentRegisterAllocator;
|
||||
use crate::types::Type;
|
||||
use crate::vm::Ctx;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
@ -246,44 +248,50 @@ impl TrampolineBufferBuilder {
|
||||
&mut self,
|
||||
target: unsafe extern "C" fn(*const CallContext, *const u64) -> u64,
|
||||
context: *const CallContext,
|
||||
num_params: u32,
|
||||
params: &[Type],
|
||||
_returns: &[Type],
|
||||
) -> usize {
|
||||
let idx = self.offsets.len();
|
||||
self.offsets.push(self.code.len());
|
||||
|
||||
let mut stack_offset: u32 = num_params.checked_mul(8).unwrap();
|
||||
let mut stack_offset: u32 = params.len().checked_mul(8).unwrap() as u32;
|
||||
if stack_offset % 16 == 0 {
|
||||
stack_offset += 8;
|
||||
}
|
||||
|
||||
self.code.extend_from_slice(&[0x48, 0x81, 0xec]); // sub ?, %rsp
|
||||
self.code.extend_from_slice(value_to_bytes(&stack_offset));
|
||||
for i in 0..num_params {
|
||||
match i {
|
||||
0..=5 => {
|
||||
// mov %?, ?(%rsp)
|
||||
let prefix: &[u8] = match i {
|
||||
0 => &[0x48, 0x89, 0xbc, 0x24], // rdi
|
||||
1 => &[0x48, 0x89, 0xb4, 0x24], // rsi
|
||||
2 => &[0x48, 0x89, 0x94, 0x24], // rdx
|
||||
3 => &[0x48, 0x89, 0x8c, 0x24], // rcx
|
||||
4 => &[0x4c, 0x89, 0x84, 0x24], // r8
|
||||
5 => &[0x4c, 0x89, 0x8c, 0x24], // r9
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let mut allocator = ArgumentRegisterAllocator::default();
|
||||
|
||||
let mut source_stack_count: u32 = 0; // # of allocated slots in the source stack.
|
||||
|
||||
for (i, ty) in params.iter().enumerate() {
|
||||
match allocator.next(*ty) {
|
||||
Some(reg) => {
|
||||
// This argument is allocated to a register.
|
||||
|
||||
let prefix = reg
|
||||
.prefix_mov_to_stack()
|
||||
.expect("cannot get instruction prefix for argument register");
|
||||
self.code.extend_from_slice(prefix);
|
||||
self.code.extend_from_slice(value_to_bytes(&(i * 8u32)));
|
||||
self.code
|
||||
.extend_from_slice(value_to_bytes(&((i as u32) * 8u32)));
|
||||
}
|
||||
_ => {
|
||||
None => {
|
||||
// This argument is allocated to the stack.
|
||||
|
||||
self.code.extend_from_slice(&[
|
||||
0x48, 0x8b, 0x84, 0x24, // mov ?(%rsp), %rax
|
||||
]);
|
||||
self.code.extend_from_slice(value_to_bytes(
|
||||
&((i - 6) * 8u32 + stack_offset + 8/* ret addr */),
|
||||
&(source_stack_count * 8u32 + stack_offset + 8/* ret addr */),
|
||||
));
|
||||
// mov %rax, ?(%rsp)
|
||||
self.code.extend_from_slice(&[0x48, 0x89, 0x84, 0x24]);
|
||||
self.code.extend_from_slice(value_to_bytes(&(i * 8u32)));
|
||||
self.code
|
||||
.extend_from_slice(value_to_bytes(&((i as u32) * 8u32)));
|
||||
source_stack_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -395,8 +403,13 @@ mod tests {
|
||||
}
|
||||
let mut builder = TrampolineBufferBuilder::new();
|
||||
let ctx = TestContext { value: 100 };
|
||||
let idx =
|
||||
builder.add_callinfo_trampoline(do_add, &ctx as *const TestContext as *const _, 8);
|
||||
let param_types: Vec<Type> = vec![Type::I32; 8];
|
||||
let idx = builder.add_callinfo_trampoline(
|
||||
do_add,
|
||||
&ctx as *const TestContext as *const _,
|
||||
¶m_types,
|
||||
&[Type::I32],
|
||||
);
|
||||
let buf = builder.build();
|
||||
let t = buf.get_trampoline(idx);
|
||||
let ret = unsafe {
|
||||
@ -407,9 +420,49 @@ mod tests {
|
||||
assert_eq!(ret, 136);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trampolines_with_floating_point() {
|
||||
unsafe extern "C" fn inner(n: *const CallContext, args: *const u64) -> u64 {
|
||||
// `n` is not really a pointer. It is the length of the argument list, casted into the pointer type.
|
||||
let n = n as usize;
|
||||
let mut result: u64 = 0;
|
||||
for i in 0..n {
|
||||
result += *args.offset(i as _);
|
||||
}
|
||||
result
|
||||
}
|
||||
let buffer = TrampBuffer::new(4096);
|
||||
let mut builder = TrampolineBufferBuilder::new();
|
||||
builder.add_callinfo_trampoline(
|
||||
inner,
|
||||
8 as _,
|
||||
&[
|
||||
Type::I32,
|
||||
Type::I32,
|
||||
Type::I32,
|
||||
Type::F32,
|
||||
Type::I32,
|
||||
Type::I32,
|
||||
Type::I32,
|
||||
Type::I32,
|
||||
],
|
||||
&[Type::I32],
|
||||
);
|
||||
let ptr = buffer.insert(builder.code()).unwrap();
|
||||
let ret = unsafe {
|
||||
let f = std::mem::transmute::<
|
||||
_,
|
||||
extern "C" fn(i32, i32, i32, f32, i32, i32, i32, i32) -> i32,
|
||||
>(ptr);
|
||||
f(1, 2, 3, f32::from_bits(4), 5, 6, 7, 8)
|
||||
};
|
||||
assert_eq!(ret, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_many_global_trampolines() {
|
||||
unsafe extern "C" fn inner(n: *const CallContext, args: *const u64) -> u64 {
|
||||
// `n` is not really a pointer. It is the length of the argument list, casted into the pointer type.
|
||||
let n = n as usize;
|
||||
let mut result: u64 = 0;
|
||||
for i in 0..n {
|
||||
@ -427,7 +480,8 @@ mod tests {
|
||||
for i in 0..5000usize {
|
||||
let mut builder = TrampolineBufferBuilder::new();
|
||||
let n = i % 8;
|
||||
builder.add_callinfo_trampoline(inner, n as _, n as _);
|
||||
let param_types: Vec<_> = (0..n).map(|_| Type::I64).collect();
|
||||
builder.add_callinfo_trampoline(inner, n as _, ¶m_types, &[Type::I64]);
|
||||
let ptr = buffer
|
||||
.insert(builder.code())
|
||||
.expect("cannot insert new code into global buffer");
|
||||
|
@ -306,16 +306,15 @@ impl<'a> DynamicFunc<'a> {
|
||||
{
|
||||
use crate::trampoline_x64::{CallContext, TrampolineBufferBuilder};
|
||||
use crate::types::Value;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
struct PolymorphicContext {
|
||||
arg_types: Vec<Type>,
|
||||
func: Box<dyn Fn(&mut vm::Ctx, &[Value]) -> Vec<Value>>,
|
||||
}
|
||||
unsafe extern "C" fn enter_host_polymorphic(
|
||||
unsafe fn do_enter_host_polymorphic(
|
||||
ctx: *const CallContext,
|
||||
args: *const u64,
|
||||
) -> u64 {
|
||||
) -> Vec<Value> {
|
||||
let ctx = &*(ctx as *const PolymorphicContext);
|
||||
let vmctx = &mut *(*args.offset(0) as *mut vm::Ctx);
|
||||
let args: Vec<Value> = ctx
|
||||
@ -335,13 +334,40 @@ impl<'a> DynamicFunc<'a> {
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let rets = (ctx.func)(vmctx, &args);
|
||||
(ctx.func)(vmctx, &args)
|
||||
}
|
||||
unsafe extern "C" fn enter_host_polymorphic_i(
|
||||
ctx: *const CallContext,
|
||||
args: *const u64,
|
||||
) -> u64 {
|
||||
let rets = do_enter_host_polymorphic(ctx, args);
|
||||
if rets.len() == 0 {
|
||||
0
|
||||
} else if rets.len() == 1 {
|
||||
u64::try_from(rets[0].to_u128()).expect(
|
||||
"128-bit return value from polymorphic host functions is not yet supported",
|
||||
)
|
||||
match rets[0] {
|
||||
Value::I32(x) => x as u64,
|
||||
Value::I64(x) => x as u64,
|
||||
_ => panic!("enter_host_polymorphic_i: invalid return type"),
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"multiple return values from polymorphic host functions is not yet supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
unsafe extern "C" fn enter_host_polymorphic_f(
|
||||
ctx: *const CallContext,
|
||||
args: *const u64,
|
||||
) -> f64 {
|
||||
let rets = do_enter_host_polymorphic(ctx, args);
|
||||
if rets.len() == 0 {
|
||||
0.0
|
||||
} else if rets.len() == 1 {
|
||||
match rets[0] {
|
||||
Value::F32(x) => f64::from_bits(x.to_bits() as u64),
|
||||
Value::F64(x) => x,
|
||||
_ => panic!("enter_host_polymorphic_f: invalid return type"),
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"multiple return values from polymorphic host functions is not yet supported"
|
||||
@ -349,9 +375,8 @@ impl<'a> DynamicFunc<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Disable "fat" closures for possible future changes.
|
||||
if mem::size_of::<F>() != 0 {
|
||||
unimplemented!("DynamicFunc with captured environment is not yet supported");
|
||||
if cfg!(not(feature = "dynamicfunc-fat-closures")) && mem::size_of::<F>() != 0 {
|
||||
unimplemented!("DynamicFunc with captured environment is disabled");
|
||||
}
|
||||
|
||||
let mut builder = TrampolineBufferBuilder::new();
|
||||
@ -360,11 +385,29 @@ impl<'a> DynamicFunc<'a> {
|
||||
func: Box::new(func),
|
||||
});
|
||||
let ctx = Box::into_raw(ctx);
|
||||
builder.add_callinfo_trampoline(
|
||||
enter_host_polymorphic,
|
||||
ctx as *const _,
|
||||
(signature.params().len() + 1) as u32, // +vmctx
|
||||
);
|
||||
|
||||
let mut native_param_types = vec![Type::I64]; // vm::Ctx is the first parameter.
|
||||
native_param_types.extend_from_slice(signature.params());
|
||||
|
||||
match signature.returns() {
|
||||
[x] if *x == Type::F32 || *x == Type::F64 => {
|
||||
builder.add_callinfo_trampoline(
|
||||
unsafe { std::mem::transmute(enter_host_polymorphic_f as usize) },
|
||||
ctx as *const _,
|
||||
&native_param_types,
|
||||
signature.returns(),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
builder.add_callinfo_trampoline(
|
||||
enter_host_polymorphic_i,
|
||||
ctx as *const _,
|
||||
&native_param_types,
|
||||
signature.returns(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let ptr = builder
|
||||
.insert_global()
|
||||
.expect("cannot bump-allocate global trampoline memory");
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-runtime"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -11,17 +11,17 @@ edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.15.0", optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.16.2", optional = true }
|
||||
lazy_static = "1.4"
|
||||
memmap = "0.7"
|
||||
|
||||
[dependencies.wasmer-runtime-core]
|
||||
path = "../runtime-core"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
|
||||
[dependencies.wasmer-clif-backend]
|
||||
path = "../clif-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
optional = true
|
||||
|
||||
# Dependencies for caching.
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-singlepass-backend"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
description = "Wasmer runtime single pass compiler backend"
|
||||
license = "MIT"
|
||||
@ -11,7 +11,7 @@ edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
dynasm = "0.5"
|
||||
dynasmrt = "0.5"
|
||||
lazy_static = "1.4"
|
||||
|
@ -32,8 +32,9 @@ use wasmer_runtime_core::{
|
||||
memory::MemoryType,
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
state::{
|
||||
x64::new_machine_state, x64::X64Register, FunctionStateMap, MachineState, MachineValue,
|
||||
ModuleStateMap, OffsetInfo, SuspendOffset, WasmAbstractValue,
|
||||
x64::new_machine_state, x64::X64Register, x64_decl::ArgumentRegisterAllocator,
|
||||
FunctionStateMap, MachineState, MachineValue, ModuleStateMap, OffsetInfo, SuspendOffset,
|
||||
WasmAbstractValue,
|
||||
},
|
||||
structures::{Map, TypedIndex},
|
||||
typed_func::{Trampoline, Wasm},
|
||||
@ -204,6 +205,7 @@ pub struct X64FunctionCode {
|
||||
|
||||
signatures: Arc<Map<SigIndex, FuncSig>>,
|
||||
function_signatures: Arc<Map<FuncIndex, SigIndex>>,
|
||||
signature: FuncSig,
|
||||
fsm: FunctionStateMap,
|
||||
offset: usize,
|
||||
|
||||
@ -712,11 +714,22 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
machine.track_state = self.config.as_ref().unwrap().track_state;
|
||||
|
||||
assembler.emit_label(begin_label);
|
||||
|
||||
let signatures = self.signatures.as_ref().unwrap();
|
||||
let function_signatures = self.function_signatures.as_ref().unwrap();
|
||||
let sig_index = function_signatures
|
||||
.get(FuncIndex::new(
|
||||
self.functions.len() + self.func_import_count,
|
||||
))
|
||||
.unwrap()
|
||||
.clone();
|
||||
let sig = signatures.get(sig_index).unwrap().clone();
|
||||
let code = X64FunctionCode {
|
||||
local_function_id: self.functions.len(),
|
||||
|
||||
signatures: self.signatures.as_ref().unwrap().clone(),
|
||||
function_signatures: self.function_signatures.as_ref().unwrap().clone(),
|
||||
signatures: signatures.clone(),
|
||||
function_signatures: function_signatures.clone(),
|
||||
signature: sig,
|
||||
fsm: FunctionStateMap::new(new_machine_state(), self.functions.len(), 32, vec![]), // only a placeholder; this is initialized later in `begin_body`
|
||||
offset: begin_offset.0,
|
||||
|
||||
@ -869,7 +882,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_import_function(&mut self) -> Result<(), CodegenError> {
|
||||
fn feed_import_function(&mut self, sigindex: SigIndex) -> Result<(), CodegenError> {
|
||||
let labels = self.function_labels.as_mut().unwrap();
|
||||
let id = labels.len();
|
||||
|
||||
@ -880,6 +893,92 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
a.emit_label(label);
|
||||
labels.insert(id, (label, Some(offset)));
|
||||
|
||||
// Singlepass internally treats all arguments as integers, but the standard System V calling convention requires
|
||||
// floating point arguments to be passed in XMM registers.
|
||||
//
|
||||
// FIXME: This is only a workaround. We should fix singlepass to use the standard CC.
|
||||
let sig = self
|
||||
.signatures
|
||||
.as_ref()
|
||||
.expect("signatures itself")
|
||||
.get(sigindex)
|
||||
.expect("signatures");
|
||||
// Translation is expensive, so only do it if needed.
|
||||
if sig
|
||||
.params()
|
||||
.iter()
|
||||
.find(|&&x| x == Type::F32 || x == Type::F64)
|
||||
.is_some()
|
||||
{
|
||||
let mut param_locations: Vec<Location> = vec![];
|
||||
|
||||
// Allocate stack space for arguments.
|
||||
let stack_offset: i32 = if sig.params().len() > 5 {
|
||||
5 * 8
|
||||
} else {
|
||||
(sig.params().len() as i32) * 8
|
||||
};
|
||||
if stack_offset > 0 {
|
||||
a.emit_sub(
|
||||
Size::S64,
|
||||
Location::Imm32(stack_offset as u32),
|
||||
Location::GPR(GPR::RSP),
|
||||
);
|
||||
}
|
||||
|
||||
// Store all arguments to the stack to prevent overwrite.
|
||||
for i in 0..sig.params().len() {
|
||||
let loc = match i {
|
||||
0..=4 => {
|
||||
static PARAM_REGS: &'static [GPR] =
|
||||
&[GPR::RSI, GPR::RDX, GPR::RCX, GPR::R8, GPR::R9];
|
||||
let loc = Location::Memory(GPR::RSP, (i * 8) as i32);
|
||||
a.emit_mov(Size::S64, Location::GPR(PARAM_REGS[i]), loc);
|
||||
loc
|
||||
}
|
||||
_ => Location::Memory(GPR::RSP, stack_offset + 8 + ((i - 5) * 8) as i32),
|
||||
};
|
||||
param_locations.push(loc);
|
||||
}
|
||||
|
||||
// Copy arguments.
|
||||
let mut argalloc = ArgumentRegisterAllocator::default();
|
||||
argalloc.next(Type::I32).unwrap(); // skip vm::Ctx
|
||||
let mut caller_stack_offset: i32 = 0;
|
||||
for (i, ty) in sig.params().iter().enumerate() {
|
||||
let prev_loc = param_locations[i];
|
||||
let target = match argalloc.next(*ty) {
|
||||
Some(X64Register::GPR(gpr)) => Location::GPR(gpr),
|
||||
Some(X64Register::XMM(xmm)) => Location::XMM(xmm),
|
||||
None => {
|
||||
// No register can be allocated. Put this argument on the stack.
|
||||
//
|
||||
// Since here we never use fewer registers than by the original call, on the caller's frame
|
||||
// we always have enough space to store the rearranged arguments, and the copy "backward" between different
|
||||
// slots in the caller argument region will always work.
|
||||
a.emit_mov(Size::S64, prev_loc, Location::GPR(GPR::RAX));
|
||||
a.emit_mov(
|
||||
Size::S64,
|
||||
Location::GPR(GPR::RAX),
|
||||
Location::Memory(GPR::RSP, stack_offset + 8 + caller_stack_offset),
|
||||
);
|
||||
caller_stack_offset += 8;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
a.emit_mov(Size::S64, prev_loc, target);
|
||||
}
|
||||
|
||||
// Restore stack pointer.
|
||||
if stack_offset > 0 {
|
||||
a.emit_add(
|
||||
Size::S64,
|
||||
Location::Imm32(stack_offset as u32),
|
||||
Location::GPR(GPR::RSP),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Emits a tail call trampoline that loads the address of the target import function
|
||||
// from Ctx and jumps to it.
|
||||
|
||||
@ -6260,7 +6359,14 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
false,
|
||||
)[0];
|
||||
self.value_stack.push(ret);
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
match return_types[0] {
|
||||
WpType::F32 | WpType::F64 => {
|
||||
a.emit_mov(Size::S64, Location::XMM(XMM::XMM0), ret);
|
||||
}
|
||||
_ => {
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Operator::CallIndirect { index, table_index } => {
|
||||
@ -6399,7 +6505,14 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
false,
|
||||
)[0];
|
||||
self.value_stack.push(ret);
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
match return_types[0] {
|
||||
WpType::F32 | WpType::F64 => {
|
||||
a.emit_mov(Size::S64, Location::XMM(XMM::XMM0), ret);
|
||||
}
|
||||
_ => {
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Operator::If { ty } => {
|
||||
@ -7614,6 +7727,18 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
self.machine.finalize_locals(a, &self.locals);
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RBP), Location::GPR(GPR::RSP));
|
||||
a.emit_pop(Size::S64, Location::GPR(GPR::RBP));
|
||||
|
||||
// Make a copy of the return value in XMM0, as required by the SysV CC.
|
||||
match self.signature.returns() {
|
||||
[x] if *x == Type::F32 || *x == Type::F64 => {
|
||||
a.emit_mov(
|
||||
Size::S64,
|
||||
Location::GPR(GPR::RAX),
|
||||
Location::XMM(XMM::XMM0),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
a.emit_ret();
|
||||
} else {
|
||||
let released = &self.value_stack[frame.value_stack_depth..];
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-spectests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer spectests library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -9,10 +9,10 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
glob = "0.3"
|
||||
wasmer-runtime = { path = "../runtime", version = "0.15.0", default-features = false}
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.15.0", optional = true}
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.15.0", features = ["test"], optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.15.0", optional = true }
|
||||
wasmer-runtime = { path = "../runtime", version = "0.16.2", default-features = false}
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.16.2", optional = true}
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.16.2", features = ["test"], optional = true }
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.16.2", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.9.1"
|
||||
|
@ -256,6 +256,16 @@ mod tests {
|
||||
Memory, Table,
|
||||
};
|
||||
|
||||
fn format_panic(e: &dyn std::any::Any) -> String {
|
||||
if let Some(s) = e.downcast_ref::<&str>() {
|
||||
format!("{}", s)
|
||||
} else if let Some(s) = e.downcast_ref::<String>() {
|
||||
format!("{}", s)
|
||||
} else {
|
||||
"(unknown)".into()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_and_run(
|
||||
path: &PathBuf,
|
||||
file_excludes: &HashSet<String>,
|
||||
@ -342,7 +352,7 @@ mod tests {
|
||||
file: filename.to_string(),
|
||||
line: line,
|
||||
kind: format!("{}", "Module"),
|
||||
message: format!("caught panic {:?}", e),
|
||||
message: format!("caught panic {}", format_panic(&e)),
|
||||
},
|
||||
&test_key,
|
||||
excludes,
|
||||
@ -798,7 +808,7 @@ mod tests {
|
||||
file: filename.to_string(),
|
||||
line: line,
|
||||
kind: format!("{}", "AssertInvalid"),
|
||||
message: format!("caught panic {:?}", p),
|
||||
message: format!("caught panic {}", format_panic(&p)),
|
||||
},
|
||||
&test_key,
|
||||
excludes,
|
||||
@ -851,7 +861,7 @@ mod tests {
|
||||
file: filename.to_string(),
|
||||
line: line,
|
||||
kind: format!("{}", "AssertMalformed"),
|
||||
message: format!("caught panic {:?}", p),
|
||||
message: format!("caught panic {}", format_panic(&p)),
|
||||
},
|
||||
&test_key,
|
||||
excludes,
|
||||
@ -975,7 +985,7 @@ mod tests {
|
||||
file: filename.to_string(),
|
||||
line: line,
|
||||
kind: format!("{}", "AssertUnlinkable"),
|
||||
message: format!("caught panic {:?}", e),
|
||||
message: format!("caught panic {}", format_panic(&e)),
|
||||
},
|
||||
&test_key,
|
||||
excludes,
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-wasi-experimental-io-devices"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
@ -14,8 +14,8 @@ maintenance = { status = "experimental" }
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
minifb = "0.13"
|
||||
wasmer-wasi = { version = "0.15.0", path = "../wasi" }
|
||||
wasmer-runtime-core = { version = "0.15.0", path = "../runtime-core" }
|
||||
wasmer-wasi = { version = "0.16.2", path = "../wasi" }
|
||||
wasmer-runtime-core = { version = "0.16.2", path = "../runtime-core" }
|
||||
ref_thread_local = "0.0"
|
||||
serde = "1"
|
||||
typetag = "0.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-wasi-tests"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Tests for our WASI implementation"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -10,18 +10,18 @@ build = "build/mod.rs"
|
||||
|
||||
[dependencies]
|
||||
# We set default features to false to be able to use the singlepass backend properly
|
||||
wasmer-runtime = { path = "../runtime", version = "0.15.0", default-features = false }
|
||||
wasmer-wasi = { path = "../wasi", version = "0.15.0" }
|
||||
wasmer-runtime = { path = "../runtime", version = "0.16.2", default-features = false }
|
||||
wasmer-wasi = { path = "../wasi", version = "0.16.2" }
|
||||
# hack to get tests to work
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.15.0", optional = true}
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.15.0", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.15.0", features = ["test"], optional = true }
|
||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.16.2", optional = true}
|
||||
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.16.2", optional = true }
|
||||
wasmer-llvm-backend = { path = "../llvm-backend", version = "0.16.2", features = ["test"], optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
glob = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
wasmer-dev-utils = { path = "../dev-utils", version = "0.15.0"}
|
||||
wasmer-dev-utils = { path = "../dev-utils", version = "0.16.2"}
|
||||
|
||||
[features]
|
||||
clif = ["wasmer-clif-backend", "wasmer-runtime/default-backend-cranelift"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-wasi"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime WASI implementation library"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -19,7 +19,7 @@ getrandom = "0.1"
|
||||
time = "0.1"
|
||||
typetag = "0.1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = "0.3"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-win-exception-handler"
|
||||
version = "0.15.0"
|
||||
version = "0.16.2"
|
||||
description = "Wasmer runtime exception handling for Windows"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
@ -8,7 +8,7 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.15.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.16.2" }
|
||||
winapi = { version = "0.3.8", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
libc = "0.2.60"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
PREVIOUS_VERSION='0.14.1'
|
||||
NEXT_VERSION='0.15.0'
|
||||
PREVIOUS_VERSION='0.16.1'
|
||||
NEXT_VERSION='0.16.2'
|
||||
|
||||
# quick hack
|
||||
fd Cargo.toml --exec sed -i '' "s/version = \"$PREVIOUS_VERSION\"/version = \"$NEXT_VERSION\"/"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 958 KiB After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 12 KiB |
@ -1,6 +1,6 @@
|
||||
[Setup]
|
||||
AppName=Wasmer
|
||||
AppVersion=0.15.0
|
||||
AppVersion=0.16.2
|
||||
DefaultDirName={pf}\Wasmer
|
||||
DefaultGroupName=Wasmer
|
||||
Compression=lzma2
|
||||
@ -23,6 +23,7 @@ Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "WASMER_CACHE_DI
|
||||
[Files]
|
||||
Source: "..\..\target\release\wasmer.exe"; DestDir: "{app}\bin"
|
||||
Source: "..\..\wapm-cli\target\release\wapm.exe"; DestDir: "{app}\bin"
|
||||
Source: "wax.cmd"; DestDir: "{app}\bin"
|
||||
|
||||
[Dirs]
|
||||
Name: "{%USERPROFILE}\.wasmer"
|
||||
|
2
src/installer/wax.cmd
Normal file
2
src/installer/wax.cmd
Normal file
@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
wapm.exe execute %*
|
Loading…
x
Reference in New Issue
Block a user