@@ -157,7 +157,7 @@ $ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unkno
157
157
```
158
158
159
159
Here the ` mvp ` "cpu" is a placeholder in LLVM for disabling all supported
160
- features by default. Cargo's ` -Zbuild-std ` feature, a Nightly Rust feature, is
160
+ features by default. Cargo's [ ` -Zbuild-std ` ] feature, a Nightly Rust feature, is
161
161
then used to recompile the standard library in addition to your own code. This
162
162
will produce a binary that uses only the original WebAssembly features by
163
163
default and no proposals since its inception.
@@ -207,3 +207,63 @@ conditionally compile code instead. This is notably different to the way native
207
207
platforms such as x86\_ 64 work, and this is due to the fact that WebAssembly
208
208
binaries must only contain code the engine understands. Native binaries work so
209
209
long as the CPU doesn't execute unknown code dynamically at runtime.
210
+
211
+ ## Unwinding
212
+
213
+ By default the ` wasm32-unknown-unknown ` target is compiled with ` -Cpanic=abort ` .
214
+ Historically this was due to the fact that there was no way to catch panics in
215
+ wasm, but since mid-2025 the WebAssembly [ ` exception-handling `
216
+ proposal] ( https://github.com/WebAssembly/exception-handling ) reached
217
+ stabilization. LLVM has support for this proposal as well and when this is all
218
+ combined together it's possible to enable ` -Cpanic=unwind ` on wasm targets.
219
+
220
+ Compiling wasm targets with ` -Cpanic=unwind ` is not as easy as just passing
221
+ ` -Cpanic=unwind ` , however:
222
+
223
+ ``` sh
224
+ $ rustc foo.rs -Cpanic=unwind --target wasm32-unknown-unknown
225
+ error: the crate ` panic_unwind` does not have the panic strategy ` unwind`
226
+ ```
227
+
228
+ Notably the precompiled standard library that is shipped through Rustup is
229
+ compiled with ` -Cpanic=abort ` , not ` -Cpanic=unwind ` . While this is the case
230
+ you're going to be required to use Cargo's [ ` -Zbuild-std ` ] feature to build with
231
+ unwinding support:
232
+
233
+ ``` sh
234
+ $ RUSTFLAGS=' -Cpanic=unwind' cargo +nightly build --target wasm32-unknown-unknown -Zbuild-std
235
+ ```
236
+
237
+ Note, however, that as of 2025-10-03 LLVM is still using the "legacy exception
238
+ instructions" by default, not the officially standard version of the
239
+ exception-handling proposal:
240
+
241
+ ``` sh
242
+ $ wasm-tools validate target/wasm32-unknown-unknown/debug/foo.wasm
243
+ error: < sysroot> /library/std/src/sys/backtrace.rs:161:5
244
+ function `std::sys::backtrace::__rust_begin_short_backtrace` failed to validate
245
+
246
+ Caused by:
247
+ 0: func 2 failed to validate
248
+ 1: legacy_exceptions feature required for try instruction (at offset 0x880)
249
+ ```
250
+
251
+ Fixing this requires passing ` -Cllvm-args=-wasm-use-legacy-eh=false ` to the Rust
252
+ compiler as well:
253
+
254
+ ``` sh
255
+ $ RUSTFLAGS=' -Cpanic=unwind -Cllvm-args=-wasm-use-legacy-eh=false' cargo +nightly build --target wasm32-unknown-unknown -Zbuild-std
256
+ $ wasm-tools validate target/wasm32-unknown-unknown/debug/foo.wasm
257
+ ```
258
+
259
+ At this time there are no concrete plans for adding new targets to the Rust
260
+ compiler which have ` -Cpanic=unwind ` enabled-by-default. The most likely route
261
+ to having this enabled is that in a few years when the ` exception-handling `
262
+ target feature is enabled by default in LLVM (due to browsers/runtime support
263
+ propagating widely enough) the targets will switch to using ` -Cpanic=unwind ` by
264
+ default. This is not for certain, however, and will likely be accompanied with
265
+ either an MCP or an RFC about changing all wasm targets in the same manner. In
266
+ the meantime using ` -Cpanic=unwind ` will require using [ ` -Zbuild-std ` ] and
267
+ passing the appropriate flags to rustc.
268
+
269
+ [ `-Zbuild-std` ] : ../../cargo/reference/unstable.html#build-std
0 commit comments