From fdef3848a01c4567abd326043b797f6bdc3f3e76 Mon Sep 17 00:00:00 2001
From: Vitaly _Vi Shukela <vi0oss@gmail.com>
Date: Fri, 30 Nov 2018 00:06:10 +0300
Subject: [PATCH 1/3] Add libstd and libcore Cargo features
 "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 #54981.
---
 src/libcore/Cargo.toml   |  4 ++++
 src/libcore/panicking.rs | 24 +++++++++++++++++++++---
 src/libstd/Cargo.toml    |  3 +++
 src/libstd/panicking.rs  | 17 +++++++++++++++--
 4 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
index 0b01cfc488bba..7fd61f07d5e7f 100644
--- a/src/libcore/Cargo.toml
+++ b/src/libcore/Cargo.toml
@@ -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 = []
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 58407de9566e9..67c0b6ada9055 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -39,9 +39,15 @@
 use fmt;
 use panic::{Location, PanicInfo};
 
-#[cold] #[inline(never)] // this is the slow path, always
+#[cold]
+// inline(never) is required even in panic_immediate_abort mode, lest linker error
+#[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
@@ -52,16 +58,28 @@ 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]
+// inline(never) is required even in panic_immediate_abort mode, lest linker error
+#[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" {
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 2b1d515c83b75..c1446218367e4 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -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.
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index a0590a800d3cc..29a0b3feefdfa 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -334,9 +334,15 @@ pub fn rust_begin_panic(info: &PanicInfo) -> ! {
 #[unstable(feature = "libstd_sys_internals",
            reason = "used by the panic! macro",
            issue = "0")]
-#[inline(never)] #[cold]
+#[cold]
+#[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),
@@ -398,8 +404,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
+// avoid code bloat at the call sites as much as possible
+// inline(never) is required even in panic_immediate_abort mode, lest linker error
+#[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

From d3f9788e596f9b7f07c165e0f382dbe2cdb02b6e Mon Sep 17 00:00:00 2001
From: Vitaly _Vi Shukela <vi0oss@gmail.com>
Date: Fri, 30 Nov 2018 02:17:05 +0300
Subject: [PATCH 2/3] panic_immediate_abort: Fix issues from review

---
 src/libcore/panicking.rs | 13 ++++++-------
 src/libstd/panicking.rs  | 11 ++++++-----
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 67c0b6ada9055..834fcd246c532 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -40,13 +40,13 @@ use fmt;
 use panic::{Location, PanicInfo};
 
 #[cold]
-// inline(never) is required even in panic_immediate_abort mode, lest linker error
-#[inline(never)]
+// 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
@@ -59,14 +59,13 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
 }
 
 #[cold]
-// inline(never) is required even in panic_immediate_abort mode, lest linker error
-#[inline(never)]
+#[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)
@@ -78,7 +77,7 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
 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
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 29a0b3feefdfa..82ceec62f357a 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -335,13 +335,15 @@ pub fn rust_begin_panic(info: &PanicInfo) -> ! {
            reason = "used by the panic! macro",
            issue = "0")]
 #[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(
@@ -404,14 +406,13 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! {
            reason = "used by the panic! macro",
            issue = "0")]
 #[cfg_attr(not(test), lang = "begin_panic")]
-// avoid code bloat at the call sites as much as possible
-// inline(never) is required even in panic_immediate_abort mode, lest linker error
-#[inline(never)]
+// 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,

From f18a8c6163fa3b1eef5aabd1baf1eef2b9789c46 Mon Sep 17 00:00:00 2001
From: Vitaly _Vi Shukela <vi0oss@gmail.com>
Date: Fri, 30 Nov 2018 02:37:04 +0300
Subject: [PATCH 3/3] Fix exceeding line width limit

---
 src/libcore/panicking.rs | 3 ++-
 src/libstd/panicking.rs  | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 834fcd246c532..aa18a60fc0f6d 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -40,7 +40,8 @@ use fmt;
 use panic::{Location, PanicInfo};
 
 #[cold]
-// never inline unless panic_immediate_abort to 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))]
 #[lang = "panic"]
 pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 82ceec62f357a..4930d35660814 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -406,7 +406,8 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! {
            reason = "used by the panic! macro",
            issue = "0")]
 #[cfg_attr(not(test), lang = "begin_panic")]
-// never inline unless panic_immediate_abort to 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)) -> ! {