Skip to content

Commit

Permalink
add wasmtime demo
Browse files Browse the repository at this point in the history
Wasmtime is a fast and secure runtime for WebAssembly. The demo
compiles and run the function `fibonacci`. The source code of
the fibonacci function is publish in the directory
examples/fibbonacci.
  • Loading branch information
stlankes authored and mkroening committed Jun 27, 2024
1 parent 6978f30 commit bbc528d
Show file tree
Hide file tree
Showing 18 changed files with 706 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ members = [
"examples/webserver",
"examples/dns",
"examples/mutex",
"examples/fibonacci",
"examples/wasmtime",
"hermit",
"hermit-abi",
]
Expand Down
11 changes: 11 additions & 0 deletions examples/fibonacci/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "fibonacci"
version = "0.1.0"
authors = ["Stefan Lankes <[email protected]>"]
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]

37 changes: 37 additions & 0 deletions examples/fibonacci/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Test library to test the wasmtime demo
use core::hint::black_box;

extern "C" {
fn now() -> f64;
}

// Just a dummy function to measure the overhead
#[no_mangle]
pub extern "C" fn foo() {}

// Calculating fibonacci numbers
#[no_mangle]
pub extern "C" fn fibonacci(n: u64) -> u64 {
let mut fib: u64 = 1;
let mut fib1: u64 = 1;
let mut fib2: u64 = 1;

for _ in 3..=n {
fib = fib1 + fib2;
fib1 = fib2;
fib2 = fib;
}

fib
}

#[no_mangle]
pub extern "C" fn bench(iterations: u64, number: u64) -> f64 {
let start = unsafe { now() };
for _ in 0..iterations {
black_box(fibonacci(black_box(number)));
}
let end = unsafe { now() };

end - start
}
20 changes: 20 additions & 0 deletions examples/wasmtime/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "wasmtime-demo"
version = "0.1.0"
edition = "2021"
authors = ["Stefan Lankes <[email protected]>"]
readme = "README.md"
license = "MIT/Apache-2.0"
keywords = ["wasm", "webassembly"]

[dependencies]
anyhow = "1.0"
bitflags = "2.5"
cfg-if = "1"
log = { version = "0.4" } #, features = ["kv_unstable"]}
simple_logger = { version = "5.0", default-features = false, features = ["nightly"]}
wasmtime = { version = "22.0", default-features = false, features = ["std", "runtime", "cranelift", "threads", "gc", "component-model"] }

[target.'cfg(target_os = "hermit")'.dependencies]
hermit = { path = "../../hermit", default-features = false, features = ["smp", "acpi", "pci", "fsgsbase", "fs", "tcp", "dhcpv4", "mmap"] }
hermit-abi = { path = "../../hermit-abi", default-features = false }
30 changes: 30 additions & 0 deletions examples/wasmtime/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
SOURCE_FILES := $(shell test -e src/ && find src -type f)

.PHONY: build
build: target/x86_64-unknown-hermit/release/wasmi_demo wasm/fib.wasm

target/x86_64-unknown-hermit/release/wasmi_demo: $(SOURCE_FILES) Cargo.* wasm/fib.wasm
cargo build \
-Zbuild-std=std,panic_abort \
--target x86_64-unknown-hermit \
--release

wasm/fib.wasm:
cd examples; cd fib; cargo build --target wasm32-wasi --release; cp target/wasm32-wasi/release/fib.wasm ../../wasm

.PHONY: clean
clean:
cargo clean
rm -f wasm/fib.wasm

.PHONY: run
run: target/x86_64-unknown-hermit/release/wasmi_demo
qemu-system-x86_64 \
-cpu qemu64,apic,fsgsbase,fxsr,rdrand,rdtscp,xsave,xsaveopt \
-display none -serial stdio \
-smp 4 \
-m 1G \
-device isa-debug-exit,iobase=0xf4,iosize=0x04 \
-kernel hermit-loader-x86_64 \
-initrd target/x86_64-unknown-hermit/release/wasmi-demo \
-netdev user,id=u1,hostfwd=tcp::3000-:3000 -device virtio-net-pci,netdev=u1,disable-legacy=on,packed=on,mq=on
20 changes: 20 additions & 0 deletions examples/wasmtime/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::process::Command;
use std::{env, io};

fn main() -> io::Result<()> {
let out_dir = env::var_os("OUT_DIR").unwrap();

let status = Command::new("cargo")
.arg("build")
.arg("-Zunstable-options")
.arg("-Zbuild-std=std,panic_abort")
.arg("--target=wasm32-unknown-unknown")
.arg("--package=fibonacci")
.arg("--release")
.arg("--out-dir")
.arg(&out_dir)
.status()?;
assert!(status.success());

Ok(())
}
22 changes: 22 additions & 0 deletions examples/wasmtime/src/arch/aarch64/longjmp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# The code is derived from the musl implementation
# of longjmp.
.section .text
.global longjmp
longjmp:
# IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
ldp x19, x20, [x0,#0]
ldp x21, x22, [x0,#16]
ldp x23, x24, [x0,#32]
ldp x25, x26, [x0,#48]
ldp x27, x28, [x0,#64]
ldp x29, x30, [x0,#80]
ldr x2, [x0,#104]
mov sp, x2
ldp d8 , d9, [x0,#112]
ldp d10, d11, [x0,#128]
ldp d12, d13, [x0,#144]
ldp d14, d15, [x0,#160]

cmp w1, 0
csinc w0, w1, wzr, ne
br x30
4 changes: 4 additions & 0 deletions examples/wasmtime/src/arch/aarch64/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use core::arch::global_asm;

global_asm!(include_str!("setjmp.s"));
global_asm!(include_str!("longjmp.s"));
20 changes: 20 additions & 0 deletions examples/wasmtime/src/arch/aarch64/setjmp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# The code is derived from the musl implementation
# of setjmp.
.section .text
.global setjmp
setjmp:
# IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
stp x19, x20, [x0,#0]
stp x21, x22, [x0,#16]
stp x23, x24, [x0,#32]
stp x25, x26, [x0,#48]
stp x27, x28, [x0,#64]
stp x29, x30, [x0,#80]
mov x2, sp
str x2, [x0,#104]
stp d8, d9, [x0,#112]
stp d10, d11, [x0,#128]
stp d12, d13, [x0,#144]
stp d14, d15, [x0,#160]
mov x0, #0
ret
9 changes: 9 additions & 0 deletions examples/wasmtime/src/arch/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cfg_if::cfg_if! {
if #[cfg(target_arch = "aarch64")] {
pub(crate) mod aarch64;
} else if #[cfg(target_arch = "x86_64")] {
pub(crate) mod x86_64;
} else if #[cfg(target_arch = "riscv64")] {
pub(crate) mod riscv64;
}
}
36 changes: 36 additions & 0 deletions examples/wasmtime/src/arch/riscv64/longjmp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# The code is derived from the musl implementation
# of longjmp.
.section .text
.global longjmp
longjmp:
ld s0, 0(a0)
ld s1, 8(a0)
ld s2, 16(a0)
ld s3, 24(a0)
ld s4, 32(a0)
ld s5, 40(a0)
ld s6, 48(a0)
ld s7, 56(a0)
ld s8, 64(a0)
ld s9, 72(a0)
ld s10, 80(a0)
ld s11, 88(a0)
ld sp, 96(a0)
ld ra, 104(a0)

fld fs0, 112(a0)
fld fs1, 120(a0)
fld fs2, 128(a0)
fld fs3, 136(a0)
fld fs4, 144(a0)
fld fs5, 152(a0)
fld fs6, 160(a0)
fld fs7, 168(a0)
fld fs8, 176(a0)
fld fs9, 184(a0)
fld fs10, 192(a0)
fld fs11, 200(a0)

seqz a0, a1
add a0, a0, a1
ret
4 changes: 4 additions & 0 deletions examples/wasmtime/src/arch/riscv64/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use core::arch::global_asm;

global_asm!(include_str!("setjmp.s"));
global_asm!(include_str!("longjmp.s"));
35 changes: 35 additions & 0 deletions examples/wasmtime/src/arch/riscv64/setjmp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# The code is derived from the musl implementation
# of setjmp.
.section .text
.global setjmp
setjmp:
sd s0, 0(a0)
sd s1, 8(a0)
sd s2, 16(a0)
sd s3, 24(a0)
sd s4, 32(a0)
sd s5, 40(a0)
sd s6, 48(a0)
sd s7, 56(a0)
sd s8, 64(a0)
sd s9, 72(a0)
sd s10, 80(a0)
sd s11, 88(a0)
sd sp, 96(a0)
sd ra, 104(a0)

fsd fs0, 112(a0)
fsd fs1, 120(a0)
fsd fs2, 128(a0)
fsd fs3, 136(a0)
fsd fs4, 144(a0)
fsd fs5, 152(a0)
fsd fs6, 160(a0)
fsd fs7, 168(a0)
fsd fs8, 176(a0)
fsd fs9, 184(a0)
fsd fs10, 192(a0)
fsd fs11, 200(a0)

li a0, 0
ret
19 changes: 19 additions & 0 deletions examples/wasmtime/src/arch/x86_64/longjmp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# The code is derived from the musl implementation
# of longjmp.
#
# Copyright 2011-2012 Nicholas J. Kain,
# licensed under standard MIT license
.section .text
.global longjmp
longjmp:
xor eax,eax
cmp esi, 1 /* CF = val ? 0 : 1 */
adc eax, esi /* eax = val + !val */
mov rbx, [rdi]
mov rbp, [rdi+8]
mov r12, [rdi+16]
mov r13, [rdi+24]
mov r14, [rdi+32]
mov r15, [rdi+40]
mov rsp, [rdi+48]
jmp [rdi+56]
4 changes: 4 additions & 0 deletions examples/wasmtime/src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use core::arch::global_asm;

global_asm!(include_str!("setjmp.s"));
global_asm!(include_str!("longjmp.s"));
20 changes: 20 additions & 0 deletions examples/wasmtime/src/arch/x86_64/setjmp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# The code is derived from the musl implementation
# of setjmp.
#
# Copyright 2011-2012 Nicholas J. Kain,
# licensed under standard MIT license
.section .text
.global setjmp
setjmp:
mov [rdi], rbx
mov [rdi+8], rbp
mov [rdi+16], r12
mov [rdi+24], r13
mov [rdi+32], r14
mov [rdi+40], r15
lea rdx, [rsp+8] # rsp without current ret addr
mov [rdi+48], rdx
mov rdi, rsp # save return addr ptr for new rip
mov [rdi+56], rdx
xor rax, rax
ret
Loading

0 comments on commit bbc528d

Please sign in to comment.