
Multi-Value All the Wasm - feross
https://hacks.mozilla.org/2019/11/multi-value-all-the-wasm/
======
reikonomusha
Slowly but surely WASM is turning into Common Lisp! (:

I kid, sort of. Greenspun and all that.

(Common Lisp has support for multiple values built in. They’re not a “data
structure” like a tuple, but rather an extension to data flow and control.
Returning a tuple vs returning multiple values are different things,
especially when the consumer of the values-produced only actually uses a
single value, as is usually the case with e.g. multiple-value-returning
functions like GETHASH or FLOOR. FLOOR returns the quotient of floor(x/y), as
well as the remainder as a second value. Most of the time you don’t need the
second value, and there’s no need to “opt-out”.)

~~~
skybrian
I was reminded of Go and Forth :-)

It's not really Forth because in WASM, each block of code needs to have a
statically determined stack effect. I wonder if there might be a nice Forth-
like syntax for WASM, though?

~~~
zozbot234
It's kinda unrealistic to endow a Forth-like syntax with things like types and
pre-determined stack effects. You end up with something not too different from
the usual lambda syntax aside from postfix application, which in this context
would simply be De Bruijn notation for lambda-like terms.

~~~
brandonbloom
I think Factor is an existence proof that you're mistaken about this.

Check out the section of the docs labeled "The stack":
[https://docs.factorcode.org/content/article-handbook-
languag...](https://docs.factorcode.org/content/article-handbook-language-
reference.html)

Note that, in particular, there is full support for stack-effect declarations
and that there is a static static-effect checker.

------
syrusakbary
It's great all this additions on Cranelift for supporting multi-value returns.
We will update Wasmer soon to support it as well. Here's the multivalue return
proposal (Phase 3 in the WebAssembly proposals):
[https://github.com/WebAssembly/multi-
value](https://github.com/WebAssembly/multi-value)

Quick question: Is multivalue return supported in LLVM? Or said in other way
...code compiled from Rust or C/C++ will output Wasm with multivalue returns?
Or only written-by-hand WebAssembly can take advantage of this at the moment?

EDIT: after reading the article more thoroughly: LLVM doesn't support
multivalue returns in Wasm yet. They are using Walrus to do wasm to wasm
transformation from the return metadata info they have in wasm-bindgen (Rust).

~~~
tlively
I am currently working on multivalue in both LLVM and Binaryen. Watch for
celebratory tweets when I finish ;)

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.

~~~
skrebbel
> _Watch for celebratory tweets when I finish ;)_

Quick heads-up: your HN bio is empty, I'd have no idea where to watch for them
tweets :-)

~~~
rch
Try @tlively52

------
chrismorgan
When new features are added to WASM, how does it all get deployed and how does
it fit in with existing browsers and such? Do compilers avoid using the new
pattern unless you say to, put in both and do some kind of runtime feature
detection for which they’ll use, or something else altogether?

~~~
azakai
When ready, browsers simply enable new features. Until then, it's usually
behind a flag you can test with.

Compilers generally require flags to enable features. There hasn't been a
post-MVP feature that has widespread enough adoption that it would make sense
for us to enable it by default.

For developers, the best thing is to make separate builds with the sets of
features you want, and pick the right build using something like wasm-feature-
detect

[https://github.com/GoogleChromeLabs/wasm-feature-
detect](https://github.com/GoogleChromeLabs/wasm-feature-detect)

There is some discussion on something like "fat binaries" which would contain
multiple builds and pick between them,

[https://github.com/WebAssembly/feature-
detection](https://github.com/WebAssembly/feature-detection)

------
jedisct1
WAVM has had support for multiple values for a long time.

Glad to see that feature finally getting more traction. This will be extremely
useful for languages such as Go.

------
lilyball
Is there any particular reason why functions and blocks had arity restrictions
until now?

