Skip to content

add slice cast support #580

Open
39ali wants to merge 2 commits intoRust-GPU:mainfrom
39ali:slice-cast
Open

add slice cast support #580
39ali wants to merge 2 commits intoRust-GPU:mainfrom
39ali:slice-cast

Conversation

@39ali
Copy link
Copy Markdown
Contributor

@39ali 39ali commented Apr 15, 2026

fixes casting array as a slice , or array to ptr :

*[T; N] -> *[T]

*[T; N] -> *T

fixes #465

Copy link
Copy Markdown
Member

@Firestar99 Firestar99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased it on main, squashed the fmt fixes and added disassembly and arrays from consts to the compiletest.

Overall, I'm super impressed how simple this has turned out to be. I haven't looked at our existing pointer emulation too deeply before, but this seems quite logical.

@LegNeato But this also shows that I've been wrong about RuntimeArray only being used via spirv_std::RuntimeArray, it is also used to represent slices. Just that those slices get removed in the post-link legalization, since they contain a pointer, so you don't actually see them in the disassembly of the compiletest.
See:

FieldsShape::Array { stride, count } => {
let element_type = ty.field(cx, 0).spirv_type(span, cx);
if ty.is_unsized() {
// There's a potential for this array to be sized, but the element to be unsized, e.g. `[[u8]; 5]`.
// However, I think rust disallows all these cases, so assert this here.
assert_eq!(count, 0);
SpirvType::RuntimeArray {
element: element_type,
}
.def(span, cx)

@39ali
Copy link
Copy Markdown
Contributor Author

39ali commented Apr 16, 2026

@Firestar99 we should probably use LogicalPtrCast in the future and resolve it in qptr, but the issue it'll get zombied since i think qptr is not on by default

Copy link
Copy Markdown
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this change even helps - is it hiding errors that don't end up mattering in the end?

One way you could check is compiling (using some Rust-GPU version without this change) with RUSTGPU_CODEGEN_ARGS=--no-early-report-zombies (which moves the "zombie" reporting much later, near the end of the SPIR-T part of the linker).

For the test, I believe this is equivalent:

// compile-flags: -C llvm-args=--no-early-report-zombies

Comment on lines +2431 to +2443
// 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);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this is needed, won't recover_access_chain_from_offset produce the same effect?

.with_type(dest_ty);
}

// array -> RuntimeArray: *[T; N] -> *[T]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is doing *[T; N] -> *T -> *[T], using an OpInBoundsAccessChain for the first step, and OpBitcast for the second step, but:

  1. that OpBitcast is illegal, but won't be seen by the same zombie-creating logic that would be triggered by using self.pointercast(elem_ptr, dest_ty)
  2. creating SpirvValueKind::LogicalPtrCast (like calling pointercast recursively would do) allows later stripping the cast, so it should be more helpful?

I can't see how this helps, other than hiding an error?

@eddyb
Copy link
Copy Markdown
Member

eddyb commented Apr 17, 2026

The test from this PR passes on main with only this change:

--- a/tests/compiletests/ui/lang/core/array-slice-cast.rs
+++ b/tests/compiletests/ui/lang/core/array-slice-cast.rs
@@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
 // build-pass
-// compile-flags: -C llvm-args=--disassemble
+// compile-flags: -C llvm-args=--disassemble -C llvm-args=--no-early-report-zombies

I've been meaning for a while to replace the old zombie system:


In this specific case, I am guessing inlining removes the need for a *[T]-typed pointer, but I don't recall us having a pass to actually remove OpBitcasts, so I'm not sure how this ends up working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using an array as a slice causes a compiler error

3 participants