Skip to content

Commit c3ce478

Browse files
attr: parse rustc_scalable_vector(N)
Extend parsing of `ReprOptions` with `rustc_scalable_vector(N)` which optionally accepts a single literal integral value - the base multiple of lanes that are in a scalable vector. Can only be applied to structs. Co-authored-by: Jamie Cunliffe <[email protected]>
1 parent a153133 commit c3ce478

File tree

16 files changed

+656
-12
lines changed

16 files changed

+656
-12
lines changed

compiler/rustc_abi/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,11 @@ bitflags! {
9393
// Other flags can still inhibit reordering and thus randomization.
9494
// The seed stored in `ReprOptions.field_shuffle_seed`.
9595
const RANDOMIZE_LAYOUT = 1 << 4;
96+
const IS_SCALABLE = 1 << 5;
9697
// Any of these flags being set prevent field reordering optimisation.
9798
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
9899
| ReprFlags::IS_SIMD.bits()
100+
| ReprFlags::IS_SCALABLE.bits()
99101
| ReprFlags::IS_LINEAR.bits();
100102
const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits();
101103
}
@@ -132,6 +134,19 @@ impl IntegerType {
132134
}
133135
}
134136

137+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
138+
#[cfg_attr(
139+
feature = "nightly",
140+
derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
141+
)]
142+
pub enum ScalableElt {
143+
/// `N` in `rustc_scalable_vector(N)` - the element count of the scalable vector
144+
ElementCount(u128),
145+
/// `rustc_scalable_vector` w/out `N`, used for tuple types of scalable vectors that only
146+
/// contain other scalable vectors
147+
Container,
148+
}
149+
135150
/// Represents the repr options provided by the user.
136151
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
137152
#[cfg_attr(
@@ -143,6 +158,8 @@ pub struct ReprOptions {
143158
pub align: Option<Align>,
144159
pub pack: Option<Align>,
145160
pub flags: ReprFlags,
161+
/// `#[rustc_scalable_vector]`
162+
pub scalable: Option<ScalableElt>,
146163
/// The seed to be used for randomizing a type's layout
147164
///
148165
/// Note: This could technically be a `u128` which would
@@ -159,6 +176,11 @@ impl ReprOptions {
159176
self.flags.contains(ReprFlags::IS_SIMD)
160177
}
161178

179+
#[inline]
180+
pub fn scalable(&self) -> bool {
181+
self.flags.contains(ReprFlags::IS_SCALABLE)
182+
}
183+
162184
#[inline]
163185
pub fn c(&self) -> bool {
164186
self.flags.contains(ReprFlags::IS_C)

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,26 @@ impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
5151
Some(AttributeKind::RustcObjectLifetimeDefault)
5252
}
5353
}
54+
55+
pub(crate) struct RustcScalableVectorParser;
56+
57+
impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
58+
const PATH: &[rustc_span::Symbol] = &[sym::rustc_scalable_vector];
59+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
60+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
61+
const TEMPLATE: AttributeTemplate = template!(Word, List: "count");
62+
63+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
64+
if args.no_args().is_ok() {
65+
return Some(AttributeKind::RustcScalableVector {
66+
element_count: None,
67+
span: cx.attr_span,
68+
});
69+
}
70+
71+
parse_single_integer(cx, args).map(|n| AttributeKind::RustcScalableVector {
72+
element_count: Some(n),
73+
span: cx.attr_span,
74+
})
75+
}
76+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::attributes::proc_macro_attrs::{
4444
use crate::attributes::repr::{AlignParser, ReprParser};
4545
use crate::attributes::rustc_internal::{
4646
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
47-
RustcObjectLifetimeDefaultParser,
47+
RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
4848
};
4949
use crate::attributes::semantics::MayDangleParser;
5050
use crate::attributes::stability::{
@@ -174,6 +174,7 @@ attribute_parsers!(
174174
Single<RustcLayoutScalarValidRangeEnd>,
175175
Single<RustcLayoutScalarValidRangeStart>,
176176
Single<RustcObjectLifetimeDefaultParser>,
177+
Single<RustcScalableVectorParser>,
177178
Single<ShouldPanicParser>,
178179
Single<SkipDuringMethodDispatchParser>,
179180
Single<TransparencyParser>,

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
11271127
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
11281128
"`#[rustc_force_inline]` forces a free function to be inlined"
11291129
),
1130+
rustc_attr!(
1131+
rustc_scalable_vector, Normal, template!(List: "count"), WarnFollowing, EncodeCrossCrate::Yes,
1132+
"`#[rustc_scalable_vector]` defines a scalable vector type"
1133+
),
11301134

11311135
// ==========================================================================
11321136
// Internal attributes, Testing:

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,14 @@ pub enum AttributeKind {
436436
/// Represents `#[rustc_object_lifetime_default]`.
437437
RustcObjectLifetimeDefault,
438438

439+
/// Represents `#[rustc_scalable_vector(N)]`
440+
RustcScalableVector {
441+
/// The base multiple of lanes that are in a scalable vector, if provided. `element_count`
442+
/// is not provided for representing tuple types.
443+
element_count: Option<u128>,
444+
span: Span,
445+
},
446+
439447
/// Represents `#[should_panic]`
440448
ShouldPanic { reason: Option<Symbol>, span: Span },
441449

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ impl AttributeKind {
7070
RustcLayoutScalarValidRangeEnd(..) => Yes,
7171
RustcLayoutScalarValidRangeStart(..) => Yes,
7272
RustcObjectLifetimeDefault => No,
73+
RustcScalableVector { .. } => Yes,
7374
ShouldPanic { .. } => No,
7475
SkipDuringMethodDispatch { .. } => No,
7576
SpecializationTrait(..) => No,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ pub use assoc::*;
2424
pub use generic_args::{GenericArgKind, TermKind, *};
2525
pub use generics::*;
2626
pub use intrinsic::IntrinsicDef;
27-
use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
27+
use rustc_abi::{
28+
Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, ScalableElt, VariantIdx,
29+
};
2830
use rustc_ast::node_id::NodeMap;
2931
pub use rustc_ast_ir::{Movability, Mutability, try_visit};
3032
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
@@ -1469,9 +1471,20 @@ impl<'tcx> TyCtxt<'tcx> {
14691471
field_shuffle_seed ^= user_seed;
14701472
}
14711473

1472-
if let Some(reprs) =
1473-
find_attr!(self.get_all_attrs(did), AttributeKind::Repr { reprs, .. } => reprs)
1474-
{
1474+
let attrs = self.get_all_attrs(did);
1475+
let elt = find_attr!(
1476+
attrs,
1477+
AttributeKind::RustcScalableVector { element_count, .. } => element_count
1478+
)
1479+
.map(|elt| match elt {
1480+
Some(n) => ScalableElt::ElementCount(*n),
1481+
None => ScalableElt::Container,
1482+
});
1483+
if elt.is_some() {
1484+
flags.insert(ReprFlags::IS_SCALABLE);
1485+
}
1486+
1487+
if let Some(reprs) = find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs) {
14751488
for (r, _) in reprs {
14761489
flags.insert(match *r {
14771490
attr::ReprRust => ReprFlags::empty(),
@@ -1530,7 +1543,14 @@ impl<'tcx> TyCtxt<'tcx> {
15301543
flags.insert(ReprFlags::IS_LINEAR);
15311544
}
15321545

1533-
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
1546+
ReprOptions {
1547+
int: size,
1548+
align: max_align,
1549+
pack: min_pack,
1550+
flags,
1551+
field_shuffle_seed,
1552+
scalable: elt,
1553+
}
15341554
}
15351555

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

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,14 @@ impl<'tcx> Ty<'tcx> {
11961196
}
11971197
}
11981198

1199+
#[inline]
1200+
pub fn is_scalable_vector(self) -> bool {
1201+
match self.kind() {
1202+
Adt(def, _) => def.repr().scalable(),
1203+
_ => false,
1204+
}
1205+
}
1206+
11991207
pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
12001208
match self.kind() {
12011209
Array(ty, _) | Slice(ty) => *ty,

compiler/rustc_passes/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,10 @@ passes_rustc_layout_scalar_valid_range_not_struct =
631631
attribute should be applied to a struct
632632
.label = not a struct
633633
634+
passes_rustc_scalable_vector =
635+
attribute should be applied to a struct
636+
.label = not a struct
637+
634638
passes_rustc_legacy_const_generics_index =
635639
#[rustc_legacy_const_generics] must have one index for each generic parameter
636640
.label = generic parameters

compiler/rustc_passes/src/check_attr.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
271271
AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span)
272272
| AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span),
273273
) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target),
274+
Attribute::Parsed(AttributeKind::RustcScalableVector {
275+
span: attr_span, ..
276+
}) => self.check_rustc_scalable_vector(*attr_span, span, target),
274277
Attribute::Parsed(AttributeKind::ExportStable) => {
275278
// handled in `check_export`
276279
}
@@ -1776,6 +1779,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
17761779
}
17771780
}
17781781

1782+
fn check_rustc_scalable_vector(&self, attr_span: Span, span: Span, target: Target) {
1783+
if target != Target::Struct {
1784+
self.dcx().emit_err(errors::RustcScalableVector { attr_span, span });
1785+
return;
1786+
}
1787+
}
1788+
17791789
/// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
17801790
fn check_rustc_legacy_const_generics(
17811791
&self,

0 commit comments

Comments
 (0)