Skip to content

Support -Cpanic=unwind on WASI targets - #156061

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
alexcrichton:unwinding-onw-asi
May 8, 2026
Merged

Support -Cpanic=unwind on WASI targets#156061
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
alexcrichton:unwinding-onw-asi

Conversation

@alexcrichton

@alexcrichton alexcrichton commented May 1, 2026

Copy link
Copy Markdown
Member

View all comments

This commit is some minor updates/restructuring in a few locations with the end result being supporting -Cpanic=unwind on WASI targets. This continues to be off-by-default insofar as WASI targets default to -Cpanic=abort, meaning that actually using anything in this commit requires -Zbuild-std. Specifically the changes made here are:

  • The self-contained sysroot for WASI targets now contains a copy of libunwind.a from wasi-sdk, first shipped with wasi-sdk-33 (also updated here).
  • The unwind crate here in this repository uses the libunwind module instead of the custom bare-metal wasm implementation of exceptions. This means that Rust uses the _Unwind_* symbols which allows it to interoperate with C/C++/etc.
  • Wasm targets are all updated to pass the LLVM argument -wasm-use-legacy-eh=false to differ from LLVM's/clang's default of using the legacy exception handling proposal for WebAssembly. This has no effect by default because panic=abort is used on most targets. Emscripten is exempted from this as the Emscripten target is explicitly intended to follow LLVM's/clang's defaults.
  • There's a single test in the test suite that links to the panic_unwind crate which ended up requiring -Wexceptions from Wasmtime, so the test parts were updated and Wasmtime was updated in CI, too.

The net result of all of this is that this should not actually affect any WebAssembly target's default behavior. Optionally, though, WASI programs can be built with exception handling via:

RUSTFLAGS='-Cpanic=unwind' cargo +nightly run -Z build-std --target wasm32-wasip2

Effectively -Zbuild-std and -Cpanic=unwind is all that's necessary to enable this support on wasm targets.

Finally, this ends up closing #154593 as well. The WASI targets are now defined to use -lunwind to implement unwinding. This means that the in-tree definition of __cpp_exception is no longer of concern and the definition is always sourced externally. If Rust is linked with other C/C++ code using WASI then these idioms are compatible with wasi-sdk, for example, to use that as a linker. The main caveat is that when using an external linker the -fwasm-exceptions argument needs to be passed to clang for it to be able to find the libunwind.a library to link against.

Closes #154593

@rustbot

rustbot commented May 1, 2026

Copy link
Copy Markdown
Collaborator

These commits modify compiler targets.
(See the Target Tier Policy.)

@rustbot rustbot added A-CI Area: Our Github Actions CI A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue. labels May 1, 2026
@rustbot

rustbot commented May 1, 2026

Copy link
Copy Markdown
Collaborator

r? @marcoieni

rustbot has assigned @marcoieni.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: infra-ci
  • infra-ci expanded to Kobzol, Mark-Simulacrum, jdno, jieyouxu, marcoieni
  • Random selection from Mark-Simulacrum, jdno, jieyouxu, marcoieni

@rustbot

This comment has been minimized.

// actually turned on, which it's not by default on this target. For
// `-Zbuild-std` builds, however, this affects when rebuilding libstd
// with unwinding.
llvm_args: cvs!["-wasm-use-legacy-eh=false"],

@bjorn3 bjorn3 May 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't

// Returns `true` if this session's target will use native wasm
// exceptions. This means that the VM does the unwinding for
// us
pub fn wants_wasm_eh(sess: &Session) -> bool {
sess.target.is_like_wasm
&& (sess.target.os != Os::Emscripten || sess.opts.unstable_opts.emscripten_wasm_eh)
}
already supposed to do this?

Edit: Might be confused with wasm vs js exception handling.

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe, yeah, that's related to the Emscripten-specific scheme of exceptions pre-wasm-exceptions of using JS instead. Effectively there's 3 modes of exceptions on Wasm:

  1. Historical JS-based support for Emscripten. That's used when wants_wasm_eh is false and is only applicable to historical versions of the Emscripten target (or -Zemscripten-wasm-eh=false)
  2. Historical wasm support. This uses the now-legacy exception-handling proposal that shipped in browsers but was never standardized. This uses wasm instructions and has wants_wasm_eh is true. LLVM by default emits this today.
  3. Modern wasm support. This uses the now-standard exception-handling proposal as the successor to the "legacy exceptions" of above. This is wants_wasm_eh is true plus an option to LLVM to use the new instructions.

For (1) the LLVM IR is different, and for (2) and (3) they're the same IR. I don't know much about (1) myself. For WASI this PR only exposes (3)

@marcoieni

Copy link
Copy Markdown
Member

The changes in src/ci/docker look good. Someone else should review the other files since I'm not familiar with them.

@alexcrichton

Copy link
Copy Markdown
Member Author

@bjorn3 would you be up for reviewing the non-infra-related bits?

Comment thread library/unwind/src/libunwind.rs
Comment thread src/bootstrap/src/core/build_steps/compile.rs
Comment thread src/bootstrap/src/lib.rs
&& let Ok(mut path) = path.into_os_string().into_string()
{
path.push_str(" run -C cache=n --dir .");
path.push_str(" run -Wexceptions -C cache=n --dir .");

@bjorn3 bjorn3 May 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no tests added that use exceptions, right?

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost yeah, but there's one test that does extern crate panic_unwind; which pulls in libunwind which pulls in a throw instruction which then needs this to validate

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that even works without //@ needs-unwind to only run the test for panic=unwind. I thought rustc refused to link a panic runtime that doesn't match the -Cpanic=..., but I guess that check is only done when the panic runtime dependency is injected by rustc, not when it is explicitly done by the user.

@rustbot

rustbot commented May 5, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@bjorn3

bjorn3 commented May 6, 2026

Copy link
Copy Markdown
Member

@bors r+

@rust-bors

rust-bors Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 13c6e60 has been approved by bjorn3

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 6, 2026
@JonathanBrouwer

Copy link
Copy Markdown
Contributor

@bors r-
#156233 (comment)

@rust-bors rust-bors Bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CI Area: Our Github Actions CI A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WASI: -Cpanic=unwind does not work

6 participants