diff --git a/src/Sema.zig b/src/Sema.zig index 835b95acb0768371855adc76ab7c7eb144bd933f..0e58f0c819bf00d512bd58aa7f346e634bdb0368 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25377,12 +25377,16 @@ pub fn explainWhyTypeIsNotExtern( .noreturn => try sema.errNote(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), .@"opaque", - .spirv, .bool, .float, .@"anyframe", => unreachable, // these *are* allowed + .spirv => { + assert(ty.isSpirvRuntimeArray(zcu)); + try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{}); + }, + .pointer => if (ty.isSlice(zcu)) { try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); } else { @@ -30541,6 +30545,10 @@ fn analyzeLoad( try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); + if (elem_ty.isSpirvRuntimeArray(zcu)) { + return sema.fail(block, src, "cannot load SPIR-V runtime array value", .{}); + } + const comptime_only = switch (elem_ty.classify(zcu)) { .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) { .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}), diff --git a/src/Type.zig b/src/Type.zig index e648e48dd3c0e44ff49d743463b3400c4cc192f4..0e54f7c51f36c9a88558c792b7fed439929f68c7 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3119,12 +3119,16 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool .noreturn => position == .ret_ty, .@"opaque", - .spirv, .bool, .float, .@"anyframe", => true, + .spirv => switch (position) { + .struct_field, .union_field => true, + .ret_ty, .param_ty, .element, .other => !ty.isSpirvRuntimeArray(zcu), + }, + .pointer => { if (ty.isSlice(zcu)) return false; const child_ty = ty.childType(zcu); diff --git a/test/cases/compile_errors/loading_spirv_runtime_array_value.zig b/test/cases/compile_errors/loading_spirv_runtime_array_value.zig new file mode 100644 index 0000000000000000000000000000000000000000..b3473fa406eb8883f7fbf372c22e075386b10f71 --- /dev/null +++ b/test/cases/compile_errors/loading_spirv_runtime_array_value.zig @@ -0,0 +1,23 @@ +const RuntimeArray = @SpirvType(.{ .runtime_array = f32 }); +const Buffer = extern struct { + data: RuntimeArray, +}; +const buf = @extern(*addrspace(.storage_buffer) Buffer, .{ + .name = "buf", + .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, +}); +export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void { + const a = buf.data; + _ = a; +} +export fn main2() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void { + const p: *addrspace(.storage_buffer) const RuntimeArray = &buf.data; + _ = p.*; +} + +// error +// backend=selfhosted +// target=spirv32-vulkan +// +// :10:15: error: cannot load SPIR-V runtime array value +// :15:12: error: cannot load SPIR-V runtime array value diff --git a/test/cases/compile_errors/spirv_runtime_array_as_value_type.zig b/test/cases/compile_errors/spirv_runtime_array_as_value_type.zig new file mode 100644 index 0000000000000000000000000000000000000000..634837d3cf86d1b8b9ed8d3288d4ee1f099ebe20 --- /dev/null +++ b/test/cases/compile_errors/spirv_runtime_array_as_value_type.zig @@ -0,0 +1,26 @@ +const RuntimeArray = @SpirvType(.{ .runtime_array = u32 }); + +const a = @extern(*addrspace(.storage_buffer) RuntimeArray, .{ + .name = "a", + .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, +}); +const b = @extern(*addrspace(.uniform) const RuntimeArray, .{ + .name = "b", + .decoration = .{ .descriptor = .{ .set = 0, .binding = 1 } }, +}); + +comptime { + _ = a; + _ = b; +} + +// error +// backend=selfhosted +// target=spirv32-vulkan +// +// :3:19: error: extern symbol cannot have type '*addrspace(.storage_buffer) @SpirvType(.runtime_array, u32)' +// :3:19: note: pointer element type '@SpirvType(.runtime_array, u32)' is not extern compatible +// :3:19: note: SPIR-V runtime arrays must be the last field of an extern struct +// :7:19: error: extern symbol cannot have type '*addrspace(.uniform) const @SpirvType(.runtime_array, u32)' +// :7:19: note: pointer element type '@SpirvType(.runtime_array, u32)' is not extern compatible +// :7:19: note: SPIR-V runtime arrays must be the last field of an extern struct