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.
This commit is contained in:
Adam Perry 2019-10-23 19:30:21 -07:00
parent 743964ad3f
commit aec97e050e
10 changed files with 130 additions and 127 deletions

View file

@ -1,8 +1,9 @@
/// Panics the current thread. /// Panics the current thread.
/// ///
/// For details, see `std::macros`. /// For details, see `std::macros`.
#[cfg(bootstrap)]
#[macro_export] #[macro_export]
#[allow_internal_unstable(core_panic)] #[allow_internal_unstable(core_panic, panic_internals)]
#[stable(feature = "core", since = "1.6.0")] #[stable(feature = "core", since = "1.6.0")]
macro_rules! panic { 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`]). /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
/// ///
/// On panic, this macro will print the values of the expressions with their /// On panic, this macro will print the values of the expressions with their

View file

@ -35,7 +35,7 @@ use crate::fmt;
pub struct PanicInfo<'a> { pub struct PanicInfo<'a> {
payload: &'a (dyn Any + Send), payload: &'a (dyn Any + Send),
message: Option<&'a fmt::Arguments<'a>>, message: Option<&'a fmt::Arguments<'a>>,
location: Location<'a>, location: &'a Location<'a>,
} }
impl<'a> PanicInfo<'a> { impl<'a> PanicInfo<'a> {
@ -45,11 +45,16 @@ impl<'a> PanicInfo<'a> {
issue = "0")] issue = "0")]
#[doc(hidden)] #[doc(hidden)]
#[inline] #[inline]
pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>, pub fn internal_constructor(
location: Location<'a>) message: Option<&'a fmt::Arguments<'a>>,
-> Self { location: &'a Location<'a>,
) -> Self {
struct NoPayload; struct NoPayload;
PanicInfo { payload: &NoPayload, location, message } PanicInfo {
location,
message,
payload: &NoPayload,
}
} }
#[doc(hidden)] #[doc(hidden)]
@ -177,7 +182,7 @@ impl<'a> Location<'a> {
and related macros", and related macros",
issue = "0")] issue = "0")]
#[doc(hidden)] #[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 } Location { file, line, col }
} }

View file

@ -29,6 +29,7 @@
use crate::fmt; use crate::fmt;
use crate::panic::{Location, PanicInfo}; use crate::panic::{Location, PanicInfo};
#[cfg(bootstrap)]
#[cold] #[cold]
// never inline unless panic_immediate_abort to avoid code // never inline unless panic_immediate_abort to avoid code
// bloat at the call sites as much as possible // 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)) 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] #[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[lang = "panic_bounds_check"] #[lang = "panic_bounds_check"]
@ -62,6 +84,22 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
len, index), file_line_col) 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] #[cold]
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
#[cfg_attr( feature="panic_immediate_abort" ,inline)] #[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 (file, line, col) = *file_line_col;
let pi = PanicInfo::internal_constructor( let location = Location::internal_constructor(file, line, col);
Some(&fmt), let pi = PanicInfo::internal_constructor(Some(&fmt), &location);
Location::internal_constructor(file, line, col), 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) } unsafe { panic_impl(&pi) }
} }

View file

@ -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 // 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")) 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> { impl Builder<'a, 'll, 'tcx> {

View file

@ -3,7 +3,6 @@
//! Code that is useful in various codegen modules. //! Code that is useful in various codegen modules.
use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt}; use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt};
use crate::abi;
use crate::consts; use crate::consts;
use crate::type_::Type; use crate::type_::Type;
use crate::type_of::LayoutLlvmExt; use crate::type_of::LayoutLlvmExt;
@ -96,16 +95,6 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
} }
impl 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 { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
unsafe { unsafe {
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint); 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 { pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
unsafe { unsafe {
assert_eq!(idx as c_uint as u64, idx); assert_eq!(idx as c_uint as u64, idx);

View file

@ -16,7 +16,6 @@ use crate::traits::*;
use std::borrow::Cow; use std::borrow::Cow;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax_pos::Pos;
use super::{FunctionCx, LocalRef}; use super::{FunctionCx, LocalRef};
use super::place::PlaceRef; use super::place::PlaceRef;
@ -422,37 +421,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Get the location information. // Get the location information.
let loc = bx.sess().source_map().lookup_char_pos(span.lo()); let loc = bx.sess().source_map().lookup_char_pos(span.lo());
let filename = Symbol::intern(&loc.file.name.to_string()); let location = bx.static_panic_location(&loc);
let line = bx.const_u32(loc.line as u32);
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
// Put together the arguments to the panic entry point. // Put together the arguments to the panic entry point.
let (lang_item, args) = match msg { let (lang_item, args) = match msg {
PanicInfo::BoundsCheck { ref len, ref index } => { PanicInfo::BoundsCheck { ref len, ref index } => {
let len = self.codegen_operand(&mut bx, len).immediate(); let len = self.codegen_operand(&mut bx, len).immediate();
let index = self.codegen_operand(&mut bx, index).immediate(); let index = self.codegen_operand(&mut bx, index).immediate();
(lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len])
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])
} }
_ => { _ => {
let msg_str = Symbol::intern(msg.description()); let msg_str = Symbol::intern(msg.description());
let msg_file_line_col = bx.static_panic_msg( let msg = bx.const_str(msg_str);
Some(msg_str), (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location])
filename,
line,
col,
"panic_loc",
);
(lang_items::PanicFnLangItem,
vec![msg_file_line_col])
} }
}; };
@ -554,22 +535,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let layout = bx.layout_of(ty); let layout = bx.layout_of(ty);
if layout.abi.is_uninhabited() { if layout.abi.is_uninhabited() {
let loc = bx.sess().source_map().lookup_char_pos(span.lo()); 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!( let msg_str = format!("Attempted to instantiate uninhabited type {}", ty);
"Attempted to instantiate uninhabited type {}", let msg = bx.const_str(Symbol::intern(&msg_str));
ty let location = bx.static_panic_location(&loc);
);
let msg_str = Symbol::intern(&str);
let msg_file_line_col = bx.static_panic_msg(
Some(msg_str),
filename,
line,
col,
"panic_loc",
);
// Obtain the panic entry point. // Obtain the panic entry point.
let def_id = let def_id =
@ -587,7 +556,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&mut bx, &mut bx,
fn_ty, fn_ty,
llfn, llfn,
&[msg_file_line_col], &[msg.0, msg.1, location],
destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
cleanup, cleanup,
); );

View file

@ -1,6 +1,5 @@
use super::BackendTypes; use super::BackendTypes;
use syntax::source_map::Loc; use syntax::source_map::Loc;
use syntax_pos::symbol::Symbol;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::ty::layout::Align; use rustc::ty::layout::Align;
@ -12,12 +11,4 @@ pub trait StaticMethods: BackendTypes {
pub trait StaticBuilderMethods: BackendTypes { pub trait StaticBuilderMethods: BackendTypes {
fn get_static(&mut self, def_id: DefId) -> Self::Value; fn get_static(&mut self, def_id: DefId) -> Self::Value;
fn static_panic_location(&mut self, loc: &Loc) -> 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;
} }

View file

@ -301,18 +301,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, bool> { ) -> InterpResult<'tcx, bool> {
let def_id = instance.def_id(); let def_id = instance.def_id();
if Some(def_id) == self.tcx.lang_items().panic_fn() { if Some(def_id) == self.tcx.lang_items().panic_fn() {
assert!(args.len() == 1); // &'static str, &core::panic::Location { &'static str, u32, u32 }
// &(&'static str, &'static str, u32, u32) assert!(args.len() == 2);
let place = self.deref_operand(args[0])?;
let (msg, file, line, col) = ( let msg_place = self.deref_operand(args[0])?;
self.mplace_field(place, 0)?, let msg = Symbol::intern(self.read_str(msg_place)?);
self.mplace_field(place, 1)?,
self.mplace_field(place, 2)?, let location = self.deref_operand(args[1])?;
self.mplace_field(place, 3)?, let (file, line, col) = (
self.mplace_field(location, 0)?,
self.mplace_field(location, 1)?,
self.mplace_field(location, 2)?,
); );
let msg_place = self.deref_operand(msg.into())?;
let msg = Symbol::intern(self.read_str(msg_place)?);
let file_place = self.deref_operand(file.into())?; let file_place = self.deref_operand(file.into())?;
let file = Symbol::intern(self.read_str(file_place)?); let file = Symbol::intern(self.read_str(file_place)?);
let line = self.read_scalar(line.into())?.to_u32()?; let line = self.read_scalar(line.into())?.to_u32()?;

View file

@ -323,10 +323,8 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>,
} }
let (file, line, col) = *file_line_col; let (file, line, col) = *file_line_col;
let info = PanicInfo::internal_constructor( let location = Location::internal_constructor(file, line, col);
Some(msg), let info = PanicInfo::internal_constructor(Some(msg), &location);
Location::internal_constructor(file, line, col),
);
continue_panic_fmt(&info) continue_panic_fmt(&info)
} }
@ -453,10 +451,8 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
} }
unsafe { unsafe {
let mut info = PanicInfo::internal_constructor( let location = Location::internal_constructor(file, line, col);
message, let mut info = PanicInfo::internal_constructor(message, &location);
Location::internal_constructor(file, line, col),
);
HOOK_LOCK.read(); HOOK_LOCK.read();
match HOOK { match HOOK {
// Some platforms know that printing to stderr won't ever actually // Some platforms know that printing to stderr won't ever actually

View file

@ -22,7 +22,7 @@
//[thin]compile-flags: -C lto=thin //[thin]compile-flags: -C lto=thin
//[fat]compile-flags: -C lto=fat //[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 // (For some reason, reproducing the LTO issue requires pulling in std
// explicitly this way.) // explicitly this way.)
@ -51,7 +51,8 @@ fn main() {
let _guard = Droppable; let _guard = Droppable;
let s = "issue-64655-allow-unwind-when-calling-panic-directly.rs"; 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(); let wait = handle.join();