mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-28 11:17:26 +03:00
acbfd79acf
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.
35 lines
728 B
Rust
35 lines
728 B
Rust
//@ compile-flags: -C panic=unwind -Copt-level=0
|
|
//@ needs-unwind
|
|
//@ only-wasm32
|
|
|
|
#![crate_type = "lib"]
|
|
|
|
// Test that `panic_in_cleanup` is called on webassembly targets when a panic
|
|
// occurs in a destructor during unwinding.
|
|
|
|
extern "Rust" {
|
|
fn may_panic();
|
|
}
|
|
|
|
struct PanicOnDrop;
|
|
|
|
impl Drop for PanicOnDrop {
|
|
fn drop(&mut self) {
|
|
unsafe { may_panic() }
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: @double_panic
|
|
// CHECK: invoke void @may_panic()
|
|
// CHECK: invoke void @{{.+}}drop_in_place{{.+}}
|
|
// CHECK: unwind label %[[TERMINATE:.*]]
|
|
//
|
|
// CHECK: [[TERMINATE]]:
|
|
// CHECK: call void @{{.*panic_in_cleanup}}
|
|
// CHECK: unreachable
|
|
#[no_mangle]
|
|
pub fn double_panic() {
|
|
let _guard = PanicOnDrop;
|
|
unsafe { may_panic() }
|
|
}
|