Skip to content

Commit 6ab7666

Browse files
committed
Error when a type requires a target feature and the target feature isn't enabled.
1 parent 8f21a5c commit 6ab7666

File tree

15 files changed

+152
-57
lines changed

15 files changed

+152
-57
lines changed

compiler/rustc_abi/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ pub struct ReprOptions {
143143
pub align: Option<Align>,
144144
pub pack: Option<Align>,
145145
pub flags: ReprFlags,
146+
pub target_feature: Option<u16>,
146147
/// The seed to be used for randomizing a type's layout
147148
///
148149
/// Note: This could technically be a `u128` which would

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub enum ReprAttr {
6464
ReprRust,
6565
ReprC,
6666
ReprPacked(Align),
67-
ReprSimd,
67+
ReprSimd(Option<u16>),
6868
ReprTransparent,
6969
ReprAlign(Align),
7070
// this one is just so we can emit a lint for it

compiler/rustc_attr_parsing/src/attributes/repr.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,28 @@ fn parse_repr<S: Stage>(
142142

143143
(Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust),
144144
(Some(sym::C), ArgParser::NoArgs) => Some(ReprC),
145-
(Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd),
145+
(Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd(None)),
146146
(Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent),
147147
(Some(name @ int_pat!()), ArgParser::NoArgs) => {
148148
// int_pat!() should make sure it always parses
149149
Some(ReprInt(int_type_of_word(name).unwrap()))
150150
}
151151

152+
(Some(sym::simd), ArgParser::List(x)) => {
153+
let Some(item) = x.single() else {
154+
todo!("Handle incorrect syntax");
155+
};
156+
let Some(lit) = item.lit() else {
157+
todo!("Handle invalid lit");
158+
};
159+
match lit.kind {
160+
LitKind::Int(v, _) => {
161+
Some(ReprSimd(Some(v.0 as u16)))
162+
}
163+
_ => todo!("Handle invalid lit kind"),
164+
}
165+
}
166+
152167
(
153168
Some(
154169
name @ sym::Rust
@@ -166,7 +181,7 @@ fn parse_repr<S: Stage>(
166181
Some(
167182
name @ sym::Rust
168183
| name @ sym::C
169-
| name @ sym::simd
184+
// | name @ sym::simd
170185
| name @ sym::transparent
171186
| name @ int_pat!(),
172187
),

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in
354354
355355
codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
356356
357+
codegen_ssa_type_depends_target_feature = The `{$ty}` type depends on the target feature `{$target_feature}` being enabled
358+
357359
codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}`
358360
.note = {$error}
359361
.command_note = {$command_formatted}

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,3 +1318,13 @@ pub(crate) struct NoMangleNameless {
13181318
pub span: Span,
13191319
pub definition: String,
13201320
}
1321+
1322+
#[derive(Diagnostic)]
1323+
#[diag(codegen_ssa_type_depends_target_feature)]
1324+
pub(crate) struct TypeDependsOnTargetFeature<'tcx> {
1325+
#[primary_span]
1326+
pub span: Span,
1327+
1328+
pub target_feature: String,
1329+
pub ty: Ty<'tcx>,
1330+
}

compiler/rustc_codegen_ssa/src/mir/analyze.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
88
use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind, traversal};
99
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
1010
use rustc_middle::{bug, span_bug};
11+
use rustc_span::Symbol;
1112
use tracing::debug;
1213

1314
use super::FunctionCx;
15+
use crate::errors::TypeDependsOnTargetFeature;
1416
use crate::traits::*;
1517

1618
pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
@@ -157,6 +159,30 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx>
157159
self.visit_local(place_ref.local, context, ___location);
158160
}
159161
}
162+
163+
fn check_type_abi_concerns(&self, local: mir::Local) {
164+
static IGNORED_CRATES: [&str; 3] = ["memchr", "core", "hashbrown"];
165+
166+
let ty = self.fx.mir.local_decls[local].ty;
167+
let ty = self.fx.monomorphize(ty);
168+
let ty = ty.peel_refs();
169+
170+
if let Some(abi_feature) = ty.abi_target_feature() {
171+
let tcx = self.fx.cx.tcx();
172+
let krate = tcx.crate_name(self.fx.instance.def_id().krate);
173+
if !IGNORED_CRATES.contains(&krate.as_str()) {
174+
if !self.fx.target_features.contains(&Symbol::intern(&abi_feature)) {
175+
let span = self.fx.mir.local_decls[local].source_info.span;
176+
177+
tcx.sess.dcx().emit_err(TypeDependsOnTargetFeature {
178+
span,
179+
ty,
180+
target_feature: abi_feature,
181+
});
182+
}
183+
}
184+
}
185+
}
160186
}
161187

162188
impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer<'a, 'b, 'tcx, Bx> {
@@ -189,6 +215,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer
189215
}
190216

191217
fn visit_local(&mut self, local: mir::Local, context: PlaceContext, ___location: Location) {
218+
self.check_type_abi_concerns(local);
219+
192220
match context {
193221
PlaceContext::MutatingUse(MutatingUseContext::Call) => {
194222
let call = ___location.block;

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use std::iter;
22

3+
use rustc_data_structures::fx::FxIndexSet;
34
use rustc_index::IndexVec;
45
use rustc_index::bit_set::DenseBitSet;
56
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
67
use rustc_middle::mir::{Body, Local, UnwindTerminateReason, traversal};
78
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
89
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
910
use rustc_middle::{bug, mir, span_bug};
11+
use rustc_span::Symbol;
1012
use rustc_target::callconv::{FnAbi, PassMode};
1113
use tracing::{debug, instrument};
1214

@@ -120,6 +122,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
120122

121123
/// Caller ___location propagated if this function has `#[track_caller]`.
122124
caller_location: Option<OperandRef<'tcx, Bx::Value>>,
125+
126+
target_features: FxIndexSet<Symbol>,
123127
}
124128

125129
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -176,6 +180,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
176180

177181
let mut mir = tcx.instance_mir(instance.def);
178182

183+
let mut target_features = tcx.sess.unstable_target_features.clone();
184+
if tcx.def_kind(instance.def_id()).has_codegen_attrs() {
185+
let attrs = tcx.codegen_fn_attrs(instance.def_id());
186+
target_features.extend(attrs.target_features.iter().map(|feature| feature.name));
187+
}
179188
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
180189
debug!("fn_abi: {:?}", fn_abi);
181190

@@ -228,6 +237,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
228237
debug_context,
229238
per_local_var_debug_info: None,
230239
caller_location: None,
240+
target_features,
231241
};
232242

233243
// It may seem like we should iterate over `required_consts` to ensure they all successfully

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,7 @@ impl<'tcx> TyCtxt<'tcx> {
15261526
let mut size = None;
15271527
let mut max_align: Option<Align> = None;
15281528
let mut min_pack: Option<Align> = None;
1529+
let mut target_feature: Option<u16> = None;
15291530

15301531
// Generate a deterministically-derived seed from the item's path hash
15311532
// to allow for cross-crate compilation to actually work
@@ -1553,7 +1554,10 @@ impl<'tcx> TyCtxt<'tcx> {
15531554
ReprFlags::empty()
15541555
}
15551556
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
1556-
attr::ReprSimd => ReprFlags::IS_SIMD,
1557+
attr::ReprSimd(feature) => {
1558+
target_feature = feature;
1559+
ReprFlags::IS_SIMD
1560+
}
15571561
attr::ReprInt(i) => {
15581562
size = Some(match i {
15591563
attr::IntType::SignedInt(x) => match x {
@@ -1602,7 +1606,14 @@ impl<'tcx> TyCtxt<'tcx> {
16021606
flags.insert(ReprFlags::IS_LINEAR);
16031607
}
16041608

1605-
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
1609+
ReprOptions {
1610+
int: size,
1611+
align: max_align,
1612+
pack: min_pack,
1613+
flags,
1614+
field_shuffle_seed,
1615+
target_feature,
1616+
}
16061617
}
16071618

16081619
/// Look up the name of a definition across crates. This does not look at HIR.

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,24 @@ impl<'tcx> Ty<'tcx> {
11911191
}
11921192
}
11931193

1194+
pub fn abi_target_feature(self) -> Option<String> {
1195+
self.ty_adt_def()
1196+
.map(|adt| {
1197+
adt.repr().target_feature.map(|id| {
1198+
String::from(match id {
1199+
0 => "neon",
1200+
1 => "sse",
1201+
2 => "sse2",
1202+
3 => "avx",
1203+
4 => "avx512f",
1204+
5 => "amx-avx512",
1205+
_ => panic!("Unknown ID: {id}"),
1206+
})
1207+
})
1208+
})
1209+
.flatten()
1210+
}
1211+
11941212
pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
11951213
let Adt(def, args) = self.kind() else {
11961214
bug!("`simd_size_and_type` called on invalid type")

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
19881988
continue;
19891989
}
19901990
}
1991-
ReprAttr::ReprSimd => {
1991+
ReprAttr::ReprSimd(_) => {
19921992
is_simd = true;
19931993
if target != Target::Struct {
19941994
self.dcx().emit_err(errors::AttrApplication::Struct {

0 commit comments

Comments
 (0)