authorbors <bors@rust-lang.org> 2024-10-17 04:34:51 UTC
committerbors <bors@rust-lang.org> 2024-10-17 04:34:51 UTC
log06d261daf62620e3449ba451898c7ad9ae750f41
tree35b821155357b77c05b8bb049a9384b0f59addf1
parentdd5127615ad626741a1116d022cf784637ac05df
parentbb531083cc0301d2152dc59746eb30472564948d

Auto merge of #129582 - nbdd0121:unwind, r=nnethercote

Make destructors on `extern "C"` frames to be executed This would make the example in #123231 print "Noisy Drop". I didn't mark this as fixing the issue because the behaviour is yet to be spec'ed. Tracking: - https://github.com/rust-lang/rust/issues/74990

8 files changed, 99 insertions(+), 17 deletions(-)

compiler/rustc_mir_transform/src/abort_unwinding_calls.rs+19-6
......@@ -51,11 +51,20 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
5151 // This will filter to functions with `extern "C-unwind"` ABIs, for
5252 // example.
5353 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
5465 if block.is_cleanup {
5566 continue;
5667 }
57 let Some(terminator) = &block.terminator else { continue };
58 let span = terminator.source_info.span;
5968
6069 let call_can_unwind = match &terminator.kind {
6170 TerminatorKind::Call { func, .. } => {
......@@ -87,14 +96,18 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
8796 if !call_can_unwind {
8897 // If this function call can't unwind, then there's no need for it
8998 // 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`).
91100 let cleanup = block.terminator_mut().unwind_mut().unwrap();
92101 *cleanup = UnwindAction::Unreachable;
93 } else if !body_can_unwind {
102 } else if !body_can_unwind
103 && matches!(terminator.unwind(), Some(UnwindAction::Continue))
104 {
94105 // Otherwise if this function can unwind, then if the outer function
95106 // 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.
98111 let cleanup = block.terminator_mut().unwind_mut().unwrap();
99112 *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
100113 }
tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir+5-1
......@@ -7,7 +7,7 @@ fn main() -> () {
77 bb0: {
88 StorageLive(_1);
99 _1 = const ();
10 asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate(abi)];
10 asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2];
1111 }
1212
1313 bb1: {
......@@ -15,4 +15,8 @@ fn main() -> () {
1515 _0 = const ();
1616 return;
1717 }
18
19 bb2 (cleanup): {
20 terminate(abi);
21 }
1822}
tests/mir-opt/asm_unwind_panic_abort.rs+3-1
......@@ -10,7 +10,9 @@
1010fn main() {
1111 // CHECK-LABEL: fn main(
1212 // CHECK: asm!(
13 // CHECK-SAME: unwind terminate(abi)
13 // CHECK-SAME: unwind: [[unwind:bb.*]]]
14 // CHECK: [[unwind]] (cleanup)
15 // CHECK-NEXT: terminate(abi)
1416 unsafe {
1517 std::arch::asm!("", options(may_unwind));
1618 }
tests/mir-opt/c_unwind_terminate.rs created+25
......@@ -0,0 +1,25 @@
1//@ needs-unwind
2
3struct Noise;
4impl Drop for Noise {
5 fn drop(&mut self) {
6 eprintln!("Noisy Drop");
7 }
8}
9
10fn panic() {
11 panic!();
12}
13
14// EMIT_MIR c_unwind_terminate.test.AbortUnwindingCalls.after.mir
15extern "C" fn test() {
16 // CHECK-LABEL: fn test(
17 // CHECK: drop
18 // CHECK-SAME: unwind: [[unwind:bb.*]]]
19 // CHECK: [[unwind]] (cleanup)
20 // CHECK-NEXT: terminate(abi)
21 let _val = Noise;
22 panic();
23}
24
25fn main() {}
tests/mir-opt/c_unwind_terminate.test.AbortUnwindingCalls.after.mir created+36
......@@ -0,0 +1,36 @@
1// MIR for `test` after AbortUnwindingCalls
2
3fn test() -> () {
4 let mut _0: ();
5 let _1: Noise;
6 let _2: ();
7 scope 1 {
8 debug _val => _1;
9 }
10
11 bb0: {
12 StorageLive(_1);
13 _1 = Noise;
14 StorageLive(_2);
15 _2 = panic() -> [return: bb1, unwind: bb3];
16 }
17
18 bb1: {
19 StorageDead(_2);
20 _0 = const ();
21 drop(_1) -> [return: bb2, unwind: bb4];
22 }
23
24 bb2: {
25 StorageDead(_1);
26 return;
27 }
28
29 bb3 (cleanup): {
30 drop(_1) -> [return: bb4, unwind terminate(cleanup)];
31 }
32
33 bb4 (cleanup): {
34 terminate(abi);
35 }
36}
tests/run-make/longjmp-across-rust/main.rs-8
......@@ -10,19 +10,11 @@ fn main() {
1010 }
1111}
1212
13struct A;
14
15impl Drop for A {
16 fn drop(&mut self) {}
17}
18
1913extern "C" fn test_middle() {
20 let _a = A;
2114 foo();
2215}
2316
2417fn foo() {
25 let _a = A;
2618 unsafe {
2719 test_end();
2820 }
tests/ui/panics/panic-in-ffi.rs+9
......@@ -2,13 +2,22 @@
22//@ exec-env:RUST_BACKTRACE=0
33//@ check-run-results
44//@ error-pattern: panic in a function that cannot unwind
5//@ error-pattern: Noisy Drop
56//@ normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
67//@ normalize-stderr-test: "\n +at [^\n]+" -> ""
78//@ normalize-stderr-test: "(core/src/panicking\.rs):[0-9]+:[0-9]+" -> "$1:$$LINE:$$COL"
89//@ needs-unwind
910//@ ignore-emscripten "RuntimeError" junk in output
1011
12struct Noise;
13impl Drop for Noise {
14 fn drop(&mut self) {
15 eprintln!("Noisy Drop");
16 }
17}
18
1119extern "C" fn panic_in_ffi() {
20 let _val = Noise;
1221 panic!("Test");
1322}
1423
tests/ui/panics/panic-in-ffi.run.stderr+2-1
......@@ -1,6 +1,7 @@
1thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5:
1thread 'main' panicked at $DIR/panic-in-ffi.rs:21:5:
22Test
33note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
4Noisy Drop
45thread 'main' panicked at core/src/panicking.rs:$LINE:$COL:
56panic in a function that cannot unwind
67stack backtrace: