Skip to content

Commit 4fd671b

Browse files
committed
Fix zero-sized Array GEPs
Previously GEP on zero-sized arrays, would fail. This change fixes arrays to instead emit runtime arrays. I do not know if this will lead to any runtime cost, but it fixes all the compile errors.
1 parent 1932353 commit 4fd671b

File tree

12 files changed

+105
-6
lines changed

12 files changed

+105
-6
lines changed

Diff for: crates/rustc_codegen_spirv/src/abi.rs

-3
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,6 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
649649
element: element_type,
650650
}
651651
.def(span, cx)
652-
} else if count == 0 {
653-
// spir-v doesn't support zero-sized arrays
654-
create_zst(cx, span, ty)
655652
} else {
656653
let count_const = cx.constant_u32(span, count as u32);
657654
let element_spv = cx.lookup_type(element_type);

Diff for: crates/rustc_codegen_spirv/src/builder/builder_methods.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
406406
let ptr = ptr.strip_ptrcasts();
407407
let mut leaf_ty = match self.lookup_type(ptr.ty) {
408408
SpirvType::Pointer { pointee } => pointee,
409-
other => self.fatal(format!("non-pointer type: {other:?}")),
409+
SpirvType::Adt { .. } => return None,
410+
other => self.fatal(format!("adjust_pointer for non-pointer type: {other:?}")),
410411
};
411412

412413
// FIXME(eddyb) this isn't efficient, `recover_access_chain_from_offset`
@@ -528,8 +529,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
528529
let stride = ty_kind.sizeof(self)?;
529530
ty_size = MaybeSized::Sized(stride);
530531

531-
indices.push((offset.bytes() / stride.bytes()).try_into().ok()?);
532-
offset = Size::from_bytes(offset.bytes() % stride.bytes());
532+
if stride.bytes() == 0 {
533+
indices.push(0);
534+
offset = Size::from_bytes(0);
535+
} else {
536+
indices.push((offset.bytes() / stride.bytes()).try_into().ok()?);
537+
offset = Size::from_bytes(offset.bytes() % stride.bytes());
538+
}
533539
}
534540
_ => return None,
535541
}
@@ -566,6 +572,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
566572
.iter()
567573
.map(|index| {
568574
result_pointee_type = match self.lookup_type(result_pointee_type) {
575+
SpirvType::Array { count, element }
576+
if self.builder.lookup_const_u64(count) == Some(0) =>
577+
{
578+
self.fatal(format!(
579+
"Cannot index into [{}; 0], will panic at runtime.",
580+
self.debug_type(element)
581+
))
582+
}
569583
SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element } => {
570584
element
571585
}

Diff for: crates/rustc_codegen_spirv/src/codegen_cx/constant.rs

+4
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,10 @@ impl<'tcx> CodegenCx<'tcx> {
549549
}
550550
self.constant_composite(ty, values.into_iter())
551551
}
552+
SpirvType::Array { count, .. } if self.builder.lookup_const_u64(count) == Some(0) =>
553+
{
554+
self.undef(ty)
555+
}
552556
SpirvType::Array { element, count } => {
553557
let count = self.builder.lookup_const_u64(count).unwrap() as usize;
554558
let values = (0..count).map(|_| {

Diff for: crates/rustc_codegen_spirv/src/spirv_type.rs

+3
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ impl SpirvType<'_> {
368368
.bytes(),
369369
)
370370
.expect("alignof: Vectors must have power-of-2 size"),
371+
Self::Array { count, .. } if cx.builder.lookup_const_u64(count) == Some(0) => {
372+
Align::from_bytes(0).unwrap()
373+
}
371374
Self::Array { element, .. }
372375
| Self::RuntimeArray { element }
373376
| Self::Matrix { element, .. } => cx.lookup_type(element).alignof(cx),

Diff for: tests/ui/lang/core/array/array_0.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![allow(unconditional_panic)]
2+
3+
// build-fail
4+
#![cfg_attr(target_arch = "spirv", no_std)]
5+
use spirv_std::spirv;
6+
7+
#[spirv(compute(threads(1, 1, 1)))]
8+
pub fn compute() {
9+
let array = [0; 0];
10+
let x = array[0];
11+
}

Diff for: tests/ui/lang/core/array/array_0.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: Cannot index into [i32; 0], will panic at runtime.
2+
--> $DIR/array_0.rs:10:13
3+
|
4+
10 | let x = array[0];
5+
| ^^^^^^^^
6+
7+
error: aborting due to 1 previous error
8+

Diff for: tests/ui/lang/core/array/array_zst_0.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// build-pass
2+
#![cfg_attr(target_arch = "spirv", no_std)]
3+
use spirv_std::spirv;
4+
5+
#[spirv(compute(threads(1, 1, 1)))]
6+
pub fn compute() {
7+
let mut array = [(); 0];
8+
for i in 0..array.len() {
9+
array[i] = ();
10+
}
11+
}

Diff for: tests/ui/lang/core/array/gep0.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// build-fail
2+
3+
#![cfg_attr(target_arch = "spirv", no_std)]
4+
use spirv_std::spirv;
5+
6+
fn example<const N: usize>() {
7+
let mut array = [0; N];
8+
for i in 0..N {
9+
array[i] += i;
10+
}
11+
}
12+
13+
#[spirv(compute(threads(1, 1, 1)))]
14+
pub fn compute() {
15+
example::<0>();
16+
}

Diff for: tests/ui/lang/core/array/gep0.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: Cannot index into [u32; 0], will panic at runtime.
2+
--> $DIR/gep0.rs:9:9
3+
|
4+
9 | array[i] += i;
5+
| ^^^^^^^^^^^^^
6+
7+
error: aborting due to 1 previous error
8+

Diff for: tests/ui/lang/core/array/oob_0_array.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// build-fail
2+
3+
#![cfg_attr(target_arch = "spirv", no_std)]
4+
use spirv_std::spirv;
5+
6+
#[spirv(compute(threads(1, 1, 1)))]
7+
pub fn compute() {
8+
let mut array = [0; 0];
9+
array[0] = 1;
10+
}

Diff for: tests/ui/lang/core/array/oob_0_array.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: this operation will panic at runtime
2+
--> $DIR/oob_0_array.rs:9:5
3+
|
4+
9 | array[0] = 1;
5+
| ^^^^^^^^ index out of bounds: the length is 0 but the index is 0
6+
|
7+
= note: `#[deny(unconditional_panic)]` on by default
8+
9+
error: aborting due to 1 previous error
10+

Diff for: tests/ui/lang/core/array/unused_array_0.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![cfg_attr(target_arch = "spirv", no_std)]
2+
use spirv_std::spirv;
3+
4+
#[spirv(compute(threads(1, 1, 1)))]
5+
pub fn compute() {
6+
let array = [0; 0];
7+
}

0 commit comments

Comments
 (0)