tlively
(i32.add
(i32.const 0)
(i32.const 1))
Many projects, including the official spec test suite and the Binaryen test suite, primarily use this format.> IIRC early pre-release-versions of WASM were entirely built from S-expressions and as a 'pure stack machine' (I may remember wrong though).
Yes, the S-expressions predate WebAssembly even being a stack machine. Originally the design was that it encoded an AST, so the folded S-expression format was the only option.
There was a lot of discussion back in the day (before my time) about creating a better text format, but no one could agree on what it should be, so they just defaulted to the S-expression idea and focused on getting WebAssembly out the door.
This blog post mentions that you can kind of emulate nominal types by putting all your types in one rec group, but then it brushes that off as inferior to using exceptions. (Which is hilarious! Good work, Andy.) What it doesn’t make clear is that people actually use this rec group trick in practice. There are two ways to do it: you can put literally all your types in one rec group, or you can emit minimal rec groups with additional “brand types” that serve no purpose but to ensure the groups have different structures. The former solution is better for code size when the entire application is one module, but the latter solution is better if there are multiple modules involved. You don’t want to repeat every type definition in every module, and using smaller rec groups lets you define only the types that are (transitively) used in each module.
The Binaryen optimizer has to ensure that it does not accidentally give distinct types the same structural identity because that would generally be observable by casts. Most of its type optimizations therefore put all the types in one rec group. However, it does have a type merging optimization that takes the casts into account[0]. That optimization is fun because it reuses the DFA minimization code from the original equirecursive type system we were experimenting with for Wasm GC. We also have a rec group minimization optimization[1] that creates minimal rec groups (by finding strongly connected components of the type definition graph), then ensures the types remain distinct first by using different permutations of the types within a rec group and then only as necessary by adding brand types.
[0]: https://github.com/WebAssembly/binaryen/blob/main/src/passes...
[1]: https://github.com/WebAssembly/binaryen/blob/main/src/passes...
I look forward to reading more about how they do the targeting and tuning.
To attend the meetings, first join the W3C WebAssembly Community Group here: https://www.w3.org/groups/cg/webassembly, then email the CG chairs at [email protected] to ask for an invite.
From there you'll get a sense of who folks are so you can pair names with faces when contributing to the various proposal discussions on the many proposal repos listed here: https://github.com/webassembly/proposals.
To get a sense of how things are run and decided, read the process documents here: https://github.com/WebAssembly/meetings/tree/main/process. The TL;DR is that the community group and its subgroups decide everything by consensus via votes during the meetings.
Other commenters are correct that LLVM IR has more information in it than WebAssembly, but that is working as intended. The idea is that toolchains will do the heavy optimization work so that WebAssembly engines can be simpler and just do the final code generation.
[1] https://developer.chrome.com/native-client/nacl-and-pnacl
Rust will be able to benefit immediately once LLVM has multivalue function support since they use their own ABI internally. But C, C++, and Rust extern functions will not be able to benefit until we additionally define a new C ABI that takes advantage of multivalue returns.
It's also worth noting that multivalue blocks only bring a code size win of a couple percent on real wasm modules, so those are much lower priority.
WebAssembly features are all different in how difficult they are to add to the specification, engines, and tools. Multivalue is unique in that it is trivial for the spec and for engines, but is extremely difficult to implement in tools.