zetzit / zz

πŸΊπŸ™ ZetZ a zymbolic verifier and tranzpiler to bare metal C
MIT License
1.6k stars 52 forks source link

Support for web assembly? #47

Open richardanaya opened 4 years ago

richardanaya commented 4 years ago

Hey, I'm a big fan of Rust, one of the reasons why I keep going back to it is they have amazing support for web assembly compilation. So does C with llvm! I think there's many devs out there who want a better language for web assembly, but C is pretty brutal. I've found myself looking for a good C trancompiled language for awhile, but none of them seem interested in making web assembly a first candidate target. Anyhow, I find ZZ interesting as a Rust dev who loves web assembly, and I would love to see a language like this compete as an alternative in that space.

Some thoughts I have for ZZ that would make it really appeal to web assembly devs (who tend to be javascript fanatics )

I sometimes program web assembly in non-Rust languages, and I've created a fairly mature library that acts as a bridge between web assembly and the browser dom that is fairly technology agnostic.

This tech could accelerate zz in the web assembly space greatly. Here's an example of a hello world:

#include "../../js_ffi.h"

export int main() {
    int log = jsffiregister("window.alert");
    jsfficall1(JS_UNDEFINED,log,TYPE_STRING,(JSValue)(int)&"Hello World!");
    return 0;
}
clang -O3 --target=wasm32 -nostdlib -I./ -Wl,--no-entry -Wl,-allow-undefined -Wl,--export-dynamic -o main.wasm src/main.c
aep commented 4 years ago

thank you so much for the suggestion! i did not realize how much that is a match made in heaven, before you asked.

a package manager that makes installing dependencies easy

high up my list, but have to fix some bugs first

a more narrower standard library that basically only does memory allocation (since that's all wasm has access to) and wasm size is important ( think no_std + alloc )

accidentally zz scores all points here because it is completely heap free. there is no separate no_std which has consistently been my main critique with rust. the entire language is built around convenient use of stack scoping, allocating 0 bytes dynamic memory. It should in theory perform better than C++ (and obviously rust)

binary sizes of zz are insane too. devguard carrier was 5mb with rust and is now 80kb with zz. thats an entire ssh and http2 server.

easy command support so that a dev could compile .zz with a simple one line command that uses maximum optimization for wasm for reducing file size

zz already builds nodejs modules. easy to add wasm.

one binary distributions for popular environments (windows, osx, linux )

of course

an easy way to do #define export attribute((visibility("default")))

thats the builtin export keyword :) zz has a bunch of stuff built in that is a natural fit to exporting clean ABIs

support for way better macros that can do things like construct json structures

i just merged proc macros, which will enable something like serde.

Here's an example of a hello world:

i like this. where can i find more about it?

richardanaya commented 4 years ago

oops, forgot to post the link! https://github.com/richardanaya/js_ffi/

jwerle commented 4 years ago

I was able to compile a hello world in release mode and run it with wasmer with the clang from the wasi-sdk by running:

$ mkdir zz-wasm
$ cd zz-wasm
$ zz init
$ CC=/opt/wasi-sdk/bin/clang zz build --release
$ wasmer ./target/release/bin/zz_wasm
hello zz-wasm
jwerle commented 4 years ago

With node@14, it can be loaded with wasi:

const { WASI } = require('wasi')
const fs = require('fs')

const wasi = new WASI(process) // argv, env
const buffer = new Uint8Array(fs.readFileSync('./target/release/bin/zz_wasm'))

WebAssembly.instantiate(buffer, {
  wasi_snapshot_preview1: wasi.wasiImport
})
  .then(onwasm)
  .catch(onerror)

function onerror(err) {
  console.error(err)
}

function onwasm(wasm) {
  wasi.start(wasm.instance)
}

ran with:

node --experimental-wasi-unstable-preview1 example.js 
jwerle commented 4 years ago

a more concrete example, with tail binding usage: https://github.com/zx-project/wasm-lib-hello-world

aep commented 4 years ago

nice. what do you think we should be part of zz? the build settings probably at least

jwerle commented 4 years ago

We should probably figure out a way to emit WASM targets or allow users to configure library target names

I put together another example here: https://github.com/little-core-labs/base64-wasm

aep commented 4 years ago

woa thats a really nice example. ideally i'd want to be able to build the entire thing with zetz, since already does have an npm module target, but currently a target can't depend on another target, so that's something i need to figure out first

jwerle commented 4 years ago

yeah this example was intended to show a ZZ implementation of Base64 that can compile to WASM format, and be used in an environment that can load and execute WebAssembly. The path with the least resistance is node.js. Ideally, I can write in ZZ, compile as usual, but know that I can compile to WASM as well. Having WASM as a compilation target just means I need to know if my module or any other ZZ modules I consume intended on using syscalls requiring a WASI.

More here too: https://github.com/little-core-labs/hyperid-wasm https://github.com/little-core-labs/varint-wasm

Overall, WASM is slow and limiting, but nice to have as a compile target

jwerle commented 4 years ago

when you say target depending on another target, do you mean one zz module depending on the built library of another?

aep commented 4 years ago

nah, there's currently no way the nodejs target can include a wasm binary because they're built in parallel