GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - Spxg/rwat: Parse annotated wat into relocatable wasm file

BranchesTags
Open more actions menu

Latest commit

 

History

38 Commits
38 Commits

Folders and files

NameName
Last commit message
Last commit date
examples
examples
 
 
src
src
 
 
tests
tests
 
 
.gitignore
.gitignore
 
 
Cargo.lock
Cargo.lock
 
 
Cargo.toml
Cargo.toml
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 

Repository files navigation

rwat

Crates.io

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>>

Annotations

rwat extends plain wat with annotations:

  • (@rwat): required on the module header to enable rwat parsing.
  • (@sym) or (@sym (name "...")): declares a symbol for a function, table, or tag import or definition.
  • (@comdat "..."): puts a defined function in a COMDAT group, allowing the linker to keep one copy of identically named groups from multiple object files.
  • (@reloc): marks the immediately preceding relocatable instruction as requiring a relocation entry. This includes call, return_call, call_indirect, return_call_indirect, throw, typed try_table catches, and table instructions such as table.get, table.copy, and table.size.

For function, table, or tag definitions, if you write (@sym) without an explicit name, rwat uses the item ID as the symbol name when available.

Functions with the same @comdat name in one module are members of the same group. The group name must only be reused for definitions that are semantically interchangeable because the linker does not compare their bodies.

Currently, rwat emits R_WASM_FUNCTION_INDEX_LEB for function indices, R_WASM_TYPE_INDEX_LEB for indirect-call type indices, R_WASM_TAG_INDEX_LEB for tag indices, and R_WASM_TABLE_NUMBER_LEB for table indices.

How It Works

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)
    |    - (@comdat)
    |    - (@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/type/table/tag immediates
    |    to fixed-width 5-byte LEBs when `(@reloc)` is present
    |    so relocation offsets stay stable
    v
patched code section
    |
    | 6. emit the `linking` symbol table and COMDAT groups,
    |    plus `reloc.CODE` entries
    v
`wasm-encoder` final assembly
    |
    v
final wasm object bytes

Why Not Use wast Directly

rwat still uses wast for standard wat parsing and encoding, but it cannot rely on wast alone for this extension:

  • (@sym) and (@reloc) are rwat annotations, not part of the official wat grammar, so wast does not parse them as first-class syntax.
  • Preserving those annotations through encoding would require parser and encoder integration points that are mostly private in wast.
  • Upstreaming this behavior would be difficult, and maintaining a private wast fork would add long-term maintenance cost.

Example

The examples directory builds two wat files and links them with lld: 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/main.wat examples/add.wat -o main.wasm -Wl,--no-entry,--export=main
# 42
wasmtime --invoke main main.wasm 20 22

About

Parse annotated wat into relocatable wasm file

noz.cx/blog/rwat

Topics

wasmwat

Resources

Readme
MIT license
Activity

Stars

6 stars

Watchers

1 watching

Forks

2 forks
Report repository

Releases

Packages

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.