Skip to content

Commit

Permalink
Make destructors on extern "C" frames to be executed
Browse files Browse the repository at this point in the history
  • Loading branch information
nbdd0121 committed Sep 27, 2024
1 parent a3f76a2 commit 1598aa4
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,20 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
// This will filter to functions with `extern "C-unwind"` ABIs, for
// example.
for block in body.basic_blocks.as_mut() {
let Some(terminator) = &mut block.terminator else { continue };
let span = terminator.source_info.span;

// If we see an `UnwindResume` terminator inside a function that cannot unwind, we need
// to replace it with `UnwindTerminate`.
if let TerminatorKind::UnwindResume = &terminator.kind
&& !body_can_unwind
{
terminator.kind = TerminatorKind::UnwindTerminate(UnwindTerminateReason::Abi);
}

if block.is_cleanup {
continue;
}
let Some(terminator) = &block.terminator else { continue };
let span = terminator.source_info.span;

let call_can_unwind = match &terminator.kind {
TerminatorKind::Call { func, .. } => {
Expand Down Expand Up @@ -87,14 +96,18 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
if !call_can_unwind {
// If this function call can't unwind, then there's no need for it
// to have a landing pad. This means that we can remove any cleanup
// registered for it.
// registered for it (and turn it into `UnwindAction::Unreachable`).
let cleanup = block.terminator_mut().unwind_mut().unwrap();
*cleanup = UnwindAction::Unreachable;
} else if !body_can_unwind {
} else if !body_can_unwind
&& matches!(terminator.unwind(), Some(UnwindAction::Continue))
{
// Otherwise if this function can unwind, then if the outer function
// can also unwind there's nothing to do. If the outer function
// can't unwind, however, we need to change the landing pad for this
// function call to one that aborts.
// can't unwind, however, we need to ensure that any `UnwindAction::Continue`
// is replaced with terminate. For those with `UnwindAction::Cleanup`,
// cleanup will still happen, and terminate will happen afterwards handled by
// the `UnwindResume` -> `UnwindTerminate` terminator replacement.
let cleanup = block.terminator_mut().unwind_mut().unwrap();
*cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
}
Expand Down

0 comments on commit 1598aa4

Please sign in to comment.