Skip to content

Commit aec97e0

Browse files
committed
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.
1 parent 743964a commit aec97e0

File tree

10 files changed

+130
-127
lines changed

10 files changed

+130
-127
lines changed

src/libcore/macros.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/// Panics the current thread.
22
///
33
/// For details, see `std::macros`.
4+
#[cfg(bootstrap)]
45
#[macro_export]
5-
#[allow_internal_unstable(core_panic)]
6+
#[allow_internal_unstable(core_panic, panic_internals)]
67
#[stable(feature = "core", since = "1.6.0")]
78
macro_rules! panic {
89
() => (
@@ -20,6 +21,38 @@ macro_rules! panic {
2021
});
2122
}
2223

24+
/// Panics the current thread.
25+
///
26+
/// For details, see `std::macros`.
27+
#[cfg(not(bootstrap))]
28+
#[macro_export]
29+
#[allow_internal_unstable(core_panic, panic_internals)]
30+
#[stable(feature = "core", since = "1.6.0")]
31+
macro_rules! panic {
32+
() => (
33+
$crate::panic!("explicit panic")
34+
);
35+
($msg:expr) => ({
36+
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
37+
$crate::file!(),
38+
$crate::line!(),
39+
$crate::column!(),
40+
);
41+
$crate::panicking::panic($msg, LOC)
42+
});
43+
($msg:expr,) => (
44+
$crate::panic!($msg)
45+
);
46+
($fmt:expr, $($arg:tt)+) => ({
47+
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
48+
$crate::file!(),
49+
$crate::line!(),
50+
$crate::column!(),
51+
);
52+
$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC)
53+
});
54+
}
55+
2356
/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
2457
///
2558
/// On panic, this macro will print the values of the expressions with their

src/libcore/panic.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::fmt;
3535
pub struct PanicInfo<'a> {
3636
payload: &'a (dyn Any + Send),
3737
message: Option<&'a fmt::Arguments<'a>>,
38-
location: Location<'a>,
38+
location: &'a Location<'a>,
3939
}
4040

4141
impl<'a> PanicInfo<'a> {
@@ -45,11 +45,16 @@ impl<'a> PanicInfo<'a> {
4545
issue = "0")]
4646
#[doc(hidden)]
4747
#[inline]
48-
pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
49-
location: Location<'a>)
50-
-> Self {
48+
pub fn internal_constructor(
49+
message: Option<&'a fmt::Arguments<'a>>,
50+
location: &'a Location<'a>,
51+
) -> Self {
5152
struct NoPayload;
52-
PanicInfo { payload: &NoPayload, location, message }
53+
PanicInfo {
54+
location,
55+
message,
56+
payload: &NoPayload,
57+
}
5358
}
5459

5560
#[doc(hidden)]
@@ -177,7 +182,7 @@ impl<'a> Location<'a> {
177182
and related macros",
178183
issue = "0")]
179184
#[doc(hidden)]
180-
pub fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
185+
pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
181186
Location { file, line, col }
182187
}
183188

src/libcore/panicking.rs

+59-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use crate::fmt;
3030
use crate::panic::{Location, PanicInfo};
3131

32+
#[cfg(bootstrap)]
3233
#[cold]
3334
// never inline unless panic_immediate_abort to avoid code
3435
// 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)) -> ! {
4950
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
5051
}
5152

53+
#[cfg(not(bootstrap))]
54+
#[cold]
55+
// never inline unless panic_immediate_abort to avoid code
56+
// bloat at the call sites as much as possible
57+
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
58+
#[lang = "panic"]
59+
pub fn panic(expr: &str, location: &Location<'_>) -> ! {
60+
if cfg!(feature = "panic_immediate_abort") {
61+
unsafe { super::intrinsics::abort() }
62+
}
63+
64+
// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
65+
// reduce size overhead. The format_args! macro uses str's Display trait to
66+
// write expr, which calls Formatter::pad, which must accommodate string
67+
// truncation and padding (even though none is used here). Using
68+
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
69+
// output binary, saving up to a few kilobytes.
70+
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location)
71+
}
72+
73+
#[cfg(bootstrap)]
5274
#[cold]
5375
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
5476
#[lang = "panic_bounds_check"]
@@ -62,6 +84,22 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
6284
len, index), file_line_col)
6385
}
6486

87+
#[cfg(not(bootstrap))]
88+
#[cold]
89+
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
90+
#[lang = "panic_bounds_check"]
91+
fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! {
92+
if cfg!(feature = "panic_immediate_abort") {
93+
unsafe { super::intrinsics::abort() }
94+
}
95+
96+
panic_fmt(
97+
format_args!("index out of bounds: the len is {} but the index is {}", len, index),
98+
location
99+
)
100+
}
101+
102+
#[cfg(bootstrap)]
65103
#[cold]
66104
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
67105
#[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
77115
}
78116

79117
let (file, line, col) = *file_line_col;
80-
let pi = PanicInfo::internal_constructor(
81-
Some(&fmt),
82-
Location::internal_constructor(file, line, col),
83-
);
118+
let location = Location::internal_constructor(file, line, col);
119+
let pi = PanicInfo::internal_constructor(Some(&fmt), &location);
120+
unsafe { panic_impl(&pi) }
121+
}
122+
123+
#[cfg(not(bootstrap))]
124+
#[cold]
125+
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
126+
#[cfg_attr( feature="panic_immediate_abort" ,inline)]
127+
pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
128+
if cfg!(feature = "panic_immediate_abort") {
129+
unsafe { super::intrinsics::abort() }
130+
}
131+
132+
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
133+
extern "Rust" {
134+
#[lang = "panic_impl"]
135+
fn panic_impl(pi: &PanicInfo<'_>) -> !;
136+
}
137+
138+
let pi = PanicInfo::internal_constructor(Some(&fmt), location);
84139
unsafe { panic_impl(&pi) }
85140
}

src/librustc_codegen_llvm/builder.rs

-30
Original file line numberDiff line numberDiff line change
@@ -1082,36 +1082,6 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
10821082
// FIXME(eddyb) move this into miri, it can be correct if e.g. field order changes
10831083
self.static_addr_of(struct_, align, Some("panic_loc"))
10841084
}
1085-
1086-
fn static_panic_msg(
1087-
&mut self,
1088-
msg: Option<Symbol>,
1089-
filename: Symbol,
1090-
line: Self::Value,
1091-
col: Self::Value,
1092-
kind: &str,
1093-
) -> Self::Value {
1094-
let align = self.tcx.data_layout.aggregate_align.abi
1095-
.max(self.tcx.data_layout.i32_align.abi)
1096-
.max(self.tcx.data_layout.pointer_align.abi);
1097-
1098-
let filename = self.const_str_slice(filename);
1099-
1100-
let with_msg_components;
1101-
let without_msg_components;
1102-
1103-
let components = if let Some(msg) = msg {
1104-
let msg = self.const_str_slice(msg);
1105-
with_msg_components = [msg, filename, line, col];
1106-
&with_msg_components as &[_]
1107-
} else {
1108-
without_msg_components = [filename, line, col];
1109-
&without_msg_components as &[_]
1110-
};
1111-
1112-
let struct_ = self.const_struct(&components, false);
1113-
self.static_addr_of(struct_, align, Some(kind))
1114-
}
11151085
}
11161086

11171087
impl Builder<'a, 'll, 'tcx> {

src/librustc_codegen_llvm/common.rs

-18
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! Code that is useful in various codegen modules.
44
55
use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt};
6-
use crate::abi;
76
use crate::consts;
87
use crate::type_::Type;
98
use crate::type_of::LayoutLlvmExt;
@@ -96,16 +95,6 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
9695
}
9796

9897
impl CodegenCx<'ll, 'tcx> {
99-
pub fn const_fat_ptr(
100-
&self,
101-
ptr: &'ll Value,
102-
meta: &'ll Value
103-
) -> &'ll Value {
104-
assert_eq!(abi::FAT_PTR_ADDR, 0);
105-
assert_eq!(abi::FAT_PTR_EXTRA, 1);
106-
self.const_struct(&[ptr, meta], false)
107-
}
108-
10998
pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
11099
unsafe {
111100
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
@@ -150,13 +139,6 @@ impl CodegenCx<'ll, 'tcx> {
150139
}
151140
}
152141

153-
pub fn const_str_slice(&self, s: Symbol) -> &'ll Value {
154-
let len = s.as_str().len();
155-
let cs = consts::ptrcast(self.const_cstr(s, false),
156-
self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
157-
self.const_fat_ptr(cs, self.const_usize(len as u64))
158-
}
159-
160142
pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
161143
unsafe {
162144
assert_eq!(idx as c_uint as u64, idx);

src/librustc_codegen_ssa/mir/block.rs

+8-39
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use crate::traits::*;
1616
use std::borrow::Cow;
1717

1818
use syntax::symbol::Symbol;
19-
use syntax_pos::Pos;
2019

2120
use super::{FunctionCx, LocalRef};
2221
use super::place::PlaceRef;
@@ -422,37 +421,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
422421

423422
// Get the location information.
424423
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
425-
let filename = Symbol::intern(&loc.file.name.to_string());
426-
let line = bx.const_u32(loc.line as u32);
427-
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
424+
let location = bx.static_panic_location(&loc);
428425

429426
// Put together the arguments to the panic entry point.
430427
let (lang_item, args) = match msg {
431428
PanicInfo::BoundsCheck { ref len, ref index } => {
432429
let len = self.codegen_operand(&mut bx, len).immediate();
433430
let index = self.codegen_operand(&mut bx, index).immediate();
434-
435-
let file_line_col = bx.static_panic_msg(
436-
None,
437-
filename,
438-
line,
439-
col,
440-
"panic_bounds_check_loc",
441-
);
442-
(lang_items::PanicBoundsCheckFnLangItem,
443-
vec![file_line_col, index, len])
431+
(lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len])
444432
}
445433
_ => {
446434
let msg_str = Symbol::intern(msg.description());
447-
let msg_file_line_col = bx.static_panic_msg(
448-
Some(msg_str),
449-
filename,
450-
line,
451-
col,
452-
"panic_loc",
453-
);
454-
(lang_items::PanicFnLangItem,
455-
vec![msg_file_line_col])
435+
let msg = bx.const_str(msg_str);
436+
(lang_items::PanicFnLangItem, vec![msg.0, msg.1, location])
456437
}
457438
};
458439

@@ -554,22 +535,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
554535
let layout = bx.layout_of(ty);
555536
if layout.abi.is_uninhabited() {
556537
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
557-
let filename = Symbol::intern(&loc.file.name.to_string());
558-
let line = bx.const_u32(loc.line as u32);
559-
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
560538

561-
let str = format!(
562-
"Attempted to instantiate uninhabited type {}",
563-
ty
564-
);
565-
let msg_str = Symbol::intern(&str);
566-
let msg_file_line_col = bx.static_panic_msg(
567-
Some(msg_str),
568-
filename,
569-
line,
570-
col,
571-
"panic_loc",
572-
);
539+
let msg_str = format!("Attempted to instantiate uninhabited type {}", ty);
540+
let msg = bx.const_str(Symbol::intern(&msg_str));
541+
let location = bx.static_panic_location(&loc);
573542

574543
// Obtain the panic entry point.
575544
let def_id =
@@ -587,7 +556,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
587556
&mut bx,
588557
fn_ty,
589558
llfn,
590-
&[msg_file_line_col],
559+
&[msg.0, msg.1, location],
591560
destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
592561
cleanup,
593562
);
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use super::BackendTypes;
22
use syntax::source_map::Loc;
3-
use syntax_pos::symbol::Symbol;
43
use rustc::hir::def_id::DefId;
54
use rustc::ty::layout::Align;
65

@@ -12,12 +11,4 @@ pub trait StaticMethods: BackendTypes {
1211
pub trait StaticBuilderMethods: BackendTypes {
1312
fn get_static(&mut self, def_id: DefId) -> Self::Value;
1413
fn static_panic_location(&mut self, loc: &Loc) -> Self::Value;
15-
fn static_panic_msg(
16-
&mut self,
17-
msg: Option<Symbol>,
18-
filename: Symbol,
19-
line: Self::Value,
20-
col: Self::Value,
21-
kind: &str,
22-
) -> Self::Value;
2314
}

src/librustc_mir/interpret/intrinsics.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
301301
) -> InterpResult<'tcx, bool> {
302302
let def_id = instance.def_id();
303303
if Some(def_id) == self.tcx.lang_items().panic_fn() {
304-
assert!(args.len() == 1);
305-
// &(&'static str, &'static str, u32, u32)
306-
let place = self.deref_operand(args[0])?;
307-
let (msg, file, line, col) = (
308-
self.mplace_field(place, 0)?,
309-
self.mplace_field(place, 1)?,
310-
self.mplace_field(place, 2)?,
311-
self.mplace_field(place, 3)?,
312-
);
304+
// &'static str, &core::panic::Location { &'static str, u32, u32 }
305+
assert!(args.len() == 2);
313306

314-
let msg_place = self.deref_operand(msg.into())?;
307+
let msg_place = self.deref_operand(args[0])?;
315308
let msg = Symbol::intern(self.read_str(msg_place)?);
309+
310+
let location = self.deref_operand(args[1])?;
311+
let (file, line, col) = (
312+
self.mplace_field(location, 0)?,
313+
self.mplace_field(location, 1)?,
314+
self.mplace_field(location, 2)?,
315+
);
316+
316317
let file_place = self.deref_operand(file.into())?;
317318
let file = Symbol::intern(self.read_str(file_place)?);
318319
let line = self.read_scalar(line.into())?.to_u32()?;

0 commit comments

Comments
 (0)