Skip to content

Add wasm_to_wat backend

An attempt towards a wasm->wat backend #689. Some discussion related to the design is at https://github.com/certik/test_wasm/pull/4 and https://github.com/certik/test_wasm/pull/5

Notes:

  1. It supports the operations supported by the current lfortran wasm backend. That is it supports:
    • integers and primitive operations involving them
    • function calls and functions that operate on integers
    • only positive integers are currently supported as ASR->WASM backend currently supports positive integers.
  2. There is a WAT_DEBUG and a DEUBUG macros provided at the top of wasm_to_wat.cpp. They were useful for me to to debug the decoding of wasm. We might/should remove them as the wasm->wat backend matures.

Example Source Code:

program main
    implicit none
    contains

    function a_sqr(x) result(r)
        implicit none
        integer, intent(in):: x
        integer :: r
        r = x * x
        return
    end function

    function add(x, y) result(r)
        implicit none
        integer, intent(in):: x, y
        integer :: r
        r = x + y
        return
    end function

    function computeCircleArea(radius) result(area)
        implicit none
        integer, intent(in):: radius
        integer :: PI, area
        PI = 3
        area = PI * a_sqr(radius)
        return
    end function

    integer function my_add(a, b) result(c)
        integer, intent(in) :: a, b
        c = a + b
        return
    end function
end program

Output:

(module
    (func $0
        (param i32) (result i32)
        (local i32)
        local.get 0
        local.get 0
        i32.mul
        local.set 1
        local.get 1
        return
    )
    (func $1
        (param i32 i32) (result i32)
        (local i32)
        local.get 0
        local.get 1
        i32.add
        local.set 2
        local.get 2
        return
    )
    (func $2
        (param i32) (result i32)
        (local i32 i32)
        i32.const 3
        local.set 2
        local.get 2
        local.get 0
        call 0
        i32.mul
        local.set 1
        local.get 1
        return
    )
    (func $3
        (param i32 i32) (result i32)
        (local i32)
        local.get 0
        local.get 1
        i32.add
        local.set 2
        local.get 2
        return
    )
    (export "a_sqr" (func $0))
    (export "add" (func $1))
    (export "computecirclearea" (func $2))
    (export "my_add" (func $3))
)

For testing the wat printed on the console:

  1. Paste our obtained wat in the WAT box on https://webassembly.github.io/wabt/demo/wat2wasm/
  2. Use the following code in the JS box to export and test our functions that were defined in the Example Source Code
const wasmInstance =
      new WebAssembly.Instance(wasmModule, {});
const { a_sqr, add, computecirclearea, my_add } = wasmInstance.exports;

console.log(add(-12, 15));
console.log(my_add(-12, 15));
console.log(a_sqr(4));
console.log(computecirclearea(5));
console.log("Success!")
  1. The output is present in the JS LOG box and is as follows
3
3
16
75
Success!
  1. It can be verified that the output is the same as in !1713 (comment 929581644)
Edited by Ubaid Shaikh

Merge request reports