From d4c539664661a93fe193a9559688e7c6c3955e0d Mon Sep 17 00:00:00 2001 From: mlugg Date: Sun, 16 Mar 2025 03:13:19 +0000 Subject: Sema: fix pointers to comptime fields of comptime-known aggregate pointers Resolves: #23190 --- src/Sema.zig | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 5c084cd4b6..788f8ba057 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -28013,12 +28013,17 @@ fn structFieldPtrByIndex( const zcu = pt.zcu; const ip = &zcu.intern_pool; - if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { - const val = try struct_ptr_val.ptrField(field_index, pt); - return Air.internedToRef(val.toIntern()); + const struct_type = zcu.typeToStruct(struct_ty).?; + const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); + + // Comptime fields are handled later + if (!field_is_comptime) { + if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { + const val = try struct_ptr_val.ptrField(field_index, pt); + return Air.internedToRef(val.toIntern()); + } } - const struct_type = zcu.typeToStruct(struct_ty).?; const field_ty = struct_type.field_types.get(ip)[field_index]; const struct_ptr_ty = sema.typeOf(struct_ptr); const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); @@ -28038,6 +28043,7 @@ fn structFieldPtrByIndex( try Type.fromInterned(struct_ptr_ty_info.child).abiAlignmentSema(pt); if (struct_type.layout == .@"packed") { + assert(!field_is_comptime); switch (struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt)) { .bit_ptr => |packed_offset| { ptr_ty_data.flags.alignment = parent_align; @@ -28048,6 +28054,7 @@ fn structFieldPtrByIndex( }, } } else if (struct_type.layout == .@"extern") { + assert(!field_is_comptime); // For extern structs, field alignment might be bigger than type's // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the // second field is aligned as u32. @@ -28071,7 +28078,7 @@ fn structFieldPtrByIndex( const ptr_field_ty = try pt.ptrTypeSema(ptr_ty_data); - if (struct_type.fieldIsComptime(ip, field_index)) { + if (field_is_comptime) { try struct_ty.resolveStructFieldInits(pt); const val = try pt.intern(.{ .ptr = .{ .ty = ptr_field_ty.toIntern(), -- cgit v1.2.3 From 95932e98e50f3762c3faf5ac3ee7c8f11f09096e Mon Sep 17 00:00:00 2001 From: mlugg Date: Sun, 16 Mar 2025 03:26:29 +0000 Subject: Sema: fix alignment of runtime field pointer of underaligned tuple --- src/Sema.zig | 16 ++++++++++++---- test/behavior/tuple.zig | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 788f8ba057..2696cbd87c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -28617,7 +28617,8 @@ fn tupleFieldPtr( const pt = sema.pt; const zcu = pt.zcu; const tuple_ptr_ty = sema.typeOf(tuple_ptr); - const tuple_ty = tuple_ptr_ty.childType(zcu); + const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu); + const tuple_ty: Type = .fromInterned(tuple_ptr_info.child); try tuple_ty.resolveFields(pt); const field_count = tuple_ty.structFieldCount(zcu); @@ -28635,9 +28636,16 @@ fn tupleFieldPtr( const ptr_field_ty = try pt.ptrTypeSema(.{ .child = field_ty.toIntern(), .flags = .{ - .is_const = !tuple_ptr_ty.ptrIsMutable(zcu), - .is_volatile = tuple_ptr_ty.isVolatilePtr(zcu), - .address_space = tuple_ptr_ty.ptrAddressSpace(zcu), + .is_const = tuple_ptr_info.flags.is_const, + .is_volatile = tuple_ptr_info.flags.is_volatile, + .address_space = tuple_ptr_info.flags.address_space, + .alignment = a: { + if (tuple_ptr_info.flags.alignment == .none) break :a .none; + // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned. + const tuple_align = tuple_ptr_info.flags.alignment; + const field_align = try field_ty.abiAlignmentSema(pt); + break :a tuple_align.min(field_align); + }, }, }); diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 492730df61..c9d3fb4b38 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -602,3 +602,21 @@ test "empty union in tuple" { try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name); try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"union"); } + +test "field pointer of underaligned tuple" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const S = struct { + fn doTheTest() !void { + const T = struct { u8, u32 }; + var val: T align(2) = .{ 1, 2 }; + + comptime assert(@TypeOf(&val[0]) == *u8); // `u8` field pointer isn't overaligned + comptime assert(@TypeOf(&val[1]) == *align(2) u32); // `u32` field pointer is correctly underaligned + + try expect(val[0] == 1); + try expect(val[1] == 2); + } + }; + try S.doTheTest(); + try comptime S.doTheTest(); +} -- cgit v1.2.3