summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/README.md22
-rw-r--r--examples/rust/Cargo.toml7
-rwxr-xr-xexamples/rust/build.sh18
-rw-r--r--examples/rust/src/tinywasm.rs47
-rw-r--r--examples/wasm-rust.rs54
-rw-r--r--examples/wasm/add.wasmbin65 -> 0 bytes
-rw-r--r--examples/wasm/add.wat16
-rw-r--r--examples/wasm/call.wat42
-rw-r--r--examples/wasm/global.wat1
-rw-r--r--examples/wasm/helloworld.wasmbin115 -> 0 bytes
-rw-r--r--examples/wasm/helloworld.wat15
-rw-r--r--examples/wasm/loop.wat84
-rw-r--r--examples/wasm/test.wat7
13 files changed, 99 insertions, 214 deletions
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..ce47073
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,22 @@
+# Examples
+
+## WasmRust
+
+These are examples using WebAssembly generated from Rust code.
+To run these, you first need to build the Rust code into WebAssembly, since the wasm files are not included in the repository to keep it small.
+This requires the `wasm32-unknown-unknown` target and `wasm-opt` to be installed (available via Binaryen).
+
+```bash
+$ ./examples/rust/build.sh
+```
+
+Then you can run the examples:
+
+```bash
+$ cargo run --example wasm-rust <example>
+```
+
+Where `<example>` is one of the following:
+
+- `hello`: A simple example that prints a number to the console.
+- `tinywasm`: Runs `hello` using TinyWasm - inside of TinyWasm itself!
diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml
index 91b6aed..9ff80dc 100644
--- a/examples/rust/Cargo.toml
+++ b/examples/rust/Cargo.toml
@@ -7,8 +7,7 @@ forced-target="wasm32-unknown-unknown"
edition="2021"
[dependencies]
-tinywasm={path="../../crates/tinywasm", default-features=false, features=["parser"]}
-embedded-alloc={version="0.5"}
+tinywasm={path="../../crates/tinywasm", features=["parser", "std"]}
[[bin]]
name="hello"
@@ -17,7 +16,3 @@ path="src/hello.rs"
[[bin]]
name="tinywasm"
path="src/tinywasm.rs"
-
-[profile.release]
-opt-level="z"
-panic="abort"
diff --git a/examples/rust/build.sh b/examples/rust/build.sh
new file mode 100755
index 0000000..2c8069a
--- /dev/null
+++ b/examples/rust/build.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+cd "$(dirname "$0")"
+
+bins=("hello" "tinywasm")
+exclude_wat=("tinywasm")
+out_dir="../../target/wasm32-unknown-unknown/wasm"
+dest_dir="out"
+
+for bin in "${bins[@]}"; do
+ cargo build --target wasm32-unknown-unknown --package rust-wasm-examples --profile=wasm --bin "$bin"
+
+ cp "$out_dir/$bin.wasm" "$dest_dir/"
+ wasm-opt "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wasm" -O --intrinsic-lowering -O
+
+ if [[ ! " ${exclude_wat[@]} " =~ " $bin " ]]; then
+ wasm2wat "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wat"
+ fi
+done
diff --git a/examples/rust/src/tinywasm.rs b/examples/rust/src/tinywasm.rs
index 4edde66..52af7b9 100644
--- a/examples/rust/src/tinywasm.rs
+++ b/examples/rust/src/tinywasm.rs
@@ -1,41 +1,32 @@
-#![no_std]
#![no_main]
+use tinywasm::{Extern, FuncContext};
-use embedded_alloc::Heap;
-// use tinywasm::{Extern, FuncContext};
-
-#[cfg(not(test))]
-#[panic_handler]
-fn panic(_info: &core::panic::PanicInfo) -> ! {
- core::arch::wasm32::unreachable()
+#[link(wasm_import_module = "env")]
+extern "C" {
+ fn printi32(x: i32);
}
-#[global_allocator]
-static HEAP: Heap = Heap::empty();
-
#[no_mangle]
-pub unsafe extern "C" fn _start() {
- // Initialize the allocator BEFORE you use it
- {
- use core::mem::MaybeUninit;
- const HEAP_SIZE: usize = 1024;
- static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
- unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
- }
-
- // now the allocator is ready types like Box, Vec can be used.
+pub extern "C" fn hello() {
let _ = run();
}
fn run() -> tinywasm::Result<()> {
- // let module = tinywasm::Module::parse_bytes(include_bytes!("../out/hello.wasm"))?;
- // let mut store = tinywasm::Store::default();
+ let module = tinywasm::Module::parse_bytes(include_bytes!("../../wasm/hello.wasm"))?;
+ let mut store = tinywasm::Store::default();
+ let mut imports = tinywasm::Imports::new();
- // let mut imports = tinywasm::Imports::new();
- // imports.define("env", "printi32", Extern::typed_func(|_: FuncContext<'_>, _: i32| Ok(())))?;
+ imports.define(
+ "env",
+ "printi32",
+ Extern::typed_func(|_: FuncContext<'_>, v: i32| {
+ unsafe { printi32(v) }
+ Ok(())
+ }),
+ )?;
+ let instance = module.instantiate(&mut store, Some(imports))?;
- // let instance = module.instantiate(&mut store, Some(imports))?;
- // let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?;
- // add_and_print.call(&mut store, (1, 2))?;
+ let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?;
+ add_and_print.call(&mut store, (1, 2))?;
Ok(())
}
diff --git a/examples/wasm-rust.rs b/examples/wasm-rust.rs
index 21d3eb8..3b8877e 100644
--- a/examples/wasm-rust.rs
+++ b/examples/wasm-rust.rs
@@ -7,35 +7,59 @@ fn main() -> Result<()> {
println!("Usage: cargo run --example wasm-rust <rust_example>");
println!("Available examples:");
println!(" hello");
+ println!(" tinywasm");
return Ok(());
}
match args[1].as_str() {
"hello" => hello()?,
+ "tinywasm" => tinywasm()?,
_ => {}
}
Ok(())
}
+fn tinywasm() -> Result<()> {
+ const TINYWASM: &[u8] = include_bytes!("./rust/out/tinywasm.wasm");
+ let module = Module::parse_bytes(&TINYWASM)?;
+ let mut store = Store::default();
+
+ let mut imports = Imports::new();
+ imports.define(
+ "env",
+ "printi32",
+ Extern::typed_func(|_: FuncContext<'_>, x: i32| {
+ println!("{}", x);
+ Ok(())
+ }),
+ )?;
+ let instance = module.instantiate(&mut store, Some(imports))?;
+
+ let hello = instance.typed_func::<(), ()>(&mut store, "hello")?;
+ hello.call(&mut store, ())?;
+
+ Ok(())
+}
+
fn hello() -> Result<()> {
- // const HELLO_WASM: &[u8] = include_bytes!("./rust/out/hello.wasm");
- // let module = Module::parse_bytes(&HELLO_WASM)?;
- // let mut store = Store::default();
+ const HELLO_WASM: &[u8] = include_bytes!("./rust/out/hello.wasm");
+ let module = Module::parse_bytes(&HELLO_WASM)?;
+ let mut store = Store::default();
- // let mut imports = Imports::new();
- // imports.define(
- // "env",
- // "printi32",
- // Extern::typed_func(|_: FuncContext<'_>, x: i32| {
- // println!("{}", x);
- // Ok(())
- // }),
- // )?;
+ let mut imports = Imports::new();
+ imports.define(
+ "env",
+ "printi32",
+ Extern::typed_func(|_: FuncContext<'_>, x: i32| {
+ println!("{}", x);
+ Ok(())
+ }),
+ )?;
- // let instance = module.instantiate(&mut store, Some(imports))?;
- // let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?;
- // add_and_print.call(&mut store, (1, 2))?;
+ let instance = module.instantiate(&mut store, Some(imports))?;
+ let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?;
+ add_and_print.call(&mut store, (1, 2))?;
Ok(())
}
diff --git a/examples/wasm/add.wasm b/examples/wasm/add.wasm
deleted file mode 100644
index 92e3432..0000000
--- a/examples/wasm/add.wasm
+++ /dev/null
Binary files differ
diff --git a/examples/wasm/add.wat b/examples/wasm/add.wat
deleted file mode 100644
index 4976689..0000000
--- a/examples/wasm/add.wat
+++ /dev/null
@@ -1,16 +0,0 @@
-(module
- (func $add (export "add") (param $a i32) (param $b i32) (result i32)
- local.get $a
- local.get $b
- i32.add)
-
- (func $sub (export "sub") (param $a i32) (param $b i32) (result i32)
- local.get $a
- local.get $b
- i32.sub)
-
- (func $add_64 (export "add_64") (param $a i64) (param $b i64) (result i64)
- local.get $a
- local.get $b
- i64.add)
-)
diff --git a/examples/wasm/call.wat b/examples/wasm/call.wat
deleted file mode 100644
index d515e78..0000000
--- a/examples/wasm/call.wat
+++ /dev/null
@@ -1,42 +0,0 @@
-(module
- (func (export "check") (param i32) (result i32)
- i64.const 0 ;; Set 0 to the stack
- local.get 0
- i32.const 10
- i32.lt_s ;; Check if input is less than 10
- if (param i64) (result i32) ;; If so,
- i32.const 1 ;; Set 1 to the stack
- return ;; And return immediately
- else ;; Otherwise,
- i32.const 0 ;; Set 0 to the stack
- return ;; And return immediately
- end) ;; End of the if/else block
-
- (func (export "simple_block") (result i32)
- (block (result i32)
- (i32.const 0)
- (i32.const 1)
- (i32.add)
- )
- )
-
- (func (export "checkloop") (result i32)
- (block (result i32)
- (i32.const 0)
- (loop (param i32)
- (block (br 2 (i32.const 18)))
- (br 0 (i32.const 20))
- )
- (i32.const 19)
- )
- )
-
-
- (func (export "param") (result i32)
- (i32.const 1)
- (loop (param i32) (result i32)
- (i32.const 2)
- (i32.add)
- )
- )
-) \ No newline at end of file
diff --git a/examples/wasm/global.wat b/examples/wasm/global.wat
deleted file mode 100644
index 22bde45..0000000
--- a/examples/wasm/global.wat
+++ /dev/null
@@ -1 +0,0 @@
-(module (global i32 (i32.const 0))) \ No newline at end of file
diff --git a/examples/wasm/helloworld.wasm b/examples/wasm/helloworld.wasm
deleted file mode 100644
index a5c95d0..0000000
--- a/examples/wasm/helloworld.wasm
+++ /dev/null
Binary files differ
diff --git a/examples/wasm/helloworld.wat b/examples/wasm/helloworld.wat
deleted file mode 100644
index b74c98f..0000000
--- a/examples/wasm/helloworld.wat
+++ /dev/null
@@ -1,15 +0,0 @@
-(module
- ;; Imports from JavaScript namespace
- (import "console" "log" (func $log (param i32 i32))) ;; Import log function
- (import "js" "mem" (memory 1)) ;; Import 1 page of memory (54kb)
-
- ;; Data section of our module
- (data (i32.const 0) "Hello World from WebAssembly!")
-
- ;; Function declaration: Exported as helloWorld(), no arguments
- (func (export "helloWorld")
- i32.const 0 ;; pass offset 0 to log
- i32.const 29 ;; pass length 29 to log (strlen of sample text)
- call $log
- )
-) \ No newline at end of file
diff --git a/examples/wasm/loop.wat b/examples/wasm/loop.wat
deleted file mode 100644
index 0dcd191..0000000
--- a/examples/wasm/loop.wat
+++ /dev/null
@@ -1,84 +0,0 @@
-(module
- (func $loop_test (export "loop_test") (result i32)
- (local i32) ;; Local 0: Counter
-
- ;; Initialize the counter
- (local.set 0 (i32.const 0))
-
- ;; Loop starts here
- (loop $my_loop
- ;; Increment the counter
- (local.set 0 (i32.add (local.get 0) (i32.const 1)))
-
- ;; Exit condition: break out of the loop if counter >= 10
- (br_if $my_loop (i32.lt_s (local.get 0) (i32.const 10)))
- )
-
- ;; Return the counter value
- (local.get 0)
- )
-
- (func $loop_test3 (export "loop_test3") (result i32)
- (local i32) ;; Local 0: Counter
-
- ;; Initialize the counter
- (local.set 0 (i32.const 0))
-
- ;; Loop starts here
- (block $exit_loop ;; Label for exiting the loop
- (loop $my_loop
- ;; Increment the counter
- (local.set 0 (i32.add (local.get 0) (i32.const 1)))
-
- ;; Prepare an index for br_table
- ;; Here, we use the counter, but you could modify this
- ;; For simplicity, 0 will continue the loop, any other value will exit
- (local.get 0)
- (i32.const 10)
- (i32.lt_s)
- (br_table $my_loop $exit_loop)
- )
- )
-
- ;; Return the counter value
- (local.get 0)
- )
-
- (func $calculate (export "loop_test2") (result i32)
- (local i32) ;; Local 0: Counter for the outer loop
- (local i32) ;; Local 1: Counter for the inner loop
- (local i32) ;; Local 2: Result variable
-
- ;; Initialize variables
- (local.set 0 (i32.const 0)) ;; Initialize outer loop counter
- (local.set 1 (i32.const 0)) ;; Initialize inner loop counter
- (local.set 2 (i32.const 0)) ;; Initialize result variable
-
- (block $outer ;; Outer loop label
- (loop $outer_loop
- (local.set 1 (i32.const 5)) ;; Reset inner loop counter for each iteration of the outer loop
-
- (block $inner ;; Inner loop label
- (loop $inner_loop
- (br_if $inner (i32.eqz (local.get 1))) ;; Break to $inner if inner loop counter is zero
-
- ;; Computation: Adding product of counters to the result
- (local.set 2 (i32.add (local.get 2) (i32.mul (local.get 0) (local.get 1))))
-
- ;; Decrement inner loop counter
- (local.set 1 (i32.sub (local.get 1) (i32.const 1)))
- )
- )
-
- ;; Increment outer loop counter
- (local.set 0 (i32.add (local.get 0) (i32.const 1)))
-
- ;; Break condition for outer loop: break if outer loop counter >= 5
- (br_if $outer (i32.ge_s (local.get 0) (i32.const 5)))
- )
- )
-
- ;; Return the result
- (local.get 2)
- )
-) \ No newline at end of file
diff --git a/examples/wasm/test.wat b/examples/wasm/test.wat
deleted file mode 100644
index 563f382..0000000
--- a/examples/wasm/test.wat
+++ /dev/null
@@ -1,7 +0,0 @@
-(module
- (func (export "test") (result i32)
- (i32.const 1)
- ;; comment
- (return (i32.const 2))
- )
-) \ No newline at end of file