From 89838eb5f005f206f22116768d6ed3d13507dbd8 Mon Sep 17 00:00:00 2001 From: Brian Ferri Date: Sat, 3 Oct 2026 00:10:06 +0200 Subject: [PATCH] spirv: build derived pointer types only where they are used --- src/codegen/spirv/CodeGen.zig | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index e059594cbebabe97e830051df2b300dd8747d8c5..b1680336219b8ee00b49472964d45730ee6f792a 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -1684,6 +1684,13 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation); } +/// Emits the pointer type that one step of a pointer derivation results in, along with its +/// pointee type. A derivation is the sequence of steps that builds a comptime-known pointer: a +/// base address, such as a declaration, an anonymous value or an integer, followed by field, +/// element and cast steps, each of which is lowered on its own. +/// This function emits instructions on every call, and they stay in the module whether or not they +/// are read, so it should only be called where the resulting type is used: a buffer struct emitted +/// without `Block` fails validation even when nothing refers to it. fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id { return cg.ptrType( try cg.pointeeType(@"addrspace", derivation.elem_ty, false), @@ -1696,13 +1703,6 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu const zcu = cg.zcu; const target = zcu.getTarget(); - // A variable on Vulkan and OpenGL is used through its own pointer, so a `nav` resolves this only - // where it is used; a type emitted and left unused stays in the module. - const result_ty_id = switch (derivation.addr) { - .nav => undefined, - else => try cg.derivedPtrType(@"addrspace", derivation), - }; - switch (derivation.addr) { .comptime_alloc, .comptime_field => unreachable, .int => |int| { @@ -1717,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu // TODO: This can probably be an OpSpecConstantOp Bitcast, but // that is not implemented by Mesa yet. Therefore, just generate it // as a runtime operation. + const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); const result_ptr_id = cg.allocId(); const value_id = try cg.constInt(.usize, int); try cg.body.emit(gpa, .OpConvertUToPtr, .{ @@ -1759,12 +1760,12 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu const nav_ty_id = try cg.resolveType(nav_ty, .indirect); const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as)); - const nav_result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); - if (decl_ptr_ty_id == nav_result_ty_id) return var_id; + const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); + if (decl_ptr_ty_id == result_ty_id) return var_id; const casted_ptr_id = cg.allocId(); try cg.body.emit(gpa, .OpBitcast, .{ - .id_result_type = nav_result_ty_id, + .id_result_type = result_ty_id, .id_result = casted_ptr_id, .operand = var_id, }); @@ -1781,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu } if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) { - return cg.constUndef(result_ty_id); + return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation)); } if (cg.storageClass(@"addrspace") != .function) { @@ -1798,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu .opt_payload => @panic("TODO"), .field => |derived| return cg.structFieldPtr( @"addrspace", - result_ty_id, + try cg.derivedPtrType(@"addrspace", derivation), derivation.elem_ty, derived.parent.elem_ty, try cg.derivePtr(@"addrspace", derived.parent.*), @@ -1850,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu const zero = try cg.constInt(.u32, 0); const ids = try cg.id_scratch.addManyAsSlice(gpa, depth); @memset(ids, zero); - return cg.accessChainId(result_ty_id, parent_ptr_id, ids); + return cg.accessChainId(try cg.derivedPtrType(@"addrspace", derivation), parent_ptr_id, ids); } else { return parent_ptr_id; } } if (target.os.tag == .opencl) { + const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); const result_ptr_id = cg.allocId(); try cg.body.emit(gpa, .OpBitcast, .{ .id_result_type = result_ty_id, -- 2.54.0