authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-03 22:33:10-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-04 06:04:30-05:00
log459f3b7edef14da7d9ec29a77329601469f08b36
tree561fb06a0b68bc2ac652aae3ea0ec034882fc828
parentea76946d2af588d135e79a97f19d128acfeb8915

codegen: fix tuple padding

Closes #25797

2 files changed, 24 insertions(+), 25 deletions(-)

src/codegen.zig+12-25
...@@ -534,9 +534,7 @@ pub fn generateSymbol(...@@ -534,9 +534,7 @@ pub fn generateSymbol(
534 while (index < vector_type.len) : (index += 1) {534 while (index < vector_type.len) : (index += 1) {
535 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {535 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
536 .bytes => unreachable,536 .bytes => unreachable,
537 .elems => |elems| elems[537 .elems => |elems| elems[math.cast(usize, index) orelse return error.Overflow],
538 math.cast(usize, index) orelse return error.Overflow
539 ],
540 .repeated_elem => |elem| elem,538 .repeated_elem => |elem| elem,
541 }), w, reloc_parent);539 }), w, reloc_parent);
542 }540 }
...@@ -551,35 +549,24 @@ pub fn generateSymbol(...@@ -551,35 +549,24 @@ pub fn generateSymbol(
551 },549 },
552 .tuple_type => |tuple| {550 .tuple_type => |tuple| {
553 const struct_begin = w.end;551 const struct_begin = w.end;
554 for (552 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, field_index| {
555 tuple.types.get(ip),553 if (field_val != .none) continue;
556 tuple.values.get(ip),
557 0..,
558 ) |field_ty, comptime_val, index| {
559 if (comptime_val != .none) continue;
560 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;554 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
561555
562 const field_val = switch (aggregate.storage) {556 try w.splatByteAll(0, math.cast(usize, struct_begin +
557 Type.fromInterned(field_ty).abiAlignment(zcu).forward(w.end - struct_begin) - w.end) orelse
558 return error.Overflow);
559 try generateSymbol(bin_file, pt, src_loc, .fromInterned(switch (aggregate.storage) {
563 .bytes => |bytes| try pt.intern(.{ .int = .{560 .bytes => |bytes| try pt.intern(.{ .int = .{
564 .ty = field_ty,561 .ty = field_ty,
565 .storage = .{ .u64 = bytes.at(index, ip) },562 .storage = .{ .u64 = bytes.at(field_index, ip) },
566 } }),563 } }),
567 .elems => |elems| elems[index],564 .elems => |elems| elems[field_index],
568 .repeated_elem => |elem| elem,565 .repeated_elem => |elem| elem,
569 };566 }), w, reloc_parent);
570
571 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent);
572 const unpadded_field_end = w.end - struct_begin;
573
574 // Pad struct members if required
575 const padded_field_end = ty.structFieldOffset(index + 1, zcu);
576 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse
577 return error.Overflow;
578
579 if (padding > 0) {
580 try w.splatByteAll(0, padding);
581 }
582 }567 }
568 try w.splatByteAll(0, math.cast(usize, struct_begin + ty.abiSize(zcu) - w.end) orelse
569 return error.Overflow);
583 },570 },
584 .struct_type => {571 .struct_type => {
585 const struct_type = ip.loadStructType(ty.toIntern());572 const struct_type = ip.loadStructType(ty.toIntern());
test/behavior/tuple.zig+12
...@@ -631,3 +631,15 @@ test "OPV tuple fields aren't comptime" {...@@ -631,3 +631,15 @@ test "OPV tuple fields aren't comptime" {
631 const t2_info = @typeInfo(T2);631 const t2_info = @typeInfo(T2);
632 try expect(!t2_info.@"struct".fields[0].is_comptime);632 try expect(!t2_info.@"struct".fields[0].is_comptime);
633}633}
634
635test "array of tuples that end with a zero-bit field followed by padding" {
636 const S = struct {
637 var foo: [2]struct { u32, u8, void } = .{ .{ 1, 2, {} }, .{ 3, 4, {} } };
638 };
639 try expect(S.foo[0][0] == 1);
640 try expect(S.foo[0][1] == 2);
641 try expect(S.foo[0][2] == {});
642 try expect(S.foo[1][0] == 3);
643 try expect(S.foo[1][1] == 4);
644 try expect(S.foo[1][2] == {});
645}