Skip to content

Commit

Permalink
Rollup merge of rust-lang#55011 - vi:panic_immediate_abort, r=alexcri…
Browse files Browse the repository at this point in the history
…chton

Add libstd Cargo feature "panic_immediate_abort"

It stop asserts and panics from libstd to automatically
include string output and formatting code.

Use case: developing static executables smaller than 50 kilobytes,
where usual formatting code is excessive while keeping debuggability
in debug mode.

May resolve rust-lang#54981.
  • Loading branch information
kennytm committed Nov 30, 2018
2 parents 440bda4 + f18a8c6 commit 2584d92
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/libcore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ path = "../libcore/benches/lib.rs"

[dev-dependencies]
rand = "0.5"

[features]
# Make panics and failed asserts immediately abort without formatting any message
panic_immediate_abort = []
24 changes: 21 additions & 3 deletions src/libcore/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,16 @@
use fmt;
use panic::{Location, PanicInfo};

#[cold] #[inline(never)] // this is the slow path, always
#[cold]
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[lang = "panic"]
pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { super::intrinsics::abort() }
}

// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
// reduce size overhead. The format_args! macro uses str's Display trait to
// write expr, which calls Formatter::pad, which must accommodate string
Expand All @@ -52,16 +59,27 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
}

#[cold] #[inline(never)]
#[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[lang = "panic_bounds_check"]
fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
index: usize, len: usize) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { super::intrinsics::abort() }
}

panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
len, index), file_line_col)
}

#[cold] #[inline(never)]
#[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[cfg_attr( feature="panic_immediate_abort" ,inline)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { super::intrinsics::abort() }
}

// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
#[allow(improper_ctypes)] // PanicInfo contains a trait object which is not FFI safe
extern "Rust" {
Expand Down
3 changes: 3 additions & 0 deletions src/libstd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ backtrace = []
panic-unwind = ["panic_unwind"]
profiler = ["profiler_builtins"]

# Make panics and failed asserts immediately abort without formatting any message
panic_immediate_abort = ["core/panic_immediate_abort"]

# An off-by-default feature which enables a linux-syscall-like ABI for libstd to
# interoperate with the host environment. Currently not well documented and
# requires rebuilding the standard library to use it.
Expand Down
19 changes: 17 additions & 2 deletions src/libstd/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,17 @@ pub fn rust_begin_panic(info: &PanicInfo) -> ! {
#[unstable(feature = "libstd_sys_internals",
reason = "used by the panic! macro",
issue = "0")]
#[inline(never)] #[cold]
#[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)]
pub fn begin_panic_fmt(msg: &fmt::Arguments,
file_line_col: &(&'static str, u32, u32)) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { intrinsics::abort() }
}

let (file, line, col) = *file_line_col;
let info = PanicInfo::internal_constructor(
Some(msg),
Expand Down Expand Up @@ -398,8 +406,15 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! {
reason = "used by the panic! macro",
issue = "0")]
#[cfg_attr(not(test), lang = "begin_panic")]
#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
// never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[cold]
pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! {
if cfg!(feature = "panic_immediate_abort") {
unsafe { intrinsics::abort() }
}

// Note that this should be the only allocation performed in this code path.
// Currently this means that panic!() on OOM will invoke this code path,
// but then again we're not really ready for panic on OOM anyway. If
Expand Down

0 comments on commit 2584d92

Please sign in to comment.