Skip to content

Commit ea49987

Browse files
committed
Prototype of scalable vectors
The representation of the element type has been changed to be a slice rather than a zero length array. Two feature gates are now required in core_arch unsized fn params and unsized locals. This still leaves unsized return types being an issue. For this we are currently bypassing some of the `Sized` trait checking to pass when the type is scalable simd. This still leaves the copy issue. For that we have marked scalable simd types as trivally pure clone copy. We have still had to remove some trait checks for the copy trait with this though as they are still performed in certain situations. The implementation of `transmute` is also an issue for us. For this a new SIMD intrinsic has been created simd_reinterpret which performs a transmute on SIMD vectors. A few intrinsics need to be able to produce an LLVM `undef` this intrinsic will also produce that when given a zero sized input.
1 parent 5dbaafd commit ea49987

File tree

49 files changed

+296
-47
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+296
-47
lines changed

compiler/rustc_abi/src/layout.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ where
383383
hide_niches(b);
384384
}
385385
Abi::Vector { element, count: _ } => hide_niches(element),
386+
Abi::ScalableVector { element, .. } => hide_niches(element),
386387
Abi::Aggregate { sized: _ } => {}
387388
}
388389
st.largest_niche = None;

compiler/rustc_abi/src/lib.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ bitflags! {
4343
// If true, the type's layout can be randomized using
4444
// the seed stored in `ReprOptions.field_shuffle_seed`
4545
const RANDOMIZE_LAYOUT = 1 << 4;
46+
const IS_SCALABLE = 1 << 5;
4647
// Any of these flags being set prevent field reordering optimisation.
4748
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits()
4849
| ReprFlags::IS_SIMD.bits()
50+
| ReprFlags::IS_SCALABLE.bits()
4951
| ReprFlags::IS_LINEAR.bits();
5052
}
5153
}
@@ -86,6 +88,7 @@ pub struct ReprOptions {
8688
pub align: Option<Align>,
8789
pub pack: Option<Align>,
8890
pub flags: ReprFlags,
91+
pub scalable: Option<u32>,
8992
/// The seed to be used for randomizing a type's layout
9093
///
9194
/// Note: This could technically be a `u128` which would
@@ -102,6 +105,11 @@ impl ReprOptions {
102105
self.flags.contains(ReprFlags::IS_SIMD)
103106
}
104107

108+
#[inline]
109+
pub fn scalable(&self) -> bool {
110+
self.flags.contains(ReprFlags::IS_SCALABLE)
111+
}
112+
105113
#[inline]
106114
pub fn c(&self) -> bool {
107115
self.flags.contains(ReprFlags::IS_C)
@@ -1266,6 +1274,10 @@ pub enum Abi {
12661274
Uninhabited,
12671275
Scalar(Scalar),
12681276
ScalarPair(Scalar, Scalar),
1277+
ScalableVector {
1278+
element: Scalar,
1279+
elt: u64,
1280+
},
12691281
Vector {
12701282
element: Scalar,
12711283
count: u64,
@@ -1283,6 +1295,7 @@ impl Abi {
12831295
match *self {
12841296
Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
12851297
Abi::Aggregate { sized } => !sized,
1298+
Abi::ScalableVector { .. } => true,
12861299
}
12871300
}
12881301

@@ -1329,7 +1342,7 @@ impl Abi {
13291342
Abi::Vector { element, count } => {
13301343
cx.data_layout().vector_align(element.size(cx) * count)
13311344
}
1332-
Abi::Uninhabited | Abi::Aggregate { .. } => return None,
1345+
Abi::Uninhabited | Abi::Aggregate { .. } | Abi::ScalableVector { .. } => return None,
13331346
})
13341347
}
13351348

@@ -1350,7 +1363,7 @@ impl Abi {
13501363
// to make the size a multiple of align (e.g. for vectors of size 3).
13511364
(element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
13521365
}
1353-
Abi::Uninhabited | Abi::Aggregate { .. } => return None,
1366+
Abi::Uninhabited | Abi::Aggregate { .. } | Abi::ScalableVector { .. } => return None,
13541367
})
13551368
}
13561369

@@ -1360,6 +1373,9 @@ impl Abi {
13601373
Abi::Scalar(s) => Abi::Scalar(s.to_union()),
13611374
Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),
13621375
Abi::Vector { element, count } => Abi::Vector { element: element.to_union(), count },
1376+
Abi::ScalableVector { element, elt } => {
1377+
Abi::ScalableVector { element: element.to_union(), elt }
1378+
}
13631379
Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true },
13641380
}
13651381
}
@@ -1646,6 +1662,11 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
16461662
self.is_sized() && self.size.bytes() == 0 && self.align.abi.bytes() == 1
16471663
}
16481664

1665+
/// Returns true if the size of the type is only known at runtime.
1666+
pub fn is_runtime_sized(&self) -> bool {
1667+
matches!(self.abi, Abi::ScalableVector { .. })
1668+
}
1669+
16491670
/// Returns `true` if the type is a ZST and not unsized.
16501671
///
16511672
/// Note that this does *not* imply that the type is irrelevant for layout! It can still have
@@ -1655,6 +1676,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
16551676
Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
16561677
Abi::Uninhabited => self.size.bytes() == 0,
16571678
Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
1679+
Abi::ScalableVector { .. } => false,
16581680
}
16591681
}
16601682

compiler/rustc_attr/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ attr_rustc_allowed_unstable_pairing =
9494
attr_rustc_promotable_pairing =
9595
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
9696
97+
attr_scalable_missing_n =
98+
invalid `scalable(num)` attribute: `scalable` needs an argument
99+
.suggestion = supply an argument here
97100
attr_soft_no_args =
98101
`soft` should not have any arguments
99102

compiler/rustc_attr/src/builtin.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,7 @@ pub enum ReprAttr {
924924
ReprSimd,
925925
ReprTransparent,
926926
ReprAlign(Align),
927+
ReprScalable(u32),
927928
}
928929

929930
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
@@ -979,6 +980,13 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
979980
recognised = true;
980981
None
981982
}
983+
sym::scalable => {
984+
sess.dcx().emit_err(session_diagnostics::ScalableAttrMissingN {
985+
span: item.span(),
986+
});
987+
recognised = true;
988+
None
989+
}
982990
name => int_type_of_word(name).map(ReprInt),
983991
};
984992

@@ -1007,6 +1015,12 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
10071015
literal_error = Some(message)
10081016
}
10091017
};
1018+
} else if name == sym::scalable {
1019+
recognised = true;
1020+
match parse_scalable(&value.kind) {
1021+
Ok(literal) => acc.push(ReprScalable(literal)),
1022+
Err(message) => literal_error = Some(message),
1023+
};
10101024
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
10111025
|| int_type_of_word(name).is_some()
10121026
{
@@ -1026,7 +1040,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
10261040
} else if let Some(meta_item) = item.meta_item() {
10271041
match &meta_item.kind {
10281042
MetaItemKind::NameValue(value) => {
1029-
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
1043+
if meta_item.has_name(sym::align)
1044+
|| meta_item.has_name(sym::packed)
1045+
|| meta_item.has_name(sym::scalable)
1046+
{
10301047
let name = meta_item.name_or_empty().to_ident_string();
10311048
recognised = true;
10321049
sess.dcx().emit_err(session_diagnostics::IncorrectReprFormatGeneric {
@@ -1245,3 +1262,11 @@ pub fn parse_confusables(attr: &Attribute) -> Option<Vec<Symbol>> {
12451262

12461263
return Some(candidates);
12471264
}
1265+
1266+
pub fn parse_scalable(node: &ast::LitKind) -> Result<u32, &'static str> {
1267+
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
1268+
(literal.get()).try_into().map_err(|_| "integer too large")
1269+
} else {
1270+
Err("not an unsuffixed integer")
1271+
}
1272+
}

compiler/rustc_attr/src/session_diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,3 +400,11 @@ pub(crate) struct UnknownVersionLiteral {
400400
#[primary_span]
401401
pub span: Span,
402402
}
403+
404+
#[derive(Diagnostic)]
405+
#[diag(attr_scalable_missing_n, code = E0798)]
406+
pub(crate) struct ScalableAttrMissingN {
407+
#[primary_span]
408+
#[suggestion(applicability = "has-placeholders", code = "scalable(...)")]
409+
pub span: Span,
410+
}

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,15 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
531531
place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
532532
}
533533

534-
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
534+
// The Copy trait isn't implemented for scalable SIMD types.
535+
// These types live somewhere between `Sized` and `Unsize`.
536+
// The bounds on `Copy` disallow the trait from being
537+
// implemented for them. As a result of this no bounds from
538+
// `Copy` apply for the type, therefore, skipping this check
539+
// should be perfectly legal.
540+
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context
541+
&& !place_ty.ty.is_scalable_simd()
542+
{
535543
let tcx = self.tcx();
536544
let trait_ref =
537545
ty::TraitRef::from_lang_item(tcx, LangItem::Copy, self.last_span, [place_ty.ty]);
@@ -1865,11 +1873,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18651873
// expressions evaluate through `as_temp` or `into` a return
18661874
// slot or local, so to find all unsized rvalues it is enough
18671875
// to check all temps, return slots and locals.
1868-
if self.reported_errors.replace((ty, span)).is_none() {
1869-
// While this is located in `nll::typeck` this error is not
1870-
// an NLL error, it's a required check to prevent creation
1871-
// of unsized rvalues in a call expression.
1872-
self.tcx().dcx().emit_err(MoveUnsized { ty, span });
1876+
if !ty.is_scalable_simd() {
1877+
if self.reported_errors.replace((ty, span)).is_none() {
1878+
// While this is located in `nll::typeck` this error is not
1879+
// an NLL error, it's a required check to prevent creation
1880+
// of unsized rvalues in a call expression.
1881+
self.tcx().dcx().emit_err(MoveUnsized { ty, span });
1882+
}
18731883
}
18741884
}
18751885
}

compiler/rustc_codegen_gcc/src/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl GccType for Reg {
9090
_ => bug!("unsupported float: {:?}", self),
9191
},
9292
RegKind::Vector => unimplemented!(), //cx.type_vector(cx.type_i8(), self.size.bytes()),
93+
RegKind::ScalableVector => unimplemented!(),
9394
}
9495
}
9596
}

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
296296
let layout = self.layout_of(tp_ty).layout;
297297
let _use_integer_compare = match layout.abi() {
298298
Scalar(_) | ScalarPair(_, _) => true,
299-
Uninhabited | Vector { .. } => false,
299+
Uninhabited | Vector { .. } | ScalableVector { .. } => false,
300300
Aggregate { .. } => {
301301
// For rusty ABIs, small aggregates are actually passed
302302
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),

compiler/rustc_codegen_gcc/src/type_of.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
8787
false,
8888
);
8989
}
90+
Abi::ScalableVector { .. } => todo!(),
9091
Abi::Uninhabited | Abi::Aggregate { .. } => {}
9192
}
9293

@@ -181,15 +182,15 @@ pub trait LayoutGccExt<'tcx> {
181182
impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
182183
fn is_gcc_immediate(&self) -> bool {
183184
match self.abi {
184-
Abi::Scalar(_) | Abi::Vector { .. } => true,
185+
Abi::Scalar(_) | Abi::Vector { .. } | Abi::ScalableVector { .. } => true,
185186
Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
186187
}
187188
}
188189

189190
fn is_gcc_scalar_pair(&self) -> bool {
190191
match self.abi {
191192
Abi::ScalarPair(..) => true,
192-
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false,
193+
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::ScalableVector { .. } | Abi::Aggregate { .. } => false,
193194
}
194195
}
195196

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ impl LlvmType for Reg {
123123
_ => bug!("unsupported float: {:?}", self),
124124
},
125125
RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
126+
RegKind::ScalableVector => cx.type_scalable_vector(cx.type_i8(), 16),
126127
}
127128
}
128129
}

0 commit comments

Comments
 (0)