Make destructors on extern "C"
frames to be executed
This commit is contained in:
parent
a3f76a26e0
commit
1598aa4f83
@ -51,11 +51,20 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||||||
// This will filter to functions with `extern "C-unwind"` ABIs, for
|
// This will filter to functions with `extern "C-unwind"` ABIs, for
|
||||||
// example.
|
// example.
|
||||||
for block in body.basic_blocks.as_mut() {
|
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 {
|
if block.is_cleanup {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let Some(terminator) = &block.terminator else { continue };
|
|
||||||
let span = terminator.source_info.span;
|
|
||||||
|
|
||||||
let call_can_unwind = match &terminator.kind {
|
let call_can_unwind = match &terminator.kind {
|
||||||
TerminatorKind::Call { func, .. } => {
|
TerminatorKind::Call { func, .. } => {
|
||||||
@ -87,14 +96,18 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||||||
if !call_can_unwind {
|
if !call_can_unwind {
|
||||||
// If this function call can't unwind, then there's no need for it
|
// 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
|
// 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();
|
let cleanup = block.terminator_mut().unwind_mut().unwrap();
|
||||||
*cleanup = UnwindAction::Unreachable;
|
*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
|
// Otherwise if this function can unwind, then if the outer function
|
||||||
// can also unwind there's nothing to do. 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
|
// can't unwind, however, we need to ensure that any `UnwindAction::Continue`
|
||||||
// function call to one that aborts.
|
// 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();
|
let cleanup = block.terminator_mut().unwind_mut().unwrap();
|
||||||
*cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
|
*cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user