WebAssemblyText

WebAssemblyText.argtypes!Method
argtypes!(ci::CodeInfo, argtypes::Dict, funcs::Dict, items::Array)

Infer argtypes and update argtypes if items[1] is in funcs.

source
WebAssemblyText.blockinfoMethod
blockinfo(ssa::Array)

Infer a tree of WebAssembly blocks from ssa and return a BlockInfo struct containing

  • a goto dict
  • a list of which blocks each ssa index is a child of.

Details

WebAssembly control instructions (mainly) consist of

  • blocks: block, loop
  • branching: br, br_if, return

Notes concerning WebAssembly control instructions:

  • We do not have Phi nodes (a block can only have one parent)
  • We do not have gotos/jumps. We can only branch backwards/up the block tree.
  • However, branching to a block continues at end of that block, which effectively is a forward jump (aka break)
  • Special case: branching to a loop block continues at start of that block (aka continue)
  • branching is specified in terms of number of levels up (br 0 goes to current block, br 1 goes to parent block and so on. return is essentialy sugar for br MAX)

So the strategy is to infer a blocktree from arbitrary gotos, insert blocks and translate gotos to branching in terms of levels up the tree.

source
WebAssemblyText.blockparseMethod
blockparse(str::String)

Initial Meta.parse() on entire input. return funcs and initialize Dicts of argtypes and imports.

Details:

  • funcs: a dict with function,expression as key,values
  • argtypes: a dict with with function,argtypes as key,values
  • imports: a dict with with function,importstring as key,values
source
WebAssemblyText.codeinfoMethod
codeinfo(func::Symbol, argtypes::Array)

Essentially code_typed() with optimize=false

Details:

Not optimizing gives a much simpler AST (without phinodes and boundchecks).

source
WebAssemblyText.getbuiltinsMethod
getbuiltins(ssa::Array)

Get an array of strings with any used builtin .wat functions as specified by the dict builtinfuncs.

source
WebAssemblyText.getimportsMethod
getimports(imports::Dict)

Get a .wat string with any used functions that are not builtins or userdefined.

Details

  • a few basic are builtin to wasm. these can be translated.
  • other basic functions are bultin to JavaScripts global Math object, these can be imported
  • many more are builtin to julia... so they need to be implemented either in .jl, .wat or .js
  • give warning if the function cant be imported from js Math.
source
WebAssemblyText.jl2watMethod
jl2wat(path::AbstractString)

Convert contents of a julia source code file to WebAssembly text.

Examples

julia> using WebAssemblyText
julia> wat = jl2wat("example.jl")
julia> println(wat)
source
WebAssemblyText.jlstring2watMethod
jlstring2wat(str::AbstractString)

Convert a string of julia source code to WebAssembly text.

Examples

julia> using WebAssemblyText
julia> str="
hello(x) = 2.0*x
hello(1.0)
";
julia> wat = jlstring2wat(str);
julia> println(wat)
(module 

(func $hello (export "hello") (param $x f32) (result f32)
( return ( f32.mul (f32.const 2.0) (local.get $x) ) ))
)
source
WebAssemblyText.jsimportentryMethod
jsimportentry(func, argtypes)

Get a string of possible javascript Math module import, assuming it exists in the Math module.

Details

from a func such as sin, return a string like "sin: (x) => Math.sin(x)"

source
WebAssemblyText.processMethod
process(func, funcs, argtypes)

Get a string with a self contained (func ) expression in .wat format

Details

The main steps of translating a single function

  • type infer func given argtypes[func]
  • structure ssa
  • update argtypes for other functions called in this function
  • translate to wat and inline to a string
  • wrap string in a function declaration
source
WebAssemblyText.restructureMethod
restructure(ci::CodeInfo, i::Integer, ssa::Array, items::Array)

Restructure items for more straightforward translation.

Details

for example, rewriting expressions like this:

  • [mul,a,b,c,d] => [mul,d,[mul,c,[mul,a,b]]]
  • [ifselse, cond, a, b] => [select, a, b, cond]
source
WebAssemblyText.structureMethod
structure(items)

Recursively format expressions as lists: [operator, operands...]

Notes:

list trees (aka S-expressions) are convenient to work with because modifying it with a recursive function is easy. Also, WebAssembly supports text format written in S-expressions so if all required functionality like overloading, phinodes and such was built into WebAssembly one could essentially do a one liner: webassemblytext = translate(structure(code_typed(somejuliafunction))

Details:

  • Expressions dont always have the operator in head, sometimes its in args[1] and head is just :call
  • pi et al are refs, so if eval(item) is a number just use the number instead of the ref
  • Const can hold anything inside it, use the value instead of the container
source
WebAssemblyText.@code_watMacro
@code_wat expression

Macro for translating a single function without adding on imports and builtins.

Examples

julia> hello(x) = 3.1*x
julia> @code_wat hello(1.2)

(func $hello (export "hello") (param $x f32) (result f32) 
(return (f32.mul (f32.const 3.1) (local.get $x))))
source