Skip to content

Commit 00f4daa

Browse files
Codegen const panic messages as function calls
This skips emitting extra arguments at every callsite (of which there can be many). For a librustc_driver build with overflow checks enabled, this cuts 0.7MB from the resulting binary.
1 parent 0ad927c commit 00f4daa

File tree

12 files changed

+255
-63
lines changed

12 files changed

+255
-63
lines changed

Diff for: compiler/rustc_codegen_cranelift/example/mini_core.rs

+30
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,36 @@ pub fn panic(_msg: &'static str) -> ! {
465465
}
466466
}
467467

468+
macro_rules! panic_const {
469+
($($lang:ident = $message:expr,)+) => {
470+
#[cfg(not(bootstrap))]
471+
pub mod panic_const {
472+
use super::*;
473+
474+
$(
475+
#[track_caller]
476+
#[lang = stringify!($lang)]
477+
pub fn $lang() -> ! {
478+
panic($message);
479+
}
480+
)+
481+
}
482+
}
483+
}
484+
485+
panic_const! {
486+
panic_const_add_overflow = "attempt to add with overflow",
487+
panic_const_sub_overflow = "attempt to subtract with overflow",
488+
panic_const_mul_overflow = "attempt to multiply with overflow",
489+
panic_const_div_overflow = "attempt to divide with overflow",
490+
panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
491+
panic_const_neg_overflow = "attempt to negate with overflow",
492+
panic_const_shr_overflow = "attempt to shift right with overflow",
493+
panic_const_shl_overflow = "attempt to shift left with overflow",
494+
panic_const_div_by_zero = "attempt to divide by zero",
495+
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
496+
}
497+
468498
#[lang = "panic_bounds_check"]
469499
#[track_caller]
470500
fn panic_bounds_check(index: usize, len: usize) -> ! {

Diff for: compiler/rustc_codegen_cranelift/src/base.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,14 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
369369
);
370370
}
371371
_ => {
372-
let msg_str = msg.description();
373-
codegen_panic(fx, msg_str, source_info);
372+
let location = fx.get_caller_location(source_info).load_scalar(fx);
373+
374+
codegen_panic_inner(
375+
fx,
376+
msg.panic_function(),
377+
&[location],
378+
Some(source_info.span),
379+
);
374380
}
375381
}
376382
}
@@ -954,20 +960,6 @@ pub(crate) fn codegen_operand<'tcx>(
954960
}
955961
}
956962

957-
pub(crate) fn codegen_panic<'tcx>(
958-
fx: &mut FunctionCx<'_, '_, 'tcx>,
959-
msg_str: &str,
960-
source_info: mir::SourceInfo,
961-
) {
962-
let location = fx.get_caller_location(source_info).load_scalar(fx);
963-
964-
let msg_ptr = fx.anonymous_str(msg_str);
965-
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
966-
let args = [msg_ptr, msg_len, location];
967-
968-
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, Some(source_info.span));
969-
}
970-
971963
pub(crate) fn codegen_panic_nounwind<'tcx>(
972964
fx: &mut FunctionCx<'_, '_, 'tcx>,
973965
msg_str: &str,

Diff for: compiler/rustc_codegen_gcc/example/mini_core.rs

+30
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,36 @@ pub fn panic(_msg: &'static str) -> ! {
418418
}
419419
}
420420

421+
macro_rules! panic_const {
422+
($($lang:ident = $message:expr,)+) => {
423+
#[cfg(not(bootstrap))]
424+
pub mod panic_const {
425+
use super::*;
426+
427+
$(
428+
#[track_caller]
429+
#[lang = stringify!($lang)]
430+
pub fn $lang() -> ! {
431+
panic($message);
432+
}
433+
)+
434+
}
435+
}
436+
}
437+
438+
panic_const! {
439+
panic_const_add_overflow = "attempt to add with overflow",
440+
panic_const_sub_overflow = "attempt to subtract with overflow",
441+
panic_const_mul_overflow = "attempt to multiply with overflow",
442+
panic_const_div_overflow = "attempt to divide with overflow",
443+
panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
444+
panic_const_neg_overflow = "attempt to negate with overflow",
445+
panic_const_shr_overflow = "attempt to shift right with overflow",
446+
panic_const_shl_overflow = "attempt to shift left with overflow",
447+
panic_const_div_by_zero = "attempt to divide by zero",
448+
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
449+
}
450+
421451
#[lang = "panic_cannot_unwind"]
422452
fn panic_cannot_unwind() -> ! {
423453
unsafe {

Diff for: compiler/rustc_codegen_ssa/src/mir/block.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -651,10 +651,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
651651
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
652652
}
653653
_ => {
654-
let msg = bx.const_str(msg.description());
655-
// It's `pub fn panic(expr: &str)`, with the wide reference being passed
656-
// as two arguments, and `#[track_caller]` adds an implicit third argument.
657-
(LangItem::Panic, vec![msg.0, msg.1, location])
654+
// It's `pub fn panic_...()` and `#[track_caller]` adds an implicit argument.
655+
(msg.panic_function(), vec![location])
658656
}
659657
};
660658

Diff for: compiler/rustc_hir/src/lang_items.rs

+19
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ language_item_table! {
246246
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
247247
PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
248248
PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0);
249+
/// Constant panic messages, used for codegen of MIR asserts.
250+
PanicAddOverflow, sym::panic_const_add_overflow, panic_const_add_overflow, Target::Fn, GenericRequirement::None;
251+
PanicSubOverflow, sym::panic_const_sub_overflow, panic_const_sub_overflow, Target::Fn, GenericRequirement::None;
252+
PanicMulOverflow, sym::panic_const_mul_overflow, panic_const_mul_overflow, Target::Fn, GenericRequirement::None;
253+
PanicDivOverflow, sym::panic_const_div_overflow, panic_const_div_overflow, Target::Fn, GenericRequirement::None;
254+
PanicRemOverflow, sym::panic_const_rem_overflow, panic_const_rem_overflow, Target::Fn, GenericRequirement::None;
255+
PanicNegOverflow, sym::panic_const_neg_overflow, panic_const_neg_overflow, Target::Fn, GenericRequirement::None;
256+
PanicShrOverflow, sym::panic_const_shr_overflow, panic_const_shr_overflow, Target::Fn, GenericRequirement::None;
257+
PanicShlOverflow, sym::panic_const_shl_overflow, panic_const_shl_overflow, Target::Fn, GenericRequirement::None;
258+
PanicDivZero, sym::panic_const_div_by_zero, panic_const_div_by_zero, Target::Fn, GenericRequirement::None;
259+
PanicRemZero, sym::panic_const_rem_by_zero, panic_const_rem_by_zero, Target::Fn, GenericRequirement::None;
260+
PanicCoroutineResumed, sym::panic_const_coroutine_resumed, panic_const_coroutine_resumed, Target::Fn, GenericRequirement::None;
261+
PanicAsyncFnResumed, sym::panic_const_async_fn_resumed, panic_const_async_fn_resumed, Target::Fn, GenericRequirement::None;
262+
PanicAsyncGenFnResumed, sym::panic_const_async_gen_fn_resumed, panic_const_async_gen_fn_resumed, Target::Fn, GenericRequirement::None;
263+
PanicGenFnNone, sym::panic_const_gen_fn_none, panic_const_gen_fn_none, Target::Fn, GenericRequirement::None;
264+
PanicCoroutineResumedPanic, sym::panic_const_coroutine_resumed_panic, panic_const_coroutine_resumed_panic, Target::Fn, GenericRequirement::None;
265+
PanicAsyncFnResumedPanic, sym::panic_const_async_fn_resumed_panic, panic_const_async_fn_resumed_panic, Target::Fn, GenericRequirement::None;
266+
PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None;
267+
PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None;
249268
/// libstd panic entry point. Necessary for const eval to be able to catch it
250269
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
251270

Diff for: compiler/rustc_middle/src/mir/terminator.rs

+49-24
Original file line numberDiff line numberDiff line change
@@ -149,44 +149,45 @@ impl<O> AssertKind<O> {
149149
matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..))
150150
}
151151

152-
/// Get the message that is printed at runtime when this assertion fails.
152+
/// Get the lang item that is invoked to print a static message when this assert fires.
153153
///
154154
/// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` by
155155
/// invoking the appropriate lang item (panic_bounds_check/panic_misaligned_pointer_dereference)
156-
/// instead of printing a static message.
157-
pub fn description(&self) -> &'static str {
156+
/// instead of printing a static message. Those have dynamic arguments that aren't present for
157+
/// the rest of the messages here.
158+
pub fn panic_function(&self) -> LangItem {
158159
use AssertKind::*;
159160
match self {
160-
Overflow(BinOp::Add, _, _) => "attempt to add with overflow",
161-
Overflow(BinOp::Sub, _, _) => "attempt to subtract with overflow",
162-
Overflow(BinOp::Mul, _, _) => "attempt to multiply with overflow",
163-
Overflow(BinOp::Div, _, _) => "attempt to divide with overflow",
164-
Overflow(BinOp::Rem, _, _) => "attempt to calculate the remainder with overflow",
165-
OverflowNeg(_) => "attempt to negate with overflow",
166-
Overflow(BinOp::Shr, _, _) => "attempt to shift right with overflow",
167-
Overflow(BinOp::Shl, _, _) => "attempt to shift left with overflow",
161+
Overflow(BinOp::Add, _, _) => LangItem::PanicAddOverflow,
162+
Overflow(BinOp::Sub, _, _) => LangItem::PanicSubOverflow,
163+
Overflow(BinOp::Mul, _, _) => LangItem::PanicMulOverflow,
164+
Overflow(BinOp::Div, _, _) => LangItem::PanicDivOverflow,
165+
Overflow(BinOp::Rem, _, _) => LangItem::PanicRemOverflow,
166+
OverflowNeg(_) => LangItem::PanicNegOverflow,
167+
Overflow(BinOp::Shr, _, _) => LangItem::PanicShrOverflow,
168+
Overflow(BinOp::Shl, _, _) => LangItem::PanicShlOverflow,
168169
Overflow(op, _, _) => bug!("{:?} cannot overflow", op),
169-
DivisionByZero(_) => "attempt to divide by zero",
170-
RemainderByZero(_) => "attempt to calculate the remainder with a divisor of zero",
171-
ResumedAfterReturn(CoroutineKind::Coroutine(_)) => "coroutine resumed after completion",
170+
DivisionByZero(_) => LangItem::PanicDivZero,
171+
RemainderByZero(_) => LangItem::PanicRemZero,
172+
ResumedAfterReturn(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumed,
172173
ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
173-
"`async fn` resumed after completion"
174+
LangItem::PanicAsyncFnResumed
174175
}
175176
ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
176-
"`async gen fn` resumed after completion"
177+
LangItem::PanicAsyncGenFnResumed
177178
}
178179
ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
179-
"`gen fn` should just keep returning `None` after completion"
180+
LangItem::PanicGenFnNone
180181
}
181-
ResumedAfterPanic(CoroutineKind::Coroutine(_)) => "coroutine resumed after panicking",
182+
ResumedAfterPanic(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumedPanic,
182183
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
183-
"`async fn` resumed after panicking"
184+
LangItem::PanicAsyncFnResumedPanic
184185
}
185186
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
186-
"`async gen fn` resumed after panicking"
187+
LangItem::PanicAsyncGenFnResumedPanic
187188
}
188189
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
189-
"`gen fn` should just keep returning `None` after panicking"
190+
LangItem::PanicGenFnNonePanic
190191
}
191192

192193
BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
@@ -198,7 +199,7 @@ impl<O> AssertKind<O> {
198199
/// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing.
199200
///
200201
/// Needs to be kept in sync with the run-time behavior (which is defined by
201-
/// `AssertKind::description` and the lang items mentioned in its docs).
202+
/// `AssertKind::panic_function` and the lang items mentioned in its docs).
202203
/// Note that we deliberately show more details here than we do at runtime, such as the actual
203204
/// numbers that overflowed -- it is much easier to do so here than at runtime.
204205
pub fn fmt_assert_args<W: fmt::Write>(&self, f: &mut W) -> fmt::Result
@@ -246,20 +247,44 @@ impl<O> AssertKind<O> {
246247
Overflow(BinOp::Shl, _, r) => {
247248
write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {r:?}")
248249
}
250+
Overflow(op, _, _) => bug!("{:?} cannot overflow", op),
249251
MisalignedPointerDereference { required, found } => {
250252
write!(
251253
f,
252254
"\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}"
253255
)
254256
}
255-
_ => write!(f, "\"{}\"", self.description()),
257+
ResumedAfterReturn(CoroutineKind::Coroutine(_)) => {
258+
write!(f, "\"coroutine resumed after completion\"")
259+
}
260+
ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
261+
write!(f, "\"`async fn` resumed after completion\"")
262+
}
263+
ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
264+
write!(f, "\"`async gen fn` resumed after completion\"")
265+
}
266+
ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
267+
write!(f, "\"`gen fn` should just keep returning `None` after completion\"")
268+
}
269+
ResumedAfterPanic(CoroutineKind::Coroutine(_)) => {
270+
write!(f, "\"coroutine resumed after panicking\"")
271+
}
272+
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => {
273+
write!(f, "\"`async fn` resumed after panicking\"")
274+
}
275+
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => {
276+
write!(f, "\"`async gen fn` resumed after panicking\"")
277+
}
278+
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
279+
write!(f, "\"`gen fn` should just keep returning `None` after panicking\"")
280+
}
256281
}
257282
}
258283

259284
/// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval).
260285
///
261286
/// Needs to be kept in sync with the run-time behavior (which is defined by
262-
/// `AssertKind::description` and the lang items mentioned in its docs).
287+
/// `AssertKind::panic_function` and the lang items mentioned in its docs).
263288
/// Note that we deliberately show more details here than we do at runtime, such as the actual
264289
/// numbers that overflowed -- it is much easier to do so here than at runtime.
265290
pub fn diagnostic_message(&self) -> DiagMessage {

Diff for: compiler/rustc_monomorphize/src/collector.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -971,16 +971,17 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
971971
}
972972
}
973973
}
974-
mir::TerminatorKind::Assert { ref msg, .. } => {
975-
let lang_item = match &**msg {
976-
mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
977-
mir::AssertKind::MisalignedPointerDereference { .. } => {
978-
LangItem::PanicMisalignedPointerDereference
979-
}
980-
_ => LangItem::Panic,
981-
};
982-
push_mono_lang_item(self, lang_item);
983-
}
974+
mir::TerminatorKind::Assert { ref msg, .. } => match &**msg {
975+
mir::AssertKind::BoundsCheck { .. } => {
976+
push_mono_lang_item(self, LangItem::PanicBoundsCheck);
977+
}
978+
mir::AssertKind::MisalignedPointerDereference { .. } => {
979+
push_mono_lang_item(self, LangItem::PanicMisalignedPointerDereference);
980+
}
981+
_ => {
982+
push_mono_lang_item(self, msg.panic_function());
983+
}
984+
},
984985
mir::TerminatorKind::UnwindTerminate(reason) => {
985986
push_mono_lang_item(self, reason.lang_item());
986987
}

Diff for: compiler/rustc_span/src/symbol.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,24 @@ symbols! {
12971297
panic_abort,
12981298
panic_bounds_check,
12991299
panic_cannot_unwind,
1300+
panic_const_add_overflow,
1301+
panic_const_async_fn_resumed,
1302+
panic_const_async_fn_resumed_panic,
1303+
panic_const_async_gen_fn_resumed,
1304+
panic_const_async_gen_fn_resumed_panic,
1305+
panic_const_coroutine_resumed,
1306+
panic_const_coroutine_resumed_panic,
1307+
panic_const_div_by_zero,
1308+
panic_const_div_overflow,
1309+
panic_const_gen_fn_none,
1310+
panic_const_gen_fn_none_panic,
1311+
panic_const_mul_overflow,
1312+
panic_const_neg_overflow,
1313+
panic_const_rem_by_zero,
1314+
panic_const_rem_overflow,
1315+
panic_const_shl_overflow,
1316+
panic_const_shr_overflow,
1317+
panic_const_sub_overflow,
13001318
panic_fmt,
13011319
panic_handler,
13021320
panic_impl,

0 commit comments

Comments
 (0)