Auto merge of #129582 - nbdd0121:unwind, r=nnethercote · rust-lang/rust@06d261d (original) (raw)
`@@ -51,11 +51,20 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
`
51
51
`` // This will filter to functions with extern "C-unwind"
ABIs, for
``
52
52
`// example.
`
53
53
`for block in body.basic_blocks.as_mut() {
`
``
54
`+
let Some(terminator) = &mut block.terminator else { continue };
`
``
55
`+
let span = terminator.source_info.span;
`
``
56
+
``
57
`` +
// If we see an UnwindResume
terminator inside a function that cannot unwind, we need
``
``
58
`` +
// to replace it with UnwindTerminate
.
``
``
59
`+
if let TerminatorKind::UnwindResume = &terminator.kind
`
``
60
`+
&& !body_can_unwind
`
``
61
`+
{
`
``
62
`+
terminator.kind = TerminatorKind::UnwindTerminate(UnwindTerminateReason::Abi);
`
``
63
`+
}
`
``
64
+
54
65
`if block.is_cleanup {
`
55
66
`continue;
`
56
67
`}
`
57
``
`-
let Some(terminator) = &block.terminator else { continue };
`
58
``
`-
let span = terminator.source_info.span;
`
59
68
``
60
69
`let call_can_unwind = match &terminator.kind {
`
61
70
`TerminatorKind::Call { func, .. } => {
`
`@@ -87,14 +96,18 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
`
87
96
`if !call_can_unwind {
`
88
97
`// If this function call can't unwind, then there's no need for it
`
89
98
`// to have a landing pad. This means that we can remove any cleanup
`
90
``
`-
// registered for it.
`
``
99
`` +
// registered for it (and turn it into UnwindAction::Unreachable
).
``
91
100
`let cleanup = block.terminator_mut().unwind_mut().unwrap();
`
92
101
`*cleanup = UnwindAction::Unreachable;
`
93
``
`-
} else if !body_can_unwind {
`
``
102
`+
} else if !body_can_unwind
`
``
103
`+
&& matches!(terminator.unwind(), Some(UnwindAction::Continue))
`
``
104
`+
{
`
94
105
`// Otherwise if this function can unwind, then if the outer function
`
95
106
`// can also unwind there's nothing to do. If the outer function
`
96
``
`-
// can't unwind, however, we need to change the landing pad for this
`
97
``
`-
// function call to one that aborts.
`
``
107
`` +
// can't unwind, however, we need to ensure that any UnwindAction::Continue
``
``
108
`` +
// is replaced with terminate. For those with UnwindAction::Cleanup
,
``
``
109
`+
// cleanup will still happen, and terminate will happen afterwards handled by
`
``
110
`` +
// the UnwindResume
-> UnwindTerminate
terminator replacement.
``
98
111
`let cleanup = block.terminator_mut().unwind_mut().unwrap();
`
99
112
`*cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
`
100
113
`}
`