Skip to content

Commit 45dcd90

Browse files
committed
Distinguish lowered-to-MIR intrinsics from handled-by-backend intrinsics
"Must be overridden" is misleading for things that a backend actually shouldn't override since they'll never see them.
1 parent 76f3ff6 commit 45dcd90

File tree

24 files changed

+188
-52
lines changed

24 files changed

+188
-52
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,11 +1278,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
12781278
// by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`.
12791279
_ => {
12801280
let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap();
1281-
if intrinsic.must_be_overridden {
1281+
if !intrinsic.has_fallback() {
12821282
span_bug!(
12831283
source_info.span,
1284-
"intrinsic {} must be overridden by codegen_cranelift, but isn't",
1284+
"intrinsic {} ({:?}) must be overridden by codegen_cranelift, but isn't",
12851285
intrinsic.name,
1286+
intrinsic.kind,
12861287
);
12871288
}
12881289
return Err(Instance::new(instance.def_id(), instance.args));

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
952952
};
953953
}
954954
Err(instance) => {
955-
if intrinsic.must_be_overridden {
955+
if !intrinsic.has_fallback() {
956956
span_bug!(
957957
span,
958-
"intrinsic {} must be overridden by codegen backend, but isn't",
958+
"intrinsic {} ({:?}) got to the codegen backend, but wasn't overridden",
959959
intrinsic.name,
960+
intrinsic.kind,
960961
);
961962
}
962963
Some(instance)

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
766766
// We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
767767
// fallback body is safe to expose on stable.
768768
let is_const_stable = intrinsic.const_stable
769-
|| (!intrinsic.must_be_overridden
769+
|| (intrinsic.has_fallback()
770770
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
771771
match tcx.lookup_const_stability(callee) {
772772
None => {

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
466466
sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?,
467467
_ => {
468468
// We haven't handled the intrinsic, let's see if we can use a fallback body.
469-
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
469+
if !ecx.tcx.intrinsic(instance.def_id()).unwrap().has_fallback() {
470470
throw_unsup_format!(
471471
"intrinsic `{intrinsic_name}` is not supported at compile-time"
472472
);

compiler/rustc_const_eval/src/interpret/call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
540540
target,
541541
unwind,
542542
)? {
543-
assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden);
543+
assert!(self.tcx.intrinsic(fallback.def_id()).unwrap().has_fallback());
544544
assert_matches!(fallback.def, ty::InstanceKind::Item(_));
545545
return self.init_fn_call(
546546
FnVal::Instance(fallback),

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
10101010
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
10111011
"the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
10121012
),
1013+
gated!(
1014+
rustc_intrinsic_lowers_to_mir, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
1015+
"the `#[rustc_intrinsic_lowers_to_mir]` attribute is used to declare intrinsics translated by `LowerIntrinsics`",
1016+
),
10131017
rustc_attr!(
10141018
rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
10151019
"#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"

compiler/rustc_middle/src/ty/intrinsic.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,39 @@ use rustc_span::def_id::DefId;
44

55
use super::TyCtxt;
66

7+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Decodable, Encodable, HashStable)]
8+
pub enum IntrinsicKind {
9+
/// The intrinsic has no meaningful body and all backends need to shim all calls to it.
10+
MustBeOverridden,
11+
/// The intrinsic lowers to MIR, so does not need to be considered by backends.
12+
LowersToMir,
13+
/// The intrinsic has a meaningful body usable by backends that don't need something special.
14+
HasFallback,
15+
}
16+
717
#[derive(Copy, Clone, Debug, Decodable, Encodable, HashStable)]
818
pub struct IntrinsicDef {
919
pub name: Symbol,
10-
/// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
11-
pub must_be_overridden: bool,
20+
/// Describes how the intrinsic is expected to be handled, based on its definition.
21+
pub kind: IntrinsicKind,
1222
/// Whether the intrinsic can be invoked from stable const fn
1323
pub const_stable: bool,
1424
}
1525

26+
impl IntrinsicDef {
27+
pub fn must_be_overridden(self) -> bool {
28+
self.kind == IntrinsicKind::MustBeOverridden
29+
}
30+
31+
pub fn has_fallback(self) -> bool {
32+
self.kind == IntrinsicKind::HasFallback
33+
}
34+
35+
pub fn lowers_to_mir(self) -> bool {
36+
self.kind == IntrinsicKind::LowersToMir
37+
}
38+
}
39+
1640
impl TyCtxt<'_> {
1741
pub fn is_intrinsic(self, def_id: DefId, name: Symbol) -> bool {
1842
let Some(i) = self.intrinsic(def_id) else { return false };

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use adt::*;
2323
pub use assoc::*;
2424
pub use generic_args::{GenericArgKind, TermKind, *};
2525
pub use generics::*;
26-
pub use intrinsic::IntrinsicDef;
26+
pub use intrinsic::{IntrinsicDef, IntrinsicKind};
2727
use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
2828
use rustc_ast::expand::StrippedCfgItem;
2929
use rustc_ast::node_id::NodeMap;

compiler/rustc_middle/src/ty/util.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,11 +1760,20 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
17601760
&& (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
17611761
|| tcx.has_attr(def_id, sym::rustc_intrinsic))
17621762
{
1763-
Some(ty::IntrinsicDef {
1764-
name: tcx.item_name(def_id.into()),
1765-
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
1766-
const_stable: tcx.has_attr(def_id, sym::rustc_intrinsic_const_stable_indirect),
1767-
})
1763+
let name = tcx.item_name(def_id.into());
1764+
let must_be_overridden = tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden);
1765+
let lowers_to_mir = tcx.has_attr(def_id, sym::rustc_intrinsic_lowers_to_mir);
1766+
let const_stable = tcx.has_attr(def_id, sym::rustc_intrinsic_const_stable_indirect);
1767+
let kind = match (must_be_overridden, lowers_to_mir) {
1768+
(false, false) => ty::IntrinsicKind::HasFallback,
1769+
(true, false) => ty::IntrinsicKind::MustBeOverridden,
1770+
(false, true) => ty::IntrinsicKind::LowersToMir,
1771+
(true, true) => bug!(
1772+
"intrinsic {name} should be marked with at most one of \
1773+
rustc_intrinsic_must_be_overridden and rustc_intrinsic_lowers_to_mir",
1774+
),
1775+
};
1776+
Some(ty::IntrinsicDef { name, kind, const_stable })
17681777
} else {
17691778
None
17701779
}

compiler/rustc_mir_build/src/build/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
997997
if let Some(source_scope) = scope {
998998
self.source_scope = source_scope;
999999
}
1000-
if self.tcx.intrinsic(self.def_id).is_some_and(|i| i.must_be_overridden) {
1000+
if self.tcx.intrinsic(self.def_id).is_some_and(|i| !i.has_fallback()) {
10011001
let source_info = self.source_info(rustc_span::DUMMY_SP);
10021002
self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
10031003
self.cfg.start_new_block().unit()

0 commit comments

Comments
 (0)