Create a new project:
$ cargo new --bin hello
$ cd hello
$ rustup target add wasm32-wasi
Build and run:
$ cargo build --release --target wasm32-wasi
$ wasm3 ./target/wasm32-wasi/release/hello.wasm
Hello, world!
Create hello.ts
:
import "wasi"
import {Console} from "as-wasi"
Console.log('Hello World!');
Create package.json
:
{
"scripts": {
"asbuild:debug": "asc hello.ts -b hello.wasm --debug",
"asbuild:optimized": "asc hello.ts -b hello.wasm -O3s --noAssert",
"asbuild:tiny": "asc hello.ts -b hello.wasm -O3z --noAssert --runtime stub --use abort=",
"build": "npm run asbuild:optimized"
},
"devDependencies": {
"assemblyscript": "*",
"as-wasi": "*"
}
}
Build and run:
$ npm install
$ npm run build
$ wasm3 hello.wasm
Hello World!
Create hello.go
:
package main
import "fmt"
func main() {
.Printf("Hello, %s!\n", "world")
fmt}
Build and run:
$ tinygo build -o hello.wasm -target wasi -no-debug hello.go
$ wasm3 hello.wasm
Hello, world!
Create hello.zig
:
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello, {s}!\n", .{"world"});
}
Build and run:
$ zig build-exe -O ReleaseSmall -target wasm32-wasi hello.zig
$ wasm3 hello.wasm
Hello, world!
Create add.zig
:
export fn add(a: i32, b: i32) i64 {
return a + b;
}
Build and run:
$ zig build-lib add.zig -O ReleaseSmall -target wasm32-freestanding
$ wasm3 --repl add.wasm
wasm3> add 1 2
Result: 3
The easiest way to start is to use Wasienv.
Create hello.cpp
:
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
return 0;
}
Or hello.c
:
#include <stdio.h>
int main() {
("Hello, %s!\n", "world");
printfreturn 0;
}
Build and run:
$ wasic++ -O3 hello.cpp -o hello.wasm
$ wasicc -O3 hello.c -o hello.wasm
$ wasm3 hello.wasm
Hello World!
Limitations:
setjmp/longjmp
and C++ exceptions
are not availablethreads
and atomics
dynamic libraries
Create hello.gr
:
print("Hello, world!")
Build and run:
$ grain compile hello.gr -o hello.wasm
$ wasm3 hello.wasm
Hello, world!
Create hello.wat
:
(module
;; wasi_snapshot_preview1!fd_write(file_descriptor, *iovs, iovs_len, nwritten) -> status_code
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; Put a message to linear memory at offset 32
(data (i32.const 32) "Hello, world!\n")
(func $main (export "_start")
;; Create a new io vector at address 0x4
(i32.store (i32.const 4) (i32.const 32)) ;; iov.iov_base - pointer to the start of the message
(i32.store (i32.const 8) (i32.const 14)) ;; iov.iov_len - length of the message
(call $fd_write
(i32.const 1) ;; file_descriptor - 1 for stdout
(i32.const 4) ;; *iovs - pointer to the io vector
(i32.const 1) ;; iovs_len - count of items in io vector
(i32.const 20) ;; nwritten - where to store the number of bytes written
)
drop ;; discard the WASI status code
)
)
Build and run:
$ wat2wasm hello.wat -o hello.wasm
$ wasm3 hello.wasm
Hello, world!
Create swap.wat
:
(module
(func (export "swap") (param i32 i32) (result i32 i32)
(get_local 1)
(get_local 0)
)
)
Build and run:
$ wat2wasm swap.wat -o swap.wasm
$ wasm3 --repl swap.wasm
wasm3> :invoke swap 123 456
Result: 456:i32, 123:i32
Drag'n'drop any of the WASI apps to WebAssembly.sh
and run:
$ wasm3-strace /tmp/hello.wasm
The execution trace will be produced:
_start () {
__wasilibc_init_preopen () {
malloc (i32: 16) {
dlmalloc (i32: 16) {
sbrk (i32: 0) {
= 131072
} sbrk (i32: 65536) {
= 131072
} = 131088
} = 131088
} calloc (i32: 24, i32: 0) {
dlmalloc (i32: 96) {
= 131120
} memset (i32: 131120, i32: 65504, i32: 0) {
= 131120
} = 131120
} po_map_assertvalid (i32: 131088) {
}po_map_assertvalid (i32: 131088) {
}
}!fd_prestat_get(3, 65528) { <native> } = 0
wasi_unstablemalloc (i32: 2) {
dlmalloc (i32: 2) {
= 131232
} = 131232
} !fd_prestat_dir_name(3, 131232, 1) { <native> } = 0
wasi_unstable__wasilibc_register_preopened_fd (i32: 3, i32: 131120) {
po_map_assertvalid (i32: 131088) {
}po_map_assertvalid (i32: 131088) {
}strdup (i32: 131232) {
strlen (i32: 131232) {
= 1
} malloc (i32: 2) {
dlmalloc (i32: 2) {
= 131248
} = 131248
} memcpy (i32: 131248, i32: 131233, i32: 131232) {
= 131248
} = 131248
} !fd_fdstat_get(3, 65496) { <native> } = 0
wasi_unstablepo_map_assertvalid (i32: 131088) {
}po_map_assertvalid (i32: 131088) {
}= 0
} free (i32: 131232) {
dlfree (i32: 131232) {
}
}!fd_prestat_get(4, 65528) { <native> } = 0
wasi_unstablemalloc (i32: 2) {
dlmalloc (i32: 2) {
= 131232
} = 131232
} !fd_prestat_dir_name(4, 131232, 1) { <native> } = 0
wasi_unstable__wasilibc_register_preopened_fd (i32: 4, i32: 131120) {
po_map_assertvalid (i32: 131088) {
}po_map_assertvalid (i32: 131088) {
}strdup (i32: 131232) {
strlen (i32: 131232) {
= 1
} malloc (i32: 2) {
dlmalloc (i32: 2) {
= 131264
} = 131264
} memcpy (i32: 131264, i32: 131233, i32: 131232) {
= 131264
} = 131264
} !fd_fdstat_get(4, 65496) { <native> } = 0
wasi_unstablepo_map_assertvalid (i32: 131088) {
}po_map_assertvalid (i32: 131088) {
}= 0
} free (i32: 131232) {
dlfree (i32: 131232) {
}
}!fd_prestat_get(5, 65528) { <native> } = 8
wasi_unstable__wasm_call_ctors () {
}__original_main () {
printf (i32: 65536, i32: 0) {
vfprintf (i32: 69512, i32: 0, i32: 65536) {
printf_core (i32: 0, i32: -1, i32: 65536, i32: -16, i32: 65480) {
= 0
} __towrite (i32: 69512) {
= 0
} printf_core (i32: 69512, i32: 8, i32: 65536, i32: -1, i32: 65480) {
__fwritex (i32: 65536, i32: 0, i32: 7) {
memcpy (i32: 68472, i32: 0, i32: 65536) {
= 68472
} = 7
} __fwritex (i32: 65543, i32: 0, i32: 0) {
memcpy (i32: 68479, i32: 0, i32: 65543) {
= 68479
} = 0
} pop_arg (i32: 64456, i32: 0, i32: 9) {
}strnlen (i32: 65548, i32: 0) {
memchr (i32: 65548, i32: 4, i32: 0) {
= 65553
} = 5
} __fwritex (i32: 67222, i32: 65553, i32: 0) {
memcpy (i32: 68479, i32: 0, i32: 67222) {
= 68479
} = 0
} __fwritex (i32: 65548, i32: 65553, i32: 5) {
memcpy (i32: 68479, i32: 0, i32: 65548) {
= 68479
} = 5
} __fwritex (i32: 65545, i32: 0, i32: 2) {
__stdout_write (i32: 69512, i32: 0, i32: 65545) {
__isatty (i32: 1) {
!fd_fdstat_get(1, 64376) { <native> } = 0
wasi_unstable= 1
} __stdio_write (i32: 69512, i32: 64368, i32: 65545) {
writev (i32: 1, i32: -16, i32: 64384) {
, world!
Hello!fd_write(1, 64384, 2, 64380) { <native> } = 0
wasi_unstable= 14
} = 2
} = 2
} memcpy (i32: 68472, i32: -1, i32: 65547) {
= 68472
} = 2
} = 14
} = 14
} = 14
} = 0
} __prepare_for_exit () {
dummy () {
}__stdio_exit () {
__ofl_lock () {
= 69504
}
}
} }
$ npm install -g wasm-metering
$ wasm-meter hello.wasm hello-metered.wasm
$ wasm3 hello-metered.wasm
Warning: Gas is limited to 500000000.0000
Hello, world!
Gas used: 20.8950
$ wasm3 --gas-limit 10 hello-metered.wasm
Warning: Gas is limited to 10.0000
Gas used: 10.0309
Error: [trap] Out of gas