August 2026 Rust Blr meetup
Published on 2026-08-22
Building a WebAssembly Interpreter from Scratch in Rust - Bhavya Bhatt
- Existing WASM runtimes are fast but not really observable
- Goal was to build an interpreter where stack traces can be mapped back to source lang, not WASM
- WASM basically solves what Docker is doing
- Languages with a Garbage Collector have to compile their whole runtime along with the application code into WASM to work. Rust has no GC => Better WASM support
- Languages targeting WASM are truly cross platform
- WASM code structured as:
type section (
Generic function type definitions that show how many params
and how many results different functions of that type can have
)
imports section
instructions/function body
exports section
- TraceWASM is a stack based VM
- A stack holding data references and instructions + memory storing arbitrary data achieves Turing Completeness
- WASM memory is just a
Vec<u8>. - To be used, a value must be first pushed onto the top of the stack but values in the
localsspace of the stack may be randomly accessed by the programmer to be pushed to the top
- WASM instructions do 3 things: push 0 or more instructions onto the stack, pop 0 or more instructions onto the stack, read data from memory
- A WASM interpreter is basically just
loop {
fetch(instructions)
pc = exec_instructions(&mut stack, &mut memory) // Mutable references to the stack and memory
if pc == end { break }
}
- Basic syntax for an instruction:
<Required stack>.<Instruction> <Value> - Required stack include stuff like
local(Function params, local vars etc.),global(Global vars),i32(Perform work on values of typei32) and other data types - Labels are used to define blocks. Essentially functions and include branches, loops etc. Has to be terminated with
end - Can reference other blocks by using relative depth indexes where 0 is the index of the parent block of the branch, 1 is the grandparent and so on
(block ;; Scope 1 (Index 1)
(block ;; Scope 0 (Index 0)
br 1 ;; Jumps to the end of Scope 1
)
)
- Parameters of block branched to are left at the top of the stack after branching
- TraceWASM supports generic memory to be used. Can program linear, cache hirearchial or distributed memory and observe stack traces for each
- Is event based
- Register based VMs (like Google's V8) allow local values to be directly accesses instead of first pushing onto the stack. Can perform tasks in lesser instructions but requires more memory accesses and hence it is less cache friendly