lcompilers / lpython

Python compiler
https://lpython.org/
Other
1.5k stars 163 forks source link

WASM: Runtime Library #1413

Open Shaikh-Ubaid opened 1 year ago

Shaikh-Ubaid commented 1 year ago

The runtime library functions that need access to libc are currently not supported in the wasm backend (and therefore also not yet supported in the wasm_x64 and wasm_x86 backends). It seems WASI or something similar could be used. This issue to plan/discuss about supporting the runtime library functions in the wasm backend.

certik commented 1 year ago

What are the possible ways forward?

One option is to use wasi-libc: https://github.com/WebAssembly/wasi-libc. This option I think would mean to compile the C runtime library using the wasi-sdk toolchain (I think), and then somehow make the compiled wasm work with our wasm output.

Another option is to take the frontend language (Fortran or Python) runtime library, that calls into C, and then implement those C functions somehow.


We also have several applications of wasm:

We should ensure that our solution works well for all three use cases.

czgdp1807 commented 1 year ago

Another option is to take the frontend language (Fortran or Python) runtime library, that calls into C, and then implement those C functions somehow.

This feels hackish to me. IMO, wasi-libc is a better direction to take. Might be difficult but feels more robust.

czgdp1807 commented 1 year ago

Another option is to take the frontend language (Fortran or Python) runtime library, that calls into C, and then implement those C functions somehow.

This feels hackish to me. IMO, wasi-libc is a better direction to take. Might be difficult but feels more robust. Is there anything that prevents us from using wasi-libc?

certik commented 1 year ago

Nothing is preventing us as far as I know.

czgdp1807 commented 1 year ago

Then we should try with wasi-libc first. If it works then good, otherwise we can go for second option. Its experimental, so we should try early to know any potential blockers with both the options. Supporting this would make WASM backend much more useful and invite a lot of users.

Shaikh-Ubaid commented 1 year ago

I will share my thoughts on this soon.

certik commented 1 year ago

The pure Fortran (and Python) library works with wasm, so the only remaining file to tackle is src/libasr/runtime/lfortran_intrinsics.c. In this file we currently have a lot of functions that do not have to be there:

That leaves the following functions:

Given this, it seems to me that we do not need the C runtime library at all, it is just a temporary measure to get things going.

For the WASM backend specifically, I would almost not bother, and rather work on moving more things into the surface language and ASR, one by one.

certik commented 1 year ago

We now use IntrinsicFunction (might need to sync ASR with LFortran). Just a few functions are ported, but sin already works.

There are two ways.

1

In the WASM backend you can implement IntrinsicFunction by changing this:

    var imports = {
        wasi_snapshot_preview1: {
            /* wasi functions */
            fd_write: fd_write,
            proc_exit: proc_exit,
        },
        js: {
            /* custom functions */
            cpu_time: cpu_time,
            show_img: show_image,
            show_img_color: show_image_color
        },
    };

Into:

    var imports = {
        wasi_snapshot_preview1: {
            /* wasi functions */
            fd_write: fd_write,
            proc_exit: proc_exit,
        },
        lcompilers: {
            /* custom functions */
            cpu_time: cpu_time,
            show_img: show_image,
            show_img_color: show_image_color,
            sin: ...,
            cos: ...,
        },
    };

2

Improve the ASR->ASR pass and instead of calling implementation in C, call pure Fortran implementation. Most likely we will implement this in ASR itself, then it is usable for LPython also. See https://github.com/lfortran/lfortran/issues/1435.

Shaikh-Ubaid commented 1 year ago

At present the wasm binary generated by lpython/lfortran works with both node and wasmtime. It seems using the first approach shared in https://github.com/lcompilers/lpython/issues/1413#issuecomment-1468467812, we can support the missing math functions by supplying them in the imports object. This way it could work with node. I am unsure if we could similarly support the math functions using wasmtime (we should investigate if it there is any way to supply custom functions via imports object using wasmtime.)

certik commented 1 year ago

Regarding 1), I think we can use wasmtime run with:

        --preload <NAME=MODULE_PATH>
            Load the given WebAssembly module before the main module

and provide the implementation of our imports in C, compile with clang to wasm and preload the module. Something like that might work and might be quite simple to maintain.

certik commented 1 year ago

I think here is how we need to move forward: we need to port ALL of our runtime library to ASR, based on the plan above (https://github.com/lcompilers/lpython/issues/1413#issuecomment-1379268440).

That will make pure Fortran or pure LPython code work completely via WASM, and our WASM->x64 backend will generate a standalone binary that will just work. If we need to link with C, then we just generate an .o, and in wasm we "import" such functions, and we leave it to the user to link it correctly.