diff options
| author | Adam Perry <adam.n.perry@gmail.com> | 2019-10-23 19:30:21 -0700 |
|---|---|---|
| committer | Adam Perry <adam.n.perry@gmail.com> | 2019-10-27 12:50:58 -0700 |
| commit | aec97e050ea5247fa13612399a7a812dbce89ec9 (patch) | |
| tree | ad7ba453a36edd6d6c530dc1fa8eb947b99fdeca | |
| parent | 743964ad3fe566ca2ce5c2de14f8733887d283fd (diff) | |
| download | rust-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.rs | 35 | ||||
| -rw-r--r-- | src/libcore/panic.rs | 17 | ||||
| -rw-r--r-- | src/libcore/panicking.rs | 63 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/builder.rs | 30 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/common.rs | 18 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/mir/block.rs | 47 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/traits/statics.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/intrinsics.rs | 21 | ||||
| -rw-r--r-- | src/libstd/panicking.rs | 12 | ||||
| -rw-r--r-- | src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs | 5 |
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(); |
