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

`}

`