Skip to content

source-academy/wasm-util

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wasm-util

wasm-util is a TypeScript library which provides a fluent, programmatic API for generating WebAssembly Text (WAT) code.

It is designed to make building, manipulating, and emitting WAT strings more intuitive and type-safe as compared to concatenating and building WAT strings by hand. Using the API will produce a WAT IR, which can then be transformed into the final WAT string with a visitor generator which comes with wasm-util.

Originally developed for the Source Academy py-slang WebAssembly compiler, wasm-util is repurposed as a separate package.

Installation

npm install

API Overview

Category Methods / Properties Description
Numeric Types i32, i64, f32, f64 Builders for numeric instructions and constants.
Memory memory.copy(), i32.load(), f64.store(), i32.load8_u(), and other narrow load operations Memory operations for load, store, and copy.
Variables local.get(), local.set(), local.tee(), global.get(), global.set() Access and mutate local/global variables.
Control (Direct) unreachable, drop, nop, br, br_table, return, select, call These control instructions can be used directly with the API with the wasm prefix. For example: wasm.unreachable() generates the WebAssembly instruction unreachable.
Control (Indirect) call, block, loop, if These control instructions must be followed with futher method calls for additional details.
wasm.block() and wasm.loop() must be followed with body().
wasm.if() must be followed by then(), and optionally by else().
All three of the above instrctions can be followed by params(), results(), or locals() to add a block type to the generated WebAssembly.

wasm.call() appears in both categories. If used by itself, it generates a call instruction with no arguments. If arguments are to be provided, follow it with args().
Module module, import, global, data, func, export, start wasm.module() should be followed by any number of import(), global(), data(), func(), export(), and start() calls to add the respective components to the module. To finalise the module, call build().
Function func, params, result, local, body wasm.func() should be followed by any number of params(), result(), and local() calls to add the respective components to the function. To add the function body, call body().
Utility wasm.buildBrTableBlocks() Helper for constructing br_table instruction trees.

Control Instruction Details

Example Usage

i32.add(i32.const(0), i32.const(3));
// Compiles to (i32.add (i32.const 0) (i32.const 3))

i32.add(i32.const(0), f64.const(3));
// Will give a TypeScript error

i32.add(i32.reinterpret_f32(f32.const(0)), i32.const(3))
// Handles type transformations correctly

A more complex example

Input:

wasm
  .func("$func")
  .params({ $x: i32, $y: i32 })
  .result(i32)
  .body(
    wasm.return(
      i32.add(
        local.get("$x"),
        local.get("$y")
      )
    )
  );

Output:

(func $func (param $x i32) (param $y i32) (result i32)
  (return
    (i32.add
      (local.get $x)
      (local.get $y)
    )
  )
)

Generating WAT string

import { i32, local, wasm, WatGenerator } from "wasm-util";

const fx = wasm
  .func("$func")
  .params({ $x: i32, $y: i32 })
  .result(i32)
  .body(
    wasm.return(
      i32.add(
        local.get("$x"),
        local.get("$y")
      )
    )
  );

const generator = new WatGenerator();
const wat = generator.visit(fx);

About

Utility functions for handling WebAssembly code

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published