about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdam Perry <adam.n.perry@gmail.com>2019-10-23 19:30:21 -0700
committerAdam Perry <adam.n.perry@gmail.com>2019-10-27 12:50:58 -0700
commitaec97e050ea5247fa13612399a7a812dbce89ec9 (patch)
treead7ba453a36edd6d6c530dc1fa8eb947b99fdeca
parent743964ad3fe566ca2ce5c2de14f8733887d283fd (diff)
downloadrust-aec97e050ea5247fa13612399a7a812dbce89ec9.tar.gz
rust-aec97e050ea5247fa13612399a7a812dbce89ec9.zip
Panicking infra uses &core::panic::Location.
This allows us to remove `static_panic_msg` from the SSA<->LLVM
boundary, along with its fat pointer representation for &str.

Also changes the signature of PanicInfo::internal_contructor to
avoid copying.

Closes #65856.
-rw-r--r--src/libcore/macros.rs35
-rw-r--r--src/libcore/panic.rs17
-rw-r--r--src/libcore/panicking.rs63
-rw-r--r--src/librustc_codegen_llvm/builder.rs30
-rw-r--r--src/librustc_codegen_llvm/common.rs18
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs47
-rw-r--r--src/librustc_codegen_ssa/traits/statics.rs9
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs21
-rw-r--r--src/libstd/panicking.rs12
-rw-r--r--src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs5
10 files changed, 130 insertions, 127 deletions
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 35558e3abcd..8ccd31c95d5 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1,8 +1,9 @@
 /// Panics the current thread.
 ///
 /// For details, see `std::macros`.
+#[cfg(bootstrap)]
 #[macro_export]
-#[allow_internal_unstable(core_panic)]
+#[allow_internal_unstable(core_panic, panic_internals)]
 #[stable(feature = "core", since = "1.6.0")]
 macro_rules! panic {
     () => (
@@ -20,6 +21,38 @@ macro_rules! panic {
     });
 }
 
+/// Panics the current thread.
+///
+/// For details, see `std::macros`.
+#[cfg(not(bootstrap))]
+#[macro_export]
+#[allow_internal_unstable(core_panic, panic_internals)]
+#[stable(feature = "core", since = "1.6.0")]
+macro_rules! panic {
+    () => (
+        $crate::panic!("explicit panic")
+    );
+    ($msg:expr) => ({
+        const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
+            $crate::file!(),
+            $crate::line!(),
+            $crate::column!(),
+        );
+        $crate::panicking::panic($msg, LOC)
+    });
+    ($msg:expr,) => (
+        $crate::panic!($msg)
+    );
+    ($fmt:expr, $($arg:tt)+) => ({
+        const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
+            $crate::file!(),
+            $crate::line!(),
+            $crate::column!(),
+        );
+        $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC)
+    });
+}
+
 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
 ///
 /// On panic, this macro will print the values of the expressions with their
diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs
index 9428ff3ef15..51bbf3a8fd2 100644
--- a/src/libcore/panic.rs
+++ b/src/libcore/panic.rs
@@ -35,7 +35,7 @@ use crate::fmt;
 pub struct PanicInfo<'a> {
     payload: &'a (dyn Any + Send),
     message: Option<&'a fmt::Arguments<'a>>,
-    location: Location<'a>,
+    location: &'a Location<'a>,
 }
 
 impl<'a> PanicInfo<'a> {
@@ -45,11 +45,16 @@ impl<'a> PanicInfo<'a> {
                 issue = "0")]
     #[doc(hidden)]
     #[inline]
-    pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
-                                location: Location<'a>)
-                                -> Self {
+    pub fn internal_constructor(
+        message: Option<&'a fmt::Arguments<'a>>,
+        location: &'a Location<'a>,
+    ) -> Self {
         struct NoPayload;
-        PanicInfo { payload: &NoPayload, location, message }
+        PanicInfo {
+            location,
+            message,
+            payload: &NoPayload,
+        }
     }
 
     #[doc(hidden)]
@@ -177,7 +182,7 @@ impl<'a> Location<'a> {
                           and related macros",
                 issue = "0")]
     #[doc(hidden)]
-    pub fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
+    pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
         Location { file, line, col }
     }
 
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index e8f0561604a..685b749776b 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -29,6 +29,7 @@
 use crate::fmt;
 use crate::panic::{Location, PanicInfo};
 
+#[cfg(bootstrap)]
 #[cold]
 // never inline unless panic_immediate_abort to avoid code
 // bloat at the call sites as much as possible
@@ -49,6 +50,27 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
     panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
 }
 
+#[cfg(not(bootstrap))]
+#[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: &str, location: &Location<'_>) -> ! {
+    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
+    // truncation and padding (even though none is used here). Using
+    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
+    // output binary, saving up to a few kilobytes.
+    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location)
+}
+
+#[cfg(bootstrap)]
 #[cold]
 #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
 #[lang = "panic_bounds_check"]
@@ -62,6 +84,22 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
                            len, index), file_line_col)
 }
 
+#[cfg(not(bootstrap))]
+#[cold]
+#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
+#[lang = "panic_bounds_check"]
+fn panic_bounds_check(location: &Location<'_>, 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),
+        location
+    )
+}
+
+#[cfg(bootstrap)]
 #[cold]
 #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
 #[cfg_attr(    feature="panic_immediate_abort" ,inline)]
@@ -77,9 +115,26 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3
     }
 
     let (file, line, col) = *file_line_col;
-    let pi = PanicInfo::internal_constructor(
-        Some(&fmt),
-        Location::internal_constructor(file, line, col),
-    );
+    let location = Location::internal_constructor(file, line, col);
+    let pi = PanicInfo::internal_constructor(Some(&fmt), &location);
+    unsafe { panic_impl(&pi) }
+}
+
+#[cfg(not(bootstrap))]
+#[cold]
+#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
+#[cfg_attr(    feature="panic_immediate_abort" ,inline)]
+pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
+    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
+    extern "Rust" {
+        #[lang = "panic_impl"]
+        fn panic_impl(pi: &PanicInfo<'_>) -> !;
+    }
+
+    let pi = PanicInfo::internal_constructor(Some(&fmt), location);
     unsafe { panic_impl(&pi) }
 }
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index ffaf8050bcb..8ac1c7b36fc 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1082,36 +1082,6 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
         // FIXME(eddyb) move this into miri, it can be correct if e.g. field order changes
         self.static_addr_of(struct_, align, Some("panic_loc"))
     }
-
-    fn static_panic_msg(
-        &mut self,
-        msg: Option<Symbol>,
-        filename: Symbol,
-        line: Self::Value,
-        col: Self::Value,
-        kind: &str,
-    ) -> Self::Value {
-        let align = self.tcx.data_layout.aggregate_align.abi
-            .max(self.tcx.data_layout.i32_align.abi)
-            .max(self.tcx.data_layout.pointer_align.abi);
-
-        let filename = self.const_str_slice(filename);
-
-        let with_msg_components;
-        let without_msg_components;
-
-        let components = if let Some(msg) = msg {
-            let msg = self.const_str_slice(msg);
-            with_msg_components = [msg, filename, line, col];
-            &with_msg_components as &[_]
-        } else {
-            without_msg_components = [filename, line, col];
-            &without_msg_components as &[_]
-        };
-
-        let struct_ = self.const_struct(&components, false);
-        self.static_addr_of(struct_, align, Some(kind))
-    }
 }
 
 impl Builder<'a, 'll, 'tcx> {
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index b4b82f67c74..f38f9dfecd3 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -3,7 +3,6 @@
 //! Code that is useful in various codegen modules.
 
 use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt};
-use crate::abi;
 use crate::consts;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
@@ -96,16 +95,6 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
 }
 
 impl CodegenCx<'ll, 'tcx> {
-    pub fn const_fat_ptr(
-        &self,
-        ptr: &'ll Value,
-        meta: &'ll Value
-    ) -> &'ll Value {
-        assert_eq!(abi::FAT_PTR_ADDR, 0);
-        assert_eq!(abi::FAT_PTR_EXTRA, 1);
-        self.const_struct(&[ptr, meta], false)
-    }
-
     pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
         unsafe {
             return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
@@ -150,13 +139,6 @@ impl CodegenCx<'ll, 'tcx> {
         }
     }
 
-    pub fn const_str_slice(&self, s: Symbol) -> &'ll Value {
-        let len = s.as_str().len();
-        let cs = consts::ptrcast(self.const_cstr(s, false),
-            self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
-        self.const_fat_ptr(cs, self.const_usize(len as u64))
-    }
-
     pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
         unsafe {
             assert_eq!(idx as c_uint as u64, idx);
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 22ea6a39552..2462ba0a33e 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -16,7 +16,6 @@ use crate::traits::*;
 use std::borrow::Cow;
 
 use syntax::symbol::Symbol;
-use syntax_pos::Pos;
 
 use super::{FunctionCx, LocalRef};
 use super::place::PlaceRef;
@@ -422,37 +421,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // Get the location information.
         let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-        let filename = Symbol::intern(&loc.file.name.to_string());
-        let line = bx.const_u32(loc.line as u32);
-        let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
+        let location = bx.static_panic_location(&loc);
 
         // Put together the arguments to the panic entry point.
         let (lang_item, args) = match msg {
             PanicInfo::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
-
-                let file_line_col = bx.static_panic_msg(
-                    None,
-                    filename,
-                    line,
-                    col,
-                    "panic_bounds_check_loc",
-                );
-                (lang_items::PanicBoundsCheckFnLangItem,
-                    vec![file_line_col, index, len])
+                (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len])
             }
             _ => {
                 let msg_str = Symbol::intern(msg.description());
-                let msg_file_line_col = bx.static_panic_msg(
-                    Some(msg_str),
-                    filename,
-                    line,
-                    col,
-                    "panic_loc",
-                );
-                (lang_items::PanicFnLangItem,
-                    vec![msg_file_line_col])
+                let msg = bx.const_str(msg_str);
+                (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location])
             }
         };
 
@@ -554,22 +535,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let layout = bx.layout_of(ty);
             if layout.abi.is_uninhabited() {
                 let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-                let filename = Symbol::intern(&loc.file.name.to_string());
-                let line = bx.const_u32(loc.line as u32);
-                let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
 
-                let str = format!(
-                    "Attempted to instantiate uninhabited type {}",
-                    ty
-                );
-                let msg_str = Symbol::intern(&str);
-                let msg_file_line_col = bx.static_panic_msg(
-                    Some(msg_str),
-                    filename,
-                    line,
-                    col,
-                    "panic_loc",
-                );
+                let msg_str = format!("Attempted to instantiate uninhabited type {}", ty);
+                let msg = bx.const_str(Symbol::intern(&msg_str));
+                let location = bx.static_panic_location(&loc);
 
                 // Obtain the panic entry point.
                 let def_id =
@@ -587,7 +556,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     &mut bx,
                     fn_ty,
                     llfn,
-                    &[msg_file_line_col],
+                    &[msg.0, msg.1, location],
                     destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
                     cleanup,
                 );
diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs
index b51f15b5823..f63cea51f43 100644
--- a/src/librustc_codegen_ssa/traits/statics.rs
+++ b/src/librustc_codegen_ssa/traits/statics.rs
@@ -1,6 +1,5 @@
 use super::BackendTypes;
 use syntax::source_map::Loc;
-use syntax_pos::symbol::Symbol;
 use rustc::hir::def_id::DefId;
 use rustc::ty::layout::Align;
 
@@ -12,12 +11,4 @@ pub trait StaticMethods: BackendTypes {
 pub trait StaticBuilderMethods: BackendTypes {
     fn get_static(&mut self, def_id: DefId) -> Self::Value;
     fn static_panic_location(&mut self, loc: &Loc) -> Self::Value;
-    fn static_panic_msg(
-        &mut self,
-        msg: Option<Symbol>,
-        filename: Symbol,
-        line: Self::Value,
-        col: Self::Value,
-        kind: &str,
-    ) -> Self::Value;
 }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 5fc23b4a69e..20cb2926d66 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -301,18 +301,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, bool> {
         let def_id = instance.def_id();
         if Some(def_id) == self.tcx.lang_items().panic_fn() {
-            assert!(args.len() == 1);
-            // &(&'static str, &'static str, u32, u32)
-            let place = self.deref_operand(args[0])?;
-            let (msg, file, line, col) = (
-                self.mplace_field(place, 0)?,
-                self.mplace_field(place, 1)?,
-                self.mplace_field(place, 2)?,
-                self.mplace_field(place, 3)?,
-            );
+            // &'static str, &core::panic::Location { &'static str, u32, u32 }
+            assert!(args.len() == 2);
 
-            let msg_place = self.deref_operand(msg.into())?;
+            let msg_place = self.deref_operand(args[0])?;
             let msg = Symbol::intern(self.read_str(msg_place)?);
+
+            let location = self.deref_operand(args[1])?;
+            let (file, line, col) = (
+                self.mplace_field(location, 0)?,
+                self.mplace_field(location, 1)?,
+                self.mplace_field(location, 2)?,
+            );
+
             let file_place = self.deref_operand(file.into())?;
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 619b1820190..f76969146fd 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -323,10 +323,8 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>,
     }
 
     let (file, line, col) = *file_line_col;
-    let info = PanicInfo::internal_constructor(
-        Some(msg),
-        Location::internal_constructor(file, line, col),
-    );
+    let location = Location::internal_constructor(file, line, col);
+    let info = PanicInfo::internal_constructor(Some(msg), &location);
     continue_panic_fmt(&info)
 }
 
@@ -453,10 +451,8 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
     }
 
     unsafe {
-        let mut info = PanicInfo::internal_constructor(
-            message,
-            Location::internal_constructor(file, line, col),
-        );
+        let location = Location::internal_constructor(file, line, col);
+        let mut info = PanicInfo::internal_constructor(message, &location);
         HOOK_LOCK.read();
         match HOOK {
             // Some platforms know that printing to stderr won't ever actually
diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
index ff10d412a11..8727c9d1ca6 100644
--- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
+++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
@@ -22,7 +22,7 @@
 //[thin]compile-flags: -C lto=thin
 //[fat]compile-flags: -C lto=fat
 
-#![feature(core_panic)]
+#![feature(core_panic, panic_internals)]
 
 // (For some reason, reproducing the LTO issue requires pulling in std
 // explicitly this way.)
@@ -51,7 +51,8 @@ fn main() {
 
         let _guard = Droppable;
         let s = "issue-64655-allow-unwind-when-calling-panic-directly.rs";
-        core::panicking::panic(&("???", s, 17, 4));
+        let location = core::panic::Location::internal_constructor(s, 17, 4);
+        core::panicking::panic("???", &location);
     });
 
     let wait = handle.join();