diff --git a/CHANGELOG.md b/CHANGELOG.md index 746759a84..9d7c23709 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ## **[Unreleased]** -- [#1710](https://github.com/wasmerio/wasmer/pull/1710) Memory for function call trampolines is now owned by the Artifact. +## 1.0.0-alpha5 - 2020-11-06 ### Added @@ -22,15 +22,26 @@ - [#1715](https://github.com/wasmerio/wasmer/pull/1715) Register errors from `wasm_module_serialize` in the Wasm C API. - [#1709](https://github.com/wasmerio/wasmer/pull/1709) Implement `wasm_module_name` and `wasm_module_set_name` in the Wasm(er) C API. - [#1700](https://github.com/wasmerio/wasmer/pull/1700) Implement `wasm_externtype_copy` in the Wasm C API. +- [#1785](https://github.com/wasmerio/wasmer/pull/1785) Add more examples on the Rust API. +- [#1783](https://github.com/wasmerio/wasmer/pull/1783) Handle initialized but empty results in `wasm_func_call` in the Wasm C API. +- [#1780](https://github.com/wasmerio/wasmer/pull/1780) Implement new SIMD zero-extend loads in compiler-llvm. +- [#1754](https://github.com/wasmerio/wasmer/pull/1754) Implement aarch64 ABI for compiler-llvm. +- [#1693](https://github.com/wasmerio/wasmer/pull/1693) Add `wasmer create-exe` subcommand. ### Changed - [#1772](https://github.com/wasmerio/wasmer/pull/1772) Remove lifetime parameter from `NativeFunc`. - [#1762](https://github.com/wasmerio/wasmer/pull/1762) Allow the `=` sign in a WASI environment variable value. +- [#1710](https://github.com/wasmerio/wasmer/pull/1710) Memory for function call trampolines is now owned by the Artifact. +- [#1781](https://github.com/wasmerio/wasmer/pull/1781) Cranelift upgrade to 0.67. +- [#1777](https://github.com/wasmerio/wasmer/pull/1777) Wasmparser update to 0.65. +- [#1775](https://github.com/wasmerio/wasmer/pull/1775) Improve LimitingTunables implementation. +- [#1720](https://github.com/wasmerio/wasmer/pull/1720) Autodetect llvm regardless of architecture. ### Fixed - [#1718](https://github.com/wasmerio/wasmer/pull/1718) Fix panic in the API in some situations when the memory's min bound was greater than the memory's max bound. +- [#1731](https://github.com/wasmerio/wasmer/pull/1731) In compiler-llvm always load before store, to trigger any traps before any bytes are written. ## 1.0.0-alpha4 - 2020-10-08 @@ -43,6 +54,7 @@ - [#1690](https://github.com/wasmerio/wasmer/pull/1690) Fix `wasm_memorytype_limits` where `min` and `max` represents pages, not bytes. Additionally, fixes the max limit sentinel value. - [#1671](https://github.com/wasmerio/wasmer/pull/1671) Fix probestack firing inappropriately, and sometimes over/under allocating stack. - [#1660](https://github.com/wasmerio/wasmer/pull/1660) Fix issue preventing map-dir aliases starting with `/` from working properly. +- [#1624](https://github.com/wasmerio/wasmer/pull/1624) Add Value::I32/Value::I64 converters from unsigned ints. ### Changed - [#1682](https://github.com/wasmerio/wasmer/pull/1682) Improve error reporting when making a memory with invalid settings. diff --git a/Cargo.toml b/Cargo.toml index caafff5a3..1039de538 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-workspace" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer workspace" authors = ["Wasmer Engineering Team "] repository = "https://github.com/wasmerio/wasmer" @@ -10,19 +10,19 @@ publish = false autoexamples = false [dependencies] -wasmer = { version = "1.0.0-alpha4", path = "lib/api", default-features = false } -wasmer-compiler = { version = "1.0.0-alpha4", path = "lib/compiler" } -wasmer-compiler-cranelift = { version = "1.0.0-alpha4", path = "lib/compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "1.0.0-alpha4", path = "lib/compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "1.0.0-alpha4", path = "lib/compiler-llvm", optional = true } -wasmer-engine = { version = "1.0.0-alpha4", path = "lib/engine" } -wasmer-engine-jit = { version = "1.0.0-alpha4", path = "lib/engine-jit", optional = true } -wasmer-engine-native = { version = "1.0.0-alpha4", path = "lib/engine-native", optional = true } -wasmer-engine-object-file = { version = "1.0.0-alpha4", path = "lib/engine-object-file", optional = true } -wasmer-wasi = { version = "1.0.0-alpha4", path = "lib/wasi", optional = true } -wasmer-wast = { version = "1.0.0-alpha4", path = "tests/lib/wast", optional = true } -wasmer-cache = { version = "1.0.0-alpha4", path = "lib/cache", optional = true } -wasmer-types = { version = "1.0.0-alpha4", path = "lib/wasmer-types" } +wasmer = { version = "1.0.0-alpha5", path = "lib/api", default-features = false } +wasmer-compiler = { version = "1.0.0-alpha5", path = "lib/compiler" } +wasmer-compiler-cranelift = { version = "1.0.0-alpha5", path = "lib/compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "1.0.0-alpha5", path = "lib/compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "1.0.0-alpha5", path = "lib/compiler-llvm", optional = true } +wasmer-engine = { version = "1.0.0-alpha5", path = "lib/engine" } +wasmer-engine-jit = { version = "1.0.0-alpha5", path = "lib/engine-jit", optional = true } +wasmer-engine-native = { version = "1.0.0-alpha5", path = "lib/engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha5", path = "lib/engine-object-file", optional = true } +wasmer-wasi = { version = "1.0.0-alpha5", path = "lib/wasi", optional = true } +wasmer-wast = { version = "1.0.0-alpha5", path = "tests/lib/wast", optional = true } +wasmer-cache = { version = "1.0.0-alpha5", path = "lib/cache", optional = true } +wasmer-types = { version = "1.0.0-alpha5", path = "lib/wasmer-types" } cfg-if = "1.0" [workspace] @@ -230,3 +230,18 @@ required-features = ["cranelift"] name = "memory" path = "examples/memory.rs" required-features = ["cranelift"] + +[[example]] +name = "instance" +path = "examples/instance.rs" +required-features = ["cranelift"] + +[[example]] +name = "errors" +path = "examples/errors.rs" +required-features = ["cranelift"] + +[[example]] +name = "imported-function-env" +path = "examples/imports_function_env.rs" +required-features = ["cranelift"] diff --git a/README.md b/README.md index bddeba897..c8224f729 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ qjs > [js logo]: ./assets/languages/js.svg [js integration]: https://github.com/wasmerio/wasmer-js [`@wasmerio` npm packages]: https://www.npmjs.com/org/wasmer -[js docs]: https://docs.wasmer.io/wasmer-js/wasmer-js +[js docs]: https://docs.wasmer.io/integrations/js/reference-api [ruby logo]: ./assets/languages/ruby.svg [ruby integration]: https://github.com/wasmerio/wasmer-ruby diff --git a/examples/README.md b/examples/README.md index 3d107cac5..ab5df2842 100644 --- a/examples/README.md +++ b/examples/README.md @@ -37,6 +37,173 @@ The examples are written in a difficulty/discovery order. Concepts that are explained in an example is not necessarily re-explained in a next example. +### Basics + +1. [**Instantiating a module**][instance], explains the basics of using Wasmer + and how to create an instance out of a Wasm module. + + _Keywords_: instance, module. + +
+ Execute the example + + ```shell + $ cargo run --example instance --release --features "cranelift" + ``` + +
+ +2. [**Handling errors**][errors], explains the basics of interacting with + Wasm module memory. + + _Keywords_: memory, module. + +
+ Execute the example + + ```shell + $ cargo run --example memory --release --features "cranelift" + ``` + +
+ +3. [**Interacting with memory**][memory], explains the basics of interacting with + Wasm module memory. + + _Keywords_: memory, module. + +
+ Execute the example + + ```shell + $ cargo run --example memory --release --features "cranelift" + ``` + +
+ +### Exports + +1. [**Exported global**][exported-global], explains how to work with + exported globals: get/set their value, have information about their + type. + + _Keywords_: export, global. + +
+ Execute the example + + ```shell + $ cargo run --example exported-globals --release --features "cranelift" + ``` + +
+ +2. [**Exported function**][exported-function], explains how to get and + how to call an exported function. They come in 2 flavors: dynamic, + and “static”/native. The pros and cons are discussed briefly. + + _Keywords_: export, function, dynamic, static, native. + +
+ Execute the example + + ```shell + $ cargo run --example exported-function --release --features "cranelift" + ``` + +
+ + +3. [**Exported memory**][exported-memory], explains how to read from + and write to exported memory. + + _Keywords_: export, memory. + +
+ Execute the example + + ```shell + $ cargo run --example exported-memory --release --features "cranelift" + ``` + +
+ +### Imports + +1. [**Imported global**][imported-global], explains how to work with + imported globals: create globals, import them, get/set their value. + + _Keywords_: import, global. + +
+ Execute the example + + ```shell + $ cargo run --example imported-globals --release --features "cranelift" + ``` + +
+ +2. [**Imported function**][imported-function], explains how to define + an imported function. They come in 2 flavors: dynamic, + and “static”/native. + + _Keywords_: import, function, dynamic, static, native. + +
+ Execute the example + + ```shell + $ cargo run --example imported-function --release --features "cranelift" + ``` + +
+ +### Externs + +1. [**Table**][table], explains how to use Wasm Tables from the Wasmer API. + + _Keywords_: basic, table, call_indirect + +
+ Execute the example + + ```shell + $ cargo run --example table --release --features "cranelift" + ``` + +
+ +2. [**Memory**][memory], explains how to use Wasm Memories from + the Wasmer API. Memory example is a work in progress. + + _Keywords_: basic, memory + +
+ Execute the example + + ```shell + $ cargo run --example memory --release --features "cranelift" + ``` + +
+ +### Tunables + +1. **Limit memory**, explains how to use Tunables to limit the + size of an exported Wasm memory + + _Keywords_: basic, tunables, memory + +
+ Execute the example + + ```shell + $ cargo run --example tunables-limit-memory --release --features "cranelift" + ``` + +
+ ### Engines 1. [**JIT engine**][engine-jit], explains what an engine is, what the @@ -107,7 +274,7 @@ example. ### Compilers -5. [**Singlepass compiler**][compiler-singlepass], explains how to use +1. [**Singlepass compiler**][compiler-singlepass], explains how to use the [`wasmer-compiler-singlepass`] compiler. _Keywords_: compiler, singlepass. @@ -121,7 +288,7 @@ example. -6. [**Cranelift compiler**][compiler-cranelift], explains how to use +2. [**Cranelift compiler**][compiler-cranelift], explains how to use the [`wasmer-compiler-cranelift`] compiler. _Keywords_: compiler, cranelift. @@ -135,7 +302,7 @@ example. -7. [**LLVM compiler**][compiler-llvm], explains how to use the +3. [**LLVM compiler**][compiler-llvm], explains how to use the [`wasmer-compiler-llvm`] compiler. _Keywords_: compiler, llvm. @@ -149,133 +316,9 @@ example. -### Exports - -8. [**Exported global**][exported-global], explains how to work with - exported globals: get/set their value, have information about their - type. - - _Keywords_: export, global. - -
- Execute the example - - ```shell - $ cargo run --example exported-globals --release --features "cranelift" - ``` - -
- -9. [**Exported function**][exported-function], explains how to get and - how to call an exported function. They come in 2 flavors: dynamic, - and “static”/native. The pros and cons are discussed briefly. - - _Keywords_: export, function, dynamic, static, native. - -
- Execute the example - - ```shell - $ cargo run --example exported-function --release --features "cranelift" - ``` - -
- - -10. [**Exported memory**][exported-memory], explains how to read from - and write to exported memory. - - _Keywords_: export, memory. - -
- Execute the example - - ```shell - $ cargo run --example exported-memory --release --features "cranelift" - ``` - -
- -### Imports - -11. [**Imported global**][imported-global], explains how to work with - imported globals: create globals, import them, get/set their value. - - _Keywords_: import, global. - -
- Execute the example - - ```shell - $ cargo run --example imported-globals --release --features "cranelift" - ``` - -
- -12. [**Imported function**][imported-function], explains how to define - an imported function. They come in 2 flavors: dynamic, - and “static”/native. - - _Keywords_: import, function, dynamic, static, native. - -
- Execute the example - - ```shell - $ cargo run --example imported-function --release --features "cranelift" - ``` - -
- -### Externs - -13. [**Table**][table], explains how to use Wasm Tables from the Wasmer API. - - _Keywords_: basic, table, call_indirect - -
- Execute the example - - ```shell - $ cargo run --example table --release --features "cranelift" - ``` - -
- -14. [**Memory**][memory], explains how to use Wasm Memories from - the Wasmer API. Memory example is a work in progress. - - _Keywords_: basic, memory - -
- Execute the example - - ```shell - $ cargo run --example memory --release --features "cranelift" - ``` - -
- -### Tunables - -15. **Limit memory**, explains how to use Tunables to limit the - size of an exported Wasm Memories - - _Keywords_: basic, tunables, memory - -
- Execute the example - - ```shell - $ cargo run --example tunables-limit-memory --release --features "cranelift" - ``` - -
- - ### Integrations -16. [**WASI**][wasi], explains how to use the [WebAssembly System +1. [**WASI**][wasi], explains how to use the [WebAssembly System Interface][WASI] (WASI), i.e. the [`wasmer-wasi`] crate. _Keywords_: wasi, system, interface @@ -301,6 +344,7 @@ example. [exported-memory]: ./exports_memory.rs [imported-global]: ./imports_global.rs [imported-function]: ./imports_function.rs +[instance]: ./instance.rs [wasi]: ./wasi.rs [table]: ./table.rs [memory]: ./memory.rs diff --git a/examples/early_exit.rs b/examples/early_exit.rs index 814ab01ff..911fd3d60 100644 --- a/examples/early_exit.rs +++ b/examples/early_exit.rs @@ -1,5 +1,18 @@ -//! This example shows how the host can terminate execution of Wasm early from -//! inside a host function called by the Wasm. +//! There are cases where you may want to interrupt this synchronous execution of the WASM module +//! while the it is calling a host function. This can be useful for saving resources, and not +//! returning back to the guest WASM for execution, when you already know the WASM execution will +//! fail, or no longer be needed. +//! +//! In this example, we will run a WASM module that calls the imported host function +//! interrupt_execution. This host function will immediately stop executing the WebAssembly module. +//! +//! You can run the example directly by executing in Wasmer root: +//! +//! ```shell +//! cargo run --example early-exit --release --features "cranelift" +//! ``` +//! +//! Ready? use anyhow::bail; use std::fmt; @@ -21,12 +34,6 @@ impl fmt::Display for ExitCode { // And then we implement `std::error::Error`. impl std::error::Error for ExitCode {} -// The host function that we'll use to terminate execution. -fn early_exit() { - // This is where it happens. - RuntimeError::raise(Box::new(ExitCode(1))); -} - fn main() -> anyhow::Result<()> { // Let's declare the Wasm module with the text representation. let wasm_bytes = wat2wasm( @@ -44,21 +51,40 @@ fn main() -> anyhow::Result<()> { "#, )?; + // Create a Store. + // Note that we don't need to specify the engine/compiler if we want to use + // the default provided by Wasmer. + // You can use `Store::default()` for that. let store = Store::new(&JIT::new(&Cranelift::default()).engine()); + + println!("Compiling module..."); + // Let's compile the Wasm module. let module = Module::new(&store, wasm_bytes)?; + // We declare the host function that we'll use to terminate execution. + fn early_exit() { + // This is where it happens. + RuntimeError::raise(Box::new(ExitCode(1))); + } + + // Create an import object. let import_object = imports! { "env" => { "early_exit" => Function::new_native(&store, early_exit), } }; + + println!("Instantiating module..."); + // Let's instantiate the Wasm module. let instance = Instance::new(&module, &import_object)?; + // Here we go. + // // Get the `run` function which we'll use as our entrypoint. - let run_func: NativeFunc<(i32, i32), i32> = - instance.exports.get_native_function("run").unwrap(); + println!("Calling `run` function..."); + let run_func: NativeFunc<(i32, i32), i32> = instance.exports.get_native_function("run")?; - // When we call a function it can either succeed or fail. + // When we call a function it can either succeed or fail. We expect it to fail. match run_func.call(1, 7) { Ok(result) => { bail!( @@ -66,12 +92,13 @@ fn main() -> anyhow::Result<()> { result ); } - // We're expecting it to fail. - // We attempt to downcast the error into the error type that we were expecting. + // In case of a failure, which we expect, we attempt to downcast the error into the error + // type that we were expecting. Err(e) => match e.downcast::() { // We found the exit code used to terminate execution. Ok(exit_code) => { println!("Exited early with exit code: {}", exit_code); + Ok(()) } Err(e) => { diff --git a/examples/errors.rs b/examples/errors.rs new file mode 100644 index 000000000..fef46c26f --- /dev/null +++ b/examples/errors.rs @@ -0,0 +1,103 @@ +//! A Wasm module can sometimes be invalid or trigger traps, and in those case we will get +//! an error back from the API. +//! +//! In this example we'll see how to handle such errors in the most +//! basic way. To do that we'll use a Wasm module that we know will +//! produce an error. +//! +//! You can run the example directly by executing in Wasmer root: +//! +//! ```shell +//! cargo run --example errors --release --features "cranelift" +//! ``` +//! +//! Ready? + +use wasmer::{imports, wat2wasm, Instance, Module, Store}; +use wasmer_compiler_cranelift::Cranelift; +use wasmer_engine_jit::JIT; + +fn main() -> Result<(), Box> { + // Let's declare the Wasm module with the text representation. + let wasm_bytes = wat2wasm( + br#" +(module + (type $do_div_by_zero_t (func (result i32))) + (func $do_div_by_zero_f (type $do_div_by_zero_t) (result i32) + i32.const 4 + i32.const 0 + i32.div_s) + + (type $div_by_zero_t (func (result i32))) + (func $div_by_zero_f (type $div_by_zero_t) (result i32) + call $do_div_by_zero_f) + (export "div_by_zero" (func $div_by_zero_f))) +"#, + )?; + + // Create a Store. + // Note that we don't need to specify the engine/compiler if we want to use + // the default provided by Wasmer. + // You can use `Store::default()` for that. + let store = Store::new(&JIT::new(&Cranelift::default()).engine()); + + println!("Compiling module..."); + // Let's compile the Wasm module. + let module = Module::new(&store, wasm_bytes)?; + + // Create an import object. + let import_object = imports! {}; + + println!("Instantiating module..."); + // Let's instantiate the Wasm module. + let instance = Instance::new(&module, &import_object)?; + + // Here we go. + // + // The Wasm module exports a function called `div_by_zero`. As its name + // implies, this function will try to do a division by zero and thus + // produce an error. + // + // Let's get it. + let div_by_zero = instance + .exports + .get_function("div_by_zero")? + .native::<(), i32>()?; + + println!("Calling `div_by_zero` function..."); + // Let's call the `div_by_zero` exported function. + let result = div_by_zero.call(); + + // When we call a function it can either succeed or fail. We expect it to fail. + match result { + Ok(_) => { + // This should have thrown an error, return an error + panic!("div_by_zero did not error"); + } + Err(e) => { + // Log the error + println!("Error caught from `div_by_zero`: {}", e.message()); + + // Errors come with a trace we can inspect to get more + // information on the execution flow. + let frames = e.trace(); + let frames_len = frames.len(); + + for i in 0..frames_len { + println!( + " Frame #{}: {:?}::{:?}", + frames_len - i, + frames[i].module_name(), + frames[i].function_name().or(Some("")).unwrap() + ); + } + } + } + + Ok(()) +} + +#[test] +fn test_exported_function() -> Result<(), Box> { + main() +} diff --git a/examples/exports_function.rs b/examples/exports_function.rs index 941733847..853f36998 100644 --- a/examples/exports_function.rs +++ b/examples/exports_function.rs @@ -72,10 +72,11 @@ fn main() -> Result<(), Box> { println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + let args = [Value::I32(1), Value::I32(2)]; + let result = sum.call(&args)?; - println!("Results: {:?}", results); - assert_eq!(results.to_vec(), vec![Value::I32(3)]); + println!("Results: {:?}", result); + assert_eq!(result.to_vec(), vec![Value::I32(3)]); // That was fun. But what if we can get rid of the `Value`s? Well, // that's possible with the `NativeFunction` API. The function @@ -85,16 +86,16 @@ fn main() -> Result<(), Box> { // `Rets`, respectively for the parameters and the results. If // those values don't match the exported function signature, an // error will be raised. - let sum = sum.native::<(i32, i32), i32>()?; + let sum_native = sum.native::<(i32, i32), i32>()?; println!("Calling `sum` function (natively)..."); // Let's call the `sum` exported function. The parameters are // statically typed Rust values of type `i32` and `i32`. The // result, in this case particular case, in a unit of type `i32`. - let result = sum.call(1, 2)?; + let result = sum_native.call(3, 4)?; println!("Results: {:?}", result); - assert_eq!(result, 3); + assert_eq!(result, 7); // Much nicer, isn't it? // diff --git a/examples/exports_global.rs b/examples/exports_global.rs index 0ad1e9b65..8884a1406 100644 --- a/examples/exports_global.rs +++ b/examples/exports_global.rs @@ -68,16 +68,16 @@ fn main() -> Result<(), Box> { let one = instance.exports.get_global("one")?; let some = instance.exports.get_global("some")?; - println!("Getting global type informations..."); + println!("Getting globals types information..."); // Let's get the globals types. The results are `GlobalType`s. let one_type = one.ty(); let some_type = some.ty(); - println!("one type: {:?} {:?}", one_type.mutability, one_type.ty); + println!("`one` type: {:?} {:?}", one_type.mutability, one_type.ty); assert_eq!(one_type.mutability, Mutability::Const); assert_eq!(one_type.ty, Type::F32); - println!("some type: {:?} {:?}", some_type.mutability, some_type.ty); + println!("`some` type: {:?} {:?}", some_type.mutability, some_type.ty); assert_eq!(some_type.mutability, Mutability::Var); assert_eq!(some_type.ty, Type::F32); @@ -93,14 +93,14 @@ fn main() -> Result<(), Box> { .get_function("get_one")? .native::<(), f32>()?; - let one_result = get_one.call()?; - let some_result = some.get(); + let one_value = get_one.call()?; + let some_value = some.get(); - println!("one value: {:?}", one_result); - assert_eq!(one_result, 1.0); + println!("`one` value: {:?}", one_value); + assert_eq!(one_value, 1.0); - println!("some value: {:?}", some_result); - assert_eq!(some_result, Value::F32(0.0)); + println!("`some` value: {:?}", some_value); + assert_eq!(some_value, Value::F32(0.0)); println!("Setting global values..."); // Trying to set the value of a immutable global (`const`) @@ -112,7 +112,7 @@ fn main() -> Result<(), Box> { ); let one_result = one.get(); - println!("one value after `set`: {:?}", one_result); + println!("`one` value after `set`: {:?}", one_result); assert_eq!(one_result, Value::F32(1.0)); // Setting the values of globals can be done in two ways: @@ -126,12 +126,12 @@ fn main() -> Result<(), Box> { .native::()?; set_some.call(21.0)?; let some_result = some.get(); - println!("some value after `set_some`: {:?}", some_result); + println!("`some` value after `set_some`: {:?}", some_result); assert_eq!(some_result, Value::F32(21.0)); some.set(Value::F32(42.0))?; let some_result = some.get(); - println!("some value after `set`: {:?}", some_result); + println!("`some` value after `set`: {:?}", some_result); assert_eq!(some_result, Value::F32(42.0)); Ok(()) diff --git a/examples/imports_function.rs b/examples/imports_function.rs index 7007b2f4f..56496fefe 100644 --- a/examples/imports_function.rs +++ b/examples/imports_function.rs @@ -70,7 +70,7 @@ fn main() -> Result<(), Box> { } let multiply_native = Function::new_native(&store, multiply); - // Create an empty import object. + // Create an import object. let import_object = imports! { "env" => { "multiply_dynamic" => multiply_dynamic, diff --git a/examples/imports_function_env.rs b/examples/imports_function_env.rs new file mode 100644 index 000000000..88caf3c6e --- /dev/null +++ b/examples/imports_function_env.rs @@ -0,0 +1,129 @@ +//! A Wasm module can import entities, like functions, memories, +//! globals and tables. +//! +//! In this example, we'll create a system for getting and adjusting a counter value. However, host +//! functions are not limited to storing data outside of WASM, they're normal host functions and +//! can do anything that the host can do. +//! +//! 1. There will be a `get_counter` function that will return an i32 of +//! the current global counter, +//! 2. There will be an `add_to_counter` function will add the passed +//! i32 value to the counter, and return an i32 of the current +//! global counter. +//! +//! You can run the example directly by executing in Wasmer root: +//! +//! ```shell +//! cargo run --example imported-function-env --release --features "cranelift" +//! ``` +//! +//! Ready? + +use std::cell::RefCell; +use std::sync::Arc; +use wasmer::{imports, wat2wasm, Function, Instance, Module, Store}; +use wasmer_compiler_cranelift::Cranelift; +use wasmer_engine_jit::JIT; + +fn main() -> Result<(), Box> { + // Let's declare the Wasm module with the text representation. + let wasm_bytes = wat2wasm( + br#" +(module + (func $get_counter (import "env" "get_counter") (result i32)) + (func $add_to_counter (import "env" "add_to_counter") (param i32) (result i32)) + + (type $increment_t (func (param i32) (result i32))) + (func $increment_f (type $increment_t) (param $x i32) (result i32) + (block + (loop + (call $add_to_counter (i32.const 1)) + (set_local $x (i32.sub (get_local $x) (i32.const 1))) + (br_if 1 (i32.eq (get_local $x) (i32.const 0))) + (br 0))) + call $get_counter) + (export "increment_counter_loop" (func $increment_f))) +"#, + )?; + + // Create a Store. + // Note that we don't need to specify the engine/compiler if we want to use + // the default provided by Wasmer. + // You can use `Store::default()` for that. + let store = Store::new(&JIT::new(&Cranelift::default()).engine()); + + println!("Compiling module..."); + // Let's compile the Wasm module. + let module = Module::new(&store, wasm_bytes)?; + + // We create some shared data here, `Arc` is required because we may + // move our WebAssembly instance to another thread to run it. RefCell + // lets us get shared mutabilty which is fine because we know we won't + // run host calls concurrently. If concurrency is a possibilty, we'd have + // to use a `Mutex`. + let shared_counter: Arc> = Arc::new(RefCell::new(0)); + + // Once we have our counter we'll wrap it inside en `Env` which we'll pass + // to our imported functions. + // + // This struct may have been anything. The only constraint is it must be + // possible to know the size of the `Env` at compile time (i.e it has to + // implement the `Sized` trait). + struct Env { + counter: Arc>, + } + + // Create the functions + fn get_counter(env: &mut Env) -> i32 { + *env.counter.borrow() + } + fn add_to_counter(env: &mut Env, add: i32) -> i32 { + let mut counter_ref = env.counter.borrow_mut(); + + *counter_ref += add; + *counter_ref + } + + // Create an import object. + let import_object = imports! { + "env" => { + "get_counter" => Function::new_native_with_env(&store, Env { counter: shared_counter.clone() }, get_counter), + "add_to_counter" => Function::new_native_with_env(&store, Env { counter: shared_counter.clone() }, add_to_counter), + } + }; + + println!("Instantiating module..."); + // Let's instantiate the Wasm module. + let instance = Instance::new(&module, &import_object)?; + + // Here we go. + // + // The Wasm module exports a function called `increment_counter_loop`. Let's get it. + let increment_counter_loop = instance + .exports + .get_function("increment_counter_loop")? + .native::()?; + + let counter_value: i32 = *shared_counter.borrow(); + println!("Initial ounter value: {:?}", counter_value); + + println!("Calling `increment_counter_loop` function..."); + // Let's call the `increment_counter_loop` exported function. + // + // It will loop five times thus incrementing our counter five times. + let result = increment_counter_loop.call(5)?; + + let counter_value: i32 = *shared_counter.borrow(); + println!("New counter value (host): {:?}", counter_value); + assert_eq!(counter_value, 5); + + println!("New counter value (guest): {:?}", counter_value); + assert_eq!(result, 5); + + Ok(()) +} + +#[test] +fn test_imported_function_env() -> Result<(), Box> { + main() +} diff --git a/examples/instance.rs b/examples/instance.rs new file mode 100644 index 000000000..9adc7910c --- /dev/null +++ b/examples/instance.rs @@ -0,0 +1,80 @@ +//! Wasmer will let you easily run Wasm module in a Rust host. +//! +//! This example illustrates the basics of using Wasmer through a "Hello World"-like project: +//! +//! 1. How to load a Wasm modules as bytes +//! 2. How to compile the module +//! 3. How to create an instance of the module +//! +//! You can run the example directly by executing in Wasmer root: +//! +//! ```shell +//! cargo run --example instance --release --features "cranelift" +//! ``` +//! +//! Ready? + +use wasmer::{imports, wat2wasm, Instance, Module, Store}; +use wasmer_compiler_cranelift::Cranelift; +use wasmer_engine_jit::JIT; + +fn main() -> Result<(), Box> { + // Let's declare the Wasm module. + // + // We are using the text representation of the module here but you can also load `.wasm` + // files using the `include_bytes!` macro. + let wasm_bytes = wat2wasm( + br#" +(module + (type $add_one_t (func (param i32) (result i32))) + (func $add_one_f (type $add_one_t) (param $value i32) (result i32) + local.get $value + i32.const 1 + i32.add) + (export "add_one" (func $add_one_f))) +"#, + )?; + + // Create a Store. + // Note that we don't need to specify the engine/compiler if we want to use + // the default provided by Wasmer. + // You can use `Store::default()` for that. + let store = Store::new(&JIT::new(&Cranelift::default()).engine()); + + println!("Compiling module..."); + // Let's compile the Wasm module. + let module = Module::new(&store, wasm_bytes)?; + + // Create an empty import object. + let import_object = imports! {}; + + println!("Instantiating module..."); + // Let's instantiate the Wasm module. + let instance = Instance::new(&module, &import_object)?; + + // We now have an instance ready to be used. + // + // From an `Instance` we can retrieve any exported entities. + // Each of these entities is covered in others examples. + // + // Here we are retrieving the exported function. We won't go into details here + // as the main focus of this example is to show how to create an instance out + // of a Wasm module and have basic interactions with it. + let add_one = instance + .exports + .get_function("add_one")? + .native::()?; + + println!("Calling `add_one` function..."); + let result = add_one.call(1)?; + + println!("Results of `add_one`: {:?}", result); + assert_eq!(result, 2); + + Ok(()) +} + +#[test] +fn test_exported_function() -> Result<(), Box> { + main() +} diff --git a/examples/memory.rs b/examples/memory.rs index 9da6d8131..d78b6dda5 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -1,4 +1,21 @@ -use wasmer::{imports, wat2wasm, Instance, Module, NativeFunc, Pages, Store}; +//! With Wasmer you'll be able to interact with guest module memory. +//! +//! This example illustrates the basics of interacting with Wasm module memory.: +//! +//! 1. How to load a Wasm modules as bytes +//! 2. How to compile the module +//! 3. How to create an instance of the module +//! +//! You can run the example directly by executing in Wasmer root: +//! +//! ```shell +//! cargo run --example memory --release --features "cranelift" +//! ``` +//! +//! Ready? + +use std::mem; +use wasmer::{imports, wat2wasm, Bytes, Instance, Module, NativeFunc, Pages, Store}; use wasmer_compiler_cranelift::Cranelift; use wasmer_engine_jit::JIT; @@ -6,6 +23,10 @@ use wasmer_engine_jit::JIT; // TODO: clean it up and comment it https://github.com/wasmerio/wasmer/issues/1749 fn main() -> anyhow::Result<()> { + // Let's declare the Wasm module. + // + // We are using the text representation of the module here but you can also load `.wasm` + // files using the `include_bytes!` macro. let wasm_bytes = wat2wasm( r#" (module @@ -32,48 +53,87 @@ fn main() -> anyhow::Result<()> { .as_bytes(), )?; - // We set up our store with an engine and a compiler. + // Create a Store. + // Note that we don't need to specify the engine/compiler if we want to use + // the default provided by Wasmer. + // You can use `Store::default()` for that. let store = Store::new(&JIT::new(&Cranelift::default()).engine()); - // Then compile our Wasm. + + println!("Compiling module..."); + // Let's compile the Wasm module. let module = Module::new(&store, wasm_bytes)?; + + // Create an empty import object. let import_object = imports! {}; - // And instantiate it with no imports. + + println!("Instantiating module..."); + // Let's instantiate the Wasm module. let instance = Instance::new(&module, &import_object)?; + // The module exports some utility functions, let's get them. + // + // These function will be used later in this example. let mem_size: NativeFunc<(), i32> = instance.exports.get_native_function("mem_size")?; let get_at: NativeFunc = instance.exports.get_native_function("get_at")?; let set_at: NativeFunc<(i32, i32), ()> = instance.exports.get_native_function("set_at")?; let memory = instance.exports.get_memory("memory")?; - let mem_addr = 0x2220; - let val = 0xFEFEFFE; - + // We now have an instance ready to be used. + // + // We will start by querying the most intersting information + // about the memory: its size. There are mainly two ways of getting + // this: + // * the size as a number of `Page`s + // * the size as a number of bytes + // + // The size in bytes can be found either by querying its pages or by + // querying the memory directly. + println!("Querying memory size..."); assert_eq!(memory.size(), Pages::from(1)); + assert_eq!(memory.size().bytes(), Bytes::from(65536 as usize)); + assert_eq!(memory.data_size(), 65536); + + // Sometimes, the guest module may also export a function to let you + // query the memory. Here we have a `mem_size` function, let's try it: + let result = mem_size.call()?; + println!("Memory size: {:?}", result); + assert_eq!(Pages::from(result as u32), memory.size()); + + // Now that we know the size of our memory, it's time to see how wa + // can change this. + // + // A memory can be grown to allow storing more things into it. Let's + // see how we can do that: + println!("Growing memory..."); + // Here we are requesting two more pages for our memory. memory.grow(2)?; assert_eq!(memory.size(), Pages::from(3)); - let result = mem_size.call()?; - assert_eq!(result, 3); + assert_eq!(memory.data_size(), 65536 * 3); - // ------------- + // Now that we know how to query and adjust the size of the memory, + // let's see how wa can write to it or read from it. + // + // We'll only focus on how to do this using exported functions, the goal + // is to show how to work with memory addresses. Here we'll use absolute + // addresses to write and read a value. + let mem_addr = 0x2220; + let val = 0xFEFEFFE; set_at.call(mem_addr, val)?; - // ------------- - let page_size = 0x1_0000; - let result = get_at.call(page_size * 3 - 4)?; - memory.grow(1025)?; - assert_eq!(result, 123456); - assert_eq!(memory.size(), Pages::from(1028)); - set_at.call(page_size * 1027 - 4, 123456)?; - let result = get_at.call(page_size * 1027 - 4)?; - assert_eq!(result, 123456); - set_at.call(1024, 123456)?; - let result = get_at.call(1024)?; - assert_eq!(result, 123456); - - // ------------- let result = get_at.call(mem_addr)?; + println!("Value at {:#x?}: {:?}", mem_addr, result); + assert_eq!(result, val); + + // Now instead of using hard coded memory addresses, let's try to write + // something at the end of the second memory page and read it. + let page_size = 0x1_0000; + let mem_addr = (page_size * 2) - mem::size_of_val(&val) as i32; + let val = 0xFEA09; + set_at.call(mem_addr, val)?; + + let result = get_at.call(mem_addr)?; + println!("Value at {:#x?}: {:?}", mem_addr, result); assert_eq!(result, val); - // ------------- Ok(()) } diff --git a/examples/tunables_limit_memory.rs b/examples/tunables_limit_memory.rs index dfe5f40cd..c87f371bc 100644 --- a/examples/tunables_limit_memory.rs +++ b/examples/tunables_limit_memory.rs @@ -16,7 +16,7 @@ use wasmer_engine_jit::JIT; /// After adjusting the memory limits, it delegates all other logic /// to the base tunables. pub struct LimitingTunables { - /// The maxium a linear memory is allowed to be (in Wasm pages, 65 KiB each). + /// The maximum a linear memory is allowed to be (in Wasm pages, 64 KiB each). /// Since Wasmer ensures there is only none or one memory, this is practically /// an upper limit for the guest memory. limit: Pages, diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 06ab6963e..2b364806e 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "High-performant WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "runtime", "vm"] @@ -11,15 +11,15 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "1.0.0-alpha4", optional = true } -wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "1.0.0-alpha4", optional = true } -wasmer-compiler-llvm = { path = "../compiler-llvm", version = "1.0.0-alpha4", optional = true } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } -wasmer-engine-jit = { path = "../engine-jit", version = "1.0.0-alpha4", optional = true } -wasmer-engine-native = { path = "../engine-native", version = "1.0.0-alpha4", optional = true } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "1.0.0-alpha5", optional = true } +wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "1.0.0-alpha5", optional = true } +wasmer-compiler-llvm = { path = "../compiler-llvm", version = "1.0.0-alpha5", optional = true } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha5" } +wasmer-engine-jit = { path = "../engine-jit", version = "1.0.0-alpha5", optional = true } +wasmer-engine-native = { path = "../engine-native", version = "1.0.0-alpha5", optional = true } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } indexmap = { version = "1.4", features = ["serde-1"] } cfg-if = "0.1" wat = { version = "1.0", optional = true } diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index b594a0f74..b7b5f4e1c 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-c-api" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer C API library" categories = ["wasm", "api-bindings"] keywords = ["wasm", "webassembly", "runtime"] @@ -15,18 +15,18 @@ edition = "2018" crate-type = ["cdylib", "rlib", "staticlib"] [dependencies] -wasmer = { version = "1.0.0-alpha4", path = "../api", default-features = false } -wasmer-compiler = { version = "1.0.0-alpha4", path = "../compiler" } -wasmer-compiler-cranelift = { version = "1.0.0-alpha4", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "1.0.0-alpha4", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "1.0.0-alpha4", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "1.0.0-alpha4", path = "../emscripten", optional = true } -wasmer-engine = { version = "1.0.0-alpha4", path = "../engine" } -wasmer-engine-jit = { version = "1.0.0-alpha4", path = "../engine-jit", optional = true } -wasmer-engine-native = { version = "1.0.0-alpha4", path = "../engine-native", optional = true } -wasmer-engine-object-file = { version = "1.0.0-alpha4", path = "../engine-object-file", optional = true } -wasmer-wasi = { version = "1.0.0-alpha4", path = "../wasi", optional = true } -wasmer-types = { version = "1.0.0-alpha4", path = "../wasmer-types" } +wasmer = { version = "1.0.0-alpha5", path = "../api", default-features = false } +wasmer-compiler = { version = "1.0.0-alpha5", path = "../compiler" } +wasmer-compiler-cranelift = { version = "1.0.0-alpha5", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "1.0.0-alpha5", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "1.0.0-alpha5", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "1.0.0-alpha5", path = "../emscripten", optional = true } +wasmer-engine = { version = "1.0.0-alpha5", path = "../engine" } +wasmer-engine-jit = { version = "1.0.0-alpha5", path = "../engine-jit", optional = true } +wasmer-engine-native = { version = "1.0.0-alpha5", path = "../engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha5", path = "../engine-object-file", optional = true } +wasmer-wasi = { version = "1.0.0-alpha5", path = "../wasi", optional = true } +wasmer-types = { version = "1.0.0-alpha5", path = "../wasmer-types" } cfg-if = "0.1" lazy_static = "1" libc = { version = "^0.2", default-features = false } @@ -37,7 +37,7 @@ typetag = { version = "0.1", optional = true } paste = "0.1" # for generating code in the same way thot the wasm-c-api does # Commented out for now until we can find a solution to the exported function problem -# wasmer-wasm-c-api = { version = "1.0.0-alpha4", path = "crates/wasm-c-api" } +# wasmer-wasm-c-api = { version = "1.0.0-alpha5", path = "crates/wasm-c-api" } [dev-dependencies] inline-c = "0.1" diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 35e468286..70e9e93cf 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -154,18 +154,34 @@ pub unsafe extern "C" fn wasm_func_call( .into_iter() .map(TryInto::try_into) .collect::, _>>() - .expect("Argument conversion failed") + .expect("Arguments conversion failed") }) .unwrap_or_default(); match func.inner.call(¶ms) { Ok(wasm_results) => { - *results = wasm_results + let vals = wasm_results .into_iter() .map(TryInto::try_into) .collect::, _>>() - .expect("Argument conversion failed") - .into(); + .expect("Results conversion failed"); + + // `results` is an uninitialized vector. Set a new value. + if results.is_uninitialized() { + *results = vals.into(); + } + // `results` is an initialized but empty vector. Fill it + // item per item. + else { + let slice = results + .into_slice_mut() + .expect("`wasm_func_call`, results' size is greater than 0 but data is NULL"); + + for (result, value) in slice.iter_mut().zip(vals.iter()) { + (*result).kind = value.kind; + (*result).of = value.of; + } + } None } diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 7e3729780..ffd95b701 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -57,12 +57,24 @@ macro_rules! wasm_declare_vec { impl [] { pub unsafe fn into_slice(&self) -> Option<&[[]]>{ - if self.data.is_null() { + if self.is_uninitialized() { return None; } Some(::std::slice::from_raw_parts(self.data, self.size)) } + + pub unsafe fn into_slice_mut(&mut self) -> Option<&mut [[]]>{ + if self.is_uninitialized() { + return None; + } + + Some(::std::slice::from_raw_parts_mut(self.data, self.size)) + } + + pub fn is_uninitialized(&self) -> bool { + self.data.is_null() + } } // TODO: investigate possible memory leak on `init` (owned pointer) diff --git a/lib/c-api/tests/wasm_c_api/CMakeLists.txt b/lib/c-api/tests/wasm_c_api/CMakeLists.txt index d725c5a4f..98c39b49f 100644 --- a/lib/c-api/tests/wasm_c_api/CMakeLists.txt +++ b/lib/c-api/tests/wasm_c_api/CMakeLists.txt @@ -4,10 +4,10 @@ project (WasmerWasmCApiTests) # Examples as tests from the `wasm-c-api` repository. add_executable(wasm-c-api-callback wasm-c-api/example/callback.c) #add_executable(wasm-c-api-finalize wasm-c-api/example/finalize.c) -#add_executable(wasm-c-api-global wasm-c-api/example/global.c) +add_executable(wasm-c-api-global wasm-c-api/example/global.c) add_executable(wasm-c-api-hello wasm-c-api/example/hello.c) #add_executable(wasm-c-api-hostref wasm-c-api/example/hostref.c) -#add_executable(wasm-c-api-memory wasm-c-api/example/memory.c) +add_executable(wasm-c-api-memory wasm-c-api/example/memory.c) #add_executable(wasm-c-api-multi wasm-c-api/example/multi.c) add_executable(wasm-c-api-reflect wasm-c-api/example/reflect.c) add_executable(wasm-c-api-serialize wasm-c-api/example/serialize.c) @@ -57,12 +57,12 @@ add_test(NAME wasm-c-api-callback # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ #) -#target_link_libraries(wasm-c-api-global general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-global PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-global -# COMMAND wasm-c-api-global -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) +target_link_libraries(wasm-c-api-global general ${WASMER_LIB}) +target_compile_options(wasm-c-api-global PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-global + COMMAND wasm-c-api-global + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) target_link_libraries(wasm-c-api-hello general ${WASMER_LIB}) target_compile_options(wasm-c-api-hello PRIVATE ${COMPILER_OPTIONS}) @@ -78,12 +78,12 @@ add_test(NAME wasm-c-api-hello # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ #) -#target_link_libraries(wasm-c-api-memory general ${WASMER_LIB}) -#target_compile_options(wasm-c-api-memory PRIVATE ${COMPILER_OPTIONS}) -#add_test(NAME wasm-c-api-memory -# COMMAND wasm-c-api-memory -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ -#) +target_link_libraries(wasm-c-api-memory general ${WASMER_LIB}) +target_compile_options(wasm-c-api-memory PRIVATE ${COMPILER_OPTIONS}) +add_test(NAME wasm-c-api-memory + COMMAND wasm-c-api-memory + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wasm-c-api/example/ +) #target_link_libraries(wasm-c-api-multi general ${WASMER_LIB}) #target_compile_options(wasm-c-api-multi PRIVATE ${COMPILER_OPTIONS}) diff --git a/lib/cache/Cargo.toml b/lib/cache/Cargo.toml index 584460397..394d87ca9 100644 --- a/lib/cache/Cargo.toml +++ b/lib/cache/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-cache" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Cache system for Wasmer WebAssembly runtime" categories = ["wasm", "caching"] keywords = ["wasm", "webassembly", "cache"] @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer = { path = "../api", version = "1.0.0-alpha4", default-features = false } +wasmer = { path = "../api", version = "1.0.0-alpha5", default-features = false } memmap = "0.7" hex = "0.4" thiserror = "1" diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index 8157c9f95..b734ca0cc 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-cli" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer CLI" categories = ["wasm", "command-line-interface"] keywords = ["wasm", "webassembly", "cli"] @@ -17,22 +17,22 @@ path = "src/bin/wasmer.rs" doc = false [dependencies] -wasmer = { version = "1.0.0-alpha4", path = "../api", default-features = false } -wasmer-compiler = { version = "1.0.0-alpha4", path = "../compiler" } -wasmer-compiler-cranelift = { version = "1.0.0-alpha4", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "1.0.0-alpha4", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "1.0.0-alpha4", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "1.0.0-alpha4", path = "../emscripten", optional = true } -wasmer-engine = { version = "1.0.0-alpha4", path = "../engine" } -wasmer-engine-jit = { version = "1.0.0-alpha4", path = "../engine-jit", optional = true } -wasmer-engine-native = { version = "1.0.0-alpha4", path = "../engine-native", optional = true } -wasmer-engine-object-file = { version = "1.0.0-alpha4", path = "../engine-object-file", optional = true } -wasmer-vm = { version = "1.0.0-alpha4", path = "../vm" } -wasmer-wasi = { version = "1.0.0-alpha4", path = "../wasi", optional = true } -wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha4", path = "../wasi-experimental-io-devices", optional = true } -wasmer-wast = { version = "1.0.0-alpha4", path = "../../tests/lib/wast", optional = true } -wasmer-cache = { version = "1.0.0-alpha4", path = "../cache", optional = true } -wasmer-types = { version = "1.0.0-alpha4", path = "../wasmer-types" } +wasmer = { version = "1.0.0-alpha5", path = "../api", default-features = false } +wasmer-compiler = { version = "1.0.0-alpha5", path = "../compiler" } +wasmer-compiler-cranelift = { version = "1.0.0-alpha5", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "1.0.0-alpha5", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "1.0.0-alpha5", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "1.0.0-alpha5", path = "../emscripten", optional = true } +wasmer-engine = { version = "1.0.0-alpha5", path = "../engine" } +wasmer-engine-jit = { version = "1.0.0-alpha5", path = "../engine-jit", optional = true } +wasmer-engine-native = { version = "1.0.0-alpha5", path = "../engine-native", optional = true } +wasmer-engine-object-file = { version = "1.0.0-alpha5", path = "../engine-object-file", optional = true } +wasmer-vm = { version = "1.0.0-alpha5", path = "../vm" } +wasmer-wasi = { version = "1.0.0-alpha5", path = "../wasi", optional = true } +wasmer-wasi-experimental-io-devices = { version = "1.0.0-alpha5", path = "../wasi-experimental-io-devices", optional = true } +wasmer-wast = { version = "1.0.0-alpha5", path = "../../tests/lib/wast", optional = true } +wasmer-cache = { version = "1.0.0-alpha5", path = "../cache", optional = true } +wasmer-types = { version = "1.0.0-alpha5", path = "../wasmer-types" } atty = "0.2" colored = "2.0" anyhow = "1.0" diff --git a/lib/compiler-cranelift/Cargo.toml b/lib/compiler-cranelift/Cargo.toml index 469a18c80..a32658c91 100644 --- a/lib/compiler-cranelift/Cargo.toml +++ b/lib/compiler-cranelift/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-cranelift" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Cranelift compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "cranelift"] @@ -12,9 +12,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5", features = ["translator"], default-features = false } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5", default-features = false, features = ["std"] } cranelift-codegen = { version = "0.67", default-features = false, features = ["x86", "arm64"] } cranelift-frontend = { version = "0.67", default-features = false } tracing = "0.1" diff --git a/lib/compiler-llvm/Cargo.toml b/lib/compiler-llvm/Cargo.toml index e5d7ca030..d4e72f50a 100644 --- a/lib/compiler-llvm/Cargo.toml +++ b/lib/compiler-llvm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-llvm" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "LLVM compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "llvm"] @@ -12,9 +12,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"] } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5", features = ["translator"] } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } target-lexicon = { version = "0.11", default-features = false } smallvec = "1" goblin = "0.2" diff --git a/lib/compiler-singlepass/Cargo.toml b/lib/compiler-singlepass/Cargo.toml index 33a595c92..abf006743 100644 --- a/lib/compiler-singlepass/Cargo.toml +++ b/lib/compiler-singlepass/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-singlepass" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Singlepass compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "singlepass"] @@ -12,9 +12,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5", features = ["translator"], default-features = false } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5", default-features = false, features = ["std"] } rayon = "1.5" hashbrown = { version = "0.9", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/lib/compiler/Cargo.toml b/lib/compiler/Cargo.toml index fcb5ab66f..64339fb9a 100644 --- a/lib/compiler/Cargo.toml +++ b/lib/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Base compiler abstraction for Wasmer WebAssembly runtime" categories = ["wasm", "no-std"] keywords = ["wasm", "webassembly", "compiler"] @@ -11,8 +11,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5", default-features = false } wasmparser = { version = "0.65", optional = true, default-features = false } target-lexicon = { version = "0.11", default-features = false } enumset = "1.0" diff --git a/lib/deprecated/runtime-core/Cargo.toml b/lib/deprecated/runtime-core/Cargo.toml index 603e56a5b..12d26452c 100644 --- a/lib/deprecated/runtime-core/Cargo.toml +++ b/lib/deprecated/runtime-core/Cargo.toml @@ -14,16 +14,16 @@ edition = "2018" maintenance = { status = "deprecated" } [dependencies] -wasmer-types = { path = "../../wasmer-types", version = "1.0.0-alpha4" } -wasmer = { path = "../../api", version = "1.0.0-alpha4" } -wasmer-cache = { path = "../../cache", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../../compiler", version = "1.0.0-alpha4", features = ["translator"] } -wasmer-compiler-llvm = { path = "../../compiler-llvm", version = "1.0.0-alpha4", optional = true } -wasmer-compiler-cranelift = { path = "../../compiler-cranelift", version = "1.0.0-alpha4", optional = true } -wasmer-compiler-singlepass = { path = "../../compiler-singlepass", version = "1.0.0-alpha4", optional = true } -wasmer-engine = { path = "../../engine", version = "1.0.0-alpha4" } -wasmer-engine-jit = { path = "../../engine-jit", version = "1.0.0-alpha4" } -wasmer-vm = { path = "../../vm", version = "1.0.0-alpha4" } +wasmer-types = { path = "../../wasmer-types", version = "1.0.0-alpha5" } +wasmer = { path = "../../api", version = "1.0.0-alpha5" } +wasmer-cache = { path = "../../cache", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../../compiler", version = "1.0.0-alpha5", features = ["translator"] } +wasmer-compiler-llvm = { path = "../../compiler-llvm", version = "1.0.0-alpha5", optional = true } +wasmer-compiler-cranelift = { path = "../../compiler-cranelift", version = "1.0.0-alpha5", optional = true } +wasmer-compiler-singlepass = { path = "../../compiler-singlepass", version = "1.0.0-alpha5", optional = true } +wasmer-engine = { path = "../../engine", version = "1.0.0-alpha5" } +wasmer-engine-jit = { path = "../../engine-jit", version = "1.0.0-alpha5" } +wasmer-vm = { path = "../../vm", version = "1.0.0-alpha5" } lazy_static = "1.4" [build-dependencies] diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 3d6616b03..f6989a7bd 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-emscripten" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Emscripten implementation library for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "abi", "emscripten", "posix"] @@ -16,7 +16,7 @@ lazy_static = "1.4" libc = "^0.2" log = "0.4" time = "0.1" -wasmer = { path = "../api", version = "1.0.0-alpha4", default-features = false } +wasmer = { path = "../api", version = "1.0.0-alpha5", default-features = false } [target.'cfg(windows)'.dependencies] getrandom = "0.2" diff --git a/lib/engine-jit/Cargo.toml b/lib/engine-jit/Cargo.toml index 7c0726b6b..8637422a2 100644 --- a/lib/engine-jit/Cargo.toml +++ b/lib/engine-jit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-jit" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer JIT Engine" categories = ["wasm"] keywords = ["wasm", "webassembly", "engine", "jit"] @@ -11,10 +11,10 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"] } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5", features = ["translator"] } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha5" } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } region = "2.2" serde = { version = "1.0", features = ["derive", "rc"] } diff --git a/lib/engine-native/Cargo.toml b/lib/engine-native/Cargo.toml index 1ee178f85..9840dcdd4 100644 --- a/lib/engine-native/Cargo.toml +++ b/lib/engine-native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-native" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer Native Engine" categories = ["wasm"] keywords = ["wasm", "webassembly", "engine", "native"] @@ -11,11 +11,11 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } -wasmer-object = { path = "../object", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha5" } +wasmer-object = { path = "../object", version = "1.0.0-alpha5" } serde = { version = "1.0", features = ["derive", "rc"] } cfg-if = "0.1" tracing = "0.1" diff --git a/lib/engine-object-file/Cargo.toml b/lib/engine-object-file/Cargo.toml index e1e414903..d41edbb99 100644 --- a/lib/engine-object-file/Cargo.toml +++ b/lib/engine-object-file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-object-file" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" authors = ["Wasmer Engineering Team "] description = "Wasmer Object File Engine" categories = ["wasm"] @@ -11,11 +11,11 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha01.0" } -wasmer-engine = { path = "../engine", version = "1.0.0-alpha4" } -wasmer-object = { path = "../object", version = "1.0.0-alpha4" } +wasmer-engine = { path = "../engine", version = "1.0.0-alpha5" } +wasmer-object = { path = "../object", version = "1.0.0-alpha5" } serde = { version = "1.0", features = ["derive", "rc"] } cfg-if = "0.1" tracing = "0.1" diff --git a/lib/engine/Cargo.toml b/lib/engine/Cargo.toml index f8eb02c67..e48f48e92 100644 --- a/lib/engine/Cargo.toml +++ b/lib/engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer Engine abstraction" categories = ["wasm"] keywords = ["wasm", "webassembly", "engine"] @@ -11,9 +11,9 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } -wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5" } +wasmer-vm = { path = "../vm", version = "1.0.0-alpha5" } target-lexicon = { version = "0.11", default-features = false } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } backtrace = "0.3" diff --git a/lib/object/Cargo.toml b/lib/object/Cargo.toml index b162366c7..67795fcc2 100644 --- a/lib/object/Cargo.toml +++ b/lib/object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-object" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer Native Object generator" categories = ["wasm"] keywords = ["wasm", "webassembly"] @@ -11,8 +11,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", default-features = false, features = [ +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha5", default-features = false, features = [ "std", "translator" ] } diff --git a/lib/vm/Cargo.toml b/lib/vm/Cargo.toml index e2a5d2ff7..c00667b16 100644 --- a/lib/vm/Cargo.toml +++ b/lib/vm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-vm" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Runtime library support for Wasmer" categories = ["wasm"] keywords = ["wasm", "webassembly"] @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } +wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha5" } region = "2.2" libc = { version = "^0.2", default-features = false } memoffset = "0.5" diff --git a/lib/vm/src/global.rs b/lib/vm/src/global.rs index b033acab8..bdf65af63 100644 --- a/lib/vm/src/global.rs +++ b/lib/vm/src/global.rs @@ -69,11 +69,11 @@ impl Global { unsafe { let definition = &*self.vm_global_definition.get(); match self.ty().ty { - Type::I32 => Value::I32(*definition.as_i32()), - Type::I64 => Value::I64(*definition.as_i64()), - Type::F32 => Value::F32(*definition.as_f32()), - Type::F64 => Value::F64(*definition.as_f64()), - Type::V128 => Value::V128(*definition.as_u128()), + Type::I32 => Value::I32(definition.to_i32()), + Type::I64 => Value::I64(definition.to_i64()), + Type::F32 => Value::F32(definition.to_f32()), + Type::F64 => Value::F64(definition.to_f64()), + Type::V128 => Value::V128(definition.to_u128()), _ => unimplemented!("Global::get for {:?}", self.ty), } } @@ -111,7 +111,7 @@ impl Global { Value::I64(i) => *definition.as_i64_mut() = i, Value::F32(f) => *definition.as_f32_mut() = f, Value::F64(f) => *definition.as_f64_mut() = f, - Value::V128(x) => *definition.as_u128_bits_mut() = x.to_ne_bytes(), + Value::V128(x) => *definition.as_bytes_mut() = x.to_ne_bytes(), _ => unimplemented!("Global::set for {:?}", val.ty()), } Ok(()) diff --git a/lib/vm/src/instance.rs b/lib/vm/src/instance.rs index f3d4ce027..de21f1ae9 100644 --- a/lib/vm/src/instance.rs +++ b/lib/vm/src/instance.rs @@ -1179,9 +1179,9 @@ fn get_memory_init_start(init: &DataInitializer<'_>, instance: &Instance) -> usi if let Some(base) = init.location.base { let val = unsafe { if let Some(def_index) = instance.module.local_global_index(base) { - *instance.global(def_index).as_u32() + instance.global(def_index).to_u32() } else { - *instance.imported_global(base).definition.as_ref().as_u32() + instance.imported_global(base).definition.as_ref().to_u32() } }; start += usize::try_from(val).unwrap(); @@ -1232,9 +1232,9 @@ fn get_table_init_start(init: &TableInitializer, instance: &Instance) -> usize { if let Some(base) = init.base { let val = unsafe { if let Some(def_index) = instance.module.local_global_index(base) { - *instance.global(def_index).as_u32() + instance.global(def_index).to_u32() } else { - *instance.imported_global(base).definition.as_ref().as_u32() + instance.imported_global(base).definition.as_ref().to_u32() } }; start += usize::try_from(val).unwrap(); @@ -1333,7 +1333,7 @@ fn initialize_globals(instance: &Instance) { GlobalInit::I64Const(x) => *(*to).as_i64_mut() = *x, GlobalInit::F32Const(x) => *(*to).as_f32_mut() = *x, GlobalInit::F64Const(x) => *(*to).as_f64_mut() = *x, - GlobalInit::V128Const(x) => *(*to).as_u128_bits_mut() = *x.bytes(), + GlobalInit::V128Const(x) => *(*to).as_bytes_mut() = *x.bytes(), GlobalInit::GetGlobal(x) => { let from: VMGlobalDefinition = if let Some(def_x) = module.local_global_index(*x) { diff --git a/lib/vm/src/libcalls.rs b/lib/vm/src/libcalls.rs index 986744d3c..5267d35a6 100644 --- a/lib/vm/src/libcalls.rs +++ b/lib/vm/src/libcalls.rs @@ -385,7 +385,8 @@ pub unsafe extern "C" fn wasmer_data_drop(vmctx: *mut VMContext, data_index: u32 /// /// # Safety /// -/// To be defined (TODO) +/// Only safe to call when wasm code is on the stack, aka `wasmer_call` or +/// `wasmer_call_trampoline` must have been previously called. #[no_mangle] pub unsafe extern "C" fn wasmer_raise_trap(trap_code: TrapCode) -> ! { let trap = Trap::new_from_runtime(trap_code); diff --git a/lib/vm/src/vmcontext.rs b/lib/vm/src/vmcontext.rs index b9eef67c7..43bdcd59d 100644 --- a/lib/vm/src/vmcontext.rs +++ b/lib/vm/src/vmcontext.rs @@ -11,6 +11,7 @@ use crate::table::Table; use crate::trap::{Trap, TrapCode}; use std::any::Any; use std::convert::TryFrom; +use std::fmt; use std::ptr::{self, NonNull}; use std::sync::Arc; use std::u32; @@ -454,6 +455,34 @@ mod test_vmtable_definition { } } +/// A typesafe wrapper around the storage for a global variables. +/// +/// # Safety +/// +/// Accessing the different members of this union is always safe because there +/// are no invalid values for any of the types and the whole object is +/// initialized by VMGlobalDefinition::new(). +#[derive(Clone, Copy)] +#[repr(C, align(16))] +pub union VMGlobalDefinitionStorage { + as_i32: i32, + as_u32: u32, + as_f32: f32, + as_i64: i64, + as_u64: u64, + as_f64: f64, + as_u128: u128, + bytes: [u8; 16], +} + +impl fmt::Debug for VMGlobalDefinitionStorage { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("VMGlobalDefinitionStorage") + .field("bytes", unsafe { &self.bytes }) + .finish() + } +} + /// The storage for a WebAssembly global defined within the instance. /// /// TODO: Pack the globals more densely, rather than using the same size @@ -461,7 +490,7 @@ mod test_vmtable_definition { #[derive(Debug, Clone)] #[repr(C, align(16))] pub struct VMGlobalDefinition { - storage: [u8; 16], + storage: VMGlobalDefinitionStorage, // If more elements are added here, remember to add offset_of tests below! } @@ -502,207 +531,158 @@ mod test_vmglobal_definition { impl VMGlobalDefinition { /// Construct a `VMGlobalDefinition`. pub fn new() -> Self { - Self { storage: [0; 16] } + Self { + storage: VMGlobalDefinitionStorage { bytes: [0; 16] }, + } } - /// Return a reference to the value as an i32. + /// Return the value as an i32. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_i32(&self) -> &i32 { - &*(self.storage.as_ref().as_ptr() as *const i32) + /// If this is not an I32 typed global it is unspecified what value is returned. + pub fn to_i32(&self) -> i32 { + unsafe { self.storage.as_i32 } } /// Return a mutable reference to the value as an i32. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has I32 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_i32_mut(&mut self) -> &mut i32 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut i32) + &mut self.storage.as_i32 } - /// Return a reference to the value as a u32. + /// Return a reference to the value as an u32. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_u32(&self) -> &u32 { - &*(self.storage.as_ref().as_ptr() as *const u32) + /// If this is not an I32 typed global it is unspecified what value is returned. + pub fn to_u32(&self) -> u32 { + unsafe { self.storage.as_u32 } } /// Return a mutable reference to the value as an u32. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has I32 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_u32_mut(&mut self) -> &mut u32 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut u32) + &mut self.storage.as_u32 } /// Return a reference to the value as an i64. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_i64(&self) -> &i64 { - &*(self.storage.as_ref().as_ptr() as *const i64) + /// If this is not an I64 typed global it is unspecified what value is returned. + pub fn to_i64(&self) -> i64 { + unsafe { self.storage.as_i64 } } /// Return a mutable reference to the value as an i64. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has I32 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_i64_mut(&mut self) -> &mut i64 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut i64) + &mut self.storage.as_i64 } /// Return a reference to the value as an u64. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_u64(&self) -> &u64 { - &*(self.storage.as_ref().as_ptr() as *const u64) + /// If this is not an I64 typed global it is unspecified what value is returned. + pub fn to_u64(&self) -> u64 { + unsafe { self.storage.as_u64 } } /// Return a mutable reference to the value as an u64. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has I64 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_u64_mut(&mut self) -> &mut u64 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut u64) + &mut self.storage.as_u64 } /// Return a reference to the value as an f32. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_f32(&self) -> &f32 { - &*(self.storage.as_ref().as_ptr() as *const f32) + /// If this is not an F32 typed global it is unspecified what value is returned. + pub fn to_f32(&self) -> f32 { + unsafe { self.storage.as_f32 } } /// Return a mutable reference to the value as an f32. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has F32 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_f32_mut(&mut self) -> &mut f32 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut f32) - } - - /// Return a reference to the value as f32 bits. - /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_f32_bits(&self) -> &u32 { - &*(self.storage.as_ref().as_ptr() as *const u32) - } - - /// Return a mutable reference to the value as f32 bits. - /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_f32_bits_mut(&mut self) -> &mut u32 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut u32) + &mut self.storage.as_f32 } /// Return a reference to the value as an f64. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_f64(&self) -> &f64 { - &*(self.storage.as_ref().as_ptr() as *const f64) + /// If this is not an F64 typed global it is unspecified what value is returned. + pub fn to_f64(&self) -> f64 { + unsafe { self.storage.as_f64 } } /// Return a mutable reference to the value as an f64. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has F64 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_f64_mut(&mut self) -> &mut f64 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut f64) - } - - /// Return a reference to the value as f64 bits. - /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_f64_bits(&self) -> &u64 { - &*(self.storage.as_ref().as_ptr() as *const u64) - } - - /// Return a mutable reference to the value as f64 bits. - /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_f64_bits_mut(&mut self) -> &mut u64 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut u64) + &mut self.storage.as_f64 } /// Return a reference to the value as an u128. /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_u128(&self) -> &u128 { - &*(self.storage.as_ref().as_ptr() as *const u128) + /// If this is not an V128 typed global it is unspecified what value is returned. + pub fn to_u128(&self) -> u128 { + unsafe { self.storage.as_u128 } } /// Return a mutable reference to the value as an u128. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] + /// It is the callers responsibility to make sure the global has V128 type. + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. pub unsafe fn as_u128_mut(&mut self) -> &mut u128 { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut u128) + &mut self.storage.as_u128 } - /// Return a reference to the value as u128 bits. + /// Return a reference to the value as bytes. + pub fn to_bytes(&self) -> [u8; 16] { + unsafe { self.storage.bytes } + } + + /// Return a mutable reference to the value as bytes. /// /// # Safety /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_u128_bits(&self) -> &[u8; 16] { - &*(self.storage.as_ref().as_ptr() as *const [u8; 16]) - } - - /// Return a mutable reference to the value as u128 bits. - /// - /// # Safety - /// - /// To be defined (TODO). - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn as_u128_bits_mut(&mut self) -> &mut [u8; 16] { - &mut *(self.storage.as_mut().as_mut_ptr() as *mut [u8; 16]) + /// Until the returned borrow is dropped, reads and writes of this global + /// must be done exclusively through this borrow. That includes reads and + /// writes of globals inside wasm functions. + pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8; 16] { + &mut self.storage.bytes } } diff --git a/lib/wasi-experimental-io-devices/Cargo.toml b/lib/wasi-experimental-io-devices/Cargo.toml index 72802219c..6218a3b1f 100644 --- a/lib/wasi-experimental-io-devices/Cargo.toml +++ b/lib/wasi-experimental-io-devices/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi-experimental-io-devices" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "An experimental non-standard WASI extension for graphics" categories = ["wasm"] keywords = ["wasm", "webassembly", "types"] @@ -14,7 +14,7 @@ edition = "2018" maintenance = { status = "experimental" } [dependencies] -wasmer-wasi = { version = "1.0.0-alpha4", path = "../wasi" } +wasmer-wasi = { version = "1.0.0-alpha5", path = "../wasi" } tracing = "0.1" minifb = "0.19" ref_thread_local = "0.0" diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index 00913d31b..ad64b45a7 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "WASI implementation library for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "wasi", "sandbox", "ABI"] @@ -21,7 +21,7 @@ getrandom = "0.2" time = "0.1" typetag = "0.1" serde = { version = "1.0", features = ["derive"] } -wasmer = { path = "../api", version = "1.0.0-alpha4", default-features = false } +wasmer = { path = "../api", version = "1.0.0-alpha5", default-features = false } [target.'cfg(windows)'.dependencies] winapi = "0.3" diff --git a/lib/wasmer-types/Cargo.toml b/lib/wasmer-types/Cargo.toml index d20306791..2f0c2008e 100644 --- a/lib/wasmer-types/Cargo.toml +++ b/lib/wasmer-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-types" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" description = "Wasmer Common Types" categories = ["wasm", "no-std", "data-structures"] keywords = ["wasm", "webassembly", "types"] diff --git a/scripts/publish.py b/scripts/publish.py index 8fce6df0b..100e82581 100644 --- a/scripts/publish.py +++ b/scripts/publish.py @@ -21,7 +21,7 @@ except ImportError: # TODO: find this automatically -target_version = "1.0.0-alpha4" +target_version = "1.0.0-alpha5" # TODO: generate this by parsing toml files dep_graph = { @@ -126,9 +126,12 @@ def main(): # sleep for 16 seconds between crates to ensure the crates.io index has time to update # this can be optimized with knowledge of our dep graph via toposort; we can even publish # crates in parallel; however this is out of scope for the first version of this script - print("Sleeping for 16 seconds to allow the `crates.io` index to update...") - time.sleep(16) - + if no_dry_run: + print("Sleeping for 16 seconds to allow the `crates.io` index to update...") + time.sleep(16) + else: + print("In dry-run: not sleeping for crates.io to update.") + if __name__ == "__main__": main() diff --git a/scripts/update-version.sh b/scripts/update-version.sh index aa1fb9dea..ad0473ba3 100755 --- a/scripts/update-version.sh +++ b/scripts/update-version.sh @@ -1,6 +1,6 @@ # A script to update the version of all the crates at the same time -PREVIOUS_VERSION='1.0.0-alpha3' -NEXT_VERSION='1.0.0-alpha4' +PREVIOUS_VERSION='1.0.0-alpha4' +NEXT_VERSION='1.0.0-alpha5' # quick hack fd Cargo.toml --exec sed -i '' "s/version = \"$PREVIOUS_VERSION\"/version = \"$NEXT_VERSION\"/" diff --git a/scripts/windows-installer/wasmer.iss b/scripts/windows-installer/wasmer.iss index ba8eb6044..7c6e6ccc9 100644 --- a/scripts/windows-installer/wasmer.iss +++ b/scripts/windows-installer/wasmer.iss @@ -1,6 +1,6 @@ [Setup] AppName=Wasmer -AppVersion=1.0.0-alpha4 +AppVersion=1.0.0-alpha5 DefaultDirName={pf}\Wasmer DefaultGroupName=Wasmer Compression=lzma2 diff --git a/tests/integration/cli/Cargo.toml b/tests/integration/cli/Cargo.toml index a6803db3b..157b51641 100644 --- a/tests/integration/cli/Cargo.toml +++ b/tests/integration/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-integration-tests-cli" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" authors = ["Wasmer Engineering Team "] description = "CLI integration tests" repository = "https://github.com/wasmerio/wasmer" diff --git a/tests/lib/engine-dummy/Cargo.toml b/tests/lib/engine-dummy/Cargo.toml index e7044a276..884c2ca8f 100644 --- a/tests/lib/engine-dummy/Cargo.toml +++ b/tests/lib/engine-dummy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-engine-dummy" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" authors = ["Wasmer Engineering Team "] description = "Wasmer placeholder engine" license = "MIT" @@ -8,10 +8,10 @@ edition = "2018" publish = false [dependencies] -wasmer-types = { path = "../../../lib/wasmer-types", version = "1.0.0-alpha4" } -wasmer-compiler = { path = "../../../lib/compiler", version = "1.0.0-alpha4" } -wasmer-vm = { path = "../../../lib/vm", version = "1.0.0-alpha4" } -wasmer-engine = { path = "../../../lib/engine", version = "1.0.0-alpha4" } +wasmer-types = { path = "../../../lib/wasmer-types", version = "1.0.0-alpha5" } +wasmer-compiler = { path = "../../../lib/compiler", version = "1.0.0-alpha5" } +wasmer-vm = { path = "../../../lib/vm", version = "1.0.0-alpha5" } +wasmer-engine = { path = "../../../lib/engine", version = "1.0.0-alpha5" } serde = { version = "1.0", features = ["derive", "rc"], optional = true } serde_bytes = { version = "0.11", optional = true } bincode = { version = "1.2", optional = true } diff --git a/tests/lib/wast/Cargo.toml b/tests/lib/wast/Cargo.toml index b9c26627f..6e60788ea 100644 --- a/tests/lib/wast/Cargo.toml +++ b/tests/lib/wast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wast" -version = "1.0.0-alpha4" +version = "1.0.0-alpha5" authors = ["Wasmer Engineering Team "] description = "wast testing support for wasmer" license = "MIT OR (Apache-2.0 WITH LLVM-exception)" @@ -12,8 +12,8 @@ edition = "2018" [dependencies] anyhow = "1.0" -wasmer = { path = "../../../lib/api", version = "1.0.0-alpha4", default-features = false } -wasmer-wasi = { path = "../../../lib/wasi", version = "1.0.0-alpha4" } +wasmer = { path = "../../../lib/api", version = "1.0.0-alpha5", default-features = false } +wasmer-wasi = { path = "../../../lib/wasi", version = "1.0.0-alpha5" } wast = "17.0" serde = "1" tempfile = "3"