Skip to content

Commit dace184

Browse files
committed
Allow SVE types to be taken by reference.
Ensures that an SVE type can have a reference taken to it. This currently emits a `dereferenceable` attribute for the ptr using the element size as the number of bytes. While not perfect this is correct as a vector will always have a least one primitive.
1 parent c4f8a92 commit dace184

File tree

8 files changed

+71
-12
lines changed

8 files changed

+71
-12
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,10 +538,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
538538
}
539539
}
540540

541-
assert_eq!(
542-
place.val.llextra.is_some(),
543-
place.layout.is_unsized() && !place.layout.is_runtime_sized()
544-
);
541+
if !place.layout.is_runtime_sized() {
542+
assert_eq!(place.val.llextra.is_some(), place.layout.is_unsized());
543+
}
545544

546545
if place.layout.is_zst() {
547546
return OperandRef::zero_sized(place.layout);

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
248248

249249
if memory_locals.contains(local) {
250250
debug!("alloc: {:?} -> place", local);
251-
if layout.is_unsized() {
251+
if layout.is_unsized() && !layout.is_runtime_sized() {
252252
LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut start_bx, layout))
253253
} else {
254254
LocalRef::Place(PlaceRef::alloca(&mut start_bx, layout))

compiler/rustc_codegen_ssa/src/traits/type_.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
8787

8888
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
8989
let param_env = ty::ParamEnv::reveal_all();
90-
if ty.is_sized(self.tcx(), param_env) {
90+
if ty.is_sized(self.tcx(), param_env) || ty.is_scalable_simd() {
9191
return false;
9292
}
9393

compiler/rustc_mir_build/src/build/expr/as_operand.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
166166
let ty = expr.ty;
167167
let param_env = this.param_env;
168168

169-
if !ty.is_sized(tcx, param_env) {
170-
// !sized means !copy, so this is an unsized move unless it's a scalable SIMD type.
171-
if !ty.is_scalable_simd() {
172-
assert!(!ty.is_copy_modulo_regions(tcx, param_env));
173-
}
169+
if !ty.is_sized(tcx, param_env) && !ty.is_scalable_simd() {
170+
// !sized means !copy, so this is an unsized move.
171+
assert!(!ty.is_copy_modulo_regions(tcx, param_env));
174172

175173
// As described above, detect the case where we are passing a value of unsized
176174
// type, and that value is coming from the deref of a box.

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
10171017
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
10181018
let param_env = ty::ParamEnv::reveal_all();
10191019
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
1020-
if ty.is_sized(tcx.tcx, param_env) {
1020+
if ty.is_sized(tcx.tcx, param_env) || ty.is_scalable_simd() {
10211021
return false;
10221022
}
10231023
let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ fn layout_of_uncached<'tcx>(
201201
}
202202

203203
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
204+
if pointee.is_scalable_simd() {
205+
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
206+
}
204207
if pointee.is_sized(tcx, param_env) {
205208
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
206209
}

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#![cfg(not(test))]
5757
//
5858
#![stable(feature = "core", since = "1.6.0")]
59+
#![cfg_attr(not(bootstrap), feature(repr_scalable))]
5960
#![doc(
6061
html_playground_url = "https://play.rust-lang.org/",
6162
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//@ only-aarch64
2+
//@ compile-flags: -C opt-level=2 --edition=2021
3+
4+
#![crate_type = "lib"]
5+
#![allow(incomplete_features, internal_features, improper_ctypes)]
6+
#![feature(
7+
repr_simd,
8+
repr_scalable,
9+
simd_ffi,
10+
unsized_locals,
11+
unsized_fn_params,
12+
link_llvm_intrinsics
13+
)]
14+
15+
#[repr(simd, scalable(4))]
16+
#[allow(non_camel_case_types)]
17+
pub struct svint32_t {
18+
_ty: [i32],
19+
}
20+
21+
#[inline(never)]
22+
#[target_feature(enable = "sve")]
23+
pub unsafe fn svdup_n_s32(op: i32) -> svint32_t {
24+
extern "C" {
25+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.dup.x.nxv4i32")]
26+
fn _svdup_n_s32(op: i32) -> svint32_t;
27+
}
28+
unsafe { _svdup_n_s32(op) }
29+
}
30+
31+
#[inline]
32+
#[target_feature(enable = "sve,sve2")]
33+
pub unsafe fn svxar_n_s32<const IMM3: i32>(op1: svint32_t, op2: svint32_t) -> svint32_t {
34+
extern "C" {
35+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.xar.nxv4i32")]
36+
fn _svxar_n_s32(op1: svint32_t, op2: svint32_t, imm3: i32) -> svint32_t;
37+
}
38+
unsafe { _svxar_n_s32(op1, op2, IMM3) }
39+
}
40+
41+
#[inline(never)]
42+
#[no_mangle]
43+
#[target_feature(enable = "sve,sve2")]
44+
// CHECK: define <vscale x 4 x i32> @pass_as_ref(ptr noalias nocapture noundef readonly align 4 dereferenceable(4) %a, <vscale x 4 x i32> %b)
45+
pub unsafe fn pass_as_ref(a: &svint32_t, b: svint32_t) -> svint32_t {
46+
// CHECK: load <vscale x 4 x i32>, ptr %a, align 4
47+
svxar_n_s32::<1>(*a, b)
48+
}
49+
50+
#[no_mangle]
51+
#[target_feature(enable = "sve,sve2")]
52+
// CHECK: define <vscale x 4 x i32> @test()
53+
pub unsafe fn test() -> svint32_t {
54+
let a = svdup_n_s32(1);
55+
let b = svdup_n_s32(2);
56+
// CHECK: call <vscale x 4 x i32> @pass_as_ref(ptr noalias noundef nonnull readonly align 4 dereferenceable(4) %a, <vscale x 4 x i32> %b)
57+
pass_as_ref(&a, b)
58+
}

0 commit comments

Comments
 (0)