| author | |
| committer | |
| log | 4c9cdc8b9189d548f00229cdfc21f1850348026f |
| tree | e95e83f4e4bc2b064a844b07bfdd8c2ddc2a7a9b |
| parent | aa3b2c557fe443b2dd55725b237d8e3ac804e414 |
| parent | 62e61e2e9b368bba001b67f4a29681b4bef4b822 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36257
Reviewed-by: Andrew Kelley <andrew@ziglang.org>31 files changed, 354 insertions(+), 196 deletions(-)
src/Sema.zig+79-45| ... | @@ -22151,34 +22151,7 @@ fn ptrCastFull( | ... | @@ -22151,34 +22151,7 @@ fn ptrCastFull( |
| 22151 | } | 22151 | } |
| 22152 | 22152 | ||
| 22153 | try sema.validateRuntimeValue(block, operand_src, operand); | 22153 | try sema.validateRuntimeValue(block, operand_src, operand); |
| 22154 | 22154 | try sema.checkLogicalPtrCast(block, src, operand_ty, dest_ty); | |
| 22155 | if (zcu.getTarget().cpu.arch.isSpirV() and | ||
| 22156 | src_info.flags.address_space != .physical_storage_buffer and | ||
| 22157 | src_info.flags.address_space == dest_info.flags.address_space and | ||
| 22158 | src_info.child != dest_info.child and | ||
| 22159 | Type.fromInterned(dest_info.child).hasRuntimeBits(zcu)) | ||
| 22160 | { | ||
| 22161 | var cur: Type = .fromInterned(src_info.child); | ||
| 22162 | while (cur.toIntern() != dest_info.child) { | ||
| 22163 | cur = switch (cur.zigTypeTag(zcu)) { | ||
| 22164 | .array, .vector => cur.childType(zcu), | ||
| 22165 | .@"struct" => if (cur.structFieldOffset(0, zcu) == 0) cur.fieldType(0, zcu) else null, | ||
| 22166 | else => null, | ||
| 22167 | } orelse return sema.failWithOwnedErrorMsg(block, msg: { | ||
| 22168 | const msg = try sema.errMsg(src, "cannot cast pointer '{f}' to '{f}'", .{ | ||
| 22169 | operand_ty.fmt(pt), dest_ty.fmt(pt), | ||
| 22170 | }); | ||
| 22171 | errdefer msg.destroy(sema.gpa); | ||
| 22172 | try sema.errNote(src, msg, "'{f}' must appear at offset 0 inside '{f}'", .{ | ||
| 22173 | Type.fromInterned(dest_info.child).fmt(pt), Type.fromInterned(src_info.child).fmt(pt), | ||
| 22174 | }); | ||
| 22175 | try sema.errNote(src, msg, "'{s}' pointers can only reach nested types through a first struct field or an array element", .{ | ||
| 22176 | @tagName(src_info.flags.address_space), | ||
| 22177 | }); | ||
| 22178 | break :msg msg; | ||
| 22179 | }); | ||
| 22180 | } | ||
| 22181 | } | ||
| 22182 | 22155 | ||
| 22183 | const can_cast_to_int = !target_util.shouldBlockPointerOps(zcu.getTarget(), operand_ty.ptrAddressSpace(zcu)); | 22156 | const can_cast_to_int = !target_util.shouldBlockPointerOps(zcu.getTarget(), operand_ty.ptrAddressSpace(zcu)); |
| 22184 | const need_null_check = can_cast_to_int and block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu); | 22157 | const need_null_check = can_cast_to_int and block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu); |
| ... | @@ -22721,6 +22694,8 @@ fn checkPtrType( | ... | @@ -22721,6 +22694,8 @@ fn checkPtrType( |
| 22721 | fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | 22694 | fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 22722 | const pt = sema.pt; | 22695 | const pt = sema.pt; |
| 22723 | const zcu = pt.zcu; | 22696 | const zcu = pt.zcu; |
| 22697 | |||
| 22698 | if (block.isComptime() or block.is_typeof) return; | ||
| 22724 | if (zcu.intern_pool.indexToKey(ty.toIntern()) == .ptr_type) { | 22699 | if (zcu.intern_pool.indexToKey(ty.toIntern()) == .ptr_type) { |
| 22725 | const target = zcu.getTarget(); | 22700 | const target = zcu.getTarget(); |
| 22726 | const as = ty.ptrAddressSpace(zcu); | 22701 | const as = ty.ptrAddressSpace(zcu); |
| ... | @@ -22731,12 +22706,8 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -22731,12 +22706,8 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 22731 | try sema.errNote( | 22706 | try sema.errNote( |
| 22732 | src, | 22707 | src, |
| 22733 | msg, | 22708 | msg, |
| 22734 | "cannot perform arithmetic on pointers with address space '{s}' on target {s}-{s}", | 22709 | "pointers with address space '{t}' do not support arithmetic or indexing on target {t}-{t}", |
| 22735 | .{ | 22710 | .{ as, target.cpu.arch.family(), target.os.tag }, |
| 22736 | @tagName(as), | ||
| 22737 | @tagName(target.cpu.arch.family()), | ||
| 22738 | @tagName(target.os.tag), | ||
| 22739 | }, | ||
| 22740 | ); | 22711 | ); |
| 22741 | break :msg msg; | 22712 | break :msg msg; |
| 22742 | }); | 22713 | }); |
| ... | @@ -22744,6 +22715,49 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -22744,6 +22715,49 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 22744 | } | 22715 | } |
| 22745 | } | 22716 | } |
| 22746 | 22717 | ||
| 22718 | fn checkLogicalPtrCast( | ||
| 22719 | sema: *Sema, | ||
| 22720 | block: *Block, | ||
| 22721 | src: LazySrcLoc, | ||
| 22722 | operand_ty: Type, | ||
| 22723 | dest_ty: Type, | ||
| 22724 | ) CompileError!void { | ||
| 22725 | const pt = sema.pt; | ||
| 22726 | const zcu = pt.zcu; | ||
| 22727 | const src_info = operand_ty.ptrInfo(zcu); | ||
| 22728 | const dest_info = dest_ty.ptrInfo(zcu); | ||
| 22729 | |||
| 22730 | if (block.isComptime() or block.is_typeof) return; | ||
| 22731 | switch (zcu.getTarget().os.tag) { | ||
| 22732 | .vulkan, .opengl => {}, | ||
| 22733 | else => return, | ||
| 22734 | } | ||
| 22735 | if (src_info.flags.address_space == .physical_storage_buffer) return; | ||
| 22736 | |||
| 22737 | var cur: Type = .fromInterned(src_info.child); | ||
| 22738 | while (cur.toIntern() != dest_info.child) { | ||
| 22739 | cur = switch (cur.zigTypeTag(zcu)) { | ||
| 22740 | .array, .vector => cur.childType(zcu), | ||
| 22741 | .@"struct" => field: { | ||
| 22742 | for (0..cur.structFieldCount(zcu)) |i| { | ||
| 22743 | const field_ty = cur.fieldType(i, zcu); | ||
| 22744 | if (field_ty.hasRuntimeBits(zcu) and cur.structFieldOffset(i, zcu) == 0) break :field field_ty; | ||
| 22745 | } | ||
| 22746 | break :field null; | ||
| 22747 | }, | ||
| 22748 | else => null, | ||
| 22749 | } orelse return sema.failWithOwnedErrorMsg(block, msg: { | ||
| 22750 | const msg = try sema.errMsg(src, "cannot cast pointer '{f}' to '{f}'", .{ operand_ty.fmt(pt), dest_ty.fmt(pt) }); | ||
| 22751 | errdefer msg.destroy(sema.gpa); | ||
| 22752 | try sema.errNote(src, msg, "'{f}' must appear at offset 0 inside '{f}'", .{ | ||
| 22753 | Type.fromInterned(dest_info.child).fmt(pt), | ||
| 22754 | Type.fromInterned(src_info.child).fmt(pt), | ||
| 22755 | }); | ||
| 22756 | break :msg msg; | ||
| 22757 | }); | ||
| 22758 | } | ||
| 22759 | } | ||
| 22760 | |||
| 22747 | fn checkVectorElemType( | 22761 | fn checkVectorElemType( |
| 22748 | sema: *Sema, | 22762 | sema: *Sema, |
| 22749 | block: *Block, | 22763 | block: *Block, |
| ... | @@ -25285,17 +25299,30 @@ fn zirBuiltinExtern( | ... | @@ -25285,17 +25299,30 @@ fn zirBuiltinExtern( |
| 25285 | .location, .descriptor => {}, | 25299 | .location, .descriptor => {}, |
| 25286 | }; | 25300 | }; |
| 25287 | 25301 | ||
| 25288 | switch (zcu.getTarget().os.tag) { | 25302 | const target = zcu.getTarget(); |
| 25289 | .vulkan, .opengl => switch (ptr_info.flags.address_space) { | 25303 | switch (target.os.tag) { |
| 25290 | .storage_buffer, .uniform, .push_constant => if (ptr_info.flags.size != .one) { | 25304 | .vulkan, .opengl => { |
| 25291 | return sema.failWithOwnedErrorMsg(block, msg: { | 25305 | const pointee = switch (elem_ty.zigTypeTag(zcu)) { |
| 25292 | const msg = try sema.errMsg(ty_src, "extern in '{s}' address space must be a single-item pointer to a struct", .{@tagName(ptr_info.flags.address_space)}); | 25306 | .array => elem_ty.childType(zcu), |
| 25293 | errdefer msg.destroy(sema.gpa); | 25307 | .spirv => if (elem_ty.isSpirvRuntimeArray(zcu)) elem_ty.childType(zcu) else elem_ty, |
| 25294 | try sema.errNote(ty_src, msg, "wrap the element type in a struct containing a runtime-sized array", .{}); | 25308 | else => elem_ty, |
| 25295 | break :msg msg; | 25309 | }; |
| 25296 | }); | 25310 | switch (ptr_info.flags.address_space) { |
| 25297 | }, | 25311 | .uniform, |
| 25298 | else => {}, | 25312 | .storage_buffer, |
| 25313 | => if (ptr_info.flags.size != .one or pointee.zigTypeTag(zcu) != .@"struct") { | ||
| 25314 | return sema.fail(block, ty_src, "extern in '{t}' address space must be a single-item pointer to a struct", .{ptr_info.flags.address_space}); | ||
| 25315 | }, | ||
| 25316 | .push_constant => if (ptr_info.flags.size != .one or elem_ty.zigTypeTag(zcu) != .@"struct") { | ||
| 25317 | return sema.fail(block, ty_src, "extern in 'push_constant' address space must be a single-item pointer to a struct", .{}); | ||
| 25318 | }, | ||
| 25319 | .constant => if (target.os.tag == .vulkan and (pointee.zigTypeTag(zcu) != .spirv or pointee.isSpirvRuntimeArray(zcu))) { | ||
| 25320 | return sema.fail(block, ty_src, "extern in 'constant' address space must point to an opaque SPIR-V type, or to an array of one", .{}); | ||
| 25321 | }, | ||
| 25322 | else => if (elem_ty.isSpirvRuntimeArray(zcu)) { | ||
| 25323 | return sema.fail(block, ty_src, "SPIR-V runtime array is not allowed in the '{t}' address space", .{ptr_info.flags.address_space}); | ||
| 25324 | }, | ||
| 25325 | } | ||
| 25299 | }, | 25326 | }, |
| 25300 | else => {}, | 25327 | else => {}, |
| 25301 | } | 25328 | } |
| ... | @@ -25717,6 +25744,9 @@ pub fn explainWhyTypeIsNotExtern( | ... | @@ -25717,6 +25744,9 @@ pub fn explainWhyTypeIsNotExtern( |
| 25717 | .spirv => { | 25744 | .spirv => { |
| 25718 | assert(ty.isSpirvRuntimeArray(zcu)); | 25745 | assert(ty.isSpirvRuntimeArray(zcu)); |
| 25719 | try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{}); | 25746 | try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{}); |
| 25747 | if (position == .other) { | ||
| 25748 | try sema.errNote(src_loc, msg, "consider enabling the 'runtime_descriptor_array' feature to use the runtime array as the extern pointee", .{}); | ||
| 25749 | } | ||
| 25720 | }, | 25750 | }, |
| 25721 | 25751 | ||
| 25722 | .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}), | 25752 | .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}), |
| ... | @@ -27351,6 +27381,7 @@ fn elemPtrOneLayerOnly( | ... | @@ -27351,6 +27381,7 @@ fn elemPtrOneLayerOnly( |
| 27351 | 27381 | ||
| 27352 | try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_src); | 27382 | try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_src); |
| 27353 | try sema.validateRuntimeValue(block, indexable_src, indexable); | 27383 | try sema.validateRuntimeValue(block, indexable_src, indexable); |
| 27384 | try sema.checkLogicalPtrOperation(block, src, indexable_ty); | ||
| 27354 | 27385 | ||
| 27355 | if (child_ty.abiSize(zcu) == 0) { | 27386 | if (child_ty.abiSize(zcu) == 0) { |
| 27356 | // zero-bit child type; just bitcast the pointer | 27387 | // zero-bit child type; just bitcast the pointer |
| ... | @@ -27423,6 +27454,7 @@ fn elemVal( | ... | @@ -27423,6 +27454,7 @@ fn elemVal( |
| 27423 | }, | 27454 | }, |
| 27424 | .partially_comptime, .fully_comptime => unreachable, // caught by `validateRuntimeElemAccess` | 27455 | .partially_comptime, .fully_comptime => unreachable, // caught by `validateRuntimeElemAccess` |
| 27425 | } | 27456 | } |
| 27457 | try sema.checkLogicalPtrOperation(block, src, indexable_ty); | ||
| 27426 | 27458 | ||
| 27427 | return block.addBinOp(.ptr_elem_val, indexable, elem_index); | 27459 | return block.addBinOp(.ptr_elem_val, indexable, elem_index); |
| 27428 | }, | 27460 | }, |
| ... | @@ -27824,6 +27856,7 @@ fn elemValSlice( | ... | @@ -27824,6 +27856,7 @@ fn elemValSlice( |
| 27824 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; | 27856 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 27825 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); | 27857 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| 27826 | } | 27858 | } |
| 27859 | try sema.checkLogicalPtrOperation(block, src, slice_ty); | ||
| 27827 | return block.addBinOp(.slice_elem_val, slice, elem_index); | 27860 | return block.addBinOp(.slice_elem_val, slice, elem_index); |
| 27828 | } | 27861 | } |
| 27829 | 27862 | ||
| ... | @@ -27875,6 +27908,7 @@ fn elemPtrSlice( | ... | @@ -27875,6 +27908,7 @@ fn elemPtrSlice( |
| 27875 | 27908 | ||
| 27876 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_src); | 27909 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_src); |
| 27877 | try sema.validateRuntimeValue(block, slice_src, slice); | 27910 | try sema.validateRuntimeValue(block, slice_src, slice); |
| 27911 | try sema.checkLogicalPtrOperation(block, src, slice_ty); | ||
| 27878 | 27912 | ||
| 27879 | if (oob_safety and block.wantSafety()) { | 27913 | if (oob_safety and block.wantSafety()) { |
| 27880 | const len_inst = len: { | 27914 | const len_inst = len: { |
src/Sema/type_resolution.zig+11| ... | @@ -334,6 +334,17 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { | ... | @@ -334,6 +334,17 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { |
| 334 | break :msg msg; | 334 | break :msg msg; |
| 335 | }); | 335 | }); |
| 336 | } | 336 | } |
| 337 | |||
| 338 | const elem_ty: Type = field_ty.childType(zcu); | ||
| 339 | if (elem_ty.zigTypeTag(zcu) == .spirv) { | ||
| 340 | return sema.failWithOwnedErrorMsg(&block, msg: { | ||
| 341 | const msg = try sema.errMsg(field_ty_src, "cannot embed SPIR-V type '{f}' in struct", .{elem_ty.fmt(pt)}); | ||
| 342 | errdefer msg.destroy(gpa); | ||
| 343 | try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); | ||
| 344 | try sema.addDeclaredHereNote(msg, field_ty); | ||
| 345 | break :msg msg; | ||
| 346 | }); | ||
| 347 | } | ||
| 337 | } else { | 348 | } else { |
| 338 | return sema.failWithOwnedErrorMsg(&block, msg: { | 349 | return sema.failWithOwnedErrorMsg(&block, msg: { |
| 339 | const msg = try sema.errMsg(field_ty_src, "cannot directly embed SPIR-V type '{f}' in struct", .{field_ty.fmt(pt)}); | 350 | const msg = try sema.errMsg(field_ty_src, "cannot directly embed SPIR-V type '{f}' in struct", .{field_ty.fmt(pt)}); |
src/Type.zig+2-1| ... | @@ -3145,7 +3145,8 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool | ... | @@ -3145,7 +3145,8 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool |
| 3145 | 3145 | ||
| 3146 | .spirv => switch (position) { | 3146 | .spirv => switch (position) { |
| 3147 | .struct_field, .union_field => true, | 3147 | .struct_field, .union_field => true, |
| 3148 | .ret_ty, .param_ty, .element, .other => !ty.isSpirvRuntimeArray(zcu), | 3148 | .ret_ty, .param_ty, .element => !ty.isSpirvRuntimeArray(zcu), |
| 3149 | .other => !ty.isSpirvRuntimeArray(zcu) or zcu.getTarget().cpu.has(.spirv, .runtime_descriptor_array), | ||
| 3149 | }, | 3150 | }, |
| 3150 | 3151 | ||
| 3151 | .pointer => { | 3152 | .pointer => { |
src/codegen/spirv/CodeGen.zig+52-17| ... | @@ -617,7 +617,8 @@ pub fn structType( | ... | @@ -617,7 +617,8 @@ pub fn structType( |
| 617 | 617 | ||
| 618 | /// Returns the layout-decorated variant of `ty` for use inside a Vulkan/OpenGL | 618 | /// Returns the layout-decorated variant of `ty` for use inside a Vulkan/OpenGL |
| 619 | /// interface block. Vulkan forbids nested Block decorations, so recursive calls | 619 | /// interface block. Vulkan forbids nested Block decorations, so recursive calls |
| 620 | /// always pass `false`. | 620 | /// pass `false`, except through an array, whose elements are each a |
| 621 | /// block of their own. | ||
| 621 | /// | 622 | /// |
| 622 | /// This is distinct from `resolveType` because SPIR-V forbids such decorations | 623 | /// This is distinct from `resolveType` because SPIR-V forbids such decorations |
| 623 | /// on the pointee of a Function-scope variable. | 624 | /// on the pointee of a Function-scope variable. |
| ... | @@ -695,26 +696,30 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id { | ... | @@ -695,26 +696,30 @@ pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id { |
| 695 | }, | 696 | }, |
| 696 | .array => id: { | 697 | .array => id: { |
| 697 | const elem_ty = ty.childType(zcu); | 698 | const elem_ty = ty.childType(zcu); |
| 698 | const elem_ty_id = try cg.layoutType(elem_ty, false); | 699 | const elem_ty_id = try cg.layoutType(elem_ty, is_block_root); |
| 699 | const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(zcu)) orelse | 700 | const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(zcu)) orelse |
| 700 | return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)}); | 701 | return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)}); |
| 701 | const id = try cg.arrayType(try cg.constInt(.u32, total_len), elem_ty_id); | 702 | const id = try cg.arrayType(try cg.constInt(.u32, total_len), elem_ty_id); |
| 702 | if (elem_ty.hasRuntimeBits(zcu)) try cg.decorate(id, .{ | 703 | if (!is_block_root and elem_ty.hasRuntimeBits(zcu)) { |
| 703 | .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) }, | 704 | try cg.decorate(id, .{ |
| 704 | }); | 705 | .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) }, |
| 706 | }); | ||
| 707 | } | ||
| 705 | break :id id; | 708 | break :id id; |
| 706 | }, | 709 | }, |
| 707 | .spirv => if (ty.isSpirvRuntimeArray(zcu)) id: { | 710 | .spirv => if (ty.isSpirvRuntimeArray(zcu)) id: { |
| 708 | const elem_ty = ty.childType(zcu); | 711 | const elem_ty = ty.childType(zcu); |
| 709 | const elem_ty_id = try cg.layoutType(elem_ty, false); | 712 | const elem_ty_id = try cg.layoutType(elem_ty, is_block_root); |
| 710 | const id = cg.allocId(); | 713 | const id = cg.allocId(); |
| 711 | try cg.sections.globals.emit(gpa, .OpTypeRuntimeArray, .{ | 714 | try cg.sections.globals.emit(gpa, .OpTypeRuntimeArray, .{ |
| 712 | .id_result = id, | 715 | .id_result = id, |
| 713 | .element_type = elem_ty_id, | 716 | .element_type = elem_ty_id, |
| 714 | }); | 717 | }); |
| 715 | if (elem_ty.hasRuntimeBits(zcu)) try cg.decorate(id, .{ | 718 | if (!is_block_root and elem_ty.hasRuntimeBits(zcu)) { |
| 716 | .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) }, | 719 | try cg.decorate(id, .{ |
| 717 | }); | 720 | .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) }, |
| 721 | }); | ||
| 722 | } | ||
| 718 | break :id id; | 723 | break :id id; |
| 719 | } else return cg.resolveType(ty, .indirect), | 724 | } else return cg.resolveType(ty, .indirect), |
| 720 | else => return cg.resolveType(ty, .indirect), | 725 | else => return cg.resolveType(ty, .indirect), |
| ... | @@ -955,11 +960,18 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -955,11 +960,18 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 955 | switch (target.os.tag) { | 960 | switch (target.os.tag) { |
| 956 | .vulkan, .opengl => { | 961 | .vulkan, .opengl => { |
| 957 | switch (storage_class) { | 962 | switch (storage_class) { |
| 958 | .uniform, .push_constant, .storage_buffer, .physical_storage_buffer => { | 963 | .uniform, |
| 964 | .push_constant, | ||
| 965 | .storage_buffer, | ||
| 966 | .physical_storage_buffer, | ||
| 967 | => { | ||
| 959 | if (ty.hasRuntimeBits(zcu)) { | 968 | if (ty.hasRuntimeBits(zcu)) { |
| 960 | try cg.decorate(ptr_ty_id, .{ | 969 | if (!ty.isSpirvRuntimeArray(zcu)) { |
| 961 | .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, | 970 | try cg.decorate( |
| 962 | }); | 971 | ptr_ty_id, |
| 972 | .{ .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) } }, | ||
| 973 | ); | ||
| 974 | } | ||
| 963 | if (!cg.needsLayout(as, ty)) try cg.decorateLayout(ty, ty_id); | 975 | if (!cg.needsLayout(as, ty)) try cg.decorateLayout(ty, ty_id); |
| 964 | } | 976 | } |
| 965 | if (key.is_const and storage_class == .storage_buffer) { | 977 | if (key.is_const and storage_class == .storage_buffer) { |
| ... | @@ -2047,6 +2059,13 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -2047,6 +2059,13 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 2047 | while (cur.toIntern() != dst_child.toIntern()) { | 2059 | while (cur.toIntern() != dst_child.toIntern()) { |
| 2048 | switch (cur.zigTypeTag(zcu)) { | 2060 | switch (cur.zigTypeTag(zcu)) { |
| 2049 | .array => { | 2061 | .array => { |
| 2062 | if (dst_child.zigTypeTag(zcu) == .array and | ||
| 2063 | dst_child.childType(zcu).toIntern() == cur.childType(zcu).toIntern() and | ||
| 2064 | dst_child.arrayLenIncludingSentinel(zcu) <= cur.arrayLenIncludingSentinel(zcu)) | ||
| 2065 | { | ||
| 2066 | cur = dst_child; | ||
| 2067 | break; | ||
| 2068 | } | ||
| 2050 | cur = cur.childType(zcu); | 2069 | cur = cur.childType(zcu); |
| 2051 | depth += 1; | 2070 | depth += 1; |
| 2052 | }, | 2071 | }, |
| ... | @@ -2086,7 +2105,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -2086,7 +2105,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 2086 | } | 2105 | } |
| 2087 | } | 2106 | } |
| 2088 | 2107 | ||
| 2089 | return cg.fail("cannot perform pointer cast: '{f}' to '{f}'", .{ | 2108 | return cg.fail("cannot cast pointer '{f}' to '{f}'", .{ |
| 2090 | parent_ptr_ty.fmt(pt), | 2109 | parent_ptr_ty.fmt(pt), |
| 2091 | oac.new_ptr_ty.fmt(pt), | 2110 | oac.new_ptr_ty.fmt(pt), |
| 2092 | }); | 2111 | }); |
| ... | @@ -6029,7 +6048,13 @@ fn bitCast( | ... | @@ -6029,7 +6048,13 @@ fn bitCast( |
| 6029 | while (cur.toIntern() != dst_child.toIntern()) : (try indices.append(gpa, 0)) { | 6048 | while (cur.toIntern() != dst_child.toIntern()) : (try indices.append(gpa, 0)) { |
| 6030 | cur = switch (cur.zigTypeTag(zcu)) { | 6049 | cur = switch (cur.zigTypeTag(zcu)) { |
| 6031 | .array, .vector => cur.childType(zcu), | 6050 | .array, .vector => cur.childType(zcu), |
| 6032 | .@"struct" => cur.fieldType(0, zcu), | 6051 | .@"struct" => field: { |
| 6052 | for (0..cur.structFieldCount(zcu)) |i| { | ||
| 6053 | const field_ty = cur.fieldType(i, zcu); | ||
| 6054 | if (field_ty.hasRuntimeBits(zcu) and cur.structFieldOffset(i, zcu) == 0) break :field field_ty; | ||
| 6055 | } | ||
| 6056 | unreachable; | ||
| 6057 | }, | ||
| 6033 | else => unreachable, | 6058 | else => unreachable, |
| 6034 | }; | 6059 | }; |
| 6035 | } | 6060 | } |
| ... | @@ -6739,9 +6764,19 @@ fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { | ... | @@ -6739,9 +6764,19 @@ fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { |
| 6739 | const zcu = cg.zcu; | 6764 | const zcu = cg.zcu; |
| 6740 | // Construct new pointer type for the resulting pointer | 6765 | // Construct new pointer type for the resulting pointer |
| 6741 | const as = ptr_ty.ptrAddressSpace(zcu); | 6766 | const as = ptr_ty.ptrAddressSpace(zcu); |
| 6742 | const elem_ty_id = try cg.pointeeType(as, ptr_ty.indexableElem(zcu), false); | 6767 | const child_ty = ptr_ty.childType(zcu); |
| 6768 | const is_single_ptr = ptr_ty.isSinglePointer(zcu); | ||
| 6769 | const elem_is_block = switch (as) { | ||
| 6770 | .uniform, .storage_buffer => switch (child_ty.zigTypeTag(cg.zcu)) { | ||
| 6771 | .array => is_single_ptr, | ||
| 6772 | .spirv => is_single_ptr and child_ty.isSpirvRuntimeArray(cg.zcu), | ||
| 6773 | else => false, | ||
| 6774 | }, | ||
| 6775 | else => false, | ||
| 6776 | }; | ||
| 6777 | const elem_ty_id = try cg.pointeeType(as, ptr_ty.indexableElem(zcu), elem_is_block); | ||
| 6743 | const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(as)); | 6778 | const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(as)); |
| 6744 | if (ptr_ty.isSinglePointer(zcu)) { | 6779 | if (is_single_ptr) { |
| 6745 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | 6780 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 6746 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. | 6781 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. |
| 6747 | return cg.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id}); | 6782 | return cg.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id}); |
test/behavior/array.zig+4| ... | @@ -7,6 +7,8 @@ const expect = testing.expect; | ... | @@ -7,6 +7,8 @@ const expect = testing.expect; |
| 7 | const expectEqual = testing.expectEqual; | 7 | const expectEqual = testing.expectEqual; |
| 8 | 8 | ||
| 9 | test "array to slice" { | 9 | test "array to slice" { |
| 10 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 11 | |||
| 10 | const a: u32 align(4) = 3; | 12 | const a: u32 align(4) = 3; |
| 11 | const b: u32 align(8) = 4; | 13 | const b: u32 align(8) = 4; |
| 12 | const a_slice: []align(1) const u32 = @as(*const [1]u32, &a)[0..]; | 14 | const a_slice: []align(1) const u32 = @as(*const [1]u32, &a)[0..]; |
| ... | @@ -19,8 +21,10 @@ test "array to slice" { | ... | @@ -19,8 +21,10 @@ test "array to slice" { |
| 19 | } | 21 | } |
| 20 | 22 | ||
| 21 | test "arrays" { | 23 | test "arrays" { |
| 24 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 22 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 25 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 23 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 26 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 27 | |||
| 24 | var array: [5]u32 = undefined; | 28 | var array: [5]u32 = undefined; |
| 25 | 29 | ||
| 26 | var i: u32 = 0; | 30 | var i: u32 = 0; |
test/behavior/backing_int.zig+6| ... | @@ -137,6 +137,8 @@ const T5 = union(E5) { | ... | @@ -137,6 +137,8 @@ const T5 = union(E5) { |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | test "@backingInt with tagged unions" { | 139 | test "@backingInt with tagged unions" { |
| 140 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 141 | |||
| 140 | const static = struct { | 142 | const static = struct { |
| 141 | fn doTheTest(v1: T1, v2: T2, v4: T4, v5: T5) !void { | 143 | fn doTheTest(v1: T1, v2: T2, v4: T4, v5: T5) !void { |
| 142 | const b1 = @backingInt(v1); | 144 | const b1 = @backingInt(v1); |
| ... | @@ -311,6 +313,8 @@ const U5 = packed union(u0) { | ... | @@ -311,6 +313,8 @@ const U5 = packed union(u0) { |
| 311 | }; | 313 | }; |
| 312 | 314 | ||
| 313 | test "@backingInt with packed unions" { | 315 | test "@backingInt with packed unions" { |
| 316 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 317 | |||
| 314 | const static = struct { | 318 | const static = struct { |
| 315 | fn doTheTest(v1: U1, v2: U2, v3: U3, v4: U4, v5: U5) !void { | 319 | fn doTheTest(v1: U1, v2: U2, v3: U3, v4: U4, v5: U5) !void { |
| 316 | const b1 = @backingInt(v1); | 320 | const b1 = @backingInt(v1); |
| ... | @@ -339,6 +343,8 @@ test "@backingInt with packed unions" { | ... | @@ -339,6 +343,8 @@ test "@backingInt with packed unions" { |
| 339 | } | 343 | } |
| 340 | 344 | ||
| 341 | test "@fromBackingInt with packed unions" { | 345 | test "@fromBackingInt with packed unions" { |
| 346 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 347 | |||
| 342 | const static = struct { | 348 | const static = struct { |
| 343 | fn doTheTest( | 349 | fn doTheTest( |
| 344 | b1: @typeInfo(U1).@"union".backing_integer.?, | 350 | b1: @typeInfo(U1).@"union".backing_integer.?, |
test/behavior/cast.zig+1| ... | @@ -1806,6 +1806,7 @@ test "cast compatible optional types" { | ... | @@ -1806,6 +1806,7 @@ test "cast compatible optional types" { |
| 1806 | 1806 | ||
| 1807 | test "coerce undefined single-item pointer of array to error union of slice" { | 1807 | test "coerce undefined single-item pointer of array to error union of slice" { |
| 1808 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1808 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1809 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 1809 | 1810 | ||
| 1810 | const a = @as([*]u8, undefined)[0..0]; | 1811 | const a = @as([*]u8, undefined)[0..0]; |
| 1811 | var b: error{a}![]const u8 = a; | 1812 | var b: error{a}![]const u8 = a; |
test/behavior/comptime_memory.zig+2| ... | @@ -437,6 +437,8 @@ test "type pun null pointer-like optional" { | ... | @@ -437,6 +437,8 @@ test "type pun null pointer-like optional" { |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | test "write empty array to end" { | 439 | test "write empty array to end" { |
| 440 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 441 | |||
| 440 | comptime var array: [5]u8 = "hello".*; | 442 | comptime var array: [5]u8 = "hello".*; |
| 441 | array[5..5].* = .{}; | 443 | array[5..5].* = .{}; |
| 442 | array[5..5].* = [0]u8{}; | 444 | array[5..5].* = [0]u8{}; |
test/behavior/for.zig+1| ... | @@ -391,6 +391,7 @@ test "raw pointer and counter" { | ... | @@ -391,6 +391,7 @@ test "raw pointer and counter" { |
| 391 | test "inline for with slice as the comptime-known" { | 391 | test "inline for with slice as the comptime-known" { |
| 392 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 392 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 393 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 393 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 394 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 394 | 395 | ||
| 395 | const comptime_slice = "hello"; | 396 | const comptime_slice = "hello"; |
| 396 | var runtime_i: usize = 3; | 397 | var runtime_i: usize = 3; |
test/behavior/math.zig+2| ... | @@ -456,6 +456,7 @@ test "division" { | ... | @@ -456,6 +456,7 @@ test "division" { |
| 456 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 456 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 457 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 457 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 458 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 458 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 459 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 459 | try testIntDivision(); | 460 | try testIntDivision(); |
| 460 | try comptime testIntDivision(); | 461 | try comptime testIntDivision(); |
| 461 | 462 | ||
| ... | @@ -649,6 +650,7 @@ test "division half-precision floats" { | ... | @@ -649,6 +650,7 @@ test "division half-precision floats" { |
| 649 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 650 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 650 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 651 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 651 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 652 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 653 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 652 | 654 | ||
| 653 | try testDivisionFP16(); | 655 | try testDivisionFP16(); |
| 654 | try comptime testDivisionFP16(); | 656 | try comptime testDivisionFP16(); |
test/behavior/packed-union.zig+3| ... | @@ -229,6 +229,8 @@ test "initialize packed union field to undefined at comptime" { | ... | @@ -229,6 +229,8 @@ test "initialize packed union field to undefined at comptime" { |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | test "convert from/to backing int" { | 231 | test "convert from/to backing int" { |
| 232 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 233 | |||
| 232 | const U = packed union(u10) { | 234 | const U = packed union(u10) { |
| 233 | a: i10, | 235 | a: i10, |
| 234 | b: enum(u10) { x, y, z }, | 236 | b: enum(u10) { x, y, z }, |
| ... | @@ -244,6 +246,7 @@ test "convert from/to backing int" { | ... | @@ -244,6 +246,7 @@ test "convert from/to backing int" { |
| 244 | 246 | ||
| 245 | test "equality with wide backing integer" { | 247 | test "equality with wide backing integer" { |
| 246 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 | 248 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 |
| 249 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 247 | 250 | ||
| 248 | const U = packed union(i200) { | 251 | const U = packed union(i200) { |
| 249 | x: u200, | 252 | x: u200, |
test/behavior/pointers.zig+1| ... | @@ -701,6 +701,7 @@ test "pointer-to-array constness for zero-size elements, var" { | ... | @@ -701,6 +701,7 @@ test "pointer-to-array constness for zero-size elements, var" { |
| 701 | 701 | ||
| 702 | test "pointer-to-array constness for zero-size elements, const" { | 702 | test "pointer-to-array constness for zero-size elements, const" { |
| 703 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 703 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 704 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 704 | 705 | ||
| 705 | try constant(); | 706 | try constant(); |
| 706 | try comptime constant(); | 707 | try comptime constant(); |
test/behavior/ptrcast.zig+2| ... | @@ -6,6 +6,7 @@ const native_endian = builtin.target.cpu.arch.endian(); | ... | @@ -6,6 +6,7 @@ const native_endian = builtin.target.cpu.arch.endian(); |
| 6 | 6 | ||
| 7 | test "reinterpret bytes as integer with nonzero offset" { | 7 | test "reinterpret bytes as integer with nonzero offset" { |
| 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 9 | 10 | ||
| 10 | try testReinterpretBytesAsInteger(); | 11 | try testReinterpretBytesAsInteger(); |
| 11 | try comptime testReinterpretBytesAsInteger(); | 12 | try comptime testReinterpretBytesAsInteger(); |
| ... | @@ -39,6 +40,7 @@ fn testReinterpretWithOffsetAndNoWellDefinedLayout() !void { | ... | @@ -39,6 +40,7 @@ fn testReinterpretWithOffsetAndNoWellDefinedLayout() !void { |
| 39 | 40 | ||
| 40 | test "reinterpret bytes inside auto-layout struct as integer with nonzero offset" { | 41 | test "reinterpret bytes inside auto-layout struct as integer with nonzero offset" { |
| 41 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 42 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 43 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 42 | 44 | ||
| 43 | try testReinterpretStructWrappedBytesAsInteger(); | 45 | try testReinterpretStructWrappedBytesAsInteger(); |
| 44 | try comptime testReinterpretStructWrappedBytesAsInteger(); | 46 | try comptime testReinterpretStructWrappedBytesAsInteger(); |
test/behavior/sizeof_and_typeof.zig+2| ... | @@ -405,6 +405,8 @@ test "Extern function calls, dereferences and field access in @TypeOf" { | ... | @@ -405,6 +405,8 @@ test "Extern function calls, dereferences and field access in @TypeOf" { |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | test "@sizeOf struct is resolved when used as operand of slicing" { | 407 | test "@sizeOf struct is resolved when used as operand of slicing" { |
| 408 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 409 | |||
| 408 | const dummy = struct {}; | 410 | const dummy = struct {}; |
| 409 | const S = struct { | 411 | const S = struct { |
| 410 | var buf: [1]u8 = undefined; | 412 | var buf: [1]u8 = undefined; |
test/behavior/slice.zig+8| ... | @@ -59,6 +59,8 @@ test "const slice" { | ... | @@ -59,6 +59,8 @@ test "const slice" { |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | test "comptime slice of undefined pointer of length 0" { | 61 | test "comptime slice of undefined pointer of length 0" { |
| 62 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 63 | |||
| 62 | const slice1 = @as([*]i32, undefined)[0..0]; | 64 | const slice1 = @as([*]i32, undefined)[0..0]; |
| 63 | try expect(slice1.len == 0); | 65 | try expect(slice1.len == 0); |
| 64 | const slice2 = @as([*]i32, undefined)[100..100]; | 66 | const slice2 = @as([*]i32, undefined)[100..100]; |
| ... | @@ -173,6 +175,8 @@ test "pass a slice of types to a function" { | ... | @@ -173,6 +175,8 @@ test "pass a slice of types to a function" { |
| 173 | 175 | ||
| 174 | test "generic malloc free" { | 176 | test "generic malloc free" { |
| 175 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 177 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 178 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 179 | |||
| 176 | const a = memAlloc(u8, 10) catch unreachable; | 180 | const a = memAlloc(u8, 10) catch unreachable; |
| 177 | memFree(u8, a); | 181 | memFree(u8, a); |
| 178 | } | 182 | } |
| ... | @@ -209,6 +213,8 @@ test "comptime slice of pointer preserves comptime var" { | ... | @@ -209,6 +213,8 @@ test "comptime slice of pointer preserves comptime var" { |
| 209 | } | 213 | } |
| 210 | 214 | ||
| 211 | test "comptime pointer cast array and then slice" { | 215 | test "comptime pointer cast array and then slice" { |
| 216 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 217 | |||
| 212 | const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; | 218 | const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; |
| 213 | 219 | ||
| 214 | const ptrA: [*]const u8 = @as([*]const u8, @ptrCast(&array)); | 220 | const ptrA: [*]const u8 = @as([*]const u8, @ptrCast(&array)); |
| ... | @@ -1079,6 +1085,8 @@ test "conditionally return second argument slice" { | ... | @@ -1079,6 +1085,8 @@ test "conditionally return second argument slice" { |
| 1079 | } | 1085 | } |
| 1080 | 1086 | ||
| 1081 | test "slice field alignment" { | 1087 | test "slice field alignment" { |
| 1088 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 1089 | |||
| 1082 | const S = struct { | 1090 | const S = struct { |
| 1083 | fn doTheTest(p: *align(1) const []u8) !void { | 1091 | fn doTheTest(p: *align(1) const []u8) !void { |
| 1084 | comptime assert(@TypeOf(&p.ptr) == *align(1) const [*]u8); | 1092 | comptime assert(@TypeOf(&p.ptr) == *align(1) const [*]u8); |
test/behavior/spirv.zig+5-6| ... | @@ -49,13 +49,12 @@ test "@SpirvType" { | ... | @@ -49,13 +49,12 @@ test "@SpirvType" { |
| 49 | _ = runtime_array; | 49 | _ = runtime_array; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | const InnerStruct = extern struct { x: u32 }; | ||
| 53 | const OuterStruct = extern struct { inner: InnerStruct, y: u32 }; | ||
| 54 | const outer_pc = @extern(*addrspace(.push_constant) const OuterStruct, .{ .name = "outer_pc" }); | ||
| 55 | |||
| 56 | test "@ptrCast to first field type" { | 52 | test "@ptrCast to first field type" { |
| 57 | const pc_inner: *addrspace(.push_constant) const InnerStruct = @ptrCast(outer_pc); | 53 | const Inner = extern struct { a: u32 }; |
| 58 | _ = pc_inner; | 54 | const Outer = extern struct { a: Inner, b: u32 }; |
| 55 | var outer: Outer = undefined; | ||
| 56 | var inner: *Inner = @ptrCast(&outer); | ||
| 57 | _ = &inner; | ||
| 59 | } | 58 | } |
| 60 | 59 | ||
| 61 | test "@SpirvType equality" { | 60 | test "@SpirvType equality" { |
test/behavior/string_literals.zig+2| ... | @@ -84,6 +84,8 @@ test "string literal pointer sentinel" { | ... | @@ -84,6 +84,8 @@ test "string literal pointer sentinel" { |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | test "sentinel slice of string literal" { | 86 | test "sentinel slice of string literal" { |
| 87 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 88 | |||
| 87 | const string = "Hello!\x00World!"; | 89 | const string = "Hello!\x00World!"; |
| 88 | try std.testing.expect(@TypeOf(string) == *const [13:0]u8); | 90 | try std.testing.expect(@TypeOf(string) == *const [13:0]u8); |
| 89 | 91 |
test/behavior/vector.zig+2| ... | @@ -680,6 +680,8 @@ test "vector division operators" { | ... | @@ -680,6 +680,8 @@ test "vector division operators" { |
| 680 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 680 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 681 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 681 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 682 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 682 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 683 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 684 | |||
| 683 | const S = struct { | 685 | const S = struct { |
| 684 | fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void { | 686 | fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void { |
| 685 | const is_signed_int = switch (@typeInfo(T)) { | 687 | const is_signed_int = switch (@typeInfo(T)) { |
test/cases/compile_errors/directly_embedding_spirv_type_in_struct_and_union.zig+13-6| ... | @@ -3,22 +3,27 @@ const RuntimeArray = @SpirvType(.{ .runtime_array = u32 }); | ... | @@ -3,22 +3,27 @@ const RuntimeArray = @SpirvType(.{ .runtime_array = u32 }); |
| 3 | const Foo = struct { | 3 | const Foo = struct { |
| 4 | s: Sampler, | 4 | s: Sampler, |
| 5 | }; | 5 | }; |
| 6 | const Baz = struct { | 6 | const Bar = struct { |
| 7 | a: RuntimeArray, | 7 | a: RuntimeArray, |
| 8 | }; | 8 | }; |
| 9 | const Qux = extern struct { | 9 | const Baz = extern struct { |
| 10 | a: RuntimeArray, | 10 | a: RuntimeArray, |
| 11 | b: u32, | 11 | b: u32, |
| 12 | }; | 12 | }; |
| 13 | const Qux = extern struct { _: @SpirvType(.{ .runtime_array = Sampler }) }; | ||
| 13 | export fn a() void { | 14 | export fn a() void { |
| 14 | var foo: Foo = undefined; | 15 | var foo: Foo = undefined; |
| 15 | _ = &foo; | 16 | _ = &foo; |
| 16 | } | 17 | } |
| 17 | export fn c() void { | 18 | export fn c() void { |
| 19 | var bar: Bar = undefined; | ||
| 20 | _ = &bar; | ||
| 21 | } | ||
| 22 | export fn d() void { | ||
| 18 | var baz: Baz = undefined; | 23 | var baz: Baz = undefined; |
| 19 | _ = &baz; | 24 | _ = &baz; |
| 20 | } | 25 | } |
| 21 | export fn d() void { | 26 | export fn e() void { |
| 22 | var qux: Qux = undefined; | 27 | var qux: Qux = undefined; |
| 23 | _ = &qux; | 28 | _ = &qux; |
| 24 | } | 29 | } |
| ... | @@ -27,9 +32,11 @@ export fn d() void { | ... | @@ -27,9 +32,11 @@ export fn d() void { |
| 27 | // backend=selfhosted | 32 | // backend=selfhosted |
| 28 | // target=spirv32-vulkan | 33 | // target=spirv32-vulkan |
| 29 | // | 34 | // |
| 30 | // :4:8: error: cannot directly embed SPIR-V type 'tmp.Sampler__SpirvType_4' in struct | 35 | // :4:8: error: cannot directly embed SPIR-V type '@SpirvType(.sampler)' in struct |
| 31 | // :4:8: note: opaque types have unknown size | 36 | // :4:8: note: opaque types have unknown size |
| 32 | // :6:13: error: non-extern struct cannot contain fields of type 'tmp.RuntimeArray__SpirvType_11' | 37 | // :6:13: error: non-extern struct cannot contain fields of type '@SpirvType(.runtime_array, u32)' |
| 33 | // :7:5: note: while checking this field | 38 | // :7:5: note: while checking this field |
| 34 | // :9:20: error: struct field of type 'tmp.RuntimeArray__SpirvType_11' must be the last field | 39 | // :9:20: error: struct field of type '@SpirvType(.runtime_array, u32)' must be the last field |
| 35 | // :10:5: note: while checking this field | 40 | // :10:5: note: while checking this field |
| 41 | // :13:32: error: cannot embed SPIR-V type '@SpirvType(.sampler)' in struct | ||
| 42 | // :13:32: note: opaque types have unknown size |
test/cases/compile_errors/extern_spirv_decoration_validation.zig+1-1| ... | @@ -10,4 +10,4 @@ comptime { | ... | @@ -10,4 +10,4 @@ comptime { |
| 10 | // backend=selfhosted | 10 | // backend=selfhosted |
| 11 | // target=spirv32-vulkan | 11 | // target=spirv32-vulkan |
| 12 | // | 12 | // |
| 13 | // :1:45: error: "flat" decoration requires "input" or "output" address space | 13 | // :1:52: error: "flat" decoration requires "input" or "output" address space |
test/cases/compile_errors/extern_spirv_storage_buffer_must_be_single_pointer.zig deleted-25| ... | @@ -1,25 +0,0 @@ | ||
| 1 | const a = @extern([*]addrspace(.storage_buffer) u32, .{ | ||
| 2 | .name = "a", | ||
| 3 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, | ||
| 4 | }); | ||
| 5 | const b = @extern([]addrspace(.uniform) u32, .{ | ||
| 6 | .name = "b", | ||
| 7 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 1 } }, | ||
| 8 | }); | ||
| 9 | const c = @extern([*c]addrspace(.push_constant) u32, .{ .name = "c" }); | ||
| 10 | comptime { | ||
| 11 | _ = a; | ||
| 12 | _ = b; | ||
| 13 | _ = c; | ||
| 14 | } | ||
| 15 | |||
| 16 | // error | ||
| 17 | // backend=selfhosted | ||
| 18 | // target=spirv32-vulkan | ||
| 19 | // | ||
| 20 | // :1:19: error: extern in 'storage_buffer' address space must be a single-item pointer to a struct | ||
| 21 | // :1:19: note: wrap the element type in a struct containing a runtime-sized array | ||
| 22 | // :5:19: error: extern in 'uniform' address space must be a single-item pointer to a struct | ||
| 23 | // :5:19: note: wrap the element type in a struct containing a runtime-sized array | ||
| 24 | // :9:19: error: extern in 'push_constant' address space must be a single-item pointer to a struct | ||
| 25 | // :9:19: note: wrap the element type in a struct containing a runtime-sized array | ||
test/cases/compile_errors/illegal_operation_on_logical_ptr.zig+40-4| ... | @@ -22,14 +22,50 @@ export fn ptrIntArithmetic() void { | ... | @@ -22,14 +22,50 @@ export fn ptrIntArithmetic() void { |
| 22 | _ = ptr0 - 10; | 22 | _ = ptr0 - 10; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | const slice: []const u8 = "abc"; | ||
| 26 | |||
| 27 | export fn sliceElemVal() void { | ||
| 28 | var i: u32 = 0; | ||
| 29 | _ = &i; | ||
| 30 | _ = slice[i]; | ||
| 31 | } | ||
| 32 | |||
| 33 | export fn sliceElemPtr() void { | ||
| 34 | var i: u32 = 0; | ||
| 35 | _ = &i; | ||
| 36 | _ = &slice[i]; | ||
| 37 | } | ||
| 38 | |||
| 39 | export fn manyElemVal() void { | ||
| 40 | var ptr: [*]const u8 = "abc"; | ||
| 41 | var i: u32 = 0; | ||
| 42 | _ = .{ &ptr, &i }; | ||
| 43 | _ = ptr[i]; | ||
| 44 | } | ||
| 45 | |||
| 46 | export fn manyElemPtr() void { | ||
| 47 | var ptr: [*]const u8 = "abc"; | ||
| 48 | var i: u32 = 0; | ||
| 49 | _ = .{ &ptr, &i }; | ||
| 50 | _ = &ptr[i]; | ||
| 51 | } | ||
| 52 | |||
| 25 | // error | 53 | // error |
| 26 | // target=spirv64-vulkan | 54 | // target=spirv64-vulkan |
| 27 | // | 55 | // |
| 28 | // :3:21: error: illegal operation on logical pointer of type '*u8' | 56 | // :3:21: error: illegal operation on logical pointer of type '*u8' |
| 29 | // :3:21: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan | 57 | // :3:21: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan |
| 30 | // :8:20: error: illegal operation on logical pointer of type '*u8' | 58 | // :8:20: error: illegal operation on logical pointer of type '*u8' |
| 31 | // :8:20: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan | 59 | // :8:20: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan |
| 32 | // :16:17: error: illegal operation on logical pointer of type '*u8' | 60 | // :16:17: error: illegal operation on logical pointer of type '*u8' |
| 33 | // :16:17: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan | 61 | // :16:17: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan |
| 34 | // :22:14: error: illegal operation on logical pointer of type '[*]u8' | 62 | // :22:14: error: illegal operation on logical pointer of type '[*]u8' |
| 35 | // :22:14: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan | 63 | // :22:14: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan |
| 64 | // :30:14: error: illegal operation on logical pointer of type '[]const u8' | ||
| 65 | // :30:14: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan | ||
| 66 | // :36:15: error: illegal operation on logical pointer of type '[]const u8' | ||
| 67 | // :36:15: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan | ||
| 68 | // :43:12: error: illegal operation on logical pointer of type '[*]const u8' | ||
| 69 | // :43:12: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan | ||
| 70 | // :50:13: error: illegal operation on logical pointer of type '[*]const u8' | ||
| 71 | // :50:13: note: pointers with address space 'generic' do not support arithmetic or indexing on target spirv-vulkan |
test/cases/compile_errors/loading_spirv_runtime_array_value.zig+2-2| ... | @@ -19,5 +19,5 @@ export fn main2() callconv(.kernel) void { | ... | @@ -19,5 +19,5 @@ export fn main2() callconv(.kernel) void { |
| 19 | // backend=selfhosted | 19 | // backend=selfhosted |
| 20 | // target=spirv32-vulkan | 20 | // target=spirv32-vulkan |
| 21 | // | 21 | // |
| 22 | // :10:15: error: cannot load SPIR-V runtime array value | 22 | // :10:18: error: cannot load SPIR-V runtime array value |
| 23 | // :15:12: error: cannot load SPIR-V runtime array value | 23 | // :15:10: error: cannot load SPIR-V runtime array value |
test/cases/compile_errors/spirv_extern_runtime_descriptor_array.zig created+49| ... | @@ -0,0 +1,49 @@ | ||
| 1 | const Buffer = extern struct { value: u32 }; | ||
| 2 | const Sampler = @SpirvType(.sampler); | ||
| 3 | const RuntimeArray = @SpirvType(.{ .runtime_array = u32 }); | ||
| 4 | const SamplerRuntimeArray = @SpirvType(.{ .runtime_array = Sampler }); | ||
| 5 | const BufferRuntimeArray = @SpirvType(.{ .runtime_array = Buffer }); | ||
| 6 | |||
| 7 | const a = @extern(*addrspace(.input) const RuntimeArray, .{ .name = "a" }); | ||
| 8 | const b = @extern(*addrspace(.uniform) const RuntimeArray, .{ .name = "b" }); | ||
| 9 | const c = @extern(*addrspace(.storage_buffer) const RuntimeArray, .{ .name = "c" }); | ||
| 10 | const d = @extern(*addrspace(.constant) const RuntimeArray, .{ .name = "d" }); | ||
| 11 | const e = @extern(*addrspace(.constant) const SamplerRuntimeArray, .{ | ||
| 12 | .name = "samplers", | ||
| 13 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, | ||
| 14 | }); | ||
| 15 | const f = @extern(*addrspace(.storage_buffer) [4]Buffer, .{ | ||
| 16 | .name = "sized_buffers", | ||
| 17 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 1 } }, | ||
| 18 | }); | ||
| 19 | const g = @extern(*addrspace(.storage_buffer) BufferRuntimeArray, .{ | ||
| 20 | .name = "buffers", | ||
| 21 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 2 } }, | ||
| 22 | }); | ||
| 23 | |||
| 24 | comptime { | ||
| 25 | _ = a; | ||
| 26 | } | ||
| 27 | comptime { | ||
| 28 | _ = b; | ||
| 29 | } | ||
| 30 | comptime { | ||
| 31 | _ = c; | ||
| 32 | } | ||
| 33 | |||
| 34 | export fn main() callconv(.{ .spirv_fragment = .{} }) void { | ||
| 35 | _ = &d[0]; | ||
| 36 | _ = &e[0]; | ||
| 37 | f[0].value = 1; | ||
| 38 | g[0].value = 2; | ||
| 39 | } | ||
| 40 | |||
| 41 | // error | ||
| 42 | // backend=selfhosted | ||
| 43 | // target=spirv32-vulkan | ||
| 44 | // cpu_features=baseline+runtime_descriptor_array | ||
| 45 | // | ||
| 46 | // :7:19: error: SPIR-V runtime array is not allowed in the 'input' address space | ||
| 47 | // :8:19: error: extern in 'uniform' address space must be a single-item pointer to a struct | ||
| 48 | // :9:19: error: extern in 'storage_buffer' address space must be a single-item pointer to a struct | ||
| 49 | // :10:19: error: extern in 'constant' address space must point to an opaque SPIR-V type, or to an array of one | ||
test/cases/compile_errors/spirv_extern_var_addrspace.zig+41-5| ... | @@ -1,11 +1,47 @@ | ... | @@ -1,11 +1,47 @@ |
| 1 | extern var x: u32; | 1 | const Block = extern struct { x: u32 }; |
| 2 | const RuntimeArray = @SpirvType(.{ .runtime_array = u32 }); | ||
| 2 | 3 | ||
| 3 | export fn main() callconv(.kernel) void { | 4 | extern var implicit_addrspace: u32; |
| 4 | _ = x; | 5 | |
| 6 | const many = @extern([*]addrspace(.storage_buffer) u32, .{ | ||
| 7 | .name = "many", | ||
| 8 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, | ||
| 9 | }); | ||
| 10 | const push_array = @extern(*addrspace(.push_constant) const [4]Block, .{ .name = "push_array" }); | ||
| 11 | const plain_constant = @extern(*addrspace(.constant) const Block, .{ | ||
| 12 | .name = "plain_constant", | ||
| 13 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 1 } }, | ||
| 14 | }); | ||
| 15 | const runtime_array = @extern(*addrspace(.storage_buffer) RuntimeArray, .{ | ||
| 16 | .name = "runtime_array", | ||
| 17 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 2 } }, | ||
| 18 | }); | ||
| 19 | |||
| 20 | comptime { | ||
| 21 | _ = implicit_addrspace; | ||
| 22 | } | ||
| 23 | comptime { | ||
| 24 | _ = many; | ||
| 25 | } | ||
| 26 | comptime { | ||
| 27 | _ = push_array; | ||
| 28 | } | ||
| 29 | comptime { | ||
| 30 | _ = plain_constant; | ||
| 31 | } | ||
| 32 | comptime { | ||
| 33 | _ = runtime_array; | ||
| 5 | } | 34 | } |
| 6 | 35 | ||
| 7 | // error | 36 | // error |
| 8 | // backend=selfhosted | 37 | // backend=selfhosted |
| 9 | // target=spirv64-vulkan | 38 | // target=spirv32-vulkan |
| 10 | // | 39 | // |
| 11 | // :1:15: error: SPIR-V extern variables require an explicit address space | 40 | // :4:32: error: SPIR-V extern variables require an explicit address space |
| 41 | // :6:22: error: extern in 'storage_buffer' address space must be a single-item pointer to a struct | ||
| 42 | // :10:28: error: extern in 'push_constant' address space must be a single-item pointer to a struct | ||
| 43 | // :11:32: error: extern in 'constant' address space must point to an opaque SPIR-V type, or to an array of one | ||
| 44 | // :15:31: error: extern symbol cannot have type '*addrspace(.storage_buffer) @SpirvType(.runtime_array, u32)' | ||
| 45 | // :15:31: note: pointer element type '@SpirvType(.runtime_array, u32)' is not extern compatible | ||
| 46 | // :15:31: note: SPIR-V runtime arrays must be the last field of an extern struct | ||
| 47 | // :15:31: note: consider enabling the 'runtime_descriptor_array' feature to use the runtime array as the extern pointee |
test/cases/compile_errors/spirv_merge_logical_pointers.zig+1| ... | @@ -11,6 +11,7 @@ export fn a() void { | ... | @@ -11,6 +11,7 @@ export fn a() void { |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | // error | 13 | // error |
| 14 | // backend=selfhosted | ||
| 14 | // target=spirv32-vulkan | 15 | // target=spirv32-vulkan |
| 15 | // | 16 | // |
| 16 | // :9:13: error: value with non-mergable pointer type '*i32' depends on runtime control flow | 17 | // :9:13: error: value with non-mergable pointer type '*i32' depends on runtime control flow |
test/cases/compile_errors/spirv_pointer_cast_requires_offset_zero.zig+7-12| ... | @@ -1,20 +1,15 @@ | ... | @@ -1,20 +1,15 @@ |
| 1 | const A = extern struct { x: u32, y: u32 }; | 1 | const Inner = extern struct { a: u32 }; |
| 2 | const B = extern struct { a: u64 }; | 2 | const Outer = extern struct { a: u32, b: Inner }; |
| 3 | |||
| 4 | const a = @extern(*addrspace(.uniform) const A, .{ | ||
| 5 | .name = "a", | ||
| 6 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, | ||
| 7 | }); | ||
| 8 | 3 | ||
| 9 | export fn main() callconv(.kernel) void { | 4 | export fn main() callconv(.kernel) void { |
| 10 | const b: *addrspace(.uniform) const B = @ptrCast(a); | 5 | var outer: Outer = undefined; |
| 11 | _ = &b; | 6 | const inner: *Inner = @ptrCast(&outer); |
| 7 | _ = &inner; | ||
| 12 | } | 8 | } |
| 13 | 9 | ||
| 14 | // error | 10 | // error |
| 15 | // backend=selfhosted | 11 | // backend=selfhosted |
| 16 | // target=spirv32-vulkan | 12 | // target=spirv32-vulkan |
| 17 | // | 13 | // |
| 18 | // :10:44: error: cannot cast pointer '*addrspace(.uniform) const A' to '*addrspace(.uniform) const B' | 14 | // :6:27: error: cannot cast pointer '*tmp.Outer' to '*tmp.Inner' |
| 19 | // :10:44: note: 'B' must appear at offset 0 inside 'A' | 15 | // :6:27: note: 'tmp.Inner' must appear at offset 0 inside 'tmp.Outer' |
| 20 | // :10:44: note: 'uniform' pointers can only reach nested types through a first struct field or an array element |
test/cases/compile_errors/spirv_runtime_array_as_value_type.zig deleted-26| ... | @@ -1,26 +0,0 @@ | ||
| 1 | const RuntimeArray = @SpirvType(.{ .runtime_array = u32 }); | ||
| 2 | |||
| 3 | const a = @extern(*addrspace(.storage_buffer) RuntimeArray, .{ | ||
| 4 | .name = "a", | ||
| 5 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 0 } }, | ||
| 6 | }); | ||
| 7 | const b = @extern(*addrspace(.uniform) const RuntimeArray, .{ | ||
| 8 | .name = "b", | ||
| 9 | .decoration = .{ .descriptor = .{ .set = 0, .binding = 1 } }, | ||
| 10 | }); | ||
| 11 | |||
| 12 | comptime { | ||
| 13 | _ = a; | ||
| 14 | _ = b; | ||
| 15 | } | ||
| 16 | |||
| 17 | // error | ||
| 18 | // backend=selfhosted | ||
| 19 | // target=spirv32-vulkan | ||
| 20 | // | ||
| 21 | // :3:19: error: extern symbol cannot have type '*addrspace(.storage_buffer) @SpirvType(.runtime_array, u32)' | ||
| 22 | // :3:19: note: pointer element type '@SpirvType(.runtime_array, u32)' is not extern compatible | ||
| 23 | // :3:19: note: SPIR-V runtime arrays must be the last field of an extern struct | ||
| 24 | // :7:19: error: extern symbol cannot have type '*addrspace(.uniform) const @SpirvType(.runtime_array, u32)' | ||
| 25 | // :7:19: note: pointer element type '@SpirvType(.runtime_array, u32)' is not extern compatible | ||
| 26 | // :7:19: note: SPIR-V runtime arrays must be the last field of an extern struct | ||
test/cases/compile_errors/spirv_slices.zig+9-25| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | export fn a() void { | 1 | export fn a() void { |
| 2 | var buf: [3]f32 = undefined; | 2 | var x: [3]f32 = .{ 1, 2, 3 }; |
| 3 | takesSlice(&buf); // error | 3 | takesSlice(&x); |
| 4 | } | 4 | } |
| 5 | 5 | ||
| 6 | fn takesSlice(buf: []f32) void { | 6 | fn takesSlice(buf: []f32) void { |
| ... | @@ -8,34 +8,18 @@ fn takesSlice(buf: []f32) void { | ... | @@ -8,34 +8,18 @@ fn takesSlice(buf: []f32) void { |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | export fn b() void { | 10 | export fn b() void { |
| 11 | var buf: [3]f32 = undefined; | 11 | const x: [3]f32 = .{ 1, 2, 3 }; |
| 12 | for (buf[0..3]) |_| {} // error | 12 | for (comptime x[0..3]) |_| {} |
| 13 | } | 13 | for (&x) |_| {} |
| 14 | 14 | for (x[0..3]) |_| {} | |
| 15 | export fn c() void { | ||
| 16 | var buf: [3]f32 = undefined; | ||
| 17 | for (&buf) |_| {} // not an error | ||
| 18 | } | ||
| 19 | |||
| 20 | export fn d() void { | ||
| 21 | const buf: [3]f32 = .{1, 2, 3}; | ||
| 22 | for (comptime buf[0..3]) |_| {} // not an error | ||
| 23 | } | ||
| 24 | |||
| 25 | export fn e() void { | ||
| 26 | const buf: [3]f32 = .{1, 2, 3}; | ||
| 27 | for (comptime buf[0..3]) |_| {} // not an error | ||
| 28 | for (buf[0..3]) |_| {} // error | ||
| 29 | } | 15 | } |
| 30 | 16 | ||
| 31 | // error | 17 | // error |
| 32 | // backend=auto | 18 | // backend=selfhosted |
| 33 | // target=spirv32-opengl,spirv32-vulkan | 19 | // target=spirv32-opengl,spirv32-vulkan |
| 34 | // cpu_features=baseline+variable_pointers | 20 | // cpu_features=baseline+variable_pointers |
| 35 | // | 21 | // |
| 36 | // :3:16: error: cannot construct slice from address space 'generic' | 22 | // :3:16: error: cannot construct slice from address space 'generic' |
| 37 | // :3:16: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V | 23 | // :3:16: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V |
| 38 | // :12:13: error: cannot construct slice from address space 'generic' | 24 | // :14:11: error: cannot construct slice from address space 'generic' |
| 39 | // :12:13: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V | 25 | // :14:11: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V |
| 40 | // :28:13: error: cannot construct slice from address space 'generic' | ||
| 41 | // :28:13: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V |
test/cases/compile_errors/spirv_unsupported_float_width.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | export fn use_f80() callconv(.kernel) void { | ||
| 2 | var x: f80 = 1.5; | ||
| 3 | _ = &x; | ||
| 4 | } | ||
| 5 | |||
| 6 | export fn use_f16() callconv(.kernel) void { | ||
| 7 | var x: f16 = 1.5; | ||
| 8 | _ = &x; | ||
| 9 | } | ||
| 10 | |||
| 11 | // error | ||
| 12 | // backend=selfhosted | ||
| 13 | // target=spirv32-vulkan | ||
| 14 | // | ||
| 15 | // :2:5: error: 'f80' is not supported on the current SPIR-V feature set | ||
| 16 | // :7:5: error: 'f16' is not supported on the current SPIR-V feature set | ||
test/src/Cases.zig+6-5| ... | @@ -389,11 +389,12 @@ fn addFromDirInner( | ... | @@ -389,11 +389,12 @@ fn addFromDirInner( |
| 389 | const resolved_target = b.resolveTargetQuery(target_query); | 389 | const resolved_target = b.resolveTargetQuery(target_query); |
| 390 | const target = &resolved_target.result; | 390 | const target = &resolved_target.result; |
| 391 | for (backends) |backend| { | 391 | for (backends) |backend| { |
| 392 | if (backend == .selfhosted and | 392 | if (backend == .selfhosted) { |
| 393 | target.cpu.arch != .aarch64 and target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64) | 393 | switch (target.cpu.arch) { |
| 394 | { | 394 | .aarch64, .wasm32, .x86_64, .spirv64, .spirv32 => {}, |
| 395 | // Other backends don't support new liveness format | 395 | // Other backends don't support new liveness format |
| 396 | continue; | 396 | else => continue, |
| 397 | } | ||
| 397 | } | 398 | } |
| 398 | 399 | ||
| 399 | if (backend == .selfhosted and target.cpu.arch == .aarch64) { | 400 | if (backend == .selfhosted and target.cpu.arch == .aarch64) { |