diff options
| author | Ralf Jung <post@ralfj.de> | 2022-10-08 10:48:53 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-10-11 22:47:31 +0200 |
| commit | 38c78a9ac17caefd4c5e6d0b332814b2ac2cf3a8 (patch) | |
| tree | 04f5f8db6af562e04089e528e77e34761b45636f | |
| parent | b61e742a394a79cd7fc58bb6b8bf9e502fd2a4cf (diff) | |
| download | rust-38c78a9ac17caefd4c5e6d0b332814b2ac2cf3a8.tar.gz rust-38c78a9ac17caefd4c5e6d0b332814b2ac2cf3a8.zip | |
reorder panicking.rs to put main entry points at the top
| -rw-r--r-- | library/core/src/panicking.rs | 128 |
1 files changed, 67 insertions, 61 deletions
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 68c8e8555d3..a9de7c94e5a 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -29,6 +29,73 @@ use crate::fmt; use crate::panic::{Location, PanicInfo}; +// First we define the two main entry points that all panics go through. +// In the end both are just convenience wrappers around `panic_impl`. + +/// The entry point for panicking with a formatted message. +/// +/// This is designed to reduce the amount of code required at the call +/// site as much as possible (so that `panic!()` has as low an impact +/// on (e.g.) the inlining of other functions as possible), by moving +/// the actual formatting into this shared place. +#[cold] +// If panic_immediate_abort, inline the abort call, +// otherwise avoid inlining because of it is cold path. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[lang = "panic_fmt"] // needed for const-evaluated panics +#[rustc_do_not_const_check] // hooked by const-eval +#[rustc_const_unstable(feature = "core_panic", issue = "none")] +pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } +} + +/// 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() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + // PanicInfo with the `can_unwind` flag set to false forces an abort. + 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. + unsafe { panic_impl(&pi) } +} + +// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions +// above. + /// The underlying implementation of libcore's `panic!` macro when no formatting is used. #[cold] // never inline unless panic_immediate_abort to avoid code @@ -97,67 +164,6 @@ 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() - } - - // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - // that gets resolved to the `#[panic_handler]` function. - extern "Rust" { - #[lang = "panic_impl"] - fn panic_impl(pi: &PanicInfo<'_>) -> !; - } - - // PanicInfo with the `can_unwind` flag set to false forces an abort. - 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. - unsafe { panic_impl(&pi) } -} - -/// The entry point for panicking with a formatted message. -/// -/// This is designed to reduce the amount of code required at the call -/// site as much as possible (so that `panic!()` has as low an impact -/// on (e.g.) the inlining of other functions as possible), by moving -/// the actual formatting into this shared place. -#[cold] -// If panic_immediate_abort, inline the abort call, -// otherwise avoid inlining because of it is cold path. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] -#[track_caller] -#[lang = "panic_fmt"] // needed for const-evaluated panics -#[rustc_do_not_const_check] // hooked by const-eval -#[rustc_const_unstable(feature = "core_panic", issue = "none")] -pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { - if cfg!(feature = "panic_immediate_abort") { - super::intrinsics::abort() - } - - // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - // that gets resolved to the `#[panic_handler]` function. - extern "Rust" { - #[lang = "panic_impl"] - fn panic_impl(pi: &PanicInfo<'_>) -> !; - } - - let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true); - - // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. - unsafe { panic_impl(&pi) } -} - /// This function is used instead of panic_fmt in const eval. #[lang = "const_panic_fmt"] #[rustc_const_unstable(feature = "core_panic", issue = "none")] |
