Skip to content

Commit 64dfd97

Browse files
committed
Add rustc_panic_entrypoint
1 parent a33907a commit 64dfd97

44 files changed

Lines changed: 1349 additions & 169 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,15 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicConstStableIndirectPar
12461246
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
12471247
}
12481248

1249+
pub(crate) struct RustcPanicEntrypointParser;
1250+
1251+
impl<S: Stage> NoArgsAttributeParser<S> for RustcPanicEntrypointParser {
1252+
const PATH: &[Symbol] = &[sym::rustc_panic_entrypoint];
1253+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1254+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1255+
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPanicEntrypoint;
1256+
}
1257+
12491258
pub(crate) struct RustcStrictCoherenceParser;
12501259

12511260
impl<S: Stage> NoArgsAttributeParser<S> for RustcStrictCoherenceParser {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ attribute_parsers!(
299299
Single<WithoutArgs<RustcObjectLifetimeDefaultParser>>,
300300
Single<WithoutArgs<RustcOffloadKernelParser>>,
301301
Single<WithoutArgs<RustcOutlivesParser>>,
302+
Single<WithoutArgs<RustcPanicEntrypointParser>>,
302303
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
303304
Single<WithoutArgs<RustcPreserveUbChecksParser>>,
304305
Single<WithoutArgs<RustcProcMacroDeclsParser>>,

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_middle::ty::layout::FnAbiOf;
1414
use rustc_middle::ty::print::with_no_trimmed_paths;
1515
use rustc_session::config::OutputFilenames;
1616
use rustc_span::Symbol;
17+
use rustc_target::spec::PanicStrategy;
1718

1819
use crate::constant::ConstantCx;
1920
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
@@ -384,6 +385,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
384385
fx.bcx.switch_to_block(failure);
385386
fx.bcx.ins().nop();
386387

388+
if fx.tcx.sess.panic_strategy() == PanicStrategy::ImmediateAbort {
389+
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
390+
continue;
391+
}
392+
387393
match &**msg {
388394
AssertKind::BoundsCheck { len, index } => {
389395
let len = codegen_operand(fx, len).load_scalar(fx);
@@ -1052,6 +1058,10 @@ pub(crate) fn codegen_panic_nounwind<'tcx>(
10521058
msg_str: &str,
10531059
span: Span,
10541060
) {
1061+
if fx.tcx.sess.panic_strategy() == PanicStrategy::ImmediateAbort {
1062+
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
1063+
}
1064+
10551065
let msg_ptr = crate::constant::pointer_for_anonymous_str(fx, msg_str);
10561066
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
10571067
let args = [msg_ptr, msg_len];

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner};
66
use rustc_hir::attrs::{
7-
AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy,
7+
AttributeKind, EiiImplResolution, InlineAttr, Linkage, OptimizeAttr, RtsanSetting, UsedBy,
88
};
99
use rustc_hir::def::DefKind;
1010
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
@@ -19,7 +19,7 @@ use rustc_middle::ty::{self as ty, TyCtxt};
1919
use rustc_session::lint;
2020
use rustc_session::parse::feature_err;
2121
use rustc_span::{Span, sym};
22-
use rustc_target::spec::Os;
22+
use rustc_target::spec::{Os, PanicStrategy};
2323

2424
use crate::errors;
2525
use crate::target_features::{
@@ -391,6 +391,24 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
391391
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
392392
}
393393
}
394+
395+
if tcx.is_panic_entrypoint(did) {
396+
// Panic entrypoints are always cold.
397+
//
398+
// If we have immediate-abort enabled, we want them to be inlined.
399+
// They shouldn't be called, but on the off-chance that they are, they should be inlined.
400+
//
401+
// When the panic strategies that support panic messages are enabled, we want panic
402+
// entrypoints outlined and optimized for size.
403+
// Most panic entrypoints want #[track_caller] but not all, so we do not add it.
404+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
405+
if tcx.sess.panic_strategy() == PanicStrategy::ImmediateAbort {
406+
codegen_fn_attrs.inline = InlineAttr::Always;
407+
} else {
408+
codegen_fn_attrs.inline = InlineAttr::Never;
409+
codegen_fn_attrs.optimize = OptimizeAttr::Size;
410+
}
411+
}
394412
}
395413

396414
fn check_result(

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_session::config::OptLevel;
1515
use rustc_span::Span;
1616
use rustc_span::source_map::Spanned;
1717
use rustc_target::callconv::{ArgAbi, ArgAttributes, CastTarget, FnAbi, PassMode};
18+
use rustc_target::spec::PanicStrategy;
1819
use tracing::{debug, info};
1920

2021
use super::operand::OperandRef;
@@ -176,22 +177,22 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
176177
if let Some(instance) = instance
177178
&& is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance)
178179
{
179-
if destination.is_some() {
180+
if tcx.is_panic_entrypoint(instance.def_id()) {
181+
info!(
182+
"compiler_builtins call to panic entrypoint {:?} replaced with abort",
183+
instance.def_id()
184+
);
185+
bx.abort();
186+
bx.unreachable();
187+
return MergingSucc::False;
188+
} else {
180189
let caller_def = fx.instance.def_id();
181190
let e = CompilerBuiltinsCannotCall {
182191
span: tcx.def_span(caller_def),
183192
caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)),
184193
callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())),
185194
};
186195
tcx.dcx().emit_err(e);
187-
} else {
188-
info!(
189-
"compiler_builtins call to diverging function {:?} replaced with abort",
190-
instance.def_id()
191-
);
192-
bx.abort();
193-
bx.unreachable();
194-
return MergingSucc::False;
195196
}
196197
}
197198

@@ -737,6 +738,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
737738
bx.switch_to_block(panic_block);
738739
self.set_debug_loc(bx, terminator.source_info);
739740

741+
if bx.tcx().sess.panic_strategy() == PanicStrategy::ImmediateAbort {
742+
bx.abort();
743+
bx.unreachable();
744+
return MergingSucc::False;
745+
}
746+
740747
// Get the location information.
741748
let location = self.get_caller_location(bx, terminator.source_info).immediate();
742749

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
13211321
"`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \
13221322
as non-const to allow large traits an easier transition to const"
13231323
),
1324+
rustc_attr!(
1325+
rustc_panic_entrypoint, AttributeType::Normal, template!(Word),
1326+
WarnFollowing, EncodeCrossCrate::Yes,
1327+
"`#[rustc_panic_entrypoint]` makes this function patchable by panic=immediate-abort",
1328+
),
13241329

13251330
BuiltinAttribute {
13261331
name: sym::rustc_diagnostic_item,

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,9 @@ pub enum AttributeKind {
12831283
/// Represents `#[rustc_outlives]`
12841284
RustcOutlives,
12851285

1286+
/// Represents `#[rustc_panic_entrypoint]`
1287+
RustcPanicEntrypoint,
1288+
12861289
/// Represents `#[rustc_paren_sugar]`.
12871290
RustcParenSugar(Span),
12881291

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ impl AttributeKind {
154154
RustcObjectLifetimeDefault => No,
155155
RustcOffloadKernel => Yes,
156156
RustcOutlives => No,
157+
RustcPanicEntrypoint => Yes,
157158
RustcParenSugar(..) => No,
158159
RustcPassByValue(..) => Yes,
159160
RustcPassIndirectlyInNonRusticAbis(..) => No,

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ language_item_table! {
235235
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
236236
FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
237237

238+
AbortIntrinsic, sym::abort_intrinsic, abort_intrinsic, Target::Fn, GenericRequirement::Exact(0);
238239
AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1);
239240
AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
240241
AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1);

0 commit comments

Comments
 (0)