Skip to content

Commit 02701d2

Browse files
committed
builder: backport rust-lang/rust#134117 ([0, i] -> [i] for array GEPs).
1 parent 41aee83 commit 02701d2

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

crates/rustc_codegen_spirv/src/builder/builder_methods.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,68 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
655655
// https://github.com/gpuweb/gpuweb/issues/33
656656
let (&ptr_base_index, indices) = combined_indices.split_first().unwrap();
657657

658+
// HACK(eddyb) this effectively removes any real support for GEPs with
659+
// any `indices` (beyond `ptr_base_index`), which should now be the case
660+
// across `rustc_codegen_ssa` (see also comment inside `inbounds_gep`).
661+
// FIXME(eddyb) are the warning + fallback path even work keeping?
662+
if !indices.is_empty() {
663+
// HACK(eddyb) Cargo silences warnings in dependencies.
664+
let force_warn = |span, msg| -> rustc_errors::Diag<'_, ()> {
665+
rustc_errors::Diag::new(
666+
self.tcx.dcx(),
667+
rustc_errors::Level::ForceWarning(None),
668+
msg,
669+
)
670+
.with_span(span)
671+
};
672+
force_warn(
673+
self.span(),
674+
format!(
675+
"[RUST-GPU BUG] `inbounds_gep` or `gep` called with \
676+
{} combined indices (expected only 1)",
677+
combined_indices.len(),
678+
),
679+
)
680+
.emit();
681+
682+
let indexed_base_ptr = self.maybe_inbounds_gep(ty, ptr, &[ptr_base_index], is_inbounds);
683+
let indexed_base_ptr_id = indexed_base_ptr.def(self);
684+
assert_ty_eq!(self, indexed_base_ptr.ty, self.type_ptr_to(ty));
685+
686+
let mut final_pointee = ty;
687+
for &index in indices {
688+
final_pointee = match self.lookup_type(final_pointee) {
689+
SpirvType::Adt { field_types, .. } => {
690+
field_types[self
691+
.builder
692+
.lookup_const_scalar(index)
693+
.expect("non-const struct index for GEP")
694+
as usize]
695+
}
696+
SpirvType::Array { element, .. }
697+
| SpirvType::RuntimeArray { element }
698+
| SpirvType::Vector { element, .. }
699+
| SpirvType::Matrix { element, .. } => element,
700+
701+
_ => self.fatal(format!(
702+
"GEP not implemented for indexing into type {}",
703+
self.debug_type(final_pointee)
704+
)),
705+
};
706+
}
707+
let final_spirv_ptr_type = self.type_ptr_to(final_pointee);
708+
709+
let indices_ids: Vec<_> = indices.iter().map(|index| index.def(self)).collect();
710+
711+
return self.emit_access_chain(
712+
final_spirv_ptr_type,
713+
indexed_base_ptr_id,
714+
None,
715+
indices_ids,
716+
is_inbounds,
717+
);
718+
}
719+
658720
// Determine if this GEP operation is effectively byte-level addressing.
659721
// This check is based on the *provided* input type `ty`. If `ty` is i8 or u8,
660722
// it suggests the caller intends to perform byte-offset calculations,
@@ -1972,6 +2034,21 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
19722034
ptr: Self::Value,
19732035
indices: &[Self::Value],
19742036
) -> Self::Value {
2037+
// HACK(eddyb) effectively a backport of this `gep [0, i]` -> `gep [i]`
2038+
// PR: https://github.com/rust-lang/rust/pull/134117 to even earlier
2039+
// nightlies - and that PR happens to remove the last GEP that can be
2040+
// emitted with any "structured" (struct/array) indices, beyond the
2041+
// "first index" (which acts as `<*T>::offset` aka "pointer arithmetic").
2042+
if let &[ptr_base_index, structured_index] = indices {
2043+
if self.builder.lookup_const_scalar(ptr_base_index) == Some(0) {
2044+
if let SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element, .. } =
2045+
self.lookup_type(ty)
2046+
{
2047+
return self.maybe_inbounds_gep(element, ptr, &[structured_index], true);
2048+
}
2049+
}
2050+
}
2051+
19752052
self.maybe_inbounds_gep(ty, ptr, indices, true)
19762053
}
19772054

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: error:0:0 - Result type (OpTypeArray) does not match the type that results from indexing into the composite (OpTypeArray).
2+
%67 = OpCompositeExtract %_arr_uint_uint_2 %49 0 0
3+
|
4+
= note: spirv-val failed
5+
= note: module `$TEST_BUILD_DIR/lang/issue-46.spv1.3`
6+
7+
error: aborting due to 1 previous error
8+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: error:0:0 - OpInBoundsAccessChain result type (OpTypeInt) does not match the type that results from indexing into the base <id> (OpTypeArray).
2+
%33 = OpInBoundsAccessChain %_ptr_StorageBuffer_uint %28 %uint_0
3+
|
4+
= note: spirv-val failed
5+
= note: module `$TEST_BUILD_DIR/storage_class/typed-buffer-simple.spv1.3`
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)