From 4d044ee7e0b1ca61b8f2205f318449780ae23bd2 Mon Sep 17 00:00:00 2001 From: kcbanner Date: Sat, 21 Oct 2023 12:03:36 -0400 Subject: sema: Add union alignment resolution - Add resolveUnionAlignment, to resolve a union's alignment only, without triggering layout resolution. - Update resolveUnionLayout to cache size, alignment, and padding. abiSizeAdvanced and abiAlignmentAdvanced now use this information instead of computing it each time. --- src/type.zig | 74 ++++++++++++------------------------------------------------ 1 file changed, 14 insertions(+), 60 deletions(-) (limited to 'src/type.zig') diff --git a/src/type.zig b/src/type.zig index 086a293351..eef3783fe6 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1034,66 +1034,20 @@ pub const Type = struct { } return .{ .scalar = big_align }; }, - .union_type => |union_type| { - if (opt_sema) |sema| { - if (union_type.flagsPtr(ip).status == .field_types_wip) { - // We'll guess "pointer-aligned", if the union has an - // underaligned pointer field then some allocations - // might require explicit alignment. - return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) }; - } - _ = try sema.resolveTypeFields(ty); - } - if (!union_type.haveFieldTypes(ip)) switch (strat) { + const flags = union_type.flagsPtr(ip).*; + if (flags.alignment != .none) return .{ .scalar = flags.alignment }; + + if (!union_type.haveLayout(ip)) switch (strat) { .eager => unreachable, // union layout not resolved - .sema => unreachable, // handled above + .sema => |sema| return .{ .scalar = try sema.resolveUnionAlignment(ty, union_type) }, .lazy => return .{ .val = (try mod.intern(.{ .int = .{ .ty = .comptime_int_type, .storage = .{ .lazy_align = ty.toIntern() }, } })).toValue() }, }; - const union_obj = ip.loadUnionType(union_type); - if (union_obj.field_names.len == 0) { - if (union_obj.hasTag(ip)) { - return abiAlignmentAdvanced(union_obj.enum_tag_ty.toType(), mod, strat); - } else { - return .{ .scalar = .@"1" }; - } - } - var max_align: Alignment = .@"1"; - if (union_obj.hasTag(ip)) max_align = union_obj.enum_tag_ty.toType().abiAlignment(mod); - for (0..union_obj.field_names.len) |field_index| { - const field_ty = union_obj.field_types.get(ip)[field_index].toType(); - const field_align = if (union_obj.field_aligns.len == 0) - .none - else - union_obj.field_aligns.get(ip)[field_index]; - if (!(field_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { - error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })).toValue() }, - else => |e| return e, - })) continue; - - const field_align_bytes: Alignment = if (field_align != .none) - field_align - else switch (try field_ty.abiAlignmentAdvanced(mod, strat)) { - .scalar => |a| a, - .val => switch (strat) { - .eager => unreachable, // struct layout not resolved - .sema => unreachable, // handled above - .lazy => return .{ .val = (try mod.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })).toValue() }, - }, - }; - max_align = max_align.max(field_align_bytes); - } - return .{ .scalar = max_align }; + return .{ .scalar = union_type.flagsPtr(ip).alignment }; }, .opaque_type => return .{ .scalar = .@"1" }, .enum_type => |enum_type| return .{ @@ -1451,8 +1405,8 @@ pub const Type = struct { }, .eager => {}, } - const union_obj = ip.loadUnionType(union_type); - return AbiSizeAdvanced{ .scalar = mod.unionAbiSize(union_obj) }; + + return .{ .scalar = union_type.size(ip).* }; }, .opaque_type => unreachable, // no size available .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) }, @@ -2680,11 +2634,11 @@ pub const Type = struct { if (struct_type.flagsPtr(ip).field_types_wip) return false; - try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type); - struct_type.flagsPtr(ip).requires_comptime = .wip; errdefer struct_type.flagsPtr(ip).requires_comptime = .unknown; + try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type); + for (0..struct_type.field_types.len) |i_usize| { const i: u32 = @intCast(i_usize); if (struct_type.fieldIsComptime(ip, i)) continue; @@ -2723,12 +2677,12 @@ pub const Type = struct { if (union_type.flagsPtr(ip).status == .field_types_wip) return false; - try sema.resolveTypeFieldsUnion(ty, union_type); - const union_obj = ip.loadUnionType(union_type); + union_type.flagsPtr(ip).requires_comptime = .wip; + errdefer union_type.flagsPtr(ip).requires_comptime = .unknown; - union_obj.flagsPtr(ip).requires_comptime = .wip; - errdefer union_obj.flagsPtr(ip).requires_comptime = .unknown; + try sema.resolveTypeFieldsUnion(ty, union_type); + const union_obj = ip.loadUnionType(union_type); for (0..union_obj.field_types.len) |field_idx| { const field_ty = union_obj.field_types.get(ip)[field_idx]; if (try field_ty.toType().comptimeOnlyAdvanced(mod, opt_sema)) { -- cgit v1.2.3