wain-exec
wain-exec is a crate to execute a WebAssembly abstract syntax tree.
Execution logic is defined in spec
This crate is part of larger wain project.
Installation
[]
= "0"
Usage
This crate assumes given Wasm syntax tree was validated.
It takes wain_ast::Module value and validates it. The tree can be parsed by wain-syntax-binary
and wain-syntax-text parsers and validated by wain-validate validator:
Using wain_exec::execute() is the easiest way. It invokes a start function in given module if presents.
Otherwise it invokes a function exported as _start.
extern crate wain_syntax_binary;
extern crate wain_validate;
extern crate wain_exec;
use fs;
use exit;
use parse;
use validate;
use execute;
// Read wasm binary
let source = read.unwrap;
// Parse binary into syntax tree
let tree = match parse ;
// Validate module
if let Err = validate
// Execute module
if let Err = execute
Or invoke specific exported function with arguments
// ...(snip)
use ;
use io;
// Create default importer to call external function supported by default
let stdin = stdin;
let stdout = stdout;
let importer = with_stdio;
// Make abstract machine runtime. It instantiates a module instance
let mut runtime = match instantiate ;
// Let's say `int add(int, int)` is exported
match runtime.invoke
Trap is returned as Err part
of Result.
wain_exec::execute() buffers stdin and stdout by default for now (this behavior may change in
the future). If this behavior is not acceptable, please specify your io::Write/io::Read values
for stdout/stdin at wain_exec::Runtime::new(). Then run the module by wain_exec::Runtime::invoke().
By default, only following C functions are supported in env module are supported as external functions
int putchar(int)(in wasm(func (param i32) (result i32)))int getchar(void)(in wasm(func (param) (result i32)))void *memcpy(void *, void *, size_t)(in wasm(func (param i32 i32 i32) (result i32)))void abort(void)(in wasm(func (param) (result)))
But you can implement your own struct which implements wain_exec::Importer for defining external
functions from Rust side.
extern crate wain_exec;
extern crate wain_ast;
use
use ValType;
let ast = ...; // Parse abstract syntax tree and validate it
let mut runtime = instantiate.unwrap;
let result = runtime.invoke;
Working examples can be seen at examples/api/ directory
Please read documentation (not yet) for details.
Implementation
Thanks to validation, checks at runtime are minimal (e.g. function signature on indirect call).
- Allocate memory, table, global variables. Initialize stack
- Interpret syntax tree nodes pushing/popping values to/from stack
Currently wain interprets a Wasm syntax tree directly. I'm planning to define an intermediate representation which can be interpreted faster.
Entrypoint is 'start function' which is defined either
- Function set in
startsection - Exported function named
_startin export section
The 1. is a standard entrypoint but Clang does not emit start section. Instead it handles _start
function as entrypoint. wain implements both entrypoints (1. is prioritized).