Earlier quoted context omitted.
Compiling WASM to C is a really good option: https://00f.net/2023/12/11/webassembly-compilation-to-c/
Shameless plug… compiling it to Go is a great option too: https://github.com/ncruces/wasm2go I've used it to translate SQLite (with a few extensions) and, that I know of, it's been used (to varying degrees of success) to translate the MARISA trie library (C++), libghostty (Zig), zlib, Perl, and QuickJS. More on-topic, I use a mix of an unevaluated expression stack and a stack-to-locals approach to translate Wasm.
WASM is not quite a stack machine
41–47 of 47 posts
Re: WASM is not quite a stack machine
#42Earlier quoted context omitted.
Compiling WASM to C is a really good option: https://00f.net/2023/12/11/webassembly-compilation-to-c/
Shameless plug… compiling it to Go is a great option too: https://github.com/ncruces/wasm2go I've used it to translate SQLite (with a few extensions) and, that I know of, it's been used (to varying degrees of success) to translate the MARISA trie library (C++), libghostty (Zig), zlib, Perl, and QuickJS. More on-topic, I use a mix of an unevaluated expression stack and a stack-to-locals approach to translate Wasm.
Re: WASM is not quite a stack machine
#43Earlier quoted context omitted.
I can't speak to Binaryen, but afaik WABT's wat2wasm and wasm-tools's wat2wasm (aka wasm-tools parse) are both 100% spec-correct in this respect. Parsing the Wasm text format doesn't require any knowledge of the type of each instruction. If you have a counterexample would love to see it! There are some cool edge cases if you want to print a mismatched multi-value instruction sequence in the folded form (which WABT an…
This is the wat2wasm tool I have been playing with: https://webassembly.github.io/wabt/demo/wat2wasm/ It refuses to accept the following (module (func (export "addTwo") (param i32 i32) (result i32) (i32.add local.get 0 local.get 1 ) ) ) which based on my reading should be accepted. I will try the tools you mentioned but I personally settled on generating the unfolded ones for my experiments as they just seem easier.
(local.get 0)
(local.get 1)Re: WASM is not quite a stack machine
#44Earlier quoted context omitted.
> tl;dr: the LISP syntax is just syntax sugar. The textual format is as "stack-like" as the binary format. Not that you're technically wrong, but I think you're begging the question. Stack-based languages/encodings, in a colloquial sense, are equated to postfix notation, e.g. `a b +` instead of the infix `a + b`. Both LISP and textual Wasm use prefix notation, e.g. `(+ a b)`. Neither of the three is any more foundati…
I am saying that textual wasm uses `a b +` (justl ike binary wasm) and `(+ a b)` is just a nicety. It is explicity sugar for the stack operations, per my reading of the spec.
> It is explicity sugar for the stack operations, per my reading of the spec.
The entire Wasm text format is syntax sugar for binary Wasm, so this is kind of a vacuous truth -- if Wasm's spec says it's a stack machine, of course everything is sugar for a stack machine. But if you weren't aware of Wasm and just saw a program in textual Wasm for the first time, I don't think the idea that it's stack-based would cross your mind.
Re: WASM is not quite a stack machine
#45Earlier quoted context omitted.
This is the wat2wasm tool I have been playing with: https://webassembly.github.io/wabt/demo/wat2wasm/ It refuses to accept the following (module (func (export "addTwo") (param i32 i32) (result i32) (i32.add local.get 0 local.get 1 ) ) ) which based on my reading should be accepted. I will try the tools you mentioned but I personally settled on generating the unfolded ones for my experiments as they just seem easier.
Don't you need parens here? (local.get 0) (local.get 1)
Re: WASM is not quite a stack machine
#46Earlier quoted context omitted.
Shameless plug… compiling it to Go is a great option too: https://github.com/ncruces/wasm2go I've used it to translate SQLite (with a few extensions) and, that I know of, it's been used (to varying degrees of success) to translate the MARISA trie library (C++), libghostty (Zig), zlib, Perl, and QuickJS. More on-topic, I use a mix of an unevaluated expression stack and a stack-to-locals approach to translate Wasm.
Interesting. I started working on this same idea a couple of years ago as a way to bypass CGo. Eventually I moved on to something else. Glad someone else is working on this. How does the generated Go performance compare to the original WASM performance?
What were you using to run Wasm instead of this?
I can compare with wazero, which I was previously using, and say performance stayed mostly in the same ballpark. Things that crossed the Go-to-Wasm boundary very often became much faster, things that stayed mostly in Wasm became slightly slower, as the wazero compiler is pretty good.
wasm2go also does not support SIMD, so if your Wasm module uses/benefits from SIMD, you'll notice.
Re: WASM is not quite a stack machine
#47Earlier quoted context omitted.
Shameless plug… compiling it to Go is a great option too: https://github.com/ncruces/wasm2go I've used it to translate SQLite (with a few extensions) and, that I know of, it's been used (to varying degrees of success) to translate the MARISA trie library (C++), libghostty (Zig), zlib, Perl, and QuickJS. More on-topic, I use a mix of an unevaluated expression stack and a stack-to-locals approach to translate Wasm.
Does that mean you could compile a wasm program to go, then run it with wazero? How many levels deep can it go?? Might be a fun blog topic :)
Go generates large Wasm modules, because it bundles its goroutine scheduler, garbage collector and standard library into the module.
Translating that back to Go will give you a pretty big Go file.
Go is "known" for being fast to compile, but that huge Go file will take (at least?) as long to compile as compiling the Go toolchain does.
wasm2go is best used on moderately sized modules (like SQLite). Last I heard, the person who tried to translate Perl got a 80MB Go file that was taking them 20min to compile.