authorgravatar for me@brianferri.devBrian Ferri <me@brianferri.dev> 2026-10-03 00:10:06+02:00
committergravatar for me@brianferri.devBrian Ferri <me@brianferri.dev> 2026-10-03 00:10:06+02:00
log89838eb5f005f206f22116768d6ed3d13507dbd8
tree7739135a2df576c6e8ae32772bfe1907c7e67cb9
parent82281d53fb9cf2883fa099cff1e06790f8099c05
signature Signed by SSH key SHA256:tmUEGJn/zF+25GuUWrgw46/H3HO5tyY5DOfoj51gjV0

spirv: build derived pointer types only where they are used


1 files changed, 15 insertions(+), 13 deletions(-)

src/codegen/spirv/CodeGen.zig+15-13
...@@ -1684,6 +1684,13 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {...@@ -1684,6 +1684,13 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
1684 return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation);1684 return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation);
1685}1685}
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.
1687fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {1694fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
1688 return cg.ptrType(1695 return cg.ptrType(
1689 try cg.pointeeType(@"addrspace", derivation.elem_ty, false),1696 try cg.pointeeType(@"addrspace", derivation.elem_ty, false),
...@@ -1696,13 +1703,6 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu...@@ -1696,13 +1703,6 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
1696 const zcu = cg.zcu;1703 const zcu = cg.zcu;
1697 const target = zcu.getTarget();1704 const target = zcu.getTarget();
16981705
1699 // A variable on Vulkan and OpenGL is used through its own pointer, so a `nav` resolves this only
1700 // where it is used; a type emitted and left unused stays in the module.
1701 const result_ty_id = switch (derivation.addr) {
1702 .nav => undefined,
1703 else => try cg.derivedPtrType(@"addrspace", derivation),
1704 };
1705
1706 switch (derivation.addr) {1706 switch (derivation.addr) {
1707 .comptime_alloc, .comptime_field => unreachable,1707 .comptime_alloc, .comptime_field => unreachable,
1708 .int => |int| {1708 .int => |int| {
...@@ -1717,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu...@@ -1717,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
1717 // TODO: This can probably be an OpSpecConstantOp Bitcast, but1717 // TODO: This can probably be an OpSpecConstantOp Bitcast, but
1718 // that is not implemented by Mesa yet. Therefore, just generate it1718 // that is not implemented by Mesa yet. Therefore, just generate it
1719 // as a runtime operation.1719 // as a runtime operation.
1720 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1720 const result_ptr_id = cg.allocId();1721 const result_ptr_id = cg.allocId();
1721 const value_id = try cg.constInt(.usize, int);1722 const value_id = try cg.constInt(.usize, int);
1722 try cg.body.emit(gpa, .OpConvertUToPtr, .{1723 try cg.body.emit(gpa, .OpConvertUToPtr, .{
...@@ -1759,12 +1760,12 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu...@@ -1759,12 +1760,12 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17591760
1760 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);1761 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
1761 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as));1762 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as));
1762 const nav_result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);1763 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1763 if (decl_ptr_ty_id == nav_result_ty_id) return var_id;1764 if (decl_ptr_ty_id == result_ty_id) return var_id;
17641765
1765 const casted_ptr_id = cg.allocId();1766 const casted_ptr_id = cg.allocId();
1766 try cg.body.emit(gpa, .OpBitcast, .{1767 try cg.body.emit(gpa, .OpBitcast, .{
1767 .id_result_type = nav_result_ty_id,1768 .id_result_type = result_ty_id,
1768 .id_result = casted_ptr_id,1769 .id_result = casted_ptr_id,
1769 .operand = var_id,1770 .operand = var_id,
1770 });1771 });
...@@ -1781,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu...@@ -1781,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
1781 }1782 }
17821783
1783 if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) {1784 if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) {
1784 return cg.constUndef(result_ty_id);1785 return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
1785 }1786 }
17861787
1787 if (cg.storageClass(@"addrspace") != .function) {1788 if (cg.storageClass(@"addrspace") != .function) {
...@@ -1798,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu...@@ -1798,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
1798 .opt_payload => @panic("TODO"),1799 .opt_payload => @panic("TODO"),
1799 .field => |derived| return cg.structFieldPtr(1800 .field => |derived| return cg.structFieldPtr(
1800 @"addrspace",1801 @"addrspace",
1801 result_ty_id,1802 try cg.derivedPtrType(@"addrspace", derivation),
1802 derivation.elem_ty,1803 derivation.elem_ty,
1803 derived.parent.elem_ty,1804 derived.parent.elem_ty,
1804 try cg.derivePtr(@"addrspace", derived.parent.*),1805 try cg.derivePtr(@"addrspace", derived.parent.*),
...@@ -1850,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu...@@ -1850,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
1850 const zero = try cg.constInt(.u32, 0);1851 const zero = try cg.constInt(.u32, 0);
1851 const ids = try cg.id_scratch.addManyAsSlice(gpa, depth);1852 const ids = try cg.id_scratch.addManyAsSlice(gpa, depth);
1852 @memset(ids, zero);1853 @memset(ids, zero);
1853 return cg.accessChainId(result_ty_id, parent_ptr_id, ids);1854 return cg.accessChainId(try cg.derivedPtrType(@"addrspace", derivation), parent_ptr_id, ids);
1854 } else {1855 } else {
1855 return parent_ptr_id;1856 return parent_ptr_id;
1856 }1857 }
1857 }1858 }
1858 if (target.os.tag == .opencl) {1859 if (target.os.tag == .opencl) {
1860 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1859 const result_ptr_id = cg.allocId();1861 const result_ptr_id = cg.allocId();
1860 try cg.body.emit(gpa, .OpBitcast, .{1862 try cg.body.emit(gpa, .OpBitcast, .{
1861 .id_result_type = result_ty_id,1863 .id_result_type = result_ty_id,