Skip to content

Commit 95d7abf

Browse files
committed
Add a scheme for moving away from extern "rust-intrinsic" entirely
1 parent b9d8f00 commit 95d7abf

File tree

28 files changed

+156
-35
lines changed

28 files changed

+156
-35
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1648,7 +1648,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
16481648

16491649
let func_ty = func.ty(body, self.infcx.tcx);
16501650
if let ty::FnDef(def_id, _) = *func_ty.kind() {
1651-
if let Some(sym::simd_shuffle) = self.tcx().intrinsic(def_id) {
1651+
if self.tcx().is_intrinsic(def_id, sym::simd_shuffle) {
16521652
if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) {
16531653
self.tcx().dcx().emit_err(SimdShuffleLastConst { span: term.source_info.span });
16541654
}

compiler/rustc_codegen_cranelift/src/abi/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
398398
Ok(()) => return,
399399
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
400400
// by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
401-
Err(()) => Some(Instance::new(instance.def_id(), instance.args)),
401+
Err(()) => {
402+
let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap();
403+
if intrinsic.must_be_overridden {
404+
span_bug!(
405+
source_info.span,
406+
"intrinsic {} must be overridden by codegen_cranelift, but isn't",
407+
intrinsic.name,
408+
);
409+
}
410+
Some(Instance::new(instance.def_id(), instance.args))
411+
}
402412
}
403413
}
404414
InstanceDef::DropGlue(_, None) => {

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_middle::ty::{self, SymbolName, TyCtxt};
1616
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
1717
use rustc_middle::util::Providers;
1818
use rustc_session::config::{CrateType, OomStrategy};
19+
use rustc_span::sym;
1920
use rustc_target::spec::{SanitizerSet, TlsModel};
2021

2122
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
@@ -81,6 +82,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
8182
return library.kind.is_statically_included().then_some(def_id);
8283
}
8384

85+
if tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) {
86+
return None;
87+
}
88+
8489
// Only consider nodes that actually have exported symbols.
8590
match tcx.def_kind(def_id) {
8691
DefKind::Fn | DefKind::Static(_) => {}

compiler/rustc_codegen_ssa/src/mir/block.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1717
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1818
use rustc_middle::ty::{self, Instance, Ty};
1919
use rustc_session::config::OptLevel;
20-
use rustc_span::{source_map::Spanned, sym, Span, Symbol};
20+
use rustc_span::{source_map::Spanned, sym, Span};
2121
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
2222
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
2323
use rustc_target::spec::abi::Abi;
@@ -672,7 +672,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
672672
&mut self,
673673
helper: &TerminatorCodegenHelper<'tcx>,
674674
bx: &mut Bx,
675-
intrinsic: Option<Symbol>,
675+
intrinsic: Option<ty::IntrinsicDef>,
676676
instance: Option<Instance<'tcx>>,
677677
source_info: mir::SourceInfo,
678678
target: Option<mir::BasicBlock>,
@@ -682,7 +682,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
682682
// Emit a panic or a no-op for `assert_*` intrinsics.
683683
// These are intrinsics that compile to panics so that we can get a message
684684
// which mentions the offending type, even from a const context.
685-
let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
685+
let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name));
686686
if let Some(requirement) = panic_intrinsic {
687687
let ty = instance.unwrap().args.type_at(0);
688688

@@ -818,7 +818,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
818818
// The arguments we'll be passing. Plus one to account for outptr, if used.
819819
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
820820

821-
if intrinsic == Some(sym::caller_location) {
821+
if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) {
822822
return if let Some(target) = target {
823823
let location =
824824
self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
@@ -838,7 +838,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
838838
}
839839

840840
let instance = match intrinsic {
841-
None | Some(sym::drop_in_place) => instance,
841+
None | Some(ty::IntrinsicDef { name: sym::drop_in_place, .. }) => instance,
842842
Some(intrinsic) => {
843843
let mut llargs = Vec::with_capacity(1);
844844
let ret_dest = self.make_return_dest(
@@ -866,7 +866,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
866866
// third argument must be constant. This is
867867
// checked by const-qualification, which also
868868
// promotes any complex rvalues to constants.
869-
if i == 2 && intrinsic == sym::simd_shuffle {
869+
if i == 2 && intrinsic.name == sym::simd_shuffle {
870870
if let mir::Operand::Constant(constant) = &arg.node {
871871
let (llval, ty) = self.simd_shuffle_indices(bx, constant);
872872
return OperandRef {
@@ -897,7 +897,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
897897
};
898898
}
899899
// Call the fallback body instead of generating the intrinsic code
900-
Err(()) => Some(Instance::new(instance.def_id(), instance.args)),
900+
Err(()) => {
901+
if intrinsic.must_be_overridden {
902+
span_bug!(
903+
span,
904+
"intrinsic {} must be overridden by codegen backend, but isn't",
905+
intrinsic.name,
906+
);
907+
}
908+
Some(Instance::new(instance.def_id(), instance.args))
909+
}
901910
}
902911
}
903912
};

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
795795
rustc_intrinsic, Normal, template!(Word), ErrorFollowing,
796796
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
797797
),
798+
rustc_attr!(
799+
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing,
800+
"the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
801+
),
798802

799803
// ==========================================================================
800804
// Internal attributes, Testing:

compiler/rustc_hir_analysis/src/check/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
473473
check_enum(tcx, def_id);
474474
}
475475
DefKind::Fn => {
476-
if let Some(name) = tcx.intrinsic(def_id) {
476+
if let Some(i) = tcx.intrinsic(def_id) {
477477
intrinsic::check_intrinsic_type(
478478
tcx,
479479
def_id,
480480
tcx.def_ident_span(def_id).unwrap(),
481-
name,
481+
i.name,
482482
Abi::Rust,
483483
)
484484
}

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
480480

481481
if let Some(def_id) = def_id
482482
&& self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
483-
&& matches!(self.tcx.intrinsic(def_id), Some(sym::const_eval_select))
483+
&& self.tcx.is_intrinsic(def_id, sym::const_eval_select)
484484
{
485485
let fn_sig = self.resolve_vars_if_possible(fn_sig);
486486
for idx in 0..=1 {

compiler/rustc_lint/src/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
12271227
}
12281228

12291229
fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
1230-
matches!(cx.tcx.intrinsic(def_id), Some(sym::transmute))
1230+
cx.tcx.is_intrinsic(def_id, sym::transmute)
12311231
}
12321232
}
12331233
}

compiler/rustc_metadata/src/rmeta/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
17441744
self.root.tables.attr_flags.get(self, index)
17451745
}
17461746

1747-
fn get_intrinsic(self, index: DefIndex) -> Option<Symbol> {
1747+
fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
17481748
self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
17491749
}
17501750

compiler/rustc_metadata/src/rmeta/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ macro_rules! define_tables {
375375

376376
define_tables! {
377377
- defaulted:
378-
intrinsic: Table<DefIndex, Option<LazyValue<Symbol>>>,
378+
intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>,
379379
is_macro_rules: Table<DefIndex, bool>,
380380
is_type_alias_impl_trait: Table<DefIndex, bool>,
381381
type_alias_is_lazy: Table<DefIndex, bool>,

compiler/rustc_middle/src/query/erase.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ trivial! {
240240
Option<rustc_span::Span>,
241241
Option<rustc_target::spec::PanicStrategy>,
242242
Option<usize>,
243-
Option<rustc_span::Symbol>,
243+
Option<rustc_middle::ty::IntrinsicDef>,
244244
Result<(), rustc_errors::ErrorGuaranteed>,
245245
Result<(), rustc_middle::traits::query::NoSolution>,
246246
Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,7 @@ rustc_queries! {
17481748
separate_provide_extern
17491749
}
17501750
/// Whether the function is an intrinsic
1751-
query intrinsic(def_id: DefId) -> Option<Symbol> {
1751+
query intrinsic(def_id: DefId) -> Option<rustc_middle::ty::IntrinsicDef> {
17521752
desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) }
17531753
separate_provide_extern
17541754
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use rustc_span::{def_id::DefId, Symbol};
2+
3+
use super::TyCtxt;
4+
5+
#[derive(Copy, Clone, Debug, Decodable, Encodable, HashStable)]
6+
pub struct IntrinsicDef {
7+
pub name: Symbol,
8+
/// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
9+
pub must_be_overridden: bool,
10+
}
11+
12+
impl TyCtxt<'_> {
13+
pub fn is_intrinsic(self, def_id: DefId, name: Symbol) -> bool {
14+
let Some(i) = self.intrinsic(def_id) else { return false };
15+
i.name == name
16+
}
17+
}

compiler/rustc_middle/src/ty/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub use adt::*;
3030
pub use assoc::*;
3131
pub use generic_args::*;
3232
pub use generics::*;
33+
pub use intrinsic::IntrinsicDef;
3334
use rustc_ast as ast;
3435
use rustc_ast::node_id::NodeMap;
3536
use rustc_attr as attr;
@@ -147,6 +148,7 @@ mod generic_args;
147148
mod generics;
148149
mod impls_ty;
149150
mod instance;
151+
mod intrinsic;
150152
mod list;
151153
mod opaque_types;
152154
mod parameterized;

compiler/rustc_middle/src/ty/parameterized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ trivially_parameterized_over_tcx! {
7575
ty::Visibility<DefIndex>,
7676
ty::adjustment::CoerceUnsizedInfo,
7777
ty::fast_reject::SimplifiedType,
78+
ty::IntrinsicDef,
7879
rustc_ast::Attribute,
7980
rustc_ast::DelimArgs,
8081
rustc_ast::expand::StrippedCfgItem<rustc_hir::def_id::DefIndex>,

compiler/rustc_middle/src/ty/util.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
1818
use rustc_index::bit_set::GrowableBitSet;
1919
use rustc_macros::HashStable;
2020
use rustc_session::Limit;
21-
use rustc_span::{sym, Symbol};
21+
use rustc_span::sym;
2222
use rustc_target::abi::{Integer, IntegerType, Primitive, Size};
2323
use rustc_target::spec::abi::Abi;
2424
use smallvec::SmallVec;
@@ -1539,11 +1539,14 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
15391539
}
15401540

15411541
/// Determines whether an item is an intrinsic by Abi. or by whether it has a `rustc_intrinsic` attribute
1542-
pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Symbol> {
1542+
pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
15431543
if matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
15441544
|| tcx.has_attr(def_id, sym::rustc_intrinsic)
15451545
{
1546-
Some(tcx.item_name(def_id.into()))
1546+
Some(ty::IntrinsicDef {
1547+
name: tcx.item_name(def_id.into()),
1548+
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
1549+
})
15471550
} else {
15481551
None
15491552
}

compiler/rustc_mir_dataflow/src/rustc_peek.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ impl PeekCall {
202202
&terminator.kind
203203
{
204204
if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() {
205-
if tcx.intrinsic(def_id)? != sym::rustc_peek {
205+
if tcx.intrinsic(def_id)?.name != sym::rustc_peek {
206206
return None;
207207
}
208208

compiler/rustc_mir_transform/src/cross_crate_inline.rs

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::query::Providers;
99
use rustc_middle::ty::TyCtxt;
1010
use rustc_session::config::InliningThreshold;
1111
use rustc_session::config::OptLevel;
12+
use rustc_span::sym;
1213

1314
pub fn provide(providers: &mut Providers) {
1415
providers.cross_crate_inlinable = cross_crate_inlinable;
@@ -22,6 +23,10 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
2223
return false;
2324
}
2425

26+
if tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) {
27+
return false;
28+
}
29+
2530
// This just reproduces the logic from Instance::requires_inline.
2631
match tcx.def_kind(def_id) {
2732
DefKind::Ctor(..) | DefKind::Closure => return true,

compiler/rustc_mir_transform/src/instsimplify.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ fn resolve_rust_intrinsic<'tcx>(
305305
func_ty: Ty<'tcx>,
306306
) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
307307
if let ty::FnDef(def_id, args) = *func_ty.kind() {
308-
let name = tcx.intrinsic(def_id)?;
309-
return Some((name, args));
308+
let intrinsic = tcx.intrinsic(def_id)?;
309+
return Some((intrinsic.name, args));
310310
}
311311
None
312312
}

compiler/rustc_mir_transform/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
165165
fn_span,
166166
..
167167
} if let ty::FnDef(def_id, _) = *const_.ty().kind()
168-
&& matches!(tcx.intrinsic(def_id), Some(sym::const_eval_select)) =>
168+
&& tcx.is_intrinsic(def_id, sym::const_eval_select) =>
169169
{
170170
let [tupled_args, called_in_const, called_at_rt]: [_; 3] =
171171
std::mem::take(args).try_into().unwrap();
@@ -637,6 +637,12 @@ fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
637637
}
638638

639639
fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
640+
if let Some(attr) = tcx.get_attr(did, sym::rustc_intrinsic_must_be_overridden) {
641+
span_bug!(
642+
attr.span,
643+
"this intrinsic must be overridden by the codegen backend, it has no meaningful body",
644+
)
645+
}
640646
if tcx.is_constructor(did.to_def_id()) {
641647
// There's no reason to run all of the MIR passes on constructors when
642648
// we can just output the MIR we want directly. This also saves const

compiler/rustc_mir_transform/src/lower_intrinsics.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
1414
if let TerminatorKind::Call { func, args, destination, target, .. } =
1515
&mut terminator.kind
1616
&& let ty::FnDef(def_id, generic_args) = *func.ty(local_decls, tcx).kind()
17-
&& let Some(intrinsic_name) = tcx.intrinsic(def_id)
17+
&& let Some(intrinsic) = tcx.intrinsic(def_id)
1818
{
19-
match intrinsic_name {
19+
match intrinsic.name {
2020
sym::unreachable => {
2121
terminator.kind = TerminatorKind::Unreachable;
2222
}
@@ -94,7 +94,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
9494
lhs = args.next().unwrap();
9595
rhs = args.next().unwrap();
9696
}
97-
let bin_op = match intrinsic_name {
97+
let bin_op = match intrinsic.name {
9898
sym::wrapping_add => BinOp::Add,
9999
sym::wrapping_sub => BinOp::Sub,
100100
sym::wrapping_mul => BinOp::Mul,
@@ -125,7 +125,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
125125
lhs = args.next().unwrap();
126126
rhs = args.next().unwrap();
127127
}
128-
let bin_op = match intrinsic_name {
128+
let bin_op = match intrinsic.name {
129129
sym::add_with_overflow => BinOp::Add,
130130
sym::sub_with_overflow => BinOp::Sub,
131131
sym::mul_with_overflow => BinOp::Mul,
@@ -144,7 +144,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
144144
sym::size_of | sym::min_align_of => {
145145
if let Some(target) = *target {
146146
let tp_ty = generic_args.type_at(0);
147-
let null_op = match intrinsic_name {
147+
let null_op = match intrinsic.name {
148148
sym::size_of => NullOp::SizeOf,
149149
sym::min_align_of => NullOp::AlignOf,
150150
_ => bug!("unexpected intrinsic"),

compiler/rustc_monomorphize/src/collector.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,11 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
10091009
return false;
10101010
}
10111011

1012+
if tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) {
1013+
// These are implemented by backends directly and have no meaningful body.
1014+
return false;
1015+
}
1016+
10121017
if def_id.is_local() {
10131018
// Local items cannot be referred to locally without monomorphizing them locally.
10141019
return true;

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,7 @@ symbols! {
14121412
rustc_inherit_overflow_checks,
14131413
rustc_insignificant_dtor,
14141414
rustc_intrinsic,
1415+
rustc_intrinsic_must_be_overridden,
14151416
rustc_layout,
14161417
rustc_layout_scalar_valid_range_end,
14171418
rustc_layout_scalar_valid_range_start,

0 commit comments

Comments
 (0)