lioeters
adrian17
> Instructions, blocks, and functions can now return more than one result value, sometimes supporting faster calling conventions and avoiding indirections.
Unfortunately, despite being "enabled", Rust+LLVM don't take advantage of this because of ABI compatibility mess. I don't know whether the story on Clang's side is similar.
azakai
This is indeed unfortunate, but on the other hand, multivalue's benefits are probably very small.
Inside functions, there is perhaps a 1-3% code size opportunity at best (https://github.com/WebAssembly/binaryen?tab=readme-ov-file#b...), and no performance advantage.
Between functions there might be a performance advantage, but as wasm VMs do more things like runtime inlining (which becomes more and more important with wasm GC and the languages that compile to it), that benefit goes away.
Dwedit
I figured out the way to get multi-value results on GCC for 32-bit ARM. Use a union to pack two 32-bit values into a 64-bit value. Return the 64-bit value. Then use a union to split the 64-bit value into two 32-bit values. I haven't tested it on other 32-bit architectures though.
acheong08
I'm using the same trick in Zig via packed structs
sapiogram
Interesting, got any links to more information?
adrian17
https://blog.rust-lang.org/2024/09/24/webassembly-targets-ch...
"As a result there is no longer any possible method of writing a function in Rust that returns multiple values at the WebAssembly function type level."
And similar queries in Rust's zulip: https://rust-lang.zulipchat.com/#narrow/channel/122651-gener...
singularity2001
premature optimization is the root of all evil and this SIMD mess could have been implemented so much more elegantly if they just followed the general variable size flexible vector proposal
varjag
Multi-value results are great for prospective Common Lisp runtimes.
romperstomper
They also say at the end "In a future post we will take a look at Wasm 3.0, which is already around the corner at this point!" so I suppose the Wasm 3.0 is coming very soon?
lioeters
Found a draft here:
WebAssembly Specification - Release 3.0 (Draft 2024-11-07) https://webassembly.github.io/spec/versions/core/WebAssembly... (PDF)
immibis
You can have an ISA sufficiently generic to run on any CPU, or one sufficiently specific to efficiently exploit SIMD on a particular CPU. Never both. That's why some platforms provider higher-level operations, like element-wise multiplication of packed arrays. I can't see whether the actual WASM2 SIMD instructions are sufficiently generic because apparently I'm rate-limited on GitHub (???) and therefore can't see the spec.
flohofwoe
https://web.archive.org/web/20250429065033/https://webassemb...
Values are hardwired to 128 bits which can be i8x16/i16x8/i32x4/i64x2 or f32x4/f64x2, so that already limits the 'feature surface' drastically.
IMHO as long as it covers the most common use cases (e.g. vec4 / mat4x4 floating point math used in games and a couple of common ALU and bit-twiddling operations on integers) that's already quite a bit better than having to fall back to scalar math.
ncruces
They were sufficient for me to implement most of `string.h` and get speedups between 4 and 16x vs “portable musl C code,” including sophisticated algorithms such as this one: http://0x80.pl/notesen/2016-11-28-simd-strfind.html
I posted about my efforts here: https://news.ycombinator.com/item?id=43935284
Or, if you wanna jump to the code: https://github.com/ncruces/go-sqlite3/blob/main/sqlite3/libc...
mdaniel
> apparently I'm rate-limited on GitHub (???) and therefore can't see the spec.
Are you also on Firefox? I've been getting those 429s a lot over the past week or so. I haven't changed my configuration other than I'm religious about the "check for updates" button, but I cannot imagine a world in which my release-branch browser is a novelty. No proxies, yes I run UBO but it is disabled for GH
eppsilon
I got some using Orion on iOS yesterday. Same engine as every other iOS browser, so I guess it's sending a user agent GH doesn't like?
pdubroy
The WebAssembly spec is quite approachable, but for anyone who is interested in learning Wasm and doesn't want to read the spec —
WebAssembly from the Ground Up (https://wasmgroundup.com/) an online book to learn Wasm by building a simple compiler in JavaScript. It starts with handcrafting bytecodes in JS, and then slowly builds up a simple programming language that compiles to Wasm.
There's a free sample available: https://wasmgroundup.com/book/contents-sample/
(Disclaimer: I'm one of the authors)
johnisgood
Side-note:
const MIN_U32 = 0;
const MAX_U32 = 2 ** 32 - 1;
function u32(v) {
if (v < MIN_U32 || v > MAX_U32) {
throw Error(`Value out of range for u32: ${v}`);
}
return leb128(v);
}
I love Ada, because you can do this: subtype U32 is Interfaces.Unsigned_64 range 0 .. 2 ** 32 - 1;
or alternatively: type U32 is mod 2 ** 32;
and then you can use attributes such as: First : constant U32 := U32'First; -- = 0
Last : constant U32 := U32'Last; -- = 2 ** 32 - 1
Range_ : constant U32 := U32'Range; -- Range 0 .. 2**32 - 1
jppittma
That's kinda cool. I bet you could take that to the next step and allow arbitrary code for validation of types/arguments at compile time.
majewsky
If you're interested to learn more in whatever language, the relevant search term is "refinement type": https://en.wikipedia.org/wiki/Refinement_type
pjmlp
Ada keeps being used as example for subranges, however they exist already in Pascal and all Modula variants.
johnisgood
I know. That said, I keep mentioning Ada because it is widely used in mission critical systems, and because it supports contracts (yes, I know, so does Eiffel), and you can do formal verification using Ada / SPARK, meaning that it could be used in place of Rust, whereas Pascal probably not.
MrResearcher
Is it possible to "instrument" the WASM code to enable in-process debugging? In other words, would it be possible to generate WASM based off some input string (my custom language) on-the-fly, and then run it with breakpoints and memory inspection, all within the same Javascript script hosted on, say, a web page?
titzer
Wizard has engine support for instrumentation, but Whamm (https://github.com/ejrgilbert/whamm) can also do instrumentation through bytecode rewriting.
MrResearcher
That still requires the usage of dev tools and linear source code mapping between the original and the generated WASM, correct? Would it be possible to avoid dev tools, and implement the debugger in Javascript? Or the WASM technology doesn't provide such an opportunity? I'd like to break on breakpoints, jump back into Javascript, unroll it into the original location in the source code, and display it all in an IDE-like window all within a browser page, and without involvement of dev tools (that can't handle non-linear conversions between source code and generated JS/WASM).
pdubroy
I'm not sure I totally understand what you mean by "in-process" here. But you could have some JavaScript that compiles some code in your custom language to WebAssembly and then execute it, and you can use the browser dev tools to set breakpoints the Wasm, inspect the memory, etc.
In the book, we don't cover source maps, but it would also be possible to generate source maps so that you can set breakpoints in (and step through) the original source code in your custom language, rather than debugging at the Wasm instruction level.
Does that answer your question?
MrResearcher
Sadly, no, I'd like to write a ~Prolog interpreter (compiler into WASM that would dynamically replace parts of the implementation as source code evolves), and have the debugger and WASM memory inspector as part of the web page written in Javascript, which was used to compiled the code in the first place. That is, would it be possible to implement a debugger and memory inspector in Javascript without resorting to dev tools? Prolog doesn't map 1:1 to WASM/Javscript via source maps, making it nearly impossible to properly debug it in dev tools.
inoffensivename
I've been working on Webassembly runtimes for the last year or so, specifically on spec compliance and performance. I came to it as a neophyte, but I've become quite fond of the specification. It's a bit hard to get started with the notation, but it's refreshing to have such a thoroughly specified language. There is a reference interpreter generated directly from the spec, which is very useful for resolving questions about what a runtime should do in a given situation.
The provided specification tests allow implementers to be confident that their runtime conforms to the spec.
Overall I think it's an impressive specification and is worth studying .
treetalker
Wasm, per footnote 1:
> A contraction of “WebAssembly”, not an acronym, hence not using all-caps.
esperent
Shouldn't it be WAsm in that case?
pseudosavant
I'm not sure. But I think we could use a new bike shed? I think it should be orange.
jmull
I would say no.
There aren't any particular rules about contractions and intermediate capitalization so we are free to choose. WAsm is more awkward than Wasm so the latter seems better.
shellac
Not that you have to use all caps for acronyms, e.g. scuba, radar, laser.
strogonoff
It’s one thing to take an acronym and “demote” it to a common noun if it’s being used often by wide public (not unlike how proper nouns become common nouns), it’s another thing to randomly pretend that a regular noun is an acronym. I’m looking at you, photographers shouting “RAW” in all caps whenever the topic comes up. “WASM” rubs me wrong for the same reason.
I admit to being guilty of this and mimicking whatever form I encounter first, but then I’d switch once I look it up. I don’t quite understand why would anyone do otherwise.
andybak
I would maybe argue that used to be acronyms but now are just... well, words.
klysm
Good luck lol
mountainriver
Is there a list of working WASM apps in the wild?
I like the idea of WASM but it often feels like DAPPs. This kinda fun idea that nothing is actually based on, maybe I’m wrong
AlexAltea
Great release with many welcome features. As a nit, I'm rather disappointed at the inclusion of fixed-size SIMD (128-bit wide) instead of adaptive SIMD instructions letting the compiler maximize SIMD width depending on host capabilities, similar to how ARM SVE works.
lifthrasiir
Personally I prefer fixed-size SIMD mainly because it enables more usages than usual vector instructions while vector instructions can be rather trivially lowered to fixed-size SIMD instructions. I'd call them as "opportunistic" usages, because those are perfectly fine without SIMD or vector but only get vectorized due to the relatively small size of SIMD registers. Those usages are significant enough that I see them as useful even with the presence of vector instructions.
camel-cdr
If you have variable length SIMD, you can always treat them as fixed-size SIMD types.
New x86 processor don't executes 128-bit SIMD, the vecto ALUs are all wider now and 128 and 256-bit instructions have the same throughput and latency.
Also, do you have an example for such "opportunistic" usages?
I suppose mainly things the SLP vectorizer can usually do already (in compiled languages, I'm not sure how good the JIT is these days).
I worry that we now may end up in a world, where "hand optimized SIMD" in WASM ends up slower than autovectorization, because you can't use the wider SIMD instructions and leave 2x (zen4) to 4x (zen5) of the performance on the table.
lifthrasiir
> Also, do you have an example for such "opportunistic" usages?
The simplest example would be copying a small number of bytes (like, copying structs). Vector instructions generally have a higher setup cost, like setting so it can't really be used for this purpose. Maybe future vector instructions have no such caveats and can be used as like SIMD, but AFAIK it's not yet the case even for RISC-V's V extension.
singularity2001
premature optimization is the root of all evil and this SIMD mess could have been implemented so much more elegantly if they just followed the general variable size wasm flexible vector proposal
subarctic
What happened there? Looks like it was created 10 years ago (is wasm even that old?) And has barely been updated in the last year
BuckRogers
A bytecode for the web was a dream for a very long time.
As a C# developer who appreciates Blazor being on the cutting edge with WASM from early on, I'm looking forward to WASM 2.0's changed being added. .NET has a massive jump on this and I think it's one of the better bets they've taken.
anentropic
Are any of the runtimes already implementing this?
adrian17
Most have been for some time now. As the announcement post says:
> the Wasm Community and Working Groups had reached consensus and finished the specification in early 2022. All major implementations have been shipping 2.0 for even longer.
> In a future post we will take a look at Wasm 3.0, which is already around the corner at this point!
Features in 3.0 presumably also being mostly implemented already, some maybe just kept behind feature flags.
titzer
Everything in 3.0 has at least two browser implementations; that's part of the requirements for advancement to phase 4.
Wasm 2.0 is complete in a handful of engines, whereas 3.0 is less well-supported.
Wizard is almost done with 3.0; only memory64 and relaxed-simd are incomplete.
thrance
Is there anywhere I could look at the "changelogs" between 1.0 and 2.0, and 2.0 and 3.0? All I could find are different versions of the spec that don't seem very keen on expliciting what changed.
Klasiaster
What's truly missing for Wasm and WASI to be an alternative to POSIX is dynamic instatiation so that a Wasm program/component can start another Wasm program/component by providing the bytecode at runtime. So far I don't think anyone is working on that.
marianoguerra
in the browser you can compile modules and create instances from arrays of numbers/bytes, here's an obfuscated example: https://wasmgroundup.com/blog/wasm-compiler-in-a-tweet
if the host provides the guest wasm module via imports a function to create and run from an array of bytes then it can be done today (if I understand you correctly).
Here's some related content: https://github.com/pdubroy/til/blob/main/wasm/2024-02-22-Run...
azakai
Yes, this can be done today, though it needs some gluing together. On the Web (and in Node etc.) you can use JavaScript to create and link the modules, which is how dynamic linking support for wasm works there:
yuri91
On the Web, you can do that today. This is what https://webvm.io does for example. It jit-compiles Wasm modules at runtime from the original X86.
singularity2001
The wasp runtime has a run_wasm host export but I guess that's cheating
packetlost
I wonder if it hasn't been done because it would break the security model
xmorse
does it? a program would be able to spawn another program only with the exports available to him
rossant
Can C functions returning structs by value be compiled to WASM?
thrance
Yes, but AFAIK you can't "export" them to JS currently.
singularity2001
that's right unfortunately these types are opaque right now
aleksi
Curious that Editor's Draft has "bikeshed" in the URL.
lifthrasiir
"Bikeshed" here refers to the Bikeshed preprocessor [1].
iFire
I got blocked writing high level wasm bindings with types other than int or float, is this still the case?
marianoguerra
with the wasm-gc proposal you get access to structs and arrays: https://github.com/WebAssembly/gc/blob/main/proposals/gc/Ove...
with the component model's wit you get higher level types like enums, option, result and generics: https://component-model.bytecodealliance.org/design/wit.html
mamidon
It's more accurate to say those do the boilerplate of memory access necessary for complex types for you. You're still basically limited to integers and floats.
But when you think about it, isn't that basically true for native languages?
singularity2001
no you don't , these types are unfortunately opaque only internally usable.
Announcement post in March 2025 summarizes the changes from WASM 1.0.
Wasm 2.0 Completed - https://webassembly.org/news/2025-03-20-wasm-2.0/
> ..here is the summary of the additions in version 2.0 of the language:
Vector instructions: With a massive 236 new instructions — more than the total number Wasm had before — it now supports 128-bit wide SIMD (single instruction, multiple data) functionality of contemporary CPUs, like Intel’s SSE or ARM’s SVE. This helps speeding up certain classes of compute-intense applications like audio/video codecs, machine learning, and some cryptography.
Bulk memory instructions: A set of new instructions allows faster copying and initialization of regions of memory or ranges of tables.
Multi-value results: Instructions, blocks, and functions can now return more than one result value, sometimes supporting faster calling conventions and avoiding indirections. In addition, block instructions now also can have inputs, enabling new program transformations.
Reference types: References to functions or pointers to external objects (e.g., JavaScript values) become available as opaque first-class values. Tables are repurposed as a general storage for such reference values, and new instructions allow accessing and mutating tables in Wasm code. In addition, modules now may define multiple tables of different types.
Non-trapping conversions: Additional instructions allow the conversion from float to integer types without the risk of trapping unexpectedly.
Sign extension instructions: A new group of instructions allows directly extending the width of signed integer value. Previously that was only possible when reading from memory.