diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 733a1956231b1..7b68fbc9e77b0 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1498,19 +1498,21 @@ where // Compute the size and alignment of the vector let size = elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; - let (repr, align) = match kind { + let (repr, size, align) = match kind { SimdVectorKind::Scalable(number_of_vectors) => ( BackendRepr::SimdScalableVector { element, count, number_of_vectors }, + size.checked_mul(number_of_vectors.0 as u64, dl) + .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?, dl.llvmlike_vector_align(size), ), // Non-power-of-two vectors have padding up to the next power-of-two. // If we're a packed repr, remove the padding while keeping the alignment as close // to a vector as possible. SimdVectorKind::PackedFixed if !count.is_power_of_two() => { - (BackendRepr::Memory { sized: true }, Align::max_aligned_factor(size)) + (BackendRepr::Memory { sized: true }, size, Align::max_aligned_factor(size)) } SimdVectorKind::PackedFixed | SimdVectorKind::Fixed => { - (BackendRepr::SimdVector { element, count }, dl.llvmlike_vector_align(size)) + (BackendRepr::SimdVector { element, count }, size, dl.llvmlike_vector_align(size)) } }; let size = size.align_to(align); diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index b3f7efb4d7cf7..7e1eafa10097f 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -755,7 +755,10 @@ impl<'a, Ty> FnAbi<'a, Ty> { if arg_idx.is_none() && arg.layout.size > Primitive::Pointer(AddressSpace::ZERO).size(cx) * 2 - && !matches!(arg.layout.backend_repr, BackendRepr::SimdVector { .. }) + && !matches!( + arg.layout.backend_repr, + BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } + ) { // Return values larger than 2 registers using a return area // pointer. LLVM and Cranelift disagree about how to return diff --git a/tests/ui/scalable-vectors/layout.rs b/tests/ui/scalable-vectors/layout.rs new file mode 100644 index 0000000000000..1bc2972e2f5d0 --- /dev/null +++ b/tests/ui/scalable-vectors/layout.rs @@ -0,0 +1,28 @@ +//@ only-aarch64 +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +// Tests that the computed layout size of scalable vectors is equal to +// `element size * element count * number of vectors`. Scalable vectors are of course scalable and +// so do not have a fixed size, but using this size with things like `llvm.memcpy` produces the +// correct and expected results. + +#[rustc_dump_layout(size)] +#[rustc_scalable_vector(4)] +struct ScalableFloat(f32); //~ ERROR: size: Size(16 bytes) + +#[rustc_dump_layout(size)] +#[rustc_scalable_vector(8)] +struct ScalableU8WithFewerCount(u8); //~ ERROR: size: Size(8 bytes) + +#[rustc_dump_layout(size)] +#[rustc_scalable_vector(16)] +struct ScalableU8(u8); //~ ERROR: size: Size(16 bytes) + +#[rustc_dump_layout(size)] +#[rustc_scalable_vector(16)] +struct ScalableBool(bool); //~ ERROR: size: Size(16 bytes) + +#[rustc_dump_layout(size)] +#[rustc_scalable_vector] +struct ScalableTuple(ScalableU8, ScalableU8, ScalableU8); //~ ERROR: size: Size(48 bytes) diff --git a/tests/ui/scalable-vectors/layout.stderr b/tests/ui/scalable-vectors/layout.stderr new file mode 100644 index 0000000000000..5867d8ee04b41 --- /dev/null +++ b/tests/ui/scalable-vectors/layout.stderr @@ -0,0 +1,32 @@ +error: size: Size(16 bytes) + --> $DIR/layout.rs:12:1 + | +LL | struct ScalableFloat(f32); + | ^^^^^^^^^^^^^^^^^^^^ + +error: size: Size(8 bytes) + --> $DIR/layout.rs:16:1 + | +LL | struct ScalableU8WithFewerCount(u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: size: Size(16 bytes) + --> $DIR/layout.rs:20:1 + | +LL | struct ScalableU8(u8); + | ^^^^^^^^^^^^^^^^^ + +error: size: Size(16 bytes) + --> $DIR/layout.rs:24:1 + | +LL | struct ScalableBool(bool); + | ^^^^^^^^^^^^^^^^^^^ + +error: size: Size(48 bytes) + --> $DIR/layout.rs:28:1 + | +LL | struct ScalableTuple(ScalableU8, ScalableU8, ScalableU8); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors +