diff options
| author | kcbanner <kcbanner@gmail.com> | 2023-10-21 12:03:36 -0400 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2023-10-31 01:35:58 +0000 |
| commit | 4d044ee7e0b1ca61b8f2205f318449780ae23bd2 (patch) | |
| tree | 682b42b724238e7dc0231685eecaf0f408a1620e /src/type.zig | |
| parent | ffaeb4533395fafcf020d0aca2f2efd58e48a384 (diff) | |
| download | zig-4d044ee7e0b1ca61b8f2205f318449780ae23bd2.tar.gz zig-4d044ee7e0b1ca61b8f2205f318449780ae23bd2.zip | |
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.
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 74 |
1 files changed, 14 insertions, 60 deletions
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)) { |
