Auto merge of #115045 - RalfJung:unwind-terminate-reason, r=davidtwco

when terminating during unwinding, show the reason why

With this, the output on double-panic becomes something like that:
```
thread 'main' panicked at src/tools/miri/tests/fail/panic/double_panic.rs:15:5:
first
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at src/tools/miri/tests/fail/panic/double_panic.rs:10:9:
second
stack backtrace:
   0:           0xbe273a - std::backtrace_rs::backtrace::miri::trace_unsynchronized::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
                               at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:99:5
   1:           0xbe22e6 - std::backtrace_rs::backtrace::miri::trace::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
                               at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:62:14
   2:           0xbe1086 - std::backtrace_rs::backtrace::trace_unsynchronized::<[closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
                               at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   3:           0xba3afd - std::sys_common::backtrace::_print_fmt
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:67:5
   4:           0xba2471 - <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:44:22
   5:           0xbcf754 - core::fmt::rt::Argument::<'_>::fmt
                               at /home/r/src/rust/rustc.3/library/core/src/fmt/rt.rs:138:9
   6:           0x9b8f81 - std::fmt::write
                               at /home/r/src/rust/rustc.3/library/core/src/fmt/mod.rs:1094:17
   7:           0x21391d - <std::sys::unix::stdio::Stderr as std::io::Write>::write_fmt
                               at /home/r/src/rust/rustc.3/library/std/src/io/mod.rs:1714:15
   8:           0xba37b1 - std::sys_common::backtrace::_print
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:47:5
   9:           0xba365b - std::sys_common::backtrace::print
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:34:9
  10:           0x143c67 - std::panic_hook_with_disk_dump::{closure#1}
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:278:22
  11:           0x144187 - std::panic_hook_with_disk_dump
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:312:9
  12:           0x143659 - std::panicking::default_hook
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:239:5
  13:           0x1482a7 - std::panicking::rust_panic_with_hook
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:729:13
  14:           0x1475d5 - std::rt::begin_panic::<&str>::{closure#0}
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:650:9
  15:           0xba496a - std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:170:18
  16:           0x147599 - std::rt::begin_panic::<&str>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:649:12
  17:            0x31916 - <Foo as std::ops::Drop>::drop
                               at src/tools/miri/tests/fail/panic/double_panic.rs:10:9
  18:           0x1a2b5e - std::ptr::drop_in_place::<Foo> - shim(Some(Foo))
                               at /home/r/src/rust/rustc.3/library/core/src/ptr/mod.rs:497:1
  19:            0x202bf - main
                               at src/tools/miri/tests/fail/panic/double_panic.rs:16:1
  20:            0xcc6a8 - <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
                               at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:250:5
  21:           0xba47d9 - std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:154:18
  22:           0x141a6a - std::rt::lang_start::<()>::{closure#0}
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:166:18
  23:            0xcca18 - std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once
                               at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:284:13
  24:           0x146469 - std::panicking::try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
  25:           0x145e09 - std::panicking::try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
  26:            0x7b0ac - std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
                               at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
  27:           0x14189b - std::rt::lang_start_internal::{closure#2}
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:48
  28:           0x146481 - std::panicking::try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
  29:           0x145e2c - std::panicking::try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
  30:            0x7b0d5 - std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
                               at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
  31:           0x1418b0 - std::rt::lang_start_internal
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:20
  32:           0x141a97 - std::rt::lang_start::<()>
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:165:17
thread 'main' panicked at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:126:5:
panic in a destructor during cleanup
stack backtrace:
   0:           0xe9f6d7 - std::backtrace_rs::backtrace::miri::trace_unsynchronized::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
                               at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:99:5
   1:           0xe9f27d - std::backtrace_rs::backtrace::miri::trace::<&mut [closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
                               at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/miri.rs:62:14
   2:           0xe9e016 - std::backtrace_rs::backtrace::trace_unsynchronized::<[closure@std::sys_common::backtrace::_print_fmt::{closure#1}]>
                               at /home/r/src/rust/rustc.3/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   3:           0xba3afd - std::sys_common::backtrace::_print_fmt
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:67:5
   4:           0xba2471 - <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:44:22
   5:           0xbcf754 - core::fmt::rt::Argument::<'_>::fmt
                               at /home/r/src/rust/rustc.3/library/core/src/fmt/rt.rs:138:9
   6:           0x9b8f81 - std::fmt::write
                               at /home/r/src/rust/rustc.3/library/core/src/fmt/mod.rs:1094:17
   7:           0x4d0895 - <std::sys::unix::stdio::Stderr as std::io::Write>::write_fmt
                               at /home/r/src/rust/rustc.3/library/std/src/io/mod.rs:1714:15
   8:           0xba37b1 - std::sys_common::backtrace::_print
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:47:5
   9:           0xba365b - std::sys_common::backtrace::print
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:34:9
  10:           0x400bd4 - std::panic_hook_with_disk_dump::{closure#1}
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:278:22
  11:           0x144187 - std::panic_hook_with_disk_dump
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:312:9
  12:           0x143659 - std::panicking::default_hook
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:239:5
  13:           0x1482a7 - std::panicking::rust_panic_with_hook
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:729:13
  14:           0x40403b - std::panicking::begin_panic_handler::{closure#0}
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:619:13
  15:           0xe618b3 - std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:170:18
  16:           0x403fc8 - std::panicking::begin_panic_handler
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:617:5
  17:           0xee23e9 - core::panicking::panic_nounwind_fmt
                               at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:96:14
  18:           0xee29e6 - core::panicking::panic_nounwind
                               at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:126:5
  19:           0xee365e - core::panicking::panic_in_cleanup
                               at /home/r/src/rust/rustc.3/library/core/src/panicking.rs:206:5
  20:            0x2028a - main
                               at src/tools/miri/tests/fail/panic/double_panic.rs:13:1
  21:           0x3895ee - <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
                               at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:250:5
  22:           0xe61725 - std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>
                               at /home/r/src/rust/rustc.3/library/std/src/sys_common/backtrace.rs:154:18
  23:           0x3fe9aa - std::rt::lang_start::<()>::{closure#0}
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:166:18
  24:           0x389962 - std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once
                               at /home/r/src/rust/rustc.3/library/core/src/ops/function.rs:284:13
  25:           0x4033b9 - std::panicking::try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
  26:           0x402d58 - std::panicking::try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
  27:           0x337ff7 - std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>
                               at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
  28:           0x3fe7e7 - std::rt::lang_start_internal::{closure#2}
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:48
  29:           0x4033d6 - std::panicking::try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:524:40
  30:           0x402d7f - std::panicking::try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>
                               at /home/r/src/rust/rustc.3/library/std/src/panicking.rs:488:19
  31:           0x338028 - std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>
                               at /home/r/src/rust/rustc.3/library/std/src/panic.rs:142:14
  32:           0x1418b0 - std::rt::lang_start_internal
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:148:20
  33:           0x3fe9dc - std::rt::lang_start::<()>
                               at /home/r/src/rust/rustc.3/library/std/src/rt.rs:165:17
thread caused non-unwinding panic. aborting.
```
If we also land https://github.com/rust-lang/rust/pull/115020, the 2nd backtrace disappears, hopefully making the "panic in a destructor during cleanup" easier to see.

Fixes https://github.com/rust-lang/rust/issues/114954.
This commit is contained in:
bors 2023-08-25 08:47:18 +00:00
commit b60f7b51a2
105 changed files with 488 additions and 304 deletions

View File

@ -202,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
}
TerminatorKind::Goto { target: _ }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {

View File

@ -770,7 +770,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
}
TerminatorKind::Goto { target: _ }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable
| TerminatorKind::UnwindResume
| TerminatorKind::Return
@ -817,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
}
}
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. }

View File

@ -1334,7 +1334,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
match &term.kind {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable
@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, block_data, "resume on non-cleanup block!")
}
}
TerminatorKind::UnwindTerminate => {
TerminatorKind::UnwindTerminate(_) => {
if !is_cleanup {
span_mirbug!(self, block_data, "abort on non-cleanup block!")
}
@ -1697,7 +1697,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, ctxt, "unwind on cleanup block")
}
}
UnwindAction::Unreachable | UnwindAction::Terminate => (),
UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
}
}

View File

@ -474,8 +474,8 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
*destination,
);
}
TerminatorKind::UnwindTerminate => {
codegen_panic_cannot_unwind(fx, source_info);
TerminatorKind::UnwindTerminate(reason) => {
codegen_unwind_terminate(fx, source_info, *reason);
}
TerminatorKind::UnwindResume => {
// FIXME implement unwinding
@ -971,13 +971,14 @@ pub(crate) fn codegen_panic_nounwind<'tcx>(
codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span);
}
pub(crate) fn codegen_panic_cannot_unwind<'tcx>(
pub(crate) fn codegen_unwind_terminate<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
source_info: mir::SourceInfo,
reason: UnwindTerminateReason,
) {
let args = [];
codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span);
codegen_panic_inner(fx, reason.lang_item(), &args, source_info.span);
}
fn codegen_panic_inner<'tcx>(

View File

@ -551,7 +551,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }

View File

@ -285,7 +285,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
match data.terminator().kind {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable

View File

@ -12,7 +12,7 @@ use crate::MemFlags;
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty};
@ -178,7 +178,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => None,
mir::UnwindAction::Terminate => {
mir::UnwindAction::Terminate(reason) => {
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.
@ -191,7 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
None
} else {
Some(fx.terminate_block())
Some(fx.terminate_block(reason))
}
}
};
@ -264,7 +264,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
) -> MergingSucc {
let unwind_target = match unwind {
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
mir::UnwindAction::Terminate => Some(fx.terminate_block()),
mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)),
mir::UnwindAction::Continue => None,
mir::UnwindAction::Unreachable => None,
};
@ -649,12 +649,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
helper: TerminatorCodegenHelper<'tcx>,
bx: &mut Bx,
terminator: &mir::Terminator<'tcx>,
reason: UnwindTerminateReason,
) {
let span = terminator.source_info.span;
self.set_debug_loc(bx, terminator.source_info);
// Obtain the panic entry point.
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item());
// Codegen the actual panic invoke/call.
let merging_succ = helper.do_call(
@ -1229,8 +1230,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
MergingSucc::False
}
mir::TerminatorKind::UnwindTerminate => {
self.codegen_terminate_terminator(helper, bx, terminator);
mir::TerminatorKind::UnwindTerminate(reason) => {
self.codegen_terminate_terminator(helper, bx, terminator, reason);
MergingSucc::False
}
@ -1579,79 +1580,81 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
})
}
fn terminate_block(&mut self) -> Bx::BasicBlock {
self.terminate_block.unwrap_or_else(|| {
let funclet;
let llbb;
let mut bx;
if base::wants_msvc_seh(self.cx.sess()) {
// This is a basic block that we're aborting the program for,
// notably in an `extern` function. These basic blocks are inserted
// so that we assert that `extern` functions do indeed not panic,
// and if they do we abort the process.
//
// On MSVC these are tricky though (where we're doing funclets). If
// we were to do a cleanuppad (like below) the normal functions like
// `longjmp` would trigger the abort logic, terminating the
// program. Instead we insert the equivalent of `catch(...)` for C++
// which magically doesn't trigger when `longjmp` files over this
// frame.
//
// Lots more discussion can be found on #48251 but this codegen is
// modeled after clang's for:
//
// try {
// foo();
// } catch (...) {
// bar();
// }
//
// which creates an IR snippet like
//
// cs_terminate:
// %cs = catchswitch within none [%cp_terminate] unwind to caller
// cp_terminate:
// %cp = catchpad within %cs [null, i32 64, null]
// ...
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;
}
llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
let funclet;
let llbb;
let mut bx;
if base::wants_msvc_seh(self.cx.sess()) {
// This is a basic block that we're aborting the program for,
// notably in an `extern` function. These basic blocks are inserted
// so that we assert that `extern` functions do indeed not panic,
// and if they do we abort the process.
//
// On MSVC these are tricky though (where we're doing funclets). If
// we were to do a cleanuppad (like below) the normal functions like
// `longjmp` would trigger the abort logic, terminating the
// program. Instead we insert the equivalent of `catch(...)` for C++
// which magically doesn't trigger when `longjmp` files over this
// frame.
//
// Lots more discussion can be found on #48251 but this codegen is
// modeled after clang's for:
//
// try {
// foo();
// } catch (...) {
// bar();
// }
//
// which creates an IR snippet like
//
// cs_terminate:
// %cs = catchswitch within none [%cp_terminate] unwind to caller
// cp_terminate:
// %cp = catchpad within %cs [null, i32 64, null]
// ...
let mut cs_bx = Bx::build(self.cx, llbb);
let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
// The "null" here is actually a RTTI type descriptor for the
// C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block.
bx = Bx::build(self.cx, cp_llbb);
let null =
bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));
let sixty_four = bx.const_i32(64);
funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
} else {
llbb = Bx::append_block(self.cx, self.llfn, "terminate");
bx = Bx::build(self.cx, llbb);
let mut cs_bx = Bx::build(self.cx, llbb);
let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
let llpersonality = self.cx.eh_personality();
bx.filter_landing_pad(llpersonality);
// The "null" here is actually a RTTI type descriptor for the
// C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block.
bx = Bx::build(self.cx, cp_llbb);
let null =
bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));
let sixty_four = bx.const_i32(64);
funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
} else {
llbb = Bx::append_block(self.cx, self.llfn, "terminate");
bx = Bx::build(self.cx, llbb);
funclet = None;
}
let llpersonality = self.cx.eh_personality();
bx.filter_landing_pad(llpersonality);
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
funclet = None;
}
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind);
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
bx.do_not_inline(llret);
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
bx.unreachable();
let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
bx.do_not_inline(llret);
self.terminate_block = Some(llbb);
llbb
})
bx.unreachable();
self.terminate_block = Some((llbb, reason));
llbb
}
/// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already

View File

@ -5,6 +5,7 @@ use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::traversal;
use rustc_middle::mir::UnwindTerminateReason;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_target::abi::call::{FnAbi, PassMode};
@ -83,8 +84,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
/// Cached unreachable block
unreachable_block: Option<Bx::BasicBlock>,
/// Cached terminate upon unwinding block
terminate_block: Option<Bx::BasicBlock>,
/// Cached terminate upon unwinding block and its reason
terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>,
/// The location where each MIR arg/var/tmp/ret is stored. This is
/// usually an `PlaceRef` representing an alloca, but not always:
@ -174,7 +175,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let mut start_bx = Bx::build(cx, start_llbb);
if mir.basic_blocks.iter().any(|bb| {
bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate))
bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate(_)))
}) {
start_bx.set_personality_fn(cx.eh_personality());
}

View File

@ -756,6 +756,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
///
/// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow
/// unwinding, and doing so is UB.
#[cold] // usually we have normal returns, not unwinding
pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> {
self.frame_mut().loc = match target {
mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
@ -763,9 +764,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
mir::UnwindAction::Unreachable => {
throw_ub_custom!(fluent::const_eval_unreachable_unwind);
}
mir::UnwindAction::Terminate => {
mir::UnwindAction::Terminate(reason) => {
self.frame_mut().loc = Right(self.frame_mut().body.span);
M::unwind_terminate(self)?;
M::unwind_terminate(self, reason)?;
// This might have pushed a new stack frame, or it terminated execution.
// Either way, `loc` will not be updated.
return Ok(());

View File

@ -222,7 +222,10 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
/// Called when unwinding reached a state where execution should be terminated.
fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
fn unwind_terminate(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
reason: mir::UnwindTerminateReason,
) -> InterpResult<'tcx>;
/// Called for all binary operations where the LHS has pointer type.
///
@ -462,6 +465,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Called immediately after a stack frame got popped, but before jumping back to the caller.
/// The `locals` have already been destroyed!
#[inline(always)]
fn after_stack_pop(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
@ -501,7 +505,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
}
#[inline(always)]
fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> {
fn unwind_terminate(
_ecx: &mut InterpCx<$mir, $tcx, Self>,
_reason: mir::UnwindTerminateReason,
) -> InterpResult<$tcx> {
unreachable!("unwinding cannot happen during compile-time evaluation")
}

View File

@ -196,8 +196,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
UnwindTerminate => {
M::unwind_terminate(self)?;
UnwindTerminate(reason) => {
M::unwind_terminate(self, reason)?;
}
// When we encounter Resume, we've finished unwinding

View File

@ -1037,7 +1037,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
self.check_op(ops::Generator(hir::GeneratorKind::Gen))
}
TerminatorKind::UnwindTerminate => {
TerminatorKind::UnwindTerminate(_) => {
// Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
span_bug!(self.span, "`Terminate` terminator outside of cleanup block")
}

View File

@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
}
}
mir::TerminatorKind::UnwindTerminate
mir::TerminatorKind::UnwindTerminate(_)
| mir::TerminatorKind::Call { .. }
| mir::TerminatorKind::Assert { .. }
| mir::TerminatorKind::FalseEdge { .. }

View File

@ -10,8 +10,8 @@ use rustc_middle::mir::{
traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef,
ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents,
START_BLOCK,
Terminator, TerminatorKind, UnOp, UnwindAction, UnwindTerminateReason, VarDebugInfo,
VarDebugInfoContents, START_BLOCK,
};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeStorageLive;
@ -274,7 +274,16 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
self.fail(location, "`UnwindAction::Continue` in no-unwind function");
}
}
UnwindAction::Unreachable | UnwindAction::Terminate => (),
UnwindAction::Terminate(UnwindTerminateReason::InCleanup) => {
if !is_cleanup {
self.fail(
location,
"`UnwindAction::Terminate(InCleanup)` in a non-cleanup block",
);
}
}
// These are allowed everywhere.
UnwindAction::Unreachable | UnwindAction::Terminate(UnwindTerminateReason::Abi) => (),
}
}
}
@ -501,7 +510,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind")
}
}
TerminatorKind::UnwindTerminate => {
TerminatorKind::UnwindTerminate(_) => {
let bb = location.block;
if !self.body.basic_blocks[bb].is_cleanup {
self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block")
@ -1233,7 +1242,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
| TerminatorKind::InlineAsm { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable => {}
}

View File

@ -238,6 +238,7 @@ language_item_table! {
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0);
/// libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;

View File

@ -1275,9 +1275,11 @@ impl<O> AssertKind<O> {
matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..))
}
/// Getting a description does not require `O` to be printable, and does not
/// require allocation.
/// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately.
/// Get the message that is printed at runtime when this assertion fails.
///
/// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` by
/// invoking the appropriate lang item (panic_bounds_check/panic_misaligned_pointer_dereference)
/// instead of printing a static message.
pub fn description(&self) -> &'static str {
use AssertKind::*;
match self {
@ -1303,6 +1305,11 @@ impl<O> AssertKind<O> {
}
/// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing.
///
/// Needs to be kept in sync with the run-time behavior (which is defined by
/// `AssertKind::description` and the lang items mentioned in its docs).
/// Note that we deliberately show more details here than we do at runtime, such as the actual
/// numbers that overflowed -- it is much easier to do so here than at runtime.
pub fn fmt_assert_args<W: Write>(&self, f: &mut W) -> fmt::Result
where
O: Debug,
@ -1358,6 +1365,12 @@ impl<O> AssertKind<O> {
}
}
/// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval).
///
/// Needs to be kept in sync with the run-time behavior (which is defined by
/// `AssertKind::description` and the lang items mentioned in its docs).
/// Note that we deliberately show more details here than we do at runtime, such as the actual
/// numbers that overflowed -- it is much easier to do so here than at runtime.
pub fn diagnostic_message(&self) -> DiagnosticMessage {
use crate::fluent_generated::*;
use AssertKind::*;

View File

@ -14,7 +14,8 @@ pub struct MirPatch<'tcx> {
resume_block: Option<BasicBlock>,
// Only for unreachable in cleanup path.
unreachable_cleanup_block: Option<BasicBlock>,
terminate_block: Option<BasicBlock>,
// Cached block for UnwindTerminate (with reason)
terminate_block: Option<(BasicBlock, UnwindTerminateReason)>,
body_span: Span,
next_local: usize,
}
@ -35,13 +36,15 @@ impl<'tcx> MirPatch<'tcx> {
for (bb, block) in body.basic_blocks.iter_enumerated() {
// Check if we already have a resume block
if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() {
if matches!(block.terminator().kind, TerminatorKind::UnwindResume)
&& block.statements.is_empty()
{
result.resume_block = Some(bb);
continue;
}
// Check if we already have an unreachable block
if let TerminatorKind::Unreachable = block.terminator().kind
if matches!(block.terminator().kind, TerminatorKind::Unreachable)
&& block.statements.is_empty()
&& block.is_cleanup
{
@ -50,8 +53,10 @@ impl<'tcx> MirPatch<'tcx> {
}
// Check if we already have a terminate block
if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() {
result.terminate_block = Some(bb);
if let TerminatorKind::UnwindTerminate(reason) = block.terminator().kind
&& block.statements.is_empty()
{
result.terminate_block = Some((bb, reason));
continue;
}
}
@ -93,20 +98,20 @@ impl<'tcx> MirPatch<'tcx> {
bb
}
pub fn terminate_block(&mut self) -> BasicBlock {
if let Some(bb) = self.terminate_block {
return bb;
pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason {
return cached_bb;
}
let bb = self.new_block(BasicBlockData {
statements: vec![],
terminator: Some(Terminator {
source_info: SourceInfo::outermost(self.body_span),
kind: TerminatorKind::UnwindTerminate,
kind: TerminatorKind::UnwindTerminate(reason),
}),
is_cleanup: true,
});
self.terminate_block = Some(bb);
self.terminate_block = Some((bb, reason));
bb
}

View File

@ -621,7 +621,7 @@ pub enum TerminatorKind<'tcx> {
///
/// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
/// cleanup blocks.
UnwindTerminate,
UnwindTerminate(UnwindTerminateReason),
/// Returns from the function.
///
@ -813,7 +813,7 @@ impl TerminatorKind<'_> {
TerminatorKind::Goto { .. } => "Goto",
TerminatorKind::SwitchInt { .. } => "SwitchInt",
TerminatorKind::UnwindResume => "UnwindResume",
TerminatorKind::UnwindTerminate => "UnwindTerminate",
TerminatorKind::UnwindTerminate(_) => "UnwindTerminate",
TerminatorKind::Return => "Return",
TerminatorKind::Unreachable => "Unreachable",
TerminatorKind::Drop { .. } => "Drop",
@ -842,11 +842,22 @@ pub enum UnwindAction {
/// Terminates the execution if unwind happens.
///
/// Depending on the platform and situation this may cause a non-unwindable panic or abort.
Terminate,
Terminate(UnwindTerminateReason),
/// Cleanups to be done.
Cleanup(BasicBlock),
}
/// The reason we are terminating the process during unwinding.
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum UnwindTerminateReason {
/// Unwinding is just not possible given the ABI of this function.
Abi,
/// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was
/// triggered by the drop glue.
InCleanup,
}
/// Information about an assertion failure.
#[derive(Clone, Hash, HashStable, PartialEq, Debug)]
#[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]

View File

@ -1,3 +1,4 @@
use rustc_hir::LangItem;
use smallvec::SmallVec;
use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
@ -100,6 +101,40 @@ impl<'a> Iterator for SwitchTargetsIter<'a> {
impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {}
impl UnwindAction {
fn cleanup_block(self) -> Option<BasicBlock> {
match self {
UnwindAction::Cleanup(bb) => Some(bb),
UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_) => None,
}
}
}
impl UnwindTerminateReason {
pub fn as_str(self) -> &'static str {
// Keep this in sync with the messages in `core/src/panicking.rs`.
match self {
UnwindTerminateReason::Abi => "panic in a function that cannot unwind",
UnwindTerminateReason::InCleanup => "panic in a destructor during cleanup",
}
}
/// A short representation of this used for MIR printing.
pub fn as_short_str(self) -> &'static str {
match self {
UnwindTerminateReason::Abi => "abi",
UnwindTerminateReason::InCleanup => "cleanup",
}
}
pub fn lang_item(self) -> LangItem {
match self {
UnwindTerminateReason::Abi => LangItem::PanicCannotUnwind,
UnwindTerminateReason::InCleanup => LangItem::PanicInCleanup,
}
}
}
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct Terminator<'tcx> {
pub source_info: SourceInfo,
@ -156,7 +191,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Some(t).into_iter().chain((&[]).into_iter().copied())
}
UnwindResume
| UnwindTerminate
| UnwindTerminate(_)
| GeneratorDrop
| Return
| Unreachable
@ -198,7 +233,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Some(t).into_iter().chain(&mut [])
}
UnwindResume
| UnwindTerminate
| UnwindTerminate(_)
| GeneratorDrop
| Return
| Unreachable
@ -215,7 +250,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@ -234,7 +269,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@ -271,18 +306,28 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
let labels = self.fmt_successor_labels();
assert_eq!(successor_count, labels.len());
let unwind = match self.unwind() {
// Not needed or included in successors
None | Some(UnwindAction::Cleanup(_)) => None,
Some(UnwindAction::Continue) => Some("unwind continue"),
Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
Some(UnwindAction::Terminate) => Some("unwind terminate"),
// `Cleanup` is already included in successors
let show_unwind = !matches!(self.unwind(), None | Some(UnwindAction::Cleanup(_)));
let fmt_unwind = |fmt: &mut Formatter<'_>| -> fmt::Result {
write!(fmt, "unwind ")?;
match self.unwind() {
// Not needed or included in successors
None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
Some(UnwindAction::Continue) => write!(fmt, "continue"),
Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"),
Some(UnwindAction::Terminate(reason)) => {
write!(fmt, "terminate({})", reason.as_short_str())
}
}
};
match (successor_count, unwind) {
(0, None) => Ok(()),
(0, Some(unwind)) => write!(fmt, " -> {unwind}"),
(1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
match (successor_count, show_unwind) {
(0, false) => Ok(()),
(0, true) => {
write!(fmt, " -> ")?;
fmt_unwind(fmt)
}
(1, false) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
_ => {
write!(fmt, " -> [")?;
for (i, target) in self.successors().enumerate() {
@ -291,8 +336,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
}
write!(fmt, "{}: {:?}", labels[i], target)?;
}
if let Some(unwind) = unwind {
write!(fmt, ", {unwind}")?;
if show_unwind {
write!(fmt, ", ")?;
fmt_unwind(fmt)?;
}
write!(fmt, "]")
}
@ -312,7 +358,9 @@ impl<'tcx> TerminatorKind<'tcx> {
Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"),
UnwindResume => write!(fmt, "resume"),
UnwindTerminate => write!(fmt, "abort"),
UnwindTerminate(reason) => {
write!(fmt, "abort({})", reason.as_short_str())
}
Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
Unreachable => write!(fmt, "unreachable"),
Drop { place, .. } => write!(fmt, "drop({place:?})"),
@ -391,7 +439,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
use self::TerminatorKind::*;
match *self {
Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![],
Return | UnwindResume | UnwindTerminate(_) | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()],
SwitchInt { ref targets, .. } => targets
.values
@ -443,7 +491,8 @@ pub enum TerminatorEdges<'mir, 'tcx> {
/// Special action for `Yield`, `Call` and `InlineAsm` terminators.
AssignOnReturn {
return_: Option<BasicBlock>,
unwind: UnwindAction,
/// The cleanup block, if it exists.
cleanup: Option<BasicBlock>,
place: CallReturnPlaces<'mir, 'tcx>,
},
/// Special edge for `SwitchInt`.
@ -486,7 +535,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
use TerminatorKind::*;
match *self {
Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => {
Return | UnwindResume | UnwindTerminate(_) | GeneratorDrop | Unreachable => {
TerminatorEdges::None
}
@ -496,7 +545,7 @@ impl<'tcx> TerminatorKind<'tcx> {
| Drop { target, unwind, place: _, replace: _ }
| FalseUnwind { real_target: target, unwind } => match unwind {
UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => {
UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => {
TerminatorEdges::Single(target)
}
},
@ -508,7 +557,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Yield { resume: target, drop, resume_arg, value: _ } => {
TerminatorEdges::AssignOnReturn {
return_: Some(target),
unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup),
cleanup: drop,
place: CallReturnPlaces::Yield(resume_arg),
}
}
@ -516,7 +565,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
TerminatorEdges::AssignOnReturn {
return_: target,
unwind,
cleanup: unwind.cleanup_block(),
place: CallReturnPlaces::Call(destination),
}
}
@ -530,7 +579,7 @@ impl<'tcx> TerminatorKind<'tcx> {
unwind,
} => TerminatorEdges::AssignOnReturn {
return_: destination,
unwind,
cleanup: unwind.cleanup_block(),
place: CallReturnPlaces::InlineAsm(operands),
},

View File

@ -470,7 +470,7 @@ macro_rules! make_mir_visitor {
match kind {
TerminatorKind::Goto { .. } |
TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate |
TerminatorKind::UnwindTerminate(_) |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable |
TerminatorKind::FalseEdge { .. } |

View File

@ -370,7 +370,7 @@ impl DropTree {
let terminator = TerminatorKind::Drop {
target: blocks[drop_data.1].unwrap(),
// The caller will handle this if needed.
unwind: UnwindAction::Terminate,
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
place: drop_data.0.local.into(),
replace: false,
};
@ -1507,7 +1507,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Yield { .. }

View File

@ -186,7 +186,7 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
match self.body[bb].terminator().kind {
// These terminators return control flow to the caller.
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume
| TerminatorKind::Return

View File

@ -80,7 +80,7 @@ impl Unwind {
fn into_action(self) -> UnwindAction {
match self {
Unwind::To(bb) => UnwindAction::Cleanup(bb),
Unwind::InCleanup => UnwindAction::Terminate,
Unwind::InCleanup => UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
}
}

View File

@ -1,5 +1,5 @@
use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, UnwindAction,
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges,
};
use std::ops::RangeInclusive;
@ -486,10 +486,10 @@ impl Direction for Forward {
propagate(target, exit_state);
propagate(unwind, exit_state);
}
TerminatorEdges::AssignOnReturn { return_, unwind, place } => {
TerminatorEdges::AssignOnReturn { return_, cleanup, place } => {
// This must be done *first*, otherwise the unwind path will see the assignments.
if let UnwindAction::Cleanup(unwind) = unwind {
propagate(unwind, exit_state);
if let Some(cleanup) = cleanup {
propagate(cleanup, exit_state);
}
if let Some(return_) = return_ {
analysis.apply_call_return_effect(exit_state, bb, place);

View File

@ -131,7 +131,7 @@ where
}
}
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::FalseEdge { .. }

View File

@ -291,7 +291,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
// Nothing to do for these. Match exhaustively so this fails to compile when new
// variants are added.
TerminatorKind::UnwindTerminate
TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. }
@ -328,7 +328,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
// Nothing to do for these. Match exhaustively so this fails to compile when new
// variants are added.
TerminatorKind::Yield { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. }
| TerminatorKind::FalseEdge { .. }

View File

@ -371,7 +371,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// need recording.
| TerminatorKind::Return
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::GeneratorDrop
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } => {}

View File

@ -270,7 +270,7 @@ pub trait ValueAnalysis<'tcx> {
}
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Assert { .. }

View File

@ -104,7 +104,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
for id in calls_to_terminate {
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
*cleanup = UnwindAction::Terminate;
*cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
}
for id in cleanups_to_remove {

View File

@ -53,8 +53,10 @@ impl AddCallGuards {
kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. },
source_info,
}) if pred_count[*destination] > 1
&& (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate)
|| self == &AllCallEdges) =>
&& (matches!(
unwind,
UnwindAction::Cleanup(_) | UnwindAction::Terminate(_)
) || self == &AllCallEdges) =>
{
// It's a critical edge, break it
let call_guard = BasicBlockData {

View File

@ -58,7 +58,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
| TerminatorKind::Assert { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { .. }

View File

@ -679,7 +679,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
// None of these have Operands to const-propagate.
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }

View File

@ -116,7 +116,7 @@ impl CoverageGraph {
match term.kind {
TerminatorKind::Return { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Yield { .. }
| TerminatorKind::SwitchInt { .. } => {
// The `bb` has more than one _outgoing_ edge, or exits the function. Save the

View File

@ -868,7 +868,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
// Retain spans from all other terminators
TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop

View File

@ -648,7 +648,7 @@ impl WriteInfo {
}
TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable { .. } => (),
TerminatorKind::Drop { .. } => {

View File

@ -362,8 +362,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
UnwindAction::Unreachable => {
Unwind::To(self.patch.unreachable_cleanup_block())
}
UnwindAction::Terminate => {
Unwind::To(self.patch.terminate_block())
UnwindAction::Terminate(reason) => {
debug_assert_ne!(
reason,
UnwindTerminateReason::InCleanup,
"we are not in a cleanup block, InCleanup reason should be impossible"
);
Unwind::To(self.patch.terminate_block(reason))
}
}
};
@ -496,7 +501,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
if let TerminatorKind::Call {
destination,
target: Some(_),
unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate,
unwind:
UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_),
..
} = data.terminator().kind
{

View File

@ -1091,7 +1091,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
UnwindAction::Cleanup(tgt) => tgt,
UnwindAction::Continue => elaborator.patch.resume_block(),
UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(),
UnwindAction::Terminate => elaborator.patch.terminate_block(),
UnwindAction::Terminate(reason) => elaborator.patch.terminate_block(reason),
})
};
elaborate_drop(
@ -1239,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// These never unwind.
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
@ -1759,7 +1759,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }

View File

@ -906,12 +906,12 @@ impl Integrator<'_, '_> {
UnwindAction::Cleanup(_) | UnwindAction::Continue => {
bug!("cleanup on cleanup block");
}
UnwindAction::Unreachable | UnwindAction::Terminate => return unwind,
UnwindAction::Unreachable | UnwindAction::Terminate(_) => return unwind,
}
}
match unwind {
UnwindAction::Unreachable | UnwindAction::Terminate => unwind,
UnwindAction::Unreachable | UnwindAction::Terminate(_) => unwind,
UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
// Add an unwind edge to the original call's cleanup block
UnwindAction::Continue => self.cleanup_block,
@ -1022,10 +1022,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
UnwindAction::Continue => TerminatorKind::UnwindResume,
UnwindAction::Unreachable => TerminatorKind::Unreachable,
UnwindAction::Terminate => TerminatorKind::UnwindTerminate,
UnwindAction::Terminate(reason) => TerminatorKind::UnwindTerminate(reason),
};
}
TerminatorKind::UnwindTerminate => {}
TerminatorKind::UnwindTerminate(_) => {}
TerminatorKind::Unreachable => {}
TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
*real_target = self.map_block(*real_target);

View File

@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. }
| TerminatorKind::Return
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable
| TerminatorKind::Call { .. }
| TerminatorKind::Assert { .. }

View File

@ -114,7 +114,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
| TerminatorKind::Assert { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Yield { .. }
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::InlineAsm { .. }
@ -166,7 +166,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
}
TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop

View File

@ -570,10 +570,10 @@ impl<'tcx> CloneShimBuilder<'tcx> {
TerminatorKind::Drop {
place: dest_field,
target: unwind,
unwind: UnwindAction::Terminate,
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
replace: false,
},
true,
/* is_cleanup */ true,
);
unwind = next_unwind;
}
@ -851,10 +851,10 @@ fn build_call_shim<'tcx>(
TerminatorKind::Drop {
place: rcvr_place(),
target: BasicBlock::new(4),
unwind: UnwindAction::Terminate,
unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
replace: false,
},
true,
/* is_cleanup */ true,
);
// BB #4 - resume

View File

@ -737,6 +737,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
let source = self.body.source_info(location).span;
let tcx = self.tcx;
let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
if should_codegen_locally(tcx, &instance) {
this.output.push(create_fn_mono_item(tcx, instance, source));
}
};
match terminator.kind {
mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx);
@ -771,19 +778,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
_ => LangItem::Panic,
};
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
push_mono_lang_item(self, lang_item);
}
mir::TerminatorKind::UnwindTerminate { .. } => {
let instance = Instance::mono(
tcx,
tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
);
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
mir::TerminatorKind::UnwindTerminate(reason) => {
push_mono_lang_item(self, reason.lang_item());
}
mir::TerminatorKind::Goto { .. }
| mir::TerminatorKind::SwitchInt { .. }
@ -796,14 +794,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
| mir::TerminatorKind::FalseUnwind { .. } => bug!(),
}
if let Some(mir::UnwindAction::Terminate) = terminator.unwind() {
let instance = Instance::mono(
tcx,
tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
);
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
if let Some(mir::UnwindAction::Terminate(reason)) = terminator.unwind() {
push_mono_lang_item(self, reason.lang_item());
}
self.super_terminator(terminator, location);

View File

@ -607,7 +607,7 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction {
match self {
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable,
UnwindAction::Terminate => stable_mir::mir::UnwindAction::Terminate,
UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate,
UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()),
}
}
@ -805,7 +805,7 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
otherwise: targets.otherwise().as_usize(),
},
UnwindResume => Terminator::Resume,
UnwindTerminate => Terminator::Abort,
UnwindTerminate(_) => Terminator::Abort,
Return => Terminator::Return,
Unreachable => Terminator::Unreachable,
Drop { place, target, unwind, replace: _ } => Terminator::Drop {

View File

@ -1104,6 +1104,7 @@ symbols! {
panic_handler,
panic_impl,
panic_implementation,
panic_in_cleanup,
panic_info,
panic_location,
panic_misaligned_pointer_dereference,

View File

@ -179,6 +179,8 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
/// Panic because we cannot unwind out of a function.
///
/// This is a separate function to avoid the codesize impact of each crate containing the string to
/// pass to `panic_nounwind`.
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
@ -186,9 +188,26 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
#[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
fn panic_cannot_unwind() -> ! {
// Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`.
panic_nounwind("panic in a function that cannot unwind")
}
/// Panic because we are unwinding out of a destructor during cleanup.
///
/// This is a separate function to avoid the codesize impact of each crate containing the string to
/// pass to `panic_nounwind`.
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg(not(bootstrap))]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
fn panic_in_cleanup() -> ! {
// Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`.
panic_nounwind("panic in a destructor during cleanup")
}
/// This function is used instead of panic_fmt in const eval.
#[lang = "const_panic_fmt"]
#[rustc_const_unstable(feature = "core_panic", issue = "none")]

View File

@ -292,7 +292,7 @@ fn check_terminator<'tcx>(
| TerminatorKind::Goto { .. }
| TerminatorKind::Return
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate
| TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable => Ok(()),
TerminatorKind::Drop { place, .. } => {
if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) {

View File

@ -3622,26 +3622,30 @@ impl<'test> TestCx<'test> {
let expected_stderr = self.load_expected_output(stderr_kind);
let expected_stdout = self.load_expected_output(stdout_kind);
let normalized_stdout = match output_kind {
let mut normalized_stdout =
self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
match output_kind {
TestOutput::Run if self.config.remote_test_client.is_some() => {
// When tests are run using the remote-test-client, the string
// 'uploaded "$TEST_BUILD_DIR/<test_executable>, waiting for result"'
// is printed to stdout by the client and then captured in the ProcRes,
// so it needs to be removed when comparing the run-pass test execution output
// so it needs to be removed when comparing the run-pass test execution output.
static REMOTE_TEST_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(
"^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-.]+)+\", waiting for result\n"
)
.unwrap()
});
REMOTE_TEST_RE
.replace(
&self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout),
"",
)
.to_string()
normalized_stdout = REMOTE_TEST_RE.replace(&normalized_stdout, "").to_string();
// When there is a panic, the remote-test-client also prints "died due to signal";
// that needs to be removed as well.
static SIGNAL_DIED_RE: Lazy<Regex> =
Lazy::new(|| Regex::new("^died due to signal [0-9]+\n").unwrap());
normalized_stdout = SIGNAL_DIED_RE.replace(&normalized_stdout, "").to_string();
// FIXME: it would be much nicer if we could just tell the remote-test-client to not
// print these things.
}
_ => self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout),
_ => {}
};
let stderr = if explicit_format {

View File

@ -975,9 +975,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
ecx.start_panic_nounwind(msg)
}
fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: mir::UnwindTerminateReason) -> InterpResult<'tcx> {
// Call the lang item.
let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap();
let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap();
let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
ecx.call_function(
panic,

View File

@ -5,7 +5,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
second
stack backtrace:
thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
panic in a function that cannot unwind
panic in a destructor during cleanup
stack backtrace:
thread caused non-unwinding panic. aborting.
error: abnormal termination: the program aborted execution
@ -20,7 +20,7 @@ LL | ABORT();
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
= note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC
note: inside `main`
--> $DIR/double_panic.rs:LL:CC
|

View File

@ -9,7 +9,7 @@ fn main() -> () {
bb0: {
StorageLive(_1);
_1 = const ();
asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate];
asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate(abi)];
}
bb1: {

View File

@ -47,7 +47,7 @@
bb2 (cleanup): {
_5 = move _6;
- drop(_6) -> [return: bb6, unwind terminate];
- drop(_6) -> [return: bb6, unwind terminate(cleanup)];
+ goto -> bb6;
}
@ -71,12 +71,12 @@
}
bb6 (cleanup): {
- drop(_5) -> [return: bb7, unwind terminate];
- drop(_5) -> [return: bb7, unwind terminate(cleanup)];
+ goto -> bb7;
}
bb7 (cleanup): {
- drop(_4) -> [return: bb8, unwind terminate];
- drop(_4) -> [return: bb8, unwind terminate(cleanup)];
+ goto -> bb8;
}

View File

@ -51,7 +51,7 @@ fn main() -> () {
bb2 (cleanup): {
_5 = move _6;
drop(_6) -> [return: bb6, unwind terminate];
drop(_6) -> [return: bb6, unwind terminate(cleanup)];
}
bb3: {
@ -73,11 +73,11 @@ fn main() -> () {
}
bb6 (cleanup): {
drop(_5) -> [return: bb7, unwind terminate];
drop(_5) -> [return: bb7, unwind terminate(cleanup)];
}
bb7 (cleanup): {
drop(_4) -> [return: bb8, unwind terminate];
drop(_4) -> [return: bb8, unwind terminate(cleanup)];
}
bb8 (cleanup): {

View File

@ -54,15 +54,15 @@ fn main() -> () {
}
bb6 (cleanup): {
drop(_7) -> [return: bb7, unwind terminate];
drop(_7) -> [return: bb7, unwind terminate(cleanup)];
}
bb7 (cleanup): {
drop(_1) -> [return: bb9, unwind terminate];
drop(_1) -> [return: bb9, unwind terminate(cleanup)];
}
bb8 (cleanup): {
drop(_5) -> [return: bb9, unwind terminate];
drop(_5) -> [return: bb9, unwind terminate(cleanup)];
}
bb9 (cleanup): {

View File

@ -54,15 +54,15 @@ fn main() -> () {
}
bb6 (cleanup): {
drop(_7) -> [return: bb7, unwind terminate];
drop(_7) -> [return: bb7, unwind terminate(cleanup)];
}
bb7 (cleanup): {
drop(_1) -> [return: bb9, unwind terminate];
drop(_1) -> [return: bb9, unwind terminate(cleanup)];
}
bb8 (cleanup): {
drop(_5) -> [return: bb9, unwind terminate];
drop(_5) -> [return: bb9, unwind terminate(cleanup)];
}
bb9 (cleanup): {

View File

@ -62,7 +62,7 @@ fn droppy() -> () {
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {

View File

@ -89,15 +89,15 @@ fn move_out_by_subslice() -> () {
}
bb9 (cleanup): {
drop(_1) -> [return: bb12, unwind terminate];
drop(_1) -> [return: bb12, unwind terminate(cleanup)];
}
bb10 (cleanup): {
drop(_7) -> [return: bb11, unwind terminate];
drop(_7) -> [return: bb11, unwind terminate(cleanup)];
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {

View File

@ -89,15 +89,15 @@ fn move_out_from_end() -> () {
}
bb9 (cleanup): {
drop(_1) -> [return: bb12, unwind terminate];
drop(_1) -> [return: bb12, unwind terminate(cleanup)];
}
bb10 (cleanup): {
drop(_7) -> [return: bb11, unwind terminate];
drop(_7) -> [return: bb11, unwind terminate(cleanup)];
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {

View File

@ -63,7 +63,7 @@
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {

View File

@ -28,7 +28,7 @@
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {

View File

@ -28,7 +28,7 @@
}
bb4 (cleanup): {
drop(_2) -> [return: bb5, unwind terminate];
drop(_2) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {

View File

@ -104,7 +104,7 @@ yields ()
bb13 (cleanup): {
StorageDead(_3);
drop(_1) -> [return: bb14, unwind terminate];
drop(_1) -> [return: bb14, unwind terminate(cleanup)];
}
bb14 (cleanup): {
@ -113,6 +113,6 @@ yields ()
bb15 (cleanup): {
StorageDead(_3);
drop(_1) -> [return: bb14, unwind terminate];
drop(_1) -> [return: bb14, unwind terminate(cleanup)];
}
}

View File

@ -17,7 +17,7 @@
StorageLive(_1);
- _1 = foo() -> [return: bb1, unwind unreachable];
+ StorageLive(_2);
+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate];
+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate(abi)];
}
bb1: {

View File

@ -32,7 +32,7 @@
+ }
+
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb4, unwind terminate];
+ drop(_2) -> [return: bb4, unwind terminate(cleanup)];
+ }
+
+ bb4 (cleanup): {

View File

@ -30,7 +30,7 @@
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -36,7 +36,7 @@
+ }
+
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb4, unwind terminate];
+ drop(_2) -> [return: bb4, unwind terminate(cleanup)];
+ }
+
+ bb4 (cleanup): {

View File

@ -36,7 +36,7 @@
+ }
+
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb4, unwind terminate];
+ drop(_2) -> [return: bb4, unwind terminate(cleanup)];
+ }
+
+ bb4 (cleanup): {

View File

@ -27,7 +27,7 @@
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -30,7 +30,7 @@
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -54,11 +54,11 @@
+ }
+
+ bb4 (cleanup): {
+ drop(_4) -> [return: bb5, unwind terminate];
+ drop(_4) -> [return: bb5, unwind terminate(cleanup)];
+ }
+
+ bb5 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate];
+ drop(_2) -> [return: bb6, unwind terminate(cleanup)];
+ }
+
+ bb6 (cleanup): {

View File

@ -155,7 +155,7 @@
- StorageDead(_1);
- return;
+ bb3 (cleanup): {
+ drop(_2) -> [return: bb2, unwind terminate];
+ drop(_2) -> [return: bb2, unwind terminate(cleanup)];
}
- bb4 (cleanup): {

View File

@ -37,7 +37,7 @@
}
bb4 (cleanup): {
drop(_1) -> [return: bb5, unwind terminate];
drop(_1) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {

View File

@ -40,7 +40,7 @@
}
bb4 (cleanup): {
drop(_1) -> [return: bb5, unwind terminate];
drop(_1) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {

View File

@ -40,7 +40,7 @@
bb4 (cleanup): {
_8 = &mut _3;
_9 = <Box<[i32]> as Drop>::drop(move _8) -> [return: bb1, unwind terminate];
_9 = <Box<[i32]> as Drop>::drop(move _8) -> [return: bb1, unwind terminate(cleanup)];
}
}

View File

@ -40,17 +40,17 @@
}
bb3 (cleanup): {
- drop(_3) -> [return: bb5, unwind terminate];
- drop(_3) -> [return: bb5, unwind terminate(cleanup)];
+ goto -> bb5;
}
bb4 (cleanup): {
- drop(_4) -> [return: bb5, unwind terminate];
- drop(_4) -> [return: bb5, unwind terminate(cleanup)];
+ goto -> bb5;
}
bb5 (cleanup): {
- drop(_2) -> [return: bb6, unwind terminate];
- drop(_2) -> [return: bb6, unwind terminate(cleanup)];
+ goto -> bb8;
}
@ -59,7 +59,7 @@
+ }
+
+ bb7 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate];
+ drop(_2) -> [return: bb6, unwind terminate(cleanup)];
+ }
+
+ bb8 (cleanup): {

View File

@ -40,17 +40,17 @@
}
bb3 (cleanup): {
- drop(_3) -> [return: bb5, unwind terminate];
- drop(_3) -> [return: bb5, unwind terminate(cleanup)];
+ goto -> bb5;
}
bb4 (cleanup): {
- drop(_4) -> [return: bb5, unwind terminate];
- drop(_4) -> [return: bb5, unwind terminate(cleanup)];
+ goto -> bb5;
}
bb5 (cleanup): {
- drop(_2) -> [return: bb6, unwind terminate];
- drop(_2) -> [return: bb6, unwind terminate(cleanup)];
+ goto -> bb8;
}
@ -59,7 +59,7 @@
+ }
+
+ bb7 (cleanup): {
+ drop(_2) -> [return: bb6, unwind terminate];
+ drop(_2) -> [return: bb6, unwind terminate(cleanup)];
+ }
+
+ bb8 (cleanup): {

View File

@ -47,7 +47,7 @@
bb3 (cleanup): {
_2 = move _5;
- drop(_5) -> [return: bb8, unwind terminate];
- drop(_5) -> [return: bb8, unwind terminate(cleanup)];
+ goto -> bb8;
}
@ -70,17 +70,17 @@
}
bb7 (cleanup): {
- drop(_4) -> [return: bb8, unwind terminate];
- drop(_4) -> [return: bb8, unwind terminate(cleanup)];
+ goto -> bb8;
}
bb8 (cleanup): {
- drop(_2) -> [return: bb9, unwind terminate];
- drop(_2) -> [return: bb9, unwind terminate(cleanup)];
+ goto -> bb9;
}
bb9 (cleanup): {
- drop(_1) -> [return: bb10, unwind terminate];
- drop(_1) -> [return: bb10, unwind terminate(cleanup)];
+ goto -> bb12;
}
@ -89,7 +89,7 @@
+ }
+
+ bb11 (cleanup): {
+ drop(_1) -> [return: bb10, unwind terminate];
+ drop(_1) -> [return: bb10, unwind terminate(cleanup)];
+ }
+
+ bb12 (cleanup): {

View File

@ -47,7 +47,7 @@
bb3 (cleanup): {
_2 = move _5;
- drop(_5) -> [return: bb8, unwind terminate];
- drop(_5) -> [return: bb8, unwind terminate(cleanup)];
+ goto -> bb8;
}
@ -70,17 +70,17 @@
}
bb7 (cleanup): {
- drop(_4) -> [return: bb8, unwind terminate];
- drop(_4) -> [return: bb8, unwind terminate(cleanup)];
+ goto -> bb8;
}
bb8 (cleanup): {
- drop(_2) -> [return: bb9, unwind terminate];
- drop(_2) -> [return: bb9, unwind terminate(cleanup)];
+ goto -> bb9;
}
bb9 (cleanup): {
- drop(_1) -> [return: bb10, unwind terminate];
- drop(_1) -> [return: bb10, unwind terminate(cleanup)];
+ goto -> bb12;
}
@ -89,7 +89,7 @@
+ }
+
+ bb11 (cleanup): {
+ drop(_1) -> [return: bb10, unwind terminate];
+ drop(_1) -> [return: bb10, unwind terminate(cleanup)];
+ }
+
+ bb12 (cleanup): {

View File

@ -58,7 +58,7 @@
+ _8 = const true;
+ _9 = const true;
_1 = move _3;
- drop(_3) -> [return: bb11, unwind terminate];
- drop(_3) -> [return: bb11, unwind terminate(cleanup)];
+ goto -> bb11;
}
@ -102,7 +102,7 @@
}
bb11 (cleanup): {
- drop(_1) -> [return: bb12, unwind terminate];
- drop(_1) -> [return: bb12, unwind terminate(cleanup)];
+ goto -> bb12;
}
@ -124,7 +124,7 @@
+ }
+
+ bb16 (cleanup): {
+ drop(_1) -> [return: bb12, unwind terminate];
+ drop(_1) -> [return: bb12, unwind terminate(cleanup)];
+ }
+
+ bb17: {

View File

@ -58,7 +58,7 @@
+ _8 = const true;
+ _9 = const true;
_1 = move _3;
- drop(_3) -> [return: bb11, unwind terminate];
- drop(_3) -> [return: bb11, unwind terminate(cleanup)];
+ goto -> bb11;
}
@ -102,7 +102,7 @@
}
bb11 (cleanup): {
- drop(_1) -> [return: bb12, unwind terminate];
- drop(_1) -> [return: bb12, unwind terminate(cleanup)];
+ goto -> bb12;
}
@ -124,7 +124,7 @@
+ }
+
+ bb16 (cleanup): {
+ drop(_1) -> [return: bb12, unwind terminate];
+ drop(_1) -> [return: bb12, unwind terminate(cleanup)];
+ }
+
+ bb17: {

View File

@ -100,11 +100,11 @@ fn test() -> Option<Box<u32>> {
}
bb11 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate];
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_5) -> [return: bb13, unwind terminate];
drop(_5) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {

View File

@ -100,11 +100,11 @@ fn test() -> Option<Box<u32>> {
}
bb11 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate];
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_5) -> [return: bb13, unwind terminate];
drop(_5) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {

View File

@ -28,7 +28,7 @@ fn bar(_1: Box<[T]>) -> () {
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate];
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -45,7 +45,7 @@ fn foo(_1: Box<[T]>) -> T {
}
bb5 (cleanup): {
drop(_1) -> [return: bb6, unwind terminate];
drop(_1) -> [return: bb6, unwind terminate(cleanup)];
}
bb6 (cleanup): {

View File

@ -243,7 +243,7 @@
}
- bb25 (cleanup): {
- drop(_2) -> [return: bb26, unwind terminate];
- drop(_2) -> [return: bb26, unwind terminate(cleanup)];
+ bb22 (cleanup): {
+ goto -> bb27;
}

View File

@ -243,7 +243,7 @@
}
- bb25 (cleanup): {
- drop(_2) -> [return: bb26, unwind terminate];
- drop(_2) -> [return: bb26, unwind terminate(cleanup)];
+ bb22 (cleanup): {
+ goto -> bb27;
}

View File

@ -31,7 +31,7 @@ fn main() -> () {
}
bb3 (cleanup): {
drop(_2) -> [return: bb4, unwind terminate];
drop(_2) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -31,7 +31,7 @@ fn main() -> () {
}
bb3 (cleanup): {
drop(_2) -> [return: bb4, unwind terminate];
drop(_2) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -33,7 +33,7 @@ fn main() -> () {
bb1 (cleanup): {
(_1.0: Aligned) = move _4;
drop(_1) -> [return: bb3, unwind terminate];
drop(_1) -> [return: bb3, unwind terminate(cleanup)];
}
bb2: {

View File

@ -83,7 +83,7 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> ()
}
bb9 (cleanup): {
drop(_5) -> [return: bb10, unwind terminate];
drop(_5) -> [return: bb10, unwind terminate(cleanup)];
}
bb10 (cleanup): {

View File

@ -75,7 +75,7 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
}
bb9 (cleanup): {
drop(_5) -> [return: bb10, unwind terminate];
drop(_5) -> [return: bb10, unwind terminate(cleanup)];
}
bb10 (cleanup): {

View File

@ -67,7 +67,7 @@ fn vec_move(_1: Vec<impl Sized>) -> () {
}
bb9 (cleanup): {
drop(_3) -> [return: bb10, unwind terminate];
drop(_3) -> [return: bb10, unwind terminate(cleanup)];
}
bb10 (cleanup): {

View File

@ -127,7 +127,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
}
bb11 (cleanup): {
drop(_3) -> [return: bb12, unwind terminate];
drop(_3) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {

View File

@ -82,7 +82,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
}
bb8 (cleanup): {
drop(_3) -> [return: bb9, unwind terminate];
drop(_3) -> [return: bb9, unwind terminate(cleanup)];
}
bb9 (cleanup): {

View File

@ -195,7 +195,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {

View File

@ -182,7 +182,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {

View File

@ -143,7 +143,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb12 (cleanup): {
drop(_2) -> [return: bb13, unwind terminate];
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {

View File

@ -196,7 +196,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
}
bb11 (cleanup): {
drop(_2) -> [return: bb12, unwind terminate];
drop(_2) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {

View File

@ -167,11 +167,11 @@ fn main() -> () {
}
bb7 (cleanup): {
drop(_21) -> [return: bb9, unwind terminate];
drop(_21) -> [return: bb9, unwind terminate(cleanup)];
}
bb8 (cleanup): {
drop(_5) -> [return: bb9, unwind terminate];
drop(_5) -> [return: bb9, unwind terminate(cleanup)];
}
bb9 (cleanup): {

View File

@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
bb3 (cleanup): {
_4 = &raw mut (*_1)[_3];
_3 = Add(move _3, const 1_usize);
drop((*_4)) -> [return: bb4, unwind terminate];
drop((*_4)) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {

View File

@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
}
bb4 (cleanup): {
drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate];
drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate(cleanup)];
}
bb5: {

Some files were not shown because too many files have changed in this diff Show More