Auto merge of #154700 - wesleywiser:revert_151771, r=jieyouxu
Revert "Fix: On wasm targets, call panic_in_cleanup if panic occurs in cleanup #151771"
Clean revert of rust-lang/rust#151771 as discussed in the [compiler team triage meeting](https://rust-lang.zulipchat.com/#narrow/channel/238009-t-compiler.2Fmeetings/topic/.5Bweekly.5D.202026-03-26/near/581957759) and https://github.com/rust-lang/rust/issues/153948#issuecomment-4137655589
Fixes (after backport): rust-lang/rust#153948
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 3eb0fd9..1d6d776 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1656,10 +1656,6 @@ fn catch_switch(
unimplemented!();
}
- fn get_funclet_cleanuppad(&self, _funclet: &Funclet) -> RValue<'gcc> {
- unimplemented!();
- }
-
// Atomic Operations
fn atomic_cmpxchg(
&mut self,
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index f3508c1..4e79e4f 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1297,10 +1297,6 @@ fn catch_switch(
ret
}
- fn get_funclet_cleanuppad(&self, funclet: &Funclet<'ll>) -> &'ll Value {
- funclet.cleanuppad()
- }
-
// Atomic Operations
fn atomic_cmpxchg(
&mut self,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index dcbd7f7..1b96be1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -214,18 +214,19 @@ fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => None,
mir::UnwindAction::Terminate(reason) => {
- if fx.mir[self.bb].is_cleanup && base::wants_wasm_eh(fx.cx.tcx().sess) {
- // For wasm, we need to generate a nested `cleanuppad within %outer_pad`
- // to catch exceptions during cleanup and call `panic_in_cleanup`.
- Some(fx.terminate_block(reason, Some(self.bb)))
- } else if fx.mir[self.bb].is_cleanup
- && base::wants_new_eh_instructions(fx.cx.tcx().sess)
- {
+ if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) {
// MSVC SEH will abort automatically if an exception tries to
// propagate out from cleanup.
+
+ // FIXME(@mirkootter): For wasm, we currently do not support terminate during
+ // cleanup, because this requires a few more changes: The current code
+ // caches the `terminate_block` for each function; funclet based code - however -
+ // requires a different terminate_block for each funclet
+ // Until this is implemented, we just do not unwind inside cleanup blocks
+
None
} else {
- Some(fx.terminate_block(reason, None))
+ Some(fx.terminate_block(reason))
}
}
};
@@ -237,7 +238,7 @@ fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
if let Some(unwind_block) = unwind_block {
let ret_llbb = if let Some((_, target)) = destination {
- self.llbb_with_cleanup(fx, target)
+ fx.llbb(target)
} else {
fx.unreachable_block()
};
@@ -308,7 +309,7 @@ fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
) -> MergingSucc {
let unwind_target = match unwind {
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
- mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason, None)),
+ mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)),
mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => None,
};
@@ -316,7 +317,7 @@ fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) {
assert!(unwind_target.is_none());
let ret_llbb = if let Some(target) = destination {
- self.llbb_with_cleanup(fx, target)
+ fx.llbb(target)
} else {
fx.unreachable_block()
};
@@ -333,7 +334,7 @@ fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
MergingSucc::False
} else if let Some(cleanup) = unwind_target {
let ret_llbb = if let Some(target) = destination {
- self.llbb_with_cleanup(fx, target)
+ fx.llbb(target)
} else {
fx.unreachable_block()
};
@@ -1895,39 +1896,8 @@ fn unreachable_block(&mut self) -> Bx::BasicBlock {
})
}
- fn terminate_block(
- &mut self,
- reason: UnwindTerminateReason,
- outer_catchpad_bb: Option<mir::BasicBlock>,
- ) -> Bx::BasicBlock {
- // mb_funclet_bb should be present if and only if the target is wasm and
- // we're terminating because of an unwind in a cleanup block. In that
- // case we have nested funclets and the inner catch_switch needs to know
- // what outer catch_pad it is contained in.
- debug_assert!(
- outer_catchpad_bb.is_some()
- == (base::wants_wasm_eh(self.cx.tcx().sess)
- && reason == UnwindTerminateReason::InCleanup)
- );
-
- // When we aren't in a wasm InCleanup block, there's only one terminate
- // block needed so we cache at START_BLOCK index.
- let mut cache_bb = mir::START_BLOCK;
- // In wasm eh InCleanup, use the outer funclet's cleanup BB as the cache
- // key.
- if let Some(outer_bb) = outer_catchpad_bb {
- let cleanup_kinds =
- self.cleanup_kinds.as_ref().expect("cleanup_kinds required for funclets");
- cache_bb = cleanup_kinds[outer_bb]
- .funclet_bb(outer_bb)
- .expect("funclet_bb should be in a funclet");
-
- // Ensure the outer funclet is created first
- if self.funclets[cache_bb].is_none() {
- self.landing_pad_for(cache_bb);
- }
- }
- if let Some((cached_bb, cached_reason)) = self.terminate_blocks[cache_bb]
+ fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock {
+ if let Some((cached_bb, cached_reason)) = self.terminate_block
&& reason == cached_reason
{
return cached_bb;
@@ -1965,35 +1935,12 @@ fn terminate_block(
// cp_terminate:
// %cp = catchpad within %cs [null, i32 64, null]
// ...
- //
- // By contrast, on WebAssembly targets, we specifically _do_ want to
- // catch foreign exceptions. The situation with MSVC is a
- // regrettable hack which we don't want to extend to other targets
- // unless necessary. For WebAssembly, to generate catch(...) and
- // catch only C++ exception instead of generating a catch_all, we
- // need to call the intrinsics @llvm.wasm.get.exception and
- // @llvm.wasm.get.ehselector in the catch pad. Since we don't do
- // this, we generate a catch_all. We originally got this behavior
- // by accident but it luckily matches our intention.
llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
+ let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
let mut cs_bx = Bx::build(self.cx, llbb);
-
- // For wasm InCleanup blocks, our catch_switch is nested within the
- // outer catchpad, so we need to provide it as the parent value to
- // catch_switch.
- let mut outer_cleanuppad = None;
- if outer_catchpad_bb.is_some() {
- // Get the outer funclet's catchpad
- let outer_funclet = self.funclets[cache_bb]
- .as_ref()
- .expect("landing_pad_for didn't create funclet");
- outer_cleanuppad = Some(cs_bx.get_funclet_cleanuppad(outer_funclet));
- }
- let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
- let cs = cs_bx.catch_switch(outer_cleanuppad, None, &[cp_llbb]);
- drop(cs_bx);
+ let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
bx = Bx::build(self.cx, cp_llbb);
let null =
@@ -2014,18 +1961,13 @@ fn terminate_block(
} else {
// Specifying more arguments than necessary usually doesn't
// hurt, but the `WasmEHPrepare` LLVM pass does not recognize
- // anything other than a single `null` as a `catch_all` block,
+ // anything other than a single `null` as a `catch (...)` block,
// leading to problems down the line during instruction
// selection.
&[null] as &[_]
};
funclet = Some(bx.catch_pad(cs, args));
- // On wasm, if we wanted to generate a catch(...) and only catch C++
- // exceptions, we'd call @llvm.wasm.get.exception and
- // @llvm.wasm.get.ehselector selectors here. We want a catch_all so
- // we leave them out. This is intentionally diverging from the MSVC
- // behavior.
} else {
llbb = Bx::append_block(self.cx, self.llfn, "terminate");
bx = Bx::build(self.cx, llbb);
@@ -2051,7 +1993,7 @@ fn terminate_block(
bx.unreachable();
- self.terminate_blocks[cache_bb] = Some((llbb, reason));
+ self.terminate_block = Some((llbb, reason));
llbb
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 5c14d6f..93da121 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -90,11 +90,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
/// Cached unreachable block
unreachable_block: Option<Bx::BasicBlock>,
- /// Cached terminate upon unwinding block and its reason. For non-wasm
- /// targets, there is at most one such block per function, stored at index
- /// `START_BLOCK`. For wasm targets, each funclet needs its own terminate
- /// block, indexed by the cleanup block that is the funclet's head.
- terminate_blocks: IndexVec<mir::BasicBlock, Option<(Bx::BasicBlock, UnwindTerminateReason)>>,
+ /// Cached terminate upon unwinding block and its reason
+ terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>,
/// A bool flag for each basic block indicating whether it is a cold block.
/// A cold block is a block that is unlikely to be executed at runtime.
@@ -230,7 +227,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
personality_slot: None,
cached_llbbs,
unreachable_block: None,
- terminate_blocks: IndexVec::from_elem(None, &mir.basic_blocks),
+ terminate_block: None,
cleanup_kinds,
landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 05e94b8..2076e2b 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -552,12 +552,12 @@ fn select(
fn set_personality_fn(&mut self, personality: Self::Function);
- // These are used by everyone except msvc and wasm EH
+ // These are used by everyone except msvc
fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value);
fn filter_landing_pad(&mut self, pers_fn: Self::Function);
fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
- // These are used by msvc and wasm EH
+ // These are used only by msvc
fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option<Self::BasicBlock>);
fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
@@ -567,7 +567,6 @@ fn catch_switch(
unwind: Option<Self::BasicBlock>,
handlers: &[Self::BasicBlock],
) -> Self::Value;
- fn get_funclet_cleanuppad(&self, funclet: &Self::Funclet) -> Self::Value;
fn atomic_cmpxchg(
&mut self,
diff --git a/tests/codegen-llvm/double_panic_wasm.rs b/tests/codegen-llvm/double_panic_wasm.rs
deleted file mode 100644
index 1eafe60..0000000
--- a/tests/codegen-llvm/double_panic_wasm.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//@ 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() }
-}
diff --git a/tests/codegen-llvm/terminating-catchpad.rs b/tests/codegen-llvm/terminating-catchpad.rs
index 7c98ea9..a2ec198 100644
--- a/tests/codegen-llvm/terminating-catchpad.rs
+++ b/tests/codegen-llvm/terminating-catchpad.rs
@@ -9,10 +9,6 @@
// 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"]
@@ -40,14 +36,8 @@ fn panic_cannot_unwind() -> ! {
#[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();
}