Commit 5ea3de55c4
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;
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;