authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-09-13 21:00:59+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-09-18 16:36:24+03:30
logec82de3637c3727bfbf2f8f6b014d144256daa95
treebb2a68f43876f2c72f25f24a5859d52d0a7b71e4
parent2d6970dd2c5f4fa7b1b141710d5d319668f0b46b

spirv: correctly map struct field indices to emitted member


3 files changed, 30 insertions(+), 6 deletions(-)

src/codegen/spirv/CodeGen.zig+30-2
......@@ -6732,7 +6732,7 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
67326732 if (field_ty.isInt(zcu)) return result_id;
67336733 return try cg.bitCast(field_ty, field_int_ty, result_id);
67346734 },
6735 else => return try cg.extractField(field_ty, object_id, field_index),
6735 else => return try cg.extractField(field_ty, object_id, cg.memberIndex(object_ty, field_index)),
67366736 },
67376737 .@"union" => switch (object_ty.containerLayout(zcu)) {
67386738 .@"packed" => {
......@@ -6882,7 +6882,8 @@ fn structFieldPtr(
68826882 return result_id;
68836883 },
68846884 .auto, .@"extern" => {
6885 return try cg.accessChain(result_ty_id, object_ptr, &.{field_index});
6885 const member_index = cg.memberIndex(object_ty, field_index);
6886 return try cg.accessChain(result_ty_id, object_ptr, &.{member_index});
68866887 },
68876888 },
68886889 .@"union" => switch (object_ty.containerLayout(zcu)) {
......@@ -6937,6 +6938,33 @@ fn structFieldPtr(
69376938 }
69386939}
69396940
6941fn memberIndex(cg: *CodeGen, struct_ty: Type, field_index: u32) u32 {
6942 const zcu = cg.zcu;
6943 const ip = &zcu.intern_pool;
6944 var index: u32 = 0;
6945 switch (ip.indexToKey(struct_ty.toIntern())) {
6946 .tuple_type => |tuple| {
6947 const types = tuple.types.get(ip)[0..field_index];
6948 for (types, tuple.values.get(ip)[0..field_index]) |field_ty_index, field_val| {
6949 const field_ty: Type = .fromInterned(field_ty_index);
6950 if (field_val != .none or !field_ty.hasRuntimeBits(zcu)) continue;
6951 index += 1;
6952 }
6953 },
6954 .struct_type => {
6955 const struct_type = ip.loadStructType(struct_ty.toIntern());
6956 var it = struct_type.iterateRuntimeOrder(ip);
6957 while (it.next()) |i| {
6958 if (i == field_index) break;
6959 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
6960 if (field_ty.hasRuntimeBits(zcu)) index += 1;
6961 }
6962 },
6963 else => unreachable,
6964 }
6965 return index;
6966}
6967
69406968fn airStructFieldPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
69416969 const ty_pl = cg.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
69426970 const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data;
test/behavior/struct.zig-2
......@@ -1945,8 +1945,6 @@ test "struct field default value is a call" {
19451945}
19461946
19471947test "aggregate initializers should allow initializing comptime fields, verifying equality" {
1948 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1949
19501948 var x: u32 = 15;
19511949 _ = &x;
19521950 const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
test/behavior/tuple.zig-2
......@@ -203,8 +203,6 @@ test "offsetOf anon struct" {
203203}
204204
205205test "initializing tuple with mixed comptime-runtime fields" {
206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
207
208206 var x: u32 = 15;
209207 _ = &x;
210208 const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });