zksecurity / wasmati

Write low-level WebAssembly, from JavaScript
MIT License
219 stars 6 forks source link

Can we output WAT or Wasm binary? #3

Open trusktr opened 1 year ago

trusktr commented 1 year ago

I love this.

Besides making a Wasm module at runtime, can this be used to output WAT text format, or Wasm binary?

I'm working on a Wasm compiler in TypeScript to compile TS to Wasm and native (not revealed yet, but will be open source). The Binaryen.js typed interface is pretty bad: parameters and return types are all just number, so we can't really learn anything from it (f.e. with intellisense in VS Code).

trusktr commented 1 year ago

Ah, I see here how example.ts outputs WAT: https://github.com/zksecurity/wasmati/blob/bd399f0236b65ec201202673e8f974a14b001bf6/examples/example.ts#L173C40-L177

Does wasmati itself convert only into bytecode directly? Do we need to do things a certain way to be compatible with Binaryen? IIRC, Binaryen supports a subset of WAT, only the S tree syntax, not stack stuff.

Would it perhaps make sense to add a directly-to-WAT option for wasmati to avoid passing through wabt?

mitschabaude commented 1 year ago

Hey @trusktr, I'm thrilled to hear that you like it! TS to wasm compiler sounds amazing.

Yeah, so currently wasmati only supports creating wasm bytecode (and parsing wasm bytecode back to wasmati's json representation, but that direction is not really used yet). Wasm bytecode is the same as the binary. So to use the output as a standalone .wasm file, you don't need wat, you just save the uint8array to a file.

The example creates wat so that I can manually double-check that the output matches the wasmati code :D

A direct-to-wat-option, from my perspective so far, would be a "nice to have". I wonder if you really need it. In any case, I think it would be fairly natural to add to/from wat at the level of the individual parser-printer combinators that I use. So what I'm saying is, it wouldn't require coding a whole new printer from scratch. However, wat is much less regular than bytecode and the individual instruction's printers would need to handle more different cases.

trusktr commented 1 year ago

Yeah, the only reason I was thinking about WAT is because I started by interpolating into WAT strings which is more human readable than binary, and thought I could pass that to Binaryen for optimization. But binaryen can receive bytecode too, so perhaps having the wasmati interface for readability and passing bytecode should work fine.

I wonder if instead of a WAT option, an option for the printer to output as a Binaryen tree would be the fastest way to hand off to Binaryen so it doesn't have to parse either WAT or bytecode.

mitschabaude commented 1 year ago

I wonder if instead of a WAT option, an option for the printer to output as a Binaryen tree would be the fastest way to hand off to Binaryen so it doesn't have to parse either WAT or bytecode.

Yeah that could be slightly faster, but fwiw I would expect the binaryen wasm -> tree parser to be pretty fast and well-tested