Skip to content

Commit 4f9b334

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 4f9b334

File tree

9 files changed

+81
-7
lines changed

9 files changed

+81
-7
lines changed

crates/rustc_codegen_spirv/src/abi.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,11 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
650650
}
651651
.def(span, cx)
652652
} else if count == 0 {
653-
// spir-v doesn't support zero-sized arrays
654-
create_zst(cx, span, ty)
653+
// create a run-time array instead of ZST ADT
654+
SpirvType::RuntimeArray {
655+
element: element_type,
656+
}
657+
.def(span, cx)
655658
} else {
656659
let count_const = cx.constant_u32(span, count as u32);
657660
let element_spv = cx.lookup_type(element_type);

crates/rustc_codegen_spirv/src/builder/builder_methods.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
528528
let stride = ty_kind.sizeof(self)?;
529529
ty_size = MaybeSized::Sized(stride);
530530

531-
indices.push((offset.bytes() / stride.bytes()).try_into().ok()?);
532-
offset = Size::from_bytes(offset.bytes() % stride.bytes());
531+
if stride.bytes() == 0 {
532+
indices.push(0);
533+
offset = Size::from_bytes(0);
534+
} else {
535+
indices.push((offset.bytes() / stride.bytes()).try_into().ok()?);
536+
offset = Size::from_bytes(offset.bytes() % stride.bytes());
537+
}
533538
}
534539
_ => return None,
535540
}
@@ -566,9 +571,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
566571
.iter()
567572
.map(|index| {
568573
result_pointee_type = match self.lookup_type(result_pointee_type) {
569-
SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element } => {
570-
element
571-
}
574+
SpirvType::Array { element, .. }
575+
| SpirvType::RuntimeArray { element } => element,
572576
_ => self.fatal(format!(
573577
"GEP not implemented for type {}",
574578
self.debug_type(result_pointee_type)

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),

tests/ui/lang/core/array/array_0.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// build-fail
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 array = [0; 0];
8+
let x = array[0];
9+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: this operation will panic at runtime
2+
--> $DIR/array_0.rs:8:13
3+
|
4+
8 | let x = array[0];
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+
+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+
}

tests/ui/lang/core/array/gep0.rs

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

0 commit comments

Comments
 (0)