rwat means reloc wat: it parses annotated wat into a wasm binary while automatically emitting linking and reloc.CODE custom sections.
The main entry point is:
pub fn parse_rwat(wat: &str) -> wast::parser::Result<Vec<u8>>rwat extends plain wat with three annotations:
(@rwat): required on the module header to enablerwatparsing.(@sym)or(@sym (name "...")): declares a symbol for a function/table import or function/table definition.(@reloc): marks the immediately preceding relocatable instruction as requiring a relocation entry. This includescall,return_call,call_indirect,return_call_indirect, and table instructions such astable.get,table.copy, andtable.size.
For function or table definitions, if you write (@sym) without an explicit name, rwat uses the item ID as the symbol name when available.
Currently, rwat only emits two WebAssembly relocation types: R_WASM_FUNCTION_INDEX_LEB for function indices and R_WASM_TABLE_NUMBER_LEB for table indices.
At a high level, rwat uses wast for text parsing and normal wasm emission, wasmparser for reading back section/operator offsets, and wasm-encoder for assembling the final output:
annotated wat
|
| 1. scan custom annotations
| - (@rwat)
| - (@sym)
| - (@reloc)
v
custom annotation metadata
+
| 2. parse the same source as normal wat with `wast`
v
wast AST / resolved module
|
| 3. `wast` encodes the module
v
plain wasm bytes
|
| 4. `wasmparser` reads raw sections
| and decodes the code section
v
code section + relocatable-immediate offsets
|
| 5. patch function/table immediates
| to fixed-width 5-byte LEBs when `(@reloc)` is present
| so relocation offsets stay stable
v
patched code section
|
| 6. emit `linking` symbol table
| and `reloc.CODE` entries
v
`wasm-encoder` final assembly
|
v
final wasm object bytes
rwat still uses wast for standard wat parsing and encoding, but it cannot rely on wast alone for this extension:
wastdoes not understand(@sym)and(@reloc)as first-class syntax, because these annotations are custom torwatrather than part of the official wat grammar.- The parser/encoder integration points needed to preserve annotation metadata through encoding are mostly private APIs, so an external crate cannot directly plug this behavior into
wast. - getting such changes accepted upstream in
wastwould be difficult, - carrying a private
wastfork would create ongoing maintenance cost.
The examples/add directory builds two wat files separately, then links them with wasm-ld: add.wat defines the add symbol, and main.wat imports it, marks the call as relocatable, and defines main(a, b).
cargo install rwat --locked
rwat examples/add/add.wat -o add.o
rwat examples/add/main.wat -o main.o
wasm-ld --no-entry --export=main main.o add.o -o main.wasm
# 42
wasmtime --invoke main main.wasm 20 22