summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2025-02-12 19:13:23 +0100
committerHenry Gressmann <mail@henrygressmann.de>2025-02-12 19:13:23 +0100
commitd6493c277eb1104aaf72a8e0e6959ce3d1cc4932 (patch)
treea82452aeb44be6b79d15fc83ddfcbd12a965520a
parent7e668f9e321c941f38395e47a29501dce0fc81a9 (diff)
fix: fix build, improve error handling
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
-rw-r--r--CHANGELOG.md7
-rw-r--r--crates/tinywasm/src/error.rs17
-rw-r--r--crates/tinywasm/src/interpreter/no_std_floats.rs9
-rw-r--r--crates/types/src/lib.rs12
-rw-r--r--examples/rust/Cargo.toml4
-rwxr-xr-xexamples/rust/build.sh4
-rw-r--r--examples/rust/src/argon2id.rs2
-rw-r--r--examples/rust/src/fibonacci.rs4
-rw-r--r--examples/rust/src/hello.rs8
-rw-r--r--examples/rust/src/host_fn.rs11
-rw-r--r--examples/rust/src/print.rs4
-rw-r--r--examples/rust/src/tinywasm.rs4
-rw-r--r--examples/rust/src/tinywasm_no_std.rs6
-rw-r--r--examples/wasm-rust.rs24
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();