For panic=unwind on Wasm targets, define __cpp_exception tag

Since llvm/llvm-project 159143, llvm no longer weak links the __cpp_exception tag into
each object that uses it. They are now defined in compiler-rt. Rust doesn't seem to
get them from compiler-rt so llvm decides they need to be imported. This adds them to
libunwind.
This commit is contained in:
Hood Chatham
2026-02-06 08:33:48 -08:00
parent 55bfca7d7d
commit 1cd345b22b
3 changed files with 40 additions and 1 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
#![cfg_attr(
all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)),
feature(link_llvm_intrinsics, simd_wasm64)
feature(link_llvm_intrinsics, simd_wasm64, asm_experimental_arch)
)]
#![allow(internal_features)]
#![deny(unsafe_op_in_unsafe_fn)]
+24
View File
@@ -2,6 +2,30 @@
#![allow(nonstandard_style)]
// Define the __cpp_exception tag that LLVM's wasm exception handling requires.
// In particular it is required to use either of:
// 1. the wasm_throw llvm intrinsic, or
// 2. the Rust try intrinsic.
//
// This must be provided since LLVM commit
// aee99e8015daa9f53ab1fd4e5b24cc4c694bdc4a which changed the tag from being
// weakly defined in each object file to being an external reference that must
// be linked from somewhere.
//
// We only define this for wasm32-unknown-unknown because on Emscripten/WASI
// targets, this symbol should be defined by the external toolchain. In
// particular, defining this on Emscripten would break Emscripten dynamic
// libraries.
#[cfg(all(target_os = "unknown", panic = "unwind"))]
core::arch::global_asm!(
".globl __cpp_exception",
#[cfg(target_pointer_width = "64")]
".tagtype __cpp_exception i64",
#[cfg(target_pointer_width = "32")]
".tagtype __cpp_exception i32",
"__cpp_exception:",
);
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum _Unwind_Reason_Code {
@@ -267,3 +267,18 @@ the meantime using `-Cpanic=unwind` will require using [`-Zbuild-std`] and
passing the appropriate flags to rustc.
[`-Zbuild-std`]: ../../cargo/reference/unstable.html#build-std
### The exception tag for panics
Rust panics are currently implemented as a specific class of C++ exceptions.
This is because llvm only supports throwing and catching the C++ exception tag
from `wasm_throw` intrinsic and the lowering for the catchpads emitted by the
Rust try intrinsic.
In particular, llvm throw and catch blocks expect a `WebAssembly.Tag` symbol
called `__cpp_exception`. If it is not defined somewhere, llvm will generate an
Emscripten style import from `env.__cpp_exception`. We don't want this, so we
define the symbol in `libunwind` but only for wasm32-unknown-unknown. WASI
doesn't currently support unwinding at all, and the Emscripten linker provides
the tag in an appropriate manner depending on what sort of binary is being
linked.