Skip to content

Commit 1cd345b

Browse files
committed
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.
1 parent 55bfca7 commit 1cd345b

3 files changed

Lines changed: 40 additions & 1 deletion

File tree

library/unwind/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
88
#![cfg_attr(
99
all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)),
10-
feature(link_llvm_intrinsics, simd_wasm64)
10+
feature(link_llvm_intrinsics, simd_wasm64, asm_experimental_arch)
1111
)]
1212
#![allow(internal_features)]
1313
#![deny(unsafe_op_in_unsafe_fn)]

library/unwind/src/wasm.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@
22
33
#![allow(nonstandard_style)]
44

5+
// Define the __cpp_exception tag that LLVM's wasm exception handling requires.
6+
// In particular it is required to use either of:
7+
// 1. the wasm_throw llvm intrinsic, or
8+
// 2. the Rust try intrinsic.
9+
//
10+
// This must be provided since LLVM commit
11+
// aee99e8015daa9f53ab1fd4e5b24cc4c694bdc4a which changed the tag from being
12+
// weakly defined in each object file to being an external reference that must
13+
// be linked from somewhere.
14+
//
15+
// We only define this for wasm32-unknown-unknown because on Emscripten/WASI
16+
// targets, this symbol should be defined by the external toolchain. In
17+
// particular, defining this on Emscripten would break Emscripten dynamic
18+
// libraries.
19+
#[cfg(all(target_os = "unknown", panic = "unwind"))]
20+
core::arch::global_asm!(
21+
".globl __cpp_exception",
22+
#[cfg(target_pointer_width = "64")]
23+
".tagtype __cpp_exception i64",
24+
#[cfg(target_pointer_width = "32")]
25+
".tagtype __cpp_exception i32",
26+
"__cpp_exception:",
27+
);
28+
529
#[repr(C)]
630
#[derive(Debug, Copy, Clone, PartialEq)]
731
pub enum _Unwind_Reason_Code {

src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,18 @@ the meantime using `-Cpanic=unwind` will require using [`-Zbuild-std`] and
267267
passing the appropriate flags to rustc.
268268

269269
[`-Zbuild-std`]: ../../cargo/reference/unstable.html#build-std
270+
271+
### The exception tag for panics
272+
273+
Rust panics are currently implemented as a specific class of C++ exceptions.
274+
This is because llvm only supports throwing and catching the C++ exception tag
275+
from `wasm_throw` intrinsic and the lowering for the catchpads emitted by the
276+
Rust try intrinsic.
277+
278+
In particular, llvm throw and catch blocks expect a `WebAssembly.Tag` symbol
279+
called `__cpp_exception`. If it is not defined somewhere, llvm will generate an
280+
Emscripten style import from `env.__cpp_exception`. We don't want this, so we
281+
define the symbol in `libunwind` but only for wasm32-unknown-unknown. WASI
282+
doesn't currently support unwinding at all, and the Emscripten linker provides
283+
the tag in an appropriate manner depending on what sort of binary is being
284+
linked.

0 commit comments

Comments
 (0)