authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-20 16:44:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-21 14:48:40-07:00
log5ea3de55c4ca89b1f9fd95e40e6dd17cc89efe23
treeec6fe5bed28ae7e691cee88f32c93402fc7124cd
parent2671aa9058b3dcff147ef01dcf3876b0bb231673

Sema: fix dependency loop regression on struct field alignment


2 files changed, 57 insertions(+), 18 deletions(-)

src/Sema.zig+49-2
......@@ -34280,9 +34280,54 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3428034280 }
3428134281}
3428234282
34283fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
34284 try sema.resolveTypeFields(ty);
34283/// Resolve a struct's alignment only without triggering resolution of its layout.
34284/// Asserts that the alignment is not yet resolved and the layout is non-packed.
34285pub fn resolveStructAlignment(
34286 sema: *Sema,
34287 ty: InternPool.Index,
34288 struct_type: InternPool.Key.StructType,
34289) CompileError!Alignment {
34290 const mod = sema.mod;
34291 const ip = &mod.intern_pool;
34292 const target = mod.getTarget();
34293
34294 assert(struct_type.flagsPtr(ip).alignment == .none);
34295 assert(struct_type.layout != .Packed);
34296
34297 if (struct_type.flagsPtr(ip).field_types_wip) {
34298 // We'll guess "pointer-aligned", if the struct has an
34299 // underaligned pointer field then some allocations
34300 // might require explicit alignment.
34301 //TODO write this bit and emit an error later if incorrect
34302 //struct_type.flagsPtr(ip).assumed_pointer_aligned = true;
34303 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
34304 struct_type.flagsPtr(ip).alignment = result;
34305 return result;
34306 }
34307
34308 try sema.resolveTypeFieldsStruct(ty, struct_type);
34309
34310 var result: Alignment = .@"1";
3428534311
34312 for (0..struct_type.field_types.len) |i| {
34313 if (struct_type.fieldIsComptime(ip, i)) continue;
34314 const field_ty = struct_type.field_types.get(ip)[i].toType();
34315 if (try sema.typeRequiresComptime(field_ty)) continue;
34316 if (try sema.typeHasRuntimeBits(field_ty)) {
34317 const field_align = try sema.structFieldAlignment(
34318 struct_type.fieldAlign(ip, i),
34319 field_ty,
34320 struct_type.layout,
34321 );
34322 result = result.max(field_align);
34323 }
34324 }
34325
34326 struct_type.flagsPtr(ip).alignment = result;
34327 return result;
34328}
34329
34330fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3428634331 const mod = sema.mod;
3428734332 const ip = &mod.intern_pool;
3428834333 const struct_type = mod.typeToStruct(ty) orelse return;
......@@ -34290,6 +34335,8 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3429034335 if (struct_type.haveLayout(ip))
3429134336 return;
3429234337
34338 try sema.resolveTypeFields(ty);
34339
3429334340 if (struct_type.layout == .Packed) {
3429434341 try semaBackingIntType(mod, struct_type);
3429534342 return;
src/type.zig+8-16
......@@ -201,7 +201,7 @@ pub const Type = struct {
201201 info.flags.alignment
202202 else
203203 info.child.toType().abiAlignment(mod);
204 try writer.print("align({d}", .{alignment});
204 try writer.print("align({d}", .{alignment.toByteUnits(0)});
205205
206206 if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {
207207 try writer.print(":{d}:{d}", .{
......@@ -992,30 +992,22 @@ pub const Type = struct {
992992 },
993993 .eager => {},
994994 }
995 assert(struct_type.backingIntType(ip).* != .none);
996995 return .{ .scalar = struct_type.backingIntType(ip).toType().abiAlignment(mod) };
997996 }
998997
999998 const flags = struct_type.flagsPtr(ip).*;
1000 if (flags.layout_resolved) return .{ .scalar = flags.alignment };
999 if (flags.alignment != .none) return .{ .scalar = flags.alignment };
10011000
1002 switch (strat) {
1003 .eager => unreachable, // struct layout not resolved
1004 .sema => |sema| {
1005 if (flags.field_types_wip) {
1006 // We'll guess "pointer-aligned", if the struct has an
1007 // underaligned pointer field then some allocations
1008 // might require explicit alignment.
1009 return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) };
1010 }
1011 try sema.resolveTypeLayout(ty);
1012 return .{ .scalar = struct_type.flagsPtr(ip).alignment };
1001 return switch (strat) {
1002 .eager => unreachable, // struct alignment not resolved
1003 .sema => |sema| .{
1004 .scalar = try sema.resolveStructAlignment(ty.toIntern(), struct_type),
10131005 },
1014 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1006 .lazy => .{ .val = (try mod.intern(.{ .int = .{
10151007 .ty = .comptime_int_type,
10161008 .storage = .{ .lazy_align = ty.toIntern() },
10171009 } })).toValue() },
1018 }
1010 };
10191011 },
10201012 .anon_struct_type => |tuple| {
10211013 var big_align: Alignment = .none;