about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-10-06 12:40:43 +0200
committerRalf Jung <post@ralfj.de>2022-10-11 22:47:31 +0200
commit66282cb47d0f4c651fc58a6f458f1e93a2dc33b7 (patch)
tree0bd9458704b90b6dde97d95e650776c14ece4526
parent2b50cd18772d3db523070d418dc0411b885a3ff4 (diff)
downloadrust-66282cb47d0f4c651fc58a6f458f1e93a2dc33b7.tar.gz
rust-66282cb47d0f4c651fc58a6f458f1e93a2dc33b7.zip
add panic_fmt_nounwind for panicing without unwinding, and use it for panic_no_unwind
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs7
-rw-r--r--library/core/src/panicking.rs22
2 files changed, 19 insertions, 10 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index cf7fde2a090..5c76016c662 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1582,13 +1582,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
-    // The panic_no_unwind function called by TerminatorKind::Abort will never
-    // unwind. If the panic handler that it invokes unwind then it will simply
-    // call the panic handler again.
-    if Some(did.to_def_id()) == tcx.lang_items().panic_no_unwind() {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-    }
-
     let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
 
     let mut inline_span = None;
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index d4afe0f5326..68c8e8555d3 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -84,12 +84,27 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
     panic!("index out of bounds: the len is {len} but the index is {index}")
 }
 
-// This function is called directly by the codegen backend, and must not have
-// any extra arguments (including those synthesized by track_caller).
+/// Panic because we cannot unwind out of a function.
+///
+/// This function is called directly by the codegen backend, and must not have
+/// any extra arguments (including those synthesized by track_caller).
 #[cold]
 #[inline(never)]
 #[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
+#[cfg_attr(not(bootstrap), rustc_nounwind)]
+#[cfg_attr(bootstrap, rustc_allocator_nounwind)]
 fn panic_no_unwind() -> ! {
+    panic_str_nounwind("panic in a function that cannot unwind")
+}
+
+/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize.
+/// Also just works on `str`, as a `fmt::Arguments` needs more space to be passed.
+#[cold]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(bootstrap), rustc_nounwind)]
+#[cfg_attr(bootstrap, rustc_allocator_nounwind)]
+pub fn panic_str_nounwind(msg: &'static str) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         super::intrinsics::abort()
     }
@@ -102,7 +117,8 @@ fn panic_no_unwind() -> ! {
     }
 
     // PanicInfo with the `can_unwind` flag set to false forces an abort.
-    let fmt = format_args!("panic in a function that cannot unwind");
+    let pieces = [msg];
+    let fmt = fmt::Arguments::new_v1(&pieces, &[]);
     let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
 
     // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.