Files
rust/tests/codegen-llvm/terminating-catchpad.rs
T
Hood Chatham acbfd79acf Fix: On wasm targets, call panic_in_cleanup if panic occurs in cleanup
Previously this was not correctly implemented. Each funclet may need its own terminate
block, so this changes the `terminate_block` into a `terminate_blocks` `IndexVec` which
can have a terminate_block for each funclet. We key on the first basic block of the
funclet -- in particular, this is the start block for the old case of the top level
terminate function.

Rather than using a catchswitch/catchpad pair, I used a cleanuppad. The reason for the
pair is to avoid catching foreign exceptions on MSVC. On wasm, it seems that the
catchswitch/catchpad pair is optimized back into a single cleanuppad and a catch_all
instruction is emitted which will catch foreign exceptions. Because the new logic is
only used on wasm, it seemed better to take the simpler approach seeing as they do the
same thing.
2026-02-24 17:47:27 +01:00

54 lines
1.7 KiB
Rust

//@ revisions: emscripten wasi seh
//@[emscripten] compile-flags: --target wasm32-unknown-emscripten -Z emscripten-wasm-eh
//@[wasi] compile-flags: --target wasm32-wasip1 -C panic=unwind
//@[seh] compile-flags: --target x86_64-pc-windows-msvc
//@[emscripten] needs-llvm-components: webassembly
//@[wasi] needs-llvm-components: webassembly
//@[seh] needs-llvm-components: x86
// Ensure a catch-all generates:
// - `catchpad ... [ptr null]` on Wasm (otherwise LLVM gets confused)
// - `catchpad ... [ptr null, i32 64, ptr null]` on Windows (otherwise we catch SEH exceptions)
//
// Unlike on windows, on Wasm, we specifically do want to catch foreign
// exceptions. To catch only C++ exceptions we'd need to call
// @llvm.wasm.get.exception and @llvm.wasm.get.ehselector in the catchpad.
#![feature(no_core, lang_items, rustc_attrs)]
#![crate_type = "lib"]
#![no_std]
#![no_core]
#[lang = "pointee_sized"]
pub trait PointeeSized {}
#[lang = "meta_sized"]
pub trait MetaSized: PointeeSized {}
#[lang = "sized"]
pub trait Sized: MetaSized {}
unsafe extern "C-unwind" {
safe fn unwinds();
}
#[lang = "panic_cannot_unwind"]
fn panic_cannot_unwind() -> ! {
loop {}
}
#[no_mangle]
#[rustc_nounwind]
pub fn doesnt_unwind() {
// CHECK: catchswitch within none [label %{{.*}}] unwind to caller
// emscripten: %catchpad = catchpad within %catchswitch [ptr null]
// wasi: %catchpad = catchpad within %catchswitch [ptr null]
// seh: %catchpad = catchpad within %catchswitch [ptr null, i32 64, ptr null]
//
// We don't call these intrinsics on wasm targets so we generate a catch_all
// instruction which also picks up foreign exceptions
// NOT: @llvm.wasm.get.exception
// NOT: @llvm.wasm.get.ehselector
unwinds();
}