authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-03-16 03:26:29+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-04-28 01:14:24+01:00
log95932e98e50f3762c3faf5ac3ee7c8f11f09096e
tree3496052f75c6aad4aada9aab8caec4ba5196646e
parentd4c539664661a93fe193a9559688e7c6c3955e0d
signaturelock-open Commit is signed but in an unrecognized format.

Sema: fix alignment of runtime field pointer of underaligned tuple


2 files changed, 30 insertions(+), 4 deletions(-)

src/Sema.zig+12-4
...@@ -28617,7 +28617,8 @@ fn tupleFieldPtr(...@@ -28617,7 +28617,8 @@ fn tupleFieldPtr(
28617 const pt = sema.pt;28617 const pt = sema.pt;
28618 const zcu = pt.zcu;28618 const zcu = pt.zcu;
28619 const tuple_ptr_ty = sema.typeOf(tuple_ptr);28619 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
28620 const tuple_ty = tuple_ptr_ty.childType(zcu);28620 const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu);
28621 const tuple_ty: Type = .fromInterned(tuple_ptr_info.child);
28621 try tuple_ty.resolveFields(pt);28622 try tuple_ty.resolveFields(pt);
28622 const field_count = tuple_ty.structFieldCount(zcu);28623 const field_count = tuple_ty.structFieldCount(zcu);
2862328624
...@@ -28635,9 +28636,16 @@ fn tupleFieldPtr(...@@ -28635,9 +28636,16 @@ fn tupleFieldPtr(
28635 const ptr_field_ty = try pt.ptrTypeSema(.{28636 const ptr_field_ty = try pt.ptrTypeSema(.{
28636 .child = field_ty.toIntern(),28637 .child = field_ty.toIntern(),
28637 .flags = .{28638 .flags = .{
28638 .is_const = !tuple_ptr_ty.ptrIsMutable(zcu),28639 .is_const = tuple_ptr_info.flags.is_const,
28639 .is_volatile = tuple_ptr_ty.isVolatilePtr(zcu),28640 .is_volatile = tuple_ptr_info.flags.is_volatile,
28640 .address_space = tuple_ptr_ty.ptrAddressSpace(zcu),28641 .address_space = tuple_ptr_info.flags.address_space,
28642 .alignment = a: {
28643 if (tuple_ptr_info.flags.alignment == .none) break :a .none;
28644 // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned.
28645 const tuple_align = tuple_ptr_info.flags.alignment;
28646 const field_align = try field_ty.abiAlignmentSema(pt);
28647 break :a tuple_align.min(field_align);
28648 },
28641 },28649 },
28642 });28650 });
2864328651
test/behavior/tuple.zig+18
...@@ -602,3 +602,21 @@ test "empty union in tuple" {...@@ -602,3 +602,21 @@ test "empty union in tuple" {
602 try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name);602 try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name);
603 try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"union");603 try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"union");
604}604}
605
606test "field pointer of underaligned tuple" {
607 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
608 const S = struct {
609 fn doTheTest() !void {
610 const T = struct { u8, u32 };
611 var val: T align(2) = .{ 1, 2 };
612
613 comptime assert(@TypeOf(&val[0]) == *u8); // `u8` field pointer isn't overaligned
614 comptime assert(@TypeOf(&val[1]) == *align(2) u32); // `u32` field pointer is correctly underaligned
615
616 try expect(val[0] == 1);
617 try expect(val[1] == 2);
618 }
619 };
620 try S.doTheTest();
621 try comptime S.doTheTest();
622}