| 
29 | 29 | use crate::fmt;  | 
30 | 30 | use crate::panic::{Location, PanicInfo};  | 
31 | 31 | 
 
  | 
 | 32 | +// First we define the two main entry points that all panics go through.  | 
 | 33 | +// In the end both are just convenience wrappers around `panic_impl`.  | 
 | 34 | + | 
 | 35 | +/// The entry point for panicking with a formatted message.  | 
 | 36 | +///  | 
 | 37 | +/// This is designed to reduce the amount of code required at the call  | 
 | 38 | +/// site as much as possible (so that `panic!()` has as low an impact  | 
 | 39 | +/// on (e.g.) the inlining of other functions as possible), by moving  | 
 | 40 | +/// the actual formatting into this shared place.  | 
 | 41 | +#[cold]  | 
 | 42 | +// If panic_immediate_abort, inline the abort call,  | 
 | 43 | +// otherwise avoid inlining because of it is cold path.  | 
 | 44 | +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]  | 
 | 45 | +#[cfg_attr(feature = "panic_immediate_abort", inline)]  | 
 | 46 | +#[track_caller]  | 
 | 47 | +#[lang = "panic_fmt"] // needed for const-evaluated panics  | 
 | 48 | +#[rustc_do_not_const_check] // hooked by const-eval  | 
 | 49 | +#[rustc_const_unstable(feature = "core_panic", issue = "none")]  | 
 | 50 | +pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {  | 
 | 51 | +    if cfg!(feature = "panic_immediate_abort") {  | 
 | 52 | +        super::intrinsics::abort()  | 
 | 53 | +    }  | 
 | 54 | + | 
 | 55 | +    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call  | 
 | 56 | +    // that gets resolved to the `#[panic_handler]` function.  | 
 | 57 | +    extern "Rust" {  | 
 | 58 | +        #[lang = "panic_impl"]  | 
 | 59 | +        fn panic_impl(pi: &PanicInfo<'_>) -> !;  | 
 | 60 | +    }  | 
 | 61 | + | 
 | 62 | +    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);  | 
 | 63 | + | 
 | 64 | +    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.  | 
 | 65 | +    unsafe { panic_impl(&pi) }  | 
 | 66 | +}  | 
 | 67 | + | 
 | 68 | +/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize.  | 
 | 69 | +/// Also just works on `str`, as a `fmt::Arguments` needs more space to be passed.  | 
 | 70 | +#[cold]  | 
 | 71 | +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]  | 
 | 72 | +#[cfg_attr(feature = "panic_immediate_abort", inline)]  | 
 | 73 | +#[cfg_attr(not(bootstrap), rustc_nounwind)]  | 
 | 74 | +#[cfg_attr(bootstrap, rustc_allocator_nounwind)]  | 
 | 75 | +pub fn panic_str_nounwind(msg: &'static str) -> ! {  | 
 | 76 | +    if cfg!(feature = "panic_immediate_abort") {  | 
 | 77 | +        super::intrinsics::abort()  | 
 | 78 | +    }  | 
 | 79 | + | 
 | 80 | +    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call  | 
 | 81 | +    // that gets resolved to the `#[panic_handler]` function.  | 
 | 82 | +    extern "Rust" {  | 
 | 83 | +        #[lang = "panic_impl"]  | 
 | 84 | +        fn panic_impl(pi: &PanicInfo<'_>) -> !;  | 
 | 85 | +    }  | 
 | 86 | + | 
 | 87 | +    // PanicInfo with the `can_unwind` flag set to false forces an abort.  | 
 | 88 | +    let pieces = [msg];  | 
 | 89 | +    let fmt = fmt::Arguments::new_v1(&pieces, &[]);  | 
 | 90 | +    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);  | 
 | 91 | + | 
 | 92 | +    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.  | 
 | 93 | +    unsafe { panic_impl(&pi) }  | 
 | 94 | +}  | 
 | 95 | + | 
 | 96 | +// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions  | 
 | 97 | +// above.  | 
 | 98 | + | 
32 | 99 | /// The underlying implementation of libcore's `panic!` macro when no formatting is used.  | 
33 | 100 | #[cold]  | 
34 | 101 | // never inline unless panic_immediate_abort to avoid code  | 
@@ -84,62 +151,17 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {  | 
84 | 151 |     panic!("index out of bounds: the len is {len} but the index is {index}")  | 
85 | 152 | }  | 
86 | 153 | 
 
  | 
87 |  | -// This function is called directly by the codegen backend, and must not have  | 
88 |  | -// any extra arguments (including those synthesized by track_caller).  | 
 | 154 | +/// Panic because we cannot unwind out of a function.  | 
 | 155 | +///  | 
 | 156 | +/// This function is called directly by the codegen backend, and must not have  | 
 | 157 | +/// any extra arguments (including those synthesized by track_caller).  | 
89 | 158 | #[cold]  | 
90 | 159 | #[inline(never)]  | 
91 | 160 | #[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function  | 
 | 161 | +#[cfg_attr(not(bootstrap), rustc_nounwind)]  | 
 | 162 | +#[cfg_attr(bootstrap, rustc_allocator_nounwind)]  | 
92 | 163 | fn panic_no_unwind() -> ! {  | 
93 |  | -    if cfg!(feature = "panic_immediate_abort") {  | 
94 |  | -        super::intrinsics::abort()  | 
95 |  | -    }  | 
96 |  | - | 
97 |  | -    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call  | 
98 |  | -    // that gets resolved to the `#[panic_handler]` function.  | 
99 |  | -    extern "Rust" {  | 
100 |  | -        #[lang = "panic_impl"]  | 
101 |  | -        fn panic_impl(pi: &PanicInfo<'_>) -> !;  | 
102 |  | -    }  | 
103 |  | - | 
104 |  | -    // PanicInfo with the `can_unwind` flag set to false forces an abort.  | 
105 |  | -    let fmt = format_args!("panic in a function that cannot unwind");  | 
106 |  | -    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);  | 
107 |  | - | 
108 |  | -    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.  | 
109 |  | -    unsafe { panic_impl(&pi) }  | 
110 |  | -}  | 
111 |  | - | 
112 |  | -/// The entry point for panicking with a formatted message.  | 
113 |  | -///  | 
114 |  | -/// This is designed to reduce the amount of code required at the call  | 
115 |  | -/// site as much as possible (so that `panic!()` has as low an impact  | 
116 |  | -/// on (e.g.) the inlining of other functions as possible), by moving  | 
117 |  | -/// the actual formatting into this shared place.  | 
118 |  | -#[cold]  | 
119 |  | -// If panic_immediate_abort, inline the abort call,  | 
120 |  | -// otherwise avoid inlining because of it is cold path.  | 
121 |  | -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]  | 
122 |  | -#[cfg_attr(feature = "panic_immediate_abort", inline)]  | 
123 |  | -#[track_caller]  | 
124 |  | -#[lang = "panic_fmt"] // needed for const-evaluated panics  | 
125 |  | -#[rustc_do_not_const_check] // hooked by const-eval  | 
126 |  | -#[rustc_const_unstable(feature = "core_panic", issue = "none")]  | 
127 |  | -pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {  | 
128 |  | -    if cfg!(feature = "panic_immediate_abort") {  | 
129 |  | -        super::intrinsics::abort()  | 
130 |  | -    }  | 
131 |  | - | 
132 |  | -    // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call  | 
133 |  | -    // that gets resolved to the `#[panic_handler]` function.  | 
134 |  | -    extern "Rust" {  | 
135 |  | -        #[lang = "panic_impl"]  | 
136 |  | -        fn panic_impl(pi: &PanicInfo<'_>) -> !;  | 
137 |  | -    }  | 
138 |  | - | 
139 |  | -    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);  | 
140 |  | - | 
141 |  | -    // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.  | 
142 |  | -    unsafe { panic_impl(&pi) }  | 
 | 164 | +    panic_str_nounwind("panic in a function that cannot unwind")  | 
143 | 165 | }  | 
144 | 166 | 
 
  | 
145 | 167 | /// This function is used instead of panic_fmt in const eval.  | 
 | 
0 commit comments