diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2025-02-12 19:13:23 +0100 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2025-02-12 19:13:23 +0100 |
| commit | d6493c277eb1104aaf72a8e0e6959ce3d1cc4932 (patch) | |
| tree | a82452aeb44be6b79d15fc83ddfcbd12a965520a | |
| parent | 7e668f9e321c941f38395e47a29501dce0fc81a9 (diff) | |
fix: fix build, improve error handling
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
| -rw-r--r-- | CHANGELOG.md | 7 | ||||
| -rw-r--r-- | crates/tinywasm/src/error.rs | 17 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/no_std_floats.rs | 9 | ||||
| -rw-r--r-- | crates/types/src/lib.rs | 12 | ||||
| -rw-r--r-- | examples/rust/Cargo.toml | 4 | ||||
| -rwxr-xr-x | examples/rust/build.sh | 4 | ||||
| -rw-r--r-- | examples/rust/src/argon2id.rs | 2 | ||||
| -rw-r--r-- | examples/rust/src/fibonacci.rs | 4 | ||||
| -rw-r--r-- | examples/rust/src/hello.rs | 8 | ||||
| -rw-r--r-- | examples/rust/src/host_fn.rs | 11 | ||||
| -rw-r--r-- | examples/rust/src/print.rs | 4 | ||||
| -rw-r--r-- | examples/rust/src/tinywasm.rs | 4 | ||||
| -rw-r--r-- | examples/rust/src/tinywasm_no_std.rs | 6 | ||||
| -rw-r--r-- | examples/wasm-rust.rs | 24 |
14 files changed, 85 insertions, 31 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0222a0b..c01787f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for the custom memory page sizes proposal ([#22](https://github.com/explodingcamera/tinywasm/pull/22) by [@danielstuart14](https://github.com/danielstuart14)) -### Changed +### Breaking Changes -- **Breaking:**: New backwards-incompatible version of the twasm format based on `postcard` (thanks [@dragonnn](https://github.com/dragonnn)) -- **Breaking:**: `RefNull` has been removed and replaced with new `FuncRef` and `ExternRef` structs +- New backwards-incompatible version of the twasm format based on `postcard` (thanks [@dragonnn](https://github.com/dragonnn)) +- `RefNull` has been removed and replaced with new `FuncRef` and `ExternRef` structs - Increased MSRV to 1.83.0 +- `tinywasm::Error` is now `non_exhaustive`, `Error::ParseError` has been rename to `Error::Parser` and `Error::Twasm` has been added. ### Fixed diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index e0510b2..1d488d8 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -1,6 +1,7 @@ use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::{fmt::Display, ops::ControlFlow}; +use tinywasm_types::archive::TwasmError; use tinywasm_types::FuncType; #[cfg(feature = "parser")] @@ -8,6 +9,7 @@ pub use tinywasm_parser::ParseError; /// Errors that can occur for `TinyWasm` operations #[derive(Debug)] +#[non_exhaustive] pub enum Error { /// A WebAssembly trap occurred Trap(Trap), @@ -41,7 +43,10 @@ pub enum Error { #[cfg(feature = "parser")] /// A parsing error occurred - ParseError(ParseError), + Parser(ParseError), + + /// A serialization error occurred + Twasm(TwasmError), } #[derive(Debug)] @@ -169,6 +174,11 @@ impl From<LinkingError> for Error { } } +impl From<TwasmError> for Error { + fn from(value: TwasmError) -> Self { + Self::Twasm(value) + } +} impl From<Trap> for Error { fn from(value: Trap) -> Self { Self::Trap(value) @@ -179,11 +189,12 @@ impl Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { #[cfg(feature = "parser")] - Self::ParseError(err) => write!(f, "error parsing module: {err:?}"), + Self::Parser(err) => write!(f, "error parsing module: {err:?}"), #[cfg(feature = "std")] Self::Io(err) => write!(f, "I/O error: {err}"), + Self::Twasm(err) => write!(f, "serialization error: {err}"), Self::Trap(trap) => write!(f, "trap: {trap}"), Self::Linker(err) => write!(f, "linking error: {err}"), Self::InvalidLabelType => write!(f, "invalid label type"), @@ -238,7 +249,7 @@ impl core::error::Error for Error {} #[cfg(feature = "parser")] impl From<tinywasm_parser::ParseError> for Error { fn from(value: tinywasm_parser::ParseError) -> Self { - Self::ParseError(value) + Self::Parser(value) } } diff --git a/crates/tinywasm/src/interpreter/no_std_floats.rs b/crates/tinywasm/src/interpreter/no_std_floats.rs index 5b9471e..e273184 100644 --- a/crates/tinywasm/src/interpreter/no_std_floats.rs +++ b/crates/tinywasm/src/interpreter/no_std_floats.rs @@ -1,34 +1,25 @@ pub(super) trait NoStdFloatExt { fn round(self) -> Self; - fn abs(self) -> Self; - fn signum(self) -> Self; fn ceil(self) -> Self; fn floor(self) -> Self; fn trunc(self) -> Self; fn sqrt(self) -> Self; - fn copysign(self, other: Self) -> Self; } #[rustfmt::skip] impl NoStdFloatExt for f64 { #[inline] fn round(self) -> Self { libm::round(self) } - #[inline] fn abs(self) -> Self { libm::fabs(self) } - #[inline] fn signum(self) -> Self { libm::copysign(1.0, self) } #[inline] fn ceil(self) -> Self { libm::ceil(self) } #[inline] fn floor(self) -> Self { libm::floor(self) } #[inline] fn trunc(self) -> Self { libm::trunc(self) } #[inline] fn sqrt(self) -> Self { libm::sqrt(self) } - #[inline] fn copysign(self, other: Self) -> Self { libm::copysign(self, other) } } #[rustfmt::skip] impl NoStdFloatExt for f32 { #[inline] fn round(self) -> Self { libm::roundf(self) } - #[inline] fn abs(self) -> Self { libm::fabsf(self) } - #[inline] fn signum(self) -> Self { libm::copysignf(1.0, self) } #[inline] fn ceil(self) -> Self { libm::ceilf(self) } #[inline] fn floor(self) -> Self { libm::floorf(self) } #[inline] fn trunc(self) -> Self { libm::truncf(self) } #[inline] fn sqrt(self) -> Self { libm::sqrtf(self) } - #[inline] fn copysign(self, other: Self) -> Self { libm::copysignf(self, other) } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 81eec13..d9f2234 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -45,6 +45,18 @@ pub use value::*; #[cfg(feature = "archive")] pub mod archive; +#[cfg(not(feature = "archive"))] +pub mod archive { + #[derive(Debug)] + pub enum TwasmError {} + impl core::fmt::Display for TwasmError { + fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Err(core::fmt::Error) + } + } + impl core::error::Error for TwasmError {} +} + /// A `TinyWasm` WebAssembly Module /// /// This is the internal representation of a WebAssembly module in `TinyWasm`. diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml index 5c6b710..da238ad 100644 --- a/examples/rust/Cargo.toml +++ b/examples/rust/Cargo.toml @@ -23,6 +23,10 @@ name="hello" path="src/hello.rs" [[bin]] +name="host_fn" +path="src/host_fn.rs" + +[[bin]] name="print" path="src/print.rs" diff --git a/examples/rust/build.sh b/examples/rust/build.sh index d0415ac..e1d320f 100755 --- a/examples/rust/build.sh +++ b/examples/rust/build.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -cd "$(dirname "$0")" +cd "$(dirname "$0")" || exit -bins=("hello" "fibonacci" "print" "tinywasm" "argon2id") +bins=("host_fn" "hello" "fibonacci" "print" "tinywasm" "argon2id") exclude_wat=("tinywasm") out_dir="./target/wasm32-unknown-unknown/wasm" dest_dir="out" diff --git a/examples/rust/src/argon2id.rs b/examples/rust/src/argon2id.rs index 01ea7ca..ff17d04 100644 --- a/examples/rust/src/argon2id.rs +++ b/examples/rust/src/argon2id.rs @@ -1,6 +1,6 @@ #![no_main] -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn argon2id(m_cost: i32, t_cost: i32, p_cost: i32) -> i32 { let password = b"password"; let salt = b"some random salt"; diff --git a/examples/rust/src/fibonacci.rs b/examples/rust/src/fibonacci.rs index b847ad5..ec4a371 100644 --- a/examples/rust/src/fibonacci.rs +++ b/examples/rust/src/fibonacci.rs @@ -1,6 +1,6 @@ #![no_main] -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn fibonacci(n: i32) -> i32 { let mut sum = 0; let mut last = 0; @@ -13,7 +13,7 @@ pub extern "C" fn fibonacci(n: i32) -> i32 { sum } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn fibonacci_recursive(n: i32) -> i32 { if n <= 1 { return n; diff --git a/examples/rust/src/hello.rs b/examples/rust/src/hello.rs index c8e2ac3..3d9f400 100644 --- a/examples/rust/src/hello.rs +++ b/examples/rust/src/hello.rs @@ -1,23 +1,23 @@ #![no_main] #[link(wasm_import_module = "env")] -extern "C" { +unsafe extern "C" { fn print_utf8(location: i64, len: i32); } const ARG: &[u8] = &[0u8; 100]; -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn arg_ptr() -> i32 { ARG.as_ptr() as i32 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn arg_size() -> i32 { ARG.len() as i32 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn hello(len: i32) { let arg = core::str::from_utf8(&ARG[0..len as usize]).unwrap(); let res = format!("Hello, {}!", arg).as_bytes().to_vec(); diff --git a/examples/rust/src/host_fn.rs b/examples/rust/src/host_fn.rs new file mode 100644 index 0000000..ada74bd --- /dev/null +++ b/examples/rust/src/host_fn.rs @@ -0,0 +1,11 @@ +#![no_main] + +#[link(wasm_import_module = "env")] +unsafe extern "C" { + fn bar(left: i64, right: i32) -> i32; +} + +#[unsafe(no_mangle)] +pub fn foo() -> i32 { + unsafe { bar(1, 2) } +} diff --git a/examples/rust/src/print.rs b/examples/rust/src/print.rs index d04daa3..d2934f0 100644 --- a/examples/rust/src/print.rs +++ b/examples/rust/src/print.rs @@ -1,11 +1,11 @@ #![no_main] #[link(wasm_import_module = "env")] -extern "C" { +unsafe extern "C" { fn printi32(x: i32); } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn add_and_print(lh: i32, rh: i32) { printi32(lh + rh); } diff --git a/examples/rust/src/tinywasm.rs b/examples/rust/src/tinywasm.rs index c3bf2d2..d3b3f8c 100644 --- a/examples/rust/src/tinywasm.rs +++ b/examples/rust/src/tinywasm.rs @@ -2,11 +2,11 @@ use tinywasm::{Extern, FuncContext}; #[link(wasm_import_module = "env")] -extern "C" { +unsafe extern "C" { fn printi32(x: i32); } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn hello() { let _ = run(); } diff --git a/examples/rust/src/tinywasm_no_std.rs b/examples/rust/src/tinywasm_no_std.rs index 9a31d20..46f1785 100644 --- a/examples/rust/src/tinywasm_no_std.rs +++ b/examples/rust/src/tinywasm_no_std.rs @@ -16,11 +16,11 @@ static ALLOCATOR: AssumeSingleThreaded<FreeListAllocator> = unsafe { AssumeSingleThreaded::new(FreeListAllocator::new()) }; #[link(wasm_import_module = "env")] -extern "C" { +unsafe extern "C" { fn printi32(x: i32); } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn hello() { let _ = run(); } @@ -30,7 +30,7 @@ fn run() -> tinywasm::Result<()> { let mut imports = tinywasm::Imports::new(); let res = tinywasm::parser::Parser::new().parse_module_bytes(include_bytes!("./print.wasm"))?; - let twasm = res.serialize_twasm(); + let twasm = res.serialize_twasm()?; let module = tinywasm::Module::parse_bytes(&twasm)?; imports.define( diff --git a/examples/wasm-rust.rs b/examples/wasm-rust.rs index 429bdcb..95769f4 100644 --- a/examples/wasm-rust.rs +++ b/examples/wasm-rust.rs @@ -33,6 +33,7 @@ fn main() -> Result<()> { println!("Available examples:"); println!(" hello"); println!(" printi32"); + println!(" host_fn"); println!(" fibonacci - calculate fibonacci(30)"); println!(" tinywasm - run printi32 inside of tinywasm inside of itself"); println!(" argon2id - run argon2id(1000, 2, 1)"); @@ -46,6 +47,7 @@ fn main() -> Result<()> { "tinywasm" => tinywasm()?, "tinywasm_no_std" => tinywasm_no_std()?, "argon2id" => argon2id()?, + "host_fn" => host_fn()?, "all" => { println!("Running all examples"); println!("\nhello.wasm:"); @@ -60,6 +62,8 @@ fn main() -> Result<()> { tinywasm_no_std()?; println!("argon2id.wasm:"); argon2id()?; + println!("\nhost_fn.wasm:"); + host_fn()?; } _ => {} } @@ -126,6 +130,26 @@ fn hello() -> Result<()> { Ok(()) } +fn host_fn() -> Result<()> { + let module = Module::parse_file("./examples/rust/out/host_fn.wasm")?; + let mut store = Store::default(); + let mut imports = Imports::new(); + imports.define( + "env", + "bar", + Extern::typed_func(|_: FuncContext<'_>, (left, right): (i64, i32)| { + assert_eq!(left, 1); + assert_eq!(right, 2); + Ok(left as i32 + right) + }), + )?; + + let instance = module.instantiate(&mut store, Some(imports))?; + let host_fn = instance.exported_func::<(), i32>(&store, "foo")?; + assert_eq!(host_fn.call(&mut store, ())?, 3); + Ok(()) +} + fn printi32() -> Result<()> { let module = Module::parse_file("./examples/rust/out/print.opt.wasm")?; let mut store = Store::default(); |
