diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index d86db1cbd00..a8cdc0deb3b 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -2423,7 +2423,46 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { "pointercast called on non-pointer dest type: {other:?}" )), }; - let dest_pointee_size = self.lookup_type(dest_pointee).sizeof(self); + + let dst_pointee_ty = self.lookup_type(dest_pointee); + let dest_pointee_size = dst_pointee_ty.sizeof(self); + let src_pointee_ty = self.lookup_type(ptr_pointee); + + // array -> element: *[T; N] -> *T + if let SpirvType::Array { + element: elem_ty, .. + } = src_pointee_ty + && elem_ty == dest_pointee + { + let zero = self.constant_u32(self.span(), 0).def(self); + return self + .emit() + .in_bounds_access_chain(dest_ty, None, ptr.def(self), [zero]) + .unwrap() + .with_type(dest_ty); + } + + // array -> RuntimeArray: *[T; N] -> *[T] + if let SpirvType::Array { + element: elem_ty, .. + } = src_pointee_ty + && let SpirvType::RuntimeArray { + element: rt_elem_ty, + } = dst_pointee_ty + && elem_ty == rt_elem_ty + { + let zero = self.constant_u32(self.span(), 0).def(self); + let elem_ptr_ty = self.type_ptr_to(elem_ty); + let elem_ptr = self + .emit() + .in_bounds_access_chain(elem_ptr_ty, None, ptr.def(self), [zero]) + .unwrap(); + return self + .emit() + .bitcast(dest_ty, None, elem_ptr) + .unwrap() + .with_type(dest_ty); + } if let Some((indices, _)) = self.recover_access_chain_from_offset( ptr_pointee, diff --git a/tests/compiletests/ui/lang/core/slice.rs b/tests/compiletests/ui/lang/core/slice.rs new file mode 100644 index 00000000000..86693a25048 --- /dev/null +++ b/tests/compiletests/ui/lang/core/slice.rs @@ -0,0 +1,20 @@ +// build-pass + +use spirv_std::spirv; + +#[spirv(compute(threads(64)))] +pub fn main( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] input: &[u32; 3], + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] output: &mut u32, +) { + // &[u32] fat pointer from a runtime storage buffer array + let slice: &[u32] = input; + let val = slice[1]; + + // *[u32; 3] -> *u32 via AccessChain (array->element path) + let array_ptr: *const [u32; 3] = input; + let element_ptr: *const u32 = array_ptr as *const u32; + let val2 = unsafe { *element_ptr }; + + *output = val + val2; +}