I was playing around a bit using Mjolnir to construct WebAssembly from Julia code. The conversion from IR to WebAssembly failed during relooping. Here's the code. It's based on similar code in XLA.jl/src/compile/convert.jl.
using Mjolnir
using Mjolnir: AType, Const, @abstract
using WebAssembly
using WebAssembly: i32, i64, f32, f64
using IRTools.All
struct Operations end
Defaults() = Mjolnir.Multi(Operations(), Mjolnir.Basic())
exprtype(ir, x) = IRTools.exprtype(ir, x, typeof = Const)
CoreTypes = Union{Int32, Int64, Float32, Float64}
for op in (+, *, -, /, ^, >, <, >=, <=, max)
@eval @abstract Operations $op(a::Const{T}, b::Const{T}) where T<:CoreTypes =
Const($op(a.value, b.value))
@eval @abstract Operations $op(a::AType{T}, b::AType{T}) where T<:CoreTypes =
Core.Compiler.return_type($op, Tuple{T,T})
end
wasmop(args, ::AType{typeof(-)}, a::AType{Int64}, b::AType{Int64}) = stmt(xcall(i64.sub, args[2:end]...), type = Int64)
wasmop(args, ::AType{typeof(>)}, a::AType{Int64}, b::AType{Int64}) = stmt(xcall(i64.gt_s, args[2:end]...), type = Int64)
wasmop(args, ::AType{typeof(*)}, a::AType{Float64}, b::AType{Float64}) = stmt(xcall(f64.mul, args[2:end]...), type = Float64)
function wasmop!(ir, v, args...; kw...)
ir[v] = wasmop(ir[v].expr.args, args...; kw...)
end
function wasmops!(ir)
for (v, st) in ir
if st.expr isa Expr
wasmop!(ir, v, exprtype.((ir,), st.expr.args)...)
elseif st.expr isa IR
ir[v] = wasmops!(st.expr)
end
end
return ir
end
function wasmtypes!(ir)
deletearg!(ir, 1)
for bl in blocks(ir)
bb = BasicBlock(bl)
for (idx, T) in enumerate(bb.argtypes)
bb.argtypes[idx] = WebAssembly.WType(T)
end
for (idx, st) in enumerate(bb.stmts)
bb.stmts[idx] = Statement(st.expr, WebAssembly.WType(st.type), st.line)
end
end
end
function convert_wasm!(ir)
wasmops!(ir)
wasmtypes!(ir)
return ir
end
function pow(x, n)
r = one(x)
while n > 0
n -= 1
r *= x
end
return r
end
ir = @trace Defaults() pow(Float64, Int)
convert_wasm!(ir)
@show ir
func = WebAssembly.irfunc(:pow, copy(ir))
The resulting IR looks reasonable for WebAssembly IR.
I was playing around a bit using Mjolnir to construct WebAssembly from Julia code. The conversion from IR to WebAssembly failed during relooping. Here's the code. It's based on similar code in XLA.jl/src/compile/convert.jl.
The resulting IR looks reasonable for WebAssembly IR.
Here's the error message when trying to use
irfunc
:I'm not sure the IR is correct or if I'm even on the right track here.