Skip to content

Commit 459f3b7

Browse files
committed
codegen: fix tuple padding
Closes #25797
1 parent ea76946 commit 459f3b7

File tree

2 files changed

+24
-25
lines changed

2 files changed

+24
-25
lines changed

src/codegen.zig

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -534,9 +534,7 @@ pub fn generateSymbol(
534534
while (index < vector_type.len) : (index += 1) {
535535
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {
536536
.bytes => unreachable,
537-
.elems => |elems| elems[
538-
math.cast(usize, index) orelse return error.Overflow
539-
],
537+
.elems => |elems| elems[math.cast(usize, index) orelse return error.Overflow],
540538
.repeated_elem => |elem| elem,
541539
}), w, reloc_parent);
542540
}
@@ -551,35 +549,24 @@ pub fn generateSymbol(
551549
},
552550
.tuple_type => |tuple| {
553551
const struct_begin = w.end;
554-
for (
555-
tuple.types.get(ip),
556-
tuple.values.get(ip),
557-
0..,
558-
) |field_ty, comptime_val, index| {
559-
if (comptime_val != .none) continue;
552+
for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, field_index| {
553+
if (field_val != .none) continue;
560554
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) {
563560
.bytes => |bytes| try pt.intern(.{ .int = .{
564561
.ty = field_ty,
565-
.storage = .{ .u64 = bytes.at(index, ip) },
562+
.storage = .{ .u64 = bytes.at(field_index, ip) },
566563
} }),
567-
.elems => |elems| elems[index],
564+
.elems => |elems| elems[field_index],
568565
.repeated_elem => |elem| elem,
569-
};
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-
}
566+
}), w, reloc_parent);
582567
}
568+
try w.splatByteAll(0, math.cast(usize, struct_begin + ty.abiSize(zcu) - w.end) orelse
569+
return error.Overflow);
583570
},
584571
.struct_type => {
585572
const struct_type = ip.loadStructType(ty.toIntern());

test/behavior/tuple.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,3 +631,15 @@ test "OPV tuple fields aren't comptime" {
631631
const t2_info = @typeInfo(T2);
632632
try expect(!t2_info.@"struct".fields[0].is_comptime);
633633
}
634+
635+
test "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+
}

0 commit comments

Comments
 (0)