blob: e718f599a3c2fa7ffb36cad2ad5ce1bde995134a [file] [log] [blame]
//@ only-wasm32
//@ revisions: WASM WASMEXN
//@ [WASMEXN] compile-flags: -C panic=unwind -Z emscripten-wasm-eh
#![crate_type = "lib"]
#![feature(core_intrinsics, wasm_exception_handling_intrinsics, link_llvm_intrinsics)]
extern "C-unwind" {
fn may_panic();
}
extern "C" {
fn log_number(number: usize);
}
struct LogOnDrop;
impl Drop for LogOnDrop {
fn drop(&mut self) {
unsafe {
log_number(0);
}
}
}
// WASM-LABEL: @test_cleanup() {{.*}}
// WASMEXN-LABEL: @test_cleanup() {{.*}} @__gxx_wasm_personality_v0
#[no_mangle]
pub fn test_cleanup() {
let _log_on_drop = LogOnDrop;
unsafe {
may_panic();
}
// WASMEXN-NOT: call
// WASMEXN: invoke void @may_panic()
// WASMEXN: %cleanuppad = cleanuppad within none []
//
// WASM: call void @may_panic()
// WASM-NOT: invoke void @may_panic()
}
// WASM-LABEL: @test_rtry() {{.*}}
// WASMEXN-LABEL: @test_rtry() {{.*}} @__gxx_wasm_personality_v0
#[no_mangle]
pub fn test_rtry() {
unsafe {
core::intrinsics::catch_unwind(
|_| {
may_panic();
},
core::ptr::null_mut(),
|data, exception| {
log_number(data as usize);
log_number(exception as usize);
},
);
}
// WASMEXN-NOT: call
// WASMEXN: invoke void @may_panic()
// WASMEXN: {{.*}} = catchswitch within none [label {{.*}}] unwind to caller
// WASMEXN: {{.*}} = catchpad within {{.*}} [ptr null]
// WASMEXN: catchret
// WASM: call void @may_panic()
// WASM-NOT: invoke void @may_panic()
// WASM-NOT: catchswitch
// WASM-NOT: catchpad
// WASM-NOT: catchret
}
// Make sure the intrinsic is not inferred as nounwind. This is a regression test for #132416.
//
// Note that this test uses the raw `wasm_throw` intrinsic because the one from
// libstd was built with `-Cpanic=abort` and it's technically not valid to use
// when this crate is compiled with `-Cpanic=unwind`.
//
// WASMEXN-LABEL: @test_intrinsic() {{.*}} @__gxx_wasm_personality_v0
#[no_mangle]
#[cfg(wasmexn)]
pub fn test_intrinsic() {
let _log_on_drop = LogOnDrop;
unsafe extern "C-unwind" {
#[link_name = "llvm.wasm.throw"]
fn wasm_throw(tag: i32, ptr: *mut u8) -> !;
}
unsafe {
wasm_throw(0, core::ptr::null_mut());
}
// WASMEXN-NOT: call
// WASMEXN: invoke void @llvm.wasm.throw(i32 noundef 0, ptr noundef null)
// WASMEXN: %cleanuppad = cleanuppad within none []
}