diff options
| -rw-r--r-- | src/Sema.zig | 51 | ||||
| -rw-r--r-- | src/type.zig | 24 |
2 files changed, 57 insertions, 18 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 41e74eae07..2f19557a17 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -34280,9 +34280,54 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void { } } -fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { - try sema.resolveTypeFields(ty); +/// Resolve a struct's alignment only without triggering resolution of its layout. +/// Asserts that the alignment is not yet resolved and the layout is non-packed. +pub fn resolveStructAlignment( + sema: *Sema, + ty: InternPool.Index, + struct_type: InternPool.Key.StructType, +) CompileError!Alignment { + const mod = sema.mod; + const ip = &mod.intern_pool; + const target = mod.getTarget(); + + assert(struct_type.flagsPtr(ip).alignment == .none); + assert(struct_type.layout != .Packed); + + if (struct_type.flagsPtr(ip).field_types_wip) { + // We'll guess "pointer-aligned", if the struct has an + // underaligned pointer field then some allocations + // might require explicit alignment. + //TODO write this bit and emit an error later if incorrect + //struct_type.flagsPtr(ip).assumed_pointer_aligned = true; + const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); + struct_type.flagsPtr(ip).alignment = result; + return result; + } + + try sema.resolveTypeFieldsStruct(ty, struct_type); + + var result: Alignment = .@"1"; + for (0..struct_type.field_types.len) |i| { + if (struct_type.fieldIsComptime(ip, i)) continue; + const field_ty = struct_type.field_types.get(ip)[i].toType(); + if (try sema.typeRequiresComptime(field_ty)) continue; + if (try sema.typeHasRuntimeBits(field_ty)) { + const field_align = try sema.structFieldAlignment( + struct_type.fieldAlign(ip, i), + field_ty, + struct_type.layout, + ); + result = result.max(field_align); + } + } + + struct_type.flagsPtr(ip).alignment = result; + return result; +} + +fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { const mod = sema.mod; const ip = &mod.intern_pool; const struct_type = mod.typeToStruct(ty) orelse return; @@ -34290,6 +34335,8 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { if (struct_type.haveLayout(ip)) return; + try sema.resolveTypeFields(ty); + if (struct_type.layout == .Packed) { try semaBackingIntType(mod, struct_type); return; diff --git a/src/type.zig b/src/type.zig index 9520a36965..5a94f9c57a 100644 --- a/src/type.zig +++ b/src/type.zig @@ -201,7 +201,7 @@ pub const Type = struct { info.flags.alignment else info.child.toType().abiAlignment(mod); - try writer.print("align({d}", .{alignment}); + try writer.print("align({d}", .{alignment.toByteUnits(0)}); if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) { try writer.print(":{d}:{d}", .{ @@ -992,30 +992,22 @@ pub const Type = struct { }, .eager => {}, } - assert(struct_type.backingIntType(ip).* != .none); return .{ .scalar = struct_type.backingIntType(ip).toType().abiAlignment(mod) }; } const flags = struct_type.flagsPtr(ip).*; - if (flags.layout_resolved) return .{ .scalar = flags.alignment }; + if (flags.alignment != .none) return .{ .scalar = flags.alignment }; - switch (strat) { - .eager => unreachable, // struct layout not resolved - .sema => |sema| { - if (flags.field_types_wip) { - // We'll guess "pointer-aligned", if the struct has an - // underaligned pointer field then some allocations - // might require explicit alignment. - return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) }; - } - try sema.resolveTypeLayout(ty); - return .{ .scalar = struct_type.flagsPtr(ip).alignment }; + return switch (strat) { + .eager => unreachable, // struct alignment not resolved + .sema => |sema| .{ + .scalar = try sema.resolveStructAlignment(ty.toIntern(), struct_type), }, - .lazy => return .{ .val = (try mod.intern(.{ .int = .{ + .lazy => .{ .val = (try mod.intern(.{ .int = .{ .ty = .comptime_int_type, .storage = .{ .lazy_align = ty.toIntern() }, } })).toValue() }, - } + }; }, .anon_struct_type => |tuple| { var big_align: Alignment = .none; |
