Skip to content

Commit aee9788

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 d24930c commit aee9788

File tree

49 files changed

+305
-51
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

+305
-51
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
@@ -47,9 +47,11 @@ bitflags! {
4747
// If true, the type's layout can be randomized using
4848
// the seed stored in `ReprOptions.field_shuffle_seed`
4949
const RANDOMIZE_LAYOUT = 1 << 4;
50+
const IS_SCALABLE = 1 << 5;
5051
// Any of these flags being set prevent field reordering optimisation.
5152
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits()
5253
| ReprFlags::IS_SIMD.bits()
54+
| ReprFlags::IS_SCALABLE.bits()
5355
| ReprFlags::IS_LINEAR.bits();
5456
}
5557
}
@@ -90,6 +92,7 @@ pub struct ReprOptions {
9092
pub align: Option<Align>,
9193
pub pack: Option<Align>,
9294
pub flags: ReprFlags,
95+
pub scalable: Option<u32>,
9396
/// The seed to be used for randomizing a type's layout
9497
///
9598
/// Note: This could technically be a `u128` which would
@@ -106,6 +109,11 @@ impl ReprOptions {
106109
self.flags.contains(ReprFlags::IS_SIMD)
107110
}
108111

112+
#[inline]
113+
pub fn scalable(&self) -> bool {
114+
self.flags.contains(ReprFlags::IS_SCALABLE)
115+
}
116+
109117
#[inline]
110118
pub fn c(&self) -> bool {
111119
self.flags.contains(ReprFlags::IS_C)
@@ -1306,6 +1314,10 @@ pub enum Abi {
13061314
Uninhabited,
13071315
Scalar(Scalar),
13081316
ScalarPair(Scalar, Scalar),
1317+
ScalableVector {
1318+
element: Scalar,
1319+
elt: u64,
1320+
},
13091321
Vector {
13101322
element: Scalar,
13111323
count: u64,
@@ -1323,6 +1335,7 @@ impl Abi {
13231335
match *self {
13241336
Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
13251337
Abi::Aggregate { sized } => !sized,
1338+
Abi::ScalableVector { .. } => true,
13261339
}
13271340
}
13281341

@@ -1369,7 +1382,7 @@ impl Abi {
13691382
Abi::Vector { element, count } => {
13701383
cx.data_layout().vector_align(element.size(cx) * count)
13711384
}
1372-
Abi::Uninhabited | Abi::Aggregate { .. } => return None,
1385+
Abi::Uninhabited | Abi::Aggregate { .. } | Abi::ScalableVector { .. } => return None,
13731386
})
13741387
}
13751388

@@ -1390,7 +1403,7 @@ impl Abi {
13901403
// to make the size a multiple of align (e.g. for vectors of size 3).
13911404
(element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
13921405
}
1393-
Abi::Uninhabited | Abi::Aggregate { .. } => return None,
1406+
Abi::Uninhabited | Abi::Aggregate { .. } | Abi::ScalableVector { .. } => return None,
13941407
})
13951408
}
13961409

@@ -1400,6 +1413,9 @@ impl Abi {
14001413
Abi::Scalar(s) => Abi::Scalar(s.to_union()),
14011414
Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()),
14021415
Abi::Vector { element, count } => Abi::Vector { element: element.to_union(), count },
1416+
Abi::ScalableVector { element, elt } => {
1417+
Abi::ScalableVector { element: element.to_union(), elt }
1418+
}
14031419
Abi::Uninhabited | Abi::Aggregate { .. } => Abi::Aggregate { sized: true },
14041420
}
14051421
}
@@ -1686,6 +1702,11 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
16861702
self.is_sized() && self.size.bytes() == 0 && self.align.abi.bytes() == 1
16871703
}
16881704

1705+
/// Returns true if the size of the type is only known at runtime.
1706+
pub fn is_runtime_sized(&self) -> bool {
1707+
matches!(self.abi, Abi::ScalableVector { .. })
1708+
}
1709+
16891710
/// Returns `true` if the type is a ZST and not unsized.
16901711
///
16911712
/// Note that this does *not* imply that the type is irrelevant for layout! It can still have
@@ -1695,6 +1716,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
16951716
Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
16961717
Abi::Uninhabited => self.size.bytes() == 0,
16971718
Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
1719+
Abi::ScalableVector { .. } => false,
16981720
}
16991721
}
17001722

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
@@ -918,6 +918,7 @@ pub enum ReprAttr {
918918
ReprSimd,
919919
ReprTransparent,
920920
ReprAlign(Align),
921+
ReprScalable(u32),
921922
}
922923

923924
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
@@ -973,6 +974,13 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
973974
recognised = true;
974975
None
975976
}
977+
sym::scalable => {
978+
sess.dcx().emit_err(session_diagnostics::ScalableAttrMissingN {
979+
span: item.span(),
980+
});
981+
recognised = true;
982+
None
983+
}
976984
name => int_type_of_word(name).map(ReprInt),
977985
};
978986

@@ -1001,6 +1009,12 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
10011009
literal_error = Some(message)
10021010
}
10031011
};
1012+
} else if name == sym::scalable {
1013+
recognised = true;
1014+
match parse_scalable(&value.kind) {
1015+
Ok(literal) => acc.push(ReprScalable(literal)),
1016+
Err(message) => literal_error = Some(message),
1017+
};
10041018
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
10051019
|| int_type_of_word(name).is_some()
10061020
{
@@ -1020,7 +1034,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
10201034
} else if let Some(meta_item) = item.meta_item() {
10211035
match &meta_item.kind {
10221036
MetaItemKind::NameValue(value) => {
1023-
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
1037+
if meta_item.has_name(sym::align)
1038+
|| meta_item.has_name(sym::packed)
1039+
|| meta_item.has_name(sym::scalable)
1040+
{
10241041
let name = meta_item.name_or_empty().to_ident_string();
10251042
recognised = true;
10261043
sess.dcx().emit_err(session_diagnostics::IncorrectReprFormatGeneric {
@@ -1239,3 +1256,11 @@ pub fn parse_confusables(attr: &Attribute) -> Option<Vec<Symbol>> {
12391256

12401257
return Some(candidates);
12411258
}
1259+
1260+
pub fn parse_scalable(node: &ast::LitKind) -> Result<u32, &'static str> {
1261+
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
1262+
(literal.get()).try_into().map_err(|_| "integer too large")
1263+
} else {
1264+
Err("not an unsuffixed integer")
1265+
}
1266+
}

compiler/rustc_attr/src/session_diagnostics.rs

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

compiler/rustc_borrowck/src/type_check/mod.rs

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

525-
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
525+
// The Copy trait isn't implemented for scalable SIMD types.
526+
// These types live somewhere between `Sized` and `Unsize`.
527+
// The bounds on `Copy` disallow the trait from being
528+
// implemented for them. As a result of this no bounds from
529+
// `Copy` apply for the type, therefore, skipping this check
530+
// should be perfectly legal.
531+
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context
532+
&& !place_ty.ty.is_scalable_simd()
533+
{
526534
let tcx = self.tcx();
527535
let trait_ref = ty::TraitRef::new(
528536
tcx,
@@ -1804,11 +1812,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18041812
// expressions evaluate through `as_temp` or `into` a return
18051813
// slot or local, so to find all unsized rvalues it is enough
18061814
// to check all temps, return slots and locals.
1807-
if self.reported_errors.replace((ty, span)).is_none() {
1808-
// While this is located in `nll::typeck` this error is not
1809-
// an NLL error, it's a required check to prevent creation
1810-
// of unsized rvalues in a call expression.
1811-
self.tcx().dcx().emit_err(MoveUnsized { ty, span });
1815+
if !ty.is_scalable_simd() {
1816+
if self.reported_errors.replace((ty, span)).is_none() {
1817+
// While this is located in `nll::typeck` this error is not
1818+
// an NLL error, it's a required check to prevent creation
1819+
// of unsized rvalues in a call expression.
1820+
self.tcx().dcx().emit_err(MoveUnsized { ty, span });
1821+
}
18121822
}
18131823
}
18141824
}

compiler/rustc_codegen_gcc/src/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ impl GccType for Reg {
8787
_ => bug!("unsupported float: {:?}", self),
8888
},
8989
RegKind::Vector => unimplemented!(), //cx.type_vector(cx.type_i8(), self.size.bytes()),
90+
RegKind::ScalableVector => unimplemented!(),
9091
}
9192
}
9293
}

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

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

compiler/rustc_codegen_gcc/src/type_of.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
8181
false,
8282
);
8383
}
84+
Abi::ScalableVector { .. } => todo!(),
8485
Abi::Uninhabited | Abi::Aggregate { .. } => {}
8586
}
8687

@@ -175,15 +176,19 @@ pub trait LayoutGccExt<'tcx> {
175176
impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
176177
fn is_gcc_immediate(&self) -> bool {
177178
match self.abi {
178-
Abi::Scalar(_) | Abi::Vector { .. } => true,
179+
Abi::Scalar(_) | Abi::Vector { .. } | Abi::ScalableVector { .. } => true,
179180
Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
180181
}
181182
}
182183

183184
fn is_gcc_scalar_pair(&self) -> bool {
184185
match self.abi {
185186
Abi::ScalarPair(..) => true,
186-
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false,
187+
Abi::Uninhabited
188+
| Abi::Scalar(_)
189+
| Abi::Vector { .. }
190+
| Abi::ScalableVector { .. }
191+
| Abi::Aggregate { .. } => false,
187192
}
188193
}
189194

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ impl LlvmType for Reg {
126126
_ => bug!("unsupported float: {:?}", self),
127127
},
128128
RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
129+
RegKind::ScalableVector => cx.type_scalable_vector(cx.type_i8(), 16),
129130
}
130131
}
131132
}

0 commit comments

Comments
 (0)