Tools for working with the WebAssembly format in Julia. In particular, this package exposes the IR as simple Julia data structures, allowing parsers and code generators to convert to/from the IR, as well as allowing optimisation passes directly on the IR in the vein of binaryen.
Build IR for a x^n
function:
using WebAssembly: i32, f64, irfunc
using IRTools.All
pow = let
ir = IR()
x = argument!(ir, f64)
n = argument!(ir, i32)
cond = block!(ir)
body = block!(ir)
ret = block!(ir)
n = argument!(cond, n, i32)
r = argument!(cond, 1.0, f64)
branch!(cond, ret, unless = push!(cond, stmt(xcall(i32.gt_s, n, Int32(0)), type = i32)))
n = push!(body, stmt(xcall(i32.sub, n, Int32(1)), type = i32))
r′ = push!(body, stmt(xcall(f64.mul, r, x), type = f64))
branch!(body, cond, n, r′)
return!(ret, r)
ir
end
julia> pow
1: (%1 :: f64, %2 :: i32)
br 2 (%2, 1.0)
2: (%3 :: i32, %4 :: f64)
%5 = (i32.gt_s)(%3, 0) :: i32
br 4 unless %5
3:
%6 = (i32.sub)(%3, 1) :: i32
%7 = (f64.mul)(%4, %1) :: f64
br 2 (%6, %7)
4:
return %4
Construct a wasm function and module:
func = irfunc(:pow, pow)
mod = WebAssembly.Module(funcs=[func],
exports=[WebAssembly.Export(:pow, :pow, :func)])
WebAssembly.binary(mod, "test.wasm")
Disassemble the result with binaryen:
shell> wasm-dis test.wasm
(module
(type $0 (func (param f64 i32) (result f64)))
(export "pow" (func $0))
(func $0 (; 0 ;) (type $0) (param $0 f64) (param $1 i32) (result f64)
(local $2 f64)
(local.set $2 (f64.const 1))
(loop $label$1
(if
(i32.eqz (i32.le_s (local.get $1) (i32.const 0)))
(block
(local.set $1
(i32.sub (local.get $1) (i32.const 1)))
(local.set $2
(f64.mul (local.get $2) (local.get $0)))
(br $label$1))))
(local.get $2)))
The latest released version of this package (0.1.1) bundles some required WebAssembly tooling via WABTBuilder and BinaryenBuilder. As of writing, these are both a little out of date and incompatible with ARM macs.
For now, those dependencies are no longer bundled if you're using the master branch of
the package. Instead, if you want to emit binaries and optimise them, you'll
need wat2wasm
and wasm-opt
on your path, respectively. With homebrew you can
get these both with brew install wabt binaryen
. Alternatively, just avoid the
WebAssembly.binary
function – everything else will work fine.