Skip to content

Commit eb885d1

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 <Jamie.Cunliffe@arm.com>
1 parent d5525a7 commit eb885d1

File tree

16 files changed

+620
-9
lines changed

16 files changed

+620
-9
lines changed

compiler/rustc_abi/src/lib.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,11 @@ bitflags! {
9696
/// If true, the type is always passed indirectly by non-Rustic ABIs.
9797
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
9898
const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS = 1 << 5;
99-
/// Any of these flags being set prevent field reordering optimisation.
100-
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
99+
const IS_SCALABLE = 1 << 6;
100+
// Any of these flags being set prevent field reordering optimisation.
101+
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
101102
| ReprFlags::IS_SIMD.bits()
103+
| ReprFlags::IS_SCALABLE.bits()
102104
| ReprFlags::IS_LINEAR.bits();
103105
const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits();
104106
}
@@ -135,6 +137,19 @@ impl IntegerType {
135137
}
136138
}
137139

140+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
141+
#[cfg_attr(
142+
feature = "nightly",
143+
derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic)
144+
)]
145+
pub enum ScalableElt {
146+
/// `N` in `rustc_scalable_vector(N)` - the element count of the scalable vector
147+
ElementCount(u16),
148+
/// `rustc_scalable_vector` w/out `N`, used for tuple types of scalable vectors that only
149+
/// contain other scalable vectors
150+
Container,
151+
}
152+
138153
/// Represents the repr options provided by the user.
139154
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
140155
#[cfg_attr(
@@ -146,6 +161,8 @@ pub struct ReprOptions {
146161
pub align: Option<Align>,
147162
pub pack: Option<Align>,
148163
pub flags: ReprFlags,
164+
/// `#[rustc_scalable_vector]`
165+
pub scalable: Option<ScalableElt>,
149166
/// The seed to be used for randomizing a type's layout
150167
///
151168
/// Note: This could technically be a `u128` which would
@@ -162,6 +179,11 @@ impl ReprOptions {
162179
self.flags.contains(ReprFlags::IS_SIMD)
163180
}
164181

182+
#[inline]
183+
pub fn scalable(&self) -> bool {
184+
self.flags.contains(ReprFlags::IS_SCALABLE)
185+
}
186+
165187
#[inline]
166188
pub fn c(&self) -> bool {
167189
self.flags.contains(ReprFlags::IS_C)

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ attr_parsing_rustc_allowed_unstable_pairing =
189189
attr_parsing_rustc_promotable_pairing =
190190
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
191191
192+
attr_parsing_rustc_scalable_vector_count_out_of_range = element count in `rustc_scalable_vector` is too large: `{$n}`
193+
.note = the value may not exceed `u16::MAX`
194+
192195
attr_parsing_soft_no_args =
193196
`soft` should not have any arguments
194197

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::prelude::*;
22
use super::util::parse_single_integer;
3+
use crate::session_diagnostics::RustcScalableVectorCountOutOfRange;
34

45
pub(crate) struct RustcMainParser;
56

@@ -76,3 +77,29 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser
7677
Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))
7778
}
7879
}
80+
81+
pub(crate) struct RustcScalableVectorParser;
82+
83+
impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
84+
const PATH: &[rustc_span::Symbol] = &[sym::rustc_scalable_vector];
85+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
86+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
87+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
88+
const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);
89+
90+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
91+
if args.no_args().is_ok() {
92+
return Some(AttributeKind::RustcScalableVector {
93+
element_count: None,
94+
span: cx.attr_span,
95+
});
96+
}
97+
98+
let n = parse_single_integer(cx, args)?;
99+
let Ok(n) = n.try_into() else {
100+
cx.emit_err(RustcScalableVectorCountOutOfRange { span: cx.attr_span, n });
101+
return None;
102+
};
103+
Some(AttributeKind::RustcScalableVector { element_count: Some(n), span: cx.attr_span })
104+
}
105+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ use crate::attributes::prototype::CustomMirParser;
5959
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
6060
use crate::attributes::rustc_internal::{
6161
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser,
62-
RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser,
62+
RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
63+
RustcSimdMonomorphizeLaneLimitParser,
6364
};
6465
use crate::attributes::semantics::MayDangleParser;
6566
use crate::attributes::stability::{
@@ -207,6 +208,7 @@ attribute_parsers!(
207208
Single<RustcLayoutScalarValidRangeEndParser>,
208209
Single<RustcLayoutScalarValidRangeStartParser>,
209210
Single<RustcObjectLifetimeDefaultParser>,
211+
Single<RustcScalableVectorParser>,
210212
Single<RustcSimdMonomorphizeLaneLimitParser>,
211213
Single<SanitizeParser>,
212214
Single<ShouldPanicParser>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,15 @@ pub(crate) struct LinkOrdinalOutOfRange {
547547
pub ordinal: u128,
548548
}
549549

550+
#[derive(Diagnostic)]
551+
#[diag(attr_parsing_rustc_scalable_vector_count_out_of_range)]
552+
#[note]
553+
pub(crate) struct RustcScalableVectorCountOutOfRange {
554+
#[primary_span]
555+
pub span: Span,
556+
pub n: u128,
557+
}
558+
550559
pub(crate) enum AttributeParseErrorReason<'a> {
551560
ExpectedNoArgs,
552561
ExpectedStringLiteral {

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
14171417
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
14181418
"`#[rustc_force_inline]` forces a free function to be inlined"
14191419
),
1420+
rustc_attr!(
1421+
rustc_scalable_vector, Normal, template!(List: &["count"]), WarnFollowing, EncodeCrossCrate::Yes,
1422+
"`#[rustc_scalable_vector]` defines a scalable vector type"
1423+
),
14201424

14211425
// ==========================================================================
14221426
// 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
@@ -717,6 +717,14 @@ pub enum AttributeKind {
717717
/// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]`
718718
RustcPassIndirectlyInNonRusticAbis(Span),
719719

720+
/// Represents `#[rustc_scalable_vector(N)]`
721+
RustcScalableVector {
722+
/// The base multiple of lanes that are in a scalable vector, if provided. `element_count`
723+
/// is not provided for representing tuple types.
724+
element_count: Option<u16>,
725+
span: Span,
726+
},
727+
720728
/// Represents `#[rustc_should_not_be_called_on_const_items]`
721729
RustcShouldNotBeCalledOnConstItems(Span),
722730

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl AttributeKind {
9191
RustcMain => No,
9292
RustcObjectLifetimeDefault => No,
9393
RustcPassIndirectlyInNonRusticAbis(..) => No,
94+
RustcScalableVector { .. } => Yes,
9495
RustcShouldNotBeCalledOnConstItems(..) => Yes,
9596
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
9697
Sanitize { .. } => No,

compiler/rustc_hir/src/attrs/pretty_printing.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::num::NonZero;
2+
use std::ops::Deref;
23

34
use rustc_abi::Align;
45
use rustc_ast::token::CommentKind;
@@ -35,6 +36,15 @@ impl<T: PrintAttribute> PrintAttribute for &T {
3536
T::print_attribute(self, p)
3637
}
3738
}
39+
impl<T: PrintAttribute> PrintAttribute for Box<T> {
40+
fn should_render(&self) -> bool {
41+
self.deref().should_render()
42+
}
43+
44+
fn print_attribute(&self, p: &mut Printer) {
45+
T::print_attribute(self.deref(), p)
46+
}
47+
}
3848
impl<T: PrintAttribute> PrintAttribute for Option<T> {
3949
fn should_render(&self) -> bool {
4050
self.as_ref().is_some_and(|x| x.should_render())

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 22 additions & 2 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::expand::typetree::{FncTree, Kind, Type, TypeTree};
2931
use rustc_ast::node_id::NodeMap;
3032
pub use rustc_ast_ir::{Movability, Mutability, try_visit};
@@ -1513,6 +1515,17 @@ impl<'tcx> TyCtxt<'tcx> {
15131515
}
15141516

15151517
let attributes = self.get_all_attrs(did);
1518+
let elt = find_attr!(
1519+
attributes,
1520+
AttributeKind::RustcScalableVector { element_count, .. } => element_count
1521+
)
1522+
.map(|elt| match elt {
1523+
Some(n) => ScalableElt::ElementCount(*n),
1524+
None => ScalableElt::Container,
1525+
});
1526+
if elt.is_some() {
1527+
flags.insert(ReprFlags::IS_SCALABLE);
1528+
}
15161529
if let Some(reprs) = find_attr!(attributes, AttributeKind::Repr { reprs, .. } => reprs) {
15171530
for (r, _) in reprs {
15181531
flags.insert(match *r {
@@ -1577,7 +1590,14 @@ impl<'tcx> TyCtxt<'tcx> {
15771590
flags.insert(ReprFlags::PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS);
15781591
}
15791592

1580-
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
1593+
ReprOptions {
1594+
int: size,
1595+
align: max_align,
1596+
pack: min_pack,
1597+
flags,
1598+
field_shuffle_seed,
1599+
scalable: elt,
1600+
}
15811601
}
15821602

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

0 commit comments

Comments
 (0)