about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs7
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs4
-rw-r--r--src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir24
-rw-r--r--src/test/mir-opt/asm_unwind_panic_abort.rs16
4 files changed, 49 insertions, 2 deletions
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index ade6555f4d2..11980382ffd 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -1,4 +1,5 @@
 use crate::MirPass;
+use rustc_ast::InlineAsmOptions;
 use rustc_hir::def::DefKind;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout;
@@ -85,6 +86,12 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
                 TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
                     layout::fn_can_unwind(tcx, None, Abi::Rust)
                 }
+                TerminatorKind::InlineAsm { options, .. } => {
+                    options.contains(InlineAsmOptions::MAY_UNWIND)
+                }
+                _ if terminator.unwind().is_some() => {
+                    span_bug!(span, "unexpected terminator that may unwind {:?}", terminator)
+                }
                 _ => continue,
             };
 
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index b7dec57b757..9e7bf5c7929 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1042,8 +1042,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::FalseEdge { .. }
-            | TerminatorKind::FalseUnwind { .. }
-            | TerminatorKind::InlineAsm { .. } => {}
+            | TerminatorKind::FalseUnwind { .. } => {}
 
             // Resume will *continue* unwinding, but if there's no other unwinding terminator it
             // will never be reached.
@@ -1057,6 +1056,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             TerminatorKind::Drop { .. }
             | TerminatorKind::DropAndReplace { .. }
             | TerminatorKind::Call { .. }
+            | TerminatorKind::InlineAsm { .. }
             | TerminatorKind::Assert { .. } => return true,
         }
     }
diff --git a/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
new file mode 100644
index 00000000000..44d722d6f9b
--- /dev/null
+++ b/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
@@ -0,0 +1,24 @@
+// MIR for `main` after AbortUnwindingCalls
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/asm_unwind_panic_abort.rs:12:11: 12:11
+    let _1: ();                          // in scope 0 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+    scope 1 {
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+        _1 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+        asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+    }
+
+    bb1: {
+        StorageDead(_1);                 // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:48: 14:49
+        _0 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:13:5: 15:6
+        return;                          // scope 0 at $DIR/asm_unwind_panic_abort.rs:16:2: 16:2
+    }
+
+    bb2 (cleanup): {
+        abort;                           // scope 0 at $DIR/asm_unwind_panic_abort.rs:12:1: 16:2
+    }
+}
diff --git a/src/test/mir-opt/asm_unwind_panic_abort.rs b/src/test/mir-opt/asm_unwind_panic_abort.rs
new file mode 100644
index 00000000000..8201d54348a
--- /dev/null
+++ b/src/test/mir-opt/asm_unwind_panic_abort.rs
@@ -0,0 +1,16 @@
+//! Tests that unwinding from an asm block is caught and forced to abort
+//! when `-C panic=abort`.
+
+// min-llvm-version: 13.0.0
+// only-x86_64
+// compile-flags: -C panic=abort
+// no-prefer-dynamic
+
+#![feature(asm_unwind)]
+
+// EMIT_MIR asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
+fn main() {
+    unsafe {
+        std::arch::asm!("", options(may_unwind));
+    }
+}