authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-06 04:16:16+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-06 04:16:16+02:00
loga7a6d1730db30d6541eedf3be1531d323eb7a93a
treee824b72f4c201d0d187cb4ee21efd32d266c7aa2
parent96b9286a1bff0cf7ce407448bc4aaadb1d446e22
parent89838eb5f005f206f22116768d6ed3d13507dbd8

Merge pull request 'spirv: fix three regressions that make Vulkan modules invalid' (#37050) from brianferri/zig:fix/spirv-regressions into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37050 Reviewed-by: Ali Cheraghi <alichraghi@noreply.codeberg.org>

3 files changed, 38 insertions(+), 17 deletions(-)

src/Air/Legalize.zig+1-1
......@@ -904,7 +904,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
904904 .splat => {
905905 const ty_op = l.air_instructions.items(.data)[@backingInt(inst)].ty_op;
906906 switch (ty_op.ty.zigTypeTag(zcu)) {
907 .vector => switch (ty_op.ty.vectorLen(zcu)) {
907 .vector => if (l.features.has(.splat_one_elem_to_bit_cast)) switch (ty_op.ty.vectorLen(zcu)) {
908908 0 => unreachable,
909909 1 => continue :inst l.replaceInst(inst, .bit_cast, .{ .ty_op = .{
910910 .ty = ty_op.ty,
src/codegen/spirv/CodeGen.zig+27-16
......@@ -1684,16 +1684,25 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
16841684 return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation);
16851685}
16861686
1687/// Emits the pointer type that one step of a pointer derivation results in, along with its
1688/// pointee type. A derivation is the sequence of steps that builds a comptime-known pointer: a
1689/// base address, such as a declaration, an anonymous value or an integer, followed by field,
1690/// element and cast steps, each of which is lowered on its own.
1691/// This function emits instructions on every call, and they stay in the module whether or not they
1692/// are read, so it should only be called where the resulting type is used: a buffer struct emitted
1693/// without `Block` fails validation even when nothing refers to it.
1694fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
1695 return cg.ptrType(
1696 try cg.pointeeType(@"addrspace", derivation.elem_ty, false),
1697 cg.storageClass(@"addrspace"),
1698 );
1699}
1700
16871701fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
16881702 const gpa = cg.gpa;
16891703 const zcu = cg.zcu;
16901704 const target = zcu.getTarget();
16911705
1692 const result_ty_id = try cg.ptrType(
1693 try cg.pointeeType(@"addrspace", derivation.elem_ty, false),
1694 cg.storageClass(@"addrspace"),
1695 );
1696
16971706 switch (derivation.addr) {
16981707 .comptime_alloc, .comptime_field => unreachable,
16991708 .int => |int| {
......@@ -1708,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17081717 // TODO: This can probably be an OpSpecConstantOp Bitcast, but
17091718 // that is not implemented by Mesa yet. Therefore, just generate it
17101719 // as a runtime operation.
1720 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
17111721 const result_ptr_id = cg.allocId();
17121722 const value_id = try cg.constInt(.usize, int);
17131723 try cg.body.emit(gpa, .OpConvertUToPtr, .{
......@@ -1727,10 +1737,10 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17271737
17281738 if (ip.isFunctionType(nav_ty.toIntern())) {
17291739 if (is_extern) return try cg.resolveExternFn(nav_index);
1730 return try cg.constUndef(result_ty_id);
1740 return try cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
17311741 }
17321742 if (!nav_ty.hasRuntimeBits(zcu) and nav_ty.zigTypeTag(zcu) != .spirv) {
1733 return cg.constUndef(result_ty_id);
1743 return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
17341744 }
17351745 if (!is_extern) {
17361746 return cg.todo("pointer to constant '{f}'", .{nav.fqn.fmt(ip)});
......@@ -1739,20 +1749,20 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17391749 const as = nav.resolved.?.@"addrspace";
17401750 assert(as != .generic);
17411751
1742 const storage_class = cg.storageClass(as);
17431752 const var_id = try cg.resolveNav(nav_index);
1744 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
1745 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class);
17461753 if (cg.needsLayout(as, nav_ty)) {
17471754 try cg.block_var_ids.put(gpa, var_id, {});
17481755 }
1749
1750 if (decl_ptr_ty_id == result_ty_id) return var_id;
17511756 switch (target.os.tag) {
17521757 .vulkan, .opengl => return var_id,
17531758 else => {},
17541759 }
17551760
1761 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
1762 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as));
1763 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1764 if (decl_ptr_ty_id == result_ty_id) return var_id;
1765
17561766 const casted_ptr_id = cg.allocId();
17571767 try cg.body.emit(gpa, .OpBitcast, .{
17581768 .id_result_type = result_ty_id,
......@@ -1772,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17721782 }
17731783
17741784 if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) {
1775 return cg.constUndef(result_ty_id);
1785 return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
17761786 }
17771787
17781788 if (cg.storageClass(@"addrspace") != .function) {
......@@ -1789,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17891799 .opt_payload => @panic("TODO"),
17901800 .field => |derived| return cg.structFieldPtr(
17911801 @"addrspace",
1792 result_ty_id,
1802 try cg.derivedPtrType(@"addrspace", derivation),
17931803 derivation.elem_ty,
17941804 derived.parent.elem_ty,
17951805 try cg.derivePtr(@"addrspace", derived.parent.*),
......@@ -1801,7 +1811,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
18011811 .many => .many_ptr,
18021812 },
18031813 @"addrspace",
1804 derived.parent.elem_ty,
1814 derivation.elem_ty,
18051815 try cg.derivePtr(@"addrspace", derived.parent.*),
18061816 try cg.constInt(.usize, derived.elem_index),
18071817 ),
......@@ -1841,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
18411851 const zero = try cg.constInt(.u32, 0);
18421852 const ids = try cg.id_scratch.addManyAsSlice(gpa, depth);
18431853 @memset(ids, zero);
1844 return cg.accessChainId(result_ty_id, parent_ptr_id, ids);
1854 return cg.accessChainId(try cg.derivedPtrType(@"addrspace", derivation), parent_ptr_id, ids);
18451855 } else {
18461856 return parent_ptr_id;
18471857 }
18481858 }
18491859 if (target.os.tag == .opencl) {
1860 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
18501861 const result_ptr_id = cg.allocId();
18511862 try cg.body.emit(gpa, .OpBitcast, .{
18521863 .id_result_type = result_ty_id,
test/behavior/splat.zig+10
......@@ -145,6 +145,16 @@ test "vector @splat" {
145145 try testForT(8 * 2, @as(f16, 3.1415));
146146 try testForT(4 * 2, @as(f32, 3.1415));
147147 try testForT(2 * 2, @as(f64, 3.1415));
148
149 // Splats into one-element vectors.
150 try testForT(1, @as(u8, 0xEE));
151 try testForT(1, @as(u16, 0xBEEF));
152 try testForT(1, @as(u32, 0xDEADBEEF));
153 try testForT(1, @as(u64, 0xCAFEF00DDEADBEEF));
154
155 try testForT(1, @as(f16, 3.1415));
156 try testForT(1, @as(f32, 3.1415));
157 try testForT(1, @as(f64, 3.1415));
148158 }
149159 };
150160 try S.doTheTest();