spirv slices are represented via an element pointer + len. On access we
get pointers to individual elements with OpPtrAccessChain
Unfortunately this is not a valid operation in most cases. For any array
defined in a function, we are generated with storage class "function".
The SPIRV spec only allows for variable pointers on data in the Workgroup
(addrspace(.shared)) or StorageBuffer storage classes (definition of
variable pointer in SPIRV spec 2.16)
SPIRV kernels with this constraint unmet cause segfaults on my machine
when trying to load them, and fail to check against spirv-val
AFAICT there is no way to represent a slice of data with storage class
"function". We can use OpAccessChain to extract an offset from an array,
however that would require a slice representation resembling {array,
offset, len}. Since arrays are typed according to their type + len,
there would be no way to re-assign a slice from a [4]f32 array to a
slice from a [2]f32 array. The types would just not match up
So the best we can do is just ban construction of slices in the
scenarios we cannot generate valid code for, and give a useful error
message to the caller
A few examples...
var buf: [3]f32 = undefined;
for (buf[0..3]) |v| {} // errors
fnThatAcceptsSlice(&buf); // errors
for (&buf) |v| {} // succeeds
comptime cbuf: [3]f32 = .{1, 2, 3};
for (cbuf[0..3]) |v| {} // errors
for (comptime cbuf[0..3]) |v| {} // succeeds
This is arguably over-restrictive. We theoretically could handle
buf[0..N] correctly, but currently SPIRV codegen will still produce
invalid OpPtrAccessChains, so I've just completely removed the ability
to produce slices