authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-10-21 12:03:36-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-10-31 01:35:58+00:00
log4d044ee7e0b1ca61b8f2205f318449780ae23bd2
tree682b42b724238e7dc0231685eecaf0f408a1620e
parentffaeb4533395fafcf020d0aca2f2efd58e48a384

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.

4 files changed, 153 insertions(+), 95 deletions(-)

src/InternPool.zig+32-3
...@@ -491,7 +491,7 @@ pub const Key = union(enum) {...@@ -491,7 +491,7 @@ pub const Key = union(enum) {
491491
492 /// The returned pointer expires with any addition to the `InternPool`.492 /// The returned pointer expires with any addition to the `InternPool`.
493 /// Asserts the struct is not packed.493 /// Asserts the struct is not packed.
494 pub fn flagsPtr(self: @This(), ip: *InternPool) *Tag.TypeStruct.Flags {494 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStruct.Flags {
495 assert(self.layout != .Packed);495 assert(self.layout != .Packed);
496 const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?;496 const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?;
497 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);497 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
...@@ -687,6 +687,18 @@ pub const Key = union(enum) {...@@ -687,6 +687,18 @@ pub const Key = union(enum) {
687 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);687 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
688 }688 }
689689
690 /// The returned pointer expires with any addition to the `InternPool`.
691 pub fn size(self: @This(), ip: *InternPool) *u32 {
692 const size_field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?;
693 return @ptrCast(&ip.extra.items[self.extra_index + size_field_index]);
694 }
695
696 /// The returned pointer expires with any addition to the `InternPool`.
697 pub fn padding(self: @This(), ip: *InternPool) *u32 {
698 const padding_field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?;
699 return @ptrCast(&ip.extra.items[self.extra_index + padding_field_index]);
700 }
701
690 pub fn haveFieldTypes(self: @This(), ip: *const InternPool) bool {702 pub fn haveFieldTypes(self: @This(), ip: *const InternPool) bool {
691 return self.flagsPtr(ip).status.haveFieldTypes();703 return self.flagsPtr(ip).status.haveFieldTypes();
692 }704 }
...@@ -1744,6 +1756,10 @@ pub const UnionType = struct {...@@ -1744,6 +1756,10 @@ pub const UnionType = struct {
1744 enum_tag_ty: Index,1756 enum_tag_ty: Index,
1745 /// The integer tag type of the enum.1757 /// The integer tag type of the enum.
1746 int_tag_ty: Index,1758 int_tag_ty: Index,
1759 /// ABI size of the union, including padding
1760 size: u64,
1761 /// Trailing padding bytes
1762 padding: u32,
1747 /// List of field names in declaration order.1763 /// List of field names in declaration order.
1748 field_names: NullTerminatedString.Slice,1764 field_names: NullTerminatedString.Slice,
1749 /// List of field types in declaration order.1765 /// List of field types in declaration order.
...@@ -1830,6 +1846,10 @@ pub const UnionType = struct {...@@ -1830,6 +1846,10 @@ pub const UnionType = struct {
1830 return self.flagsPtr(ip).runtime_tag.hasTag();1846 return self.flagsPtr(ip).runtime_tag.hasTag();
1831 }1847 }
18321848
1849 pub fn haveFieldTypes(self: UnionType, ip: *const InternPool) bool {
1850 return self.flagsPtr(ip).status.haveFieldTypes();
1851 }
1852
1833 pub fn haveLayout(self: UnionType, ip: *const InternPool) bool {1853 pub fn haveLayout(self: UnionType, ip: *const InternPool) bool {
1834 return self.flagsPtr(ip).status.haveLayout();1854 return self.flagsPtr(ip).status.haveLayout();
1835 }1855 }
...@@ -1867,6 +1887,8 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {...@@ -1867,6 +1887,8 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {
1867 .namespace = type_union.data.namespace,1887 .namespace = type_union.data.namespace,
1868 .enum_tag_ty = enum_ty,1888 .enum_tag_ty = enum_ty,
1869 .int_tag_ty = enum_info.tag_ty,1889 .int_tag_ty = enum_info.tag_ty,
1890 .size = type_union.data.padding,
1891 .padding = type_union.data.padding,
1870 .field_names = enum_info.names,1892 .field_names = enum_info.names,
1871 .names_map = enum_info.names_map,1893 .names_map = enum_info.names_map,
1872 .field_types = .{1894 .field_types = .{
...@@ -2943,6 +2965,10 @@ pub const Tag = enum(u8) {...@@ -2943,6 +2965,10 @@ pub const Tag = enum(u8) {
2943 /// 1. field align: Alignment for each field; declaration order2965 /// 1. field align: Alignment for each field; declaration order
2944 pub const TypeUnion = struct {2966 pub const TypeUnion = struct {
2945 flags: Flags,2967 flags: Flags,
2968 // Only valid after .have_layout
2969 size: u32,
2970 // Only valid after .have_layout
2971 padding: u32,
2946 decl: Module.Decl.Index,2972 decl: Module.Decl.Index,
2947 namespace: Module.Namespace.Index,2973 namespace: Module.Namespace.Index,
2948 /// The enum that provides the list of field names and values.2974 /// The enum that provides the list of field names and values.
...@@ -2957,7 +2983,8 @@ pub const Tag = enum(u8) {...@@ -2957,7 +2983,8 @@ pub const Tag = enum(u8) {
2957 status: UnionType.Status,2983 status: UnionType.Status,
2958 requires_comptime: RequiresComptime,2984 requires_comptime: RequiresComptime,
2959 assumed_runtime_bits: bool,2985 assumed_runtime_bits: bool,
2960 _: u21 = 0,2986 alignment: Alignment,
2987 _: u15 = 0,
2961 };2988 };
2962 };2989 };
29632990
...@@ -3021,7 +3048,7 @@ pub const Tag = enum(u8) {...@@ -3021,7 +3048,7 @@ pub const Tag = enum(u8) {
3021 any_comptime_fields: bool,3048 any_comptime_fields: bool,
3022 any_default_inits: bool,3049 any_default_inits: bool,
3023 any_aligned_fields: bool,3050 any_aligned_fields: bool,
3024 /// `undefined` until the layout_resolved3051 /// `.none` until layout_resolved
3025 alignment: Alignment,3052 alignment: Alignment,
3026 /// Dependency loop detection when resolving struct alignment.3053 /// Dependency loop detection when resolving struct alignment.
3027 alignment_wip: bool,3054 alignment_wip: bool,
...@@ -5262,6 +5289,8 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat...@@ -5262,6 +5289,8 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
52625289
5263 const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{5290 const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{
5264 .flags = ini.flags,5291 .flags = ini.flags,
5292 .size = std.math.maxInt(u32),
5293 .padding = std.math.maxInt(u32),
5265 .decl = ini.decl,5294 .decl = ini.decl,
5266 .namespace = ini.namespace,5295 .namespace = ini.namespace,
5267 .tag_ty = ini.enum_tag_ty,5296 .tag_ty = ini.enum_tag_ty,
src/Module.zig+3-23
...@@ -6538,31 +6538,11 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {...@@ -6538,31 +6538,11 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
6538 .padding = 0,6538 .padding = 0,
6539 };6539 };
6540 }6540 }
6541 // Put the tag before or after the payload depending on which one's6541
6542 // alignment is greater.
6543 const tag_size = u.enum_tag_ty.toType().abiSize(mod);6542 const tag_size = u.enum_tag_ty.toType().abiSize(mod);
6544 const tag_align = u.enum_tag_ty.toType().abiAlignment(mod).max(.@"1");6543 const tag_align = u.enum_tag_ty.toType().abiAlignment(mod).max(.@"1");
6545 var size: u64 = 0;
6546 var padding: u32 = undefined;
6547 if (tag_align.compare(.gte, payload_align)) {
6548 // {Tag, Payload}
6549 size += tag_size;
6550 size = payload_align.forward(size);
6551 size += payload_size;
6552 const prev_size = size;
6553 size = tag_align.forward(size);
6554 padding = @intCast(size - prev_size);
6555 } else {
6556 // {Payload, Tag}
6557 size += payload_size;
6558 size = tag_align.forward(size);
6559 size += tag_size;
6560 const prev_size = size;
6561 size = payload_align.forward(size);
6562 padding = @intCast(size - prev_size);
6563 }
6564 return .{6544 return .{
6565 .abi_size = size,6545 .abi_size = u.size,
6566 .abi_align = tag_align.max(payload_align),6546 .abi_align = tag_align.max(payload_align),
6567 .most_aligned_field = most_aligned_field,6547 .most_aligned_field = most_aligned_field,
6568 .most_aligned_field_size = most_aligned_field_size,6548 .most_aligned_field_size = most_aligned_field_size,
...@@ -6571,7 +6551,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {...@@ -6571,7 +6551,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
6571 .payload_align = payload_align,6551 .payload_align = payload_align,
6572 .tag_align = tag_align,6552 .tag_align = tag_align,
6573 .tag_size = tag_size,6553 .tag_size = tag_size,
6574 .padding = padding,6554 .padding = u.padding,
6575 };6555 };
6576}6556}
65776557
src/Sema.zig+104-9
...@@ -3200,6 +3200,7 @@ fn zirUnionDecl(...@@ -3200,6 +3200,7 @@ fn zirUnionDecl(
3200 .any_aligned_fields = small.any_aligned_fields,3200 .any_aligned_fields = small.any_aligned_fields,
3201 .requires_comptime = .unknown,3201 .requires_comptime = .unknown,
3202 .assumed_runtime_bits = false,3202 .assumed_runtime_bits = false,
3203 .alignment = .none,
3203 },3204 },
3204 .decl = new_decl_index,3205 .decl = new_decl_index,
3205 .namespace = new_namespace_index,3206 .namespace = new_namespace_index,
...@@ -20988,6 +20989,7 @@ fn zirReify(...@@ -20988,6 +20989,7 @@ fn zirReify(
20988 .any_aligned_fields = any_aligned_fields,20989 .any_aligned_fields = any_aligned_fields,
20989 .requires_comptime = .unknown,20990 .requires_comptime = .unknown,
20990 .assumed_runtime_bits = false,20991 .assumed_runtime_bits = false,
20992 .alignment = .none,
20991 },20993 },
20992 .field_types = union_fields.items(.type),20994 .field_types = union_fields.items(.type),
20993 .field_aligns = if (any_aligned_fields) union_fields.items(.alignment) else &.{},20995 .field_aligns = if (any_aligned_fields) union_fields.items(.alignment) else &.{},
...@@ -34921,11 +34923,56 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void...@@ -34921,11 +34923,56 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
34921 return sema.failWithOwnedErrorMsg(block, msg);34923 return sema.failWithOwnedErrorMsg(block, msg);
34922}34924}
3492334925
34926/// Resolve a unions's alignment only without triggering resolution of its layout.
34927/// Asserts that the alignment is not yet resolved.
34928pub fn resolveUnionAlignment(
34929 sema: *Sema,
34930 ty: Type,
34931 union_type: InternPool.Key.UnionType,
34932) CompileError!Alignment {
34933 const mod = sema.mod;
34934 const ip = &mod.intern_pool;
34935 const target = mod.getTarget();
34936
34937 assert(!union_type.haveLayout(ip));
34938
34939 if (union_type.flagsPtr(ip).status == .field_types_wip) {
34940 // We'll guess "pointer-aligned", if the union has an
34941 // underaligned pointer field then some allocations
34942 // might require explicit alignment.
34943 return Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
34944 }
34945
34946 try sema.resolveTypeFieldsUnion(ty, union_type);
34947
34948 const union_obj = ip.loadUnionType(union_type);
34949 var max_align: Alignment = .@"1";
34950 for (0..union_obj.field_names.len) |field_index| {
34951 const field_ty = union_obj.field_types.get(ip)[field_index].toType();
34952 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
34953
34954 const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index));
34955 const field_align = if (explicit_align != .none)
34956 explicit_align
34957 else
34958 try sema.typeAbiAlignment(field_ty);
34959
34960 max_align = max_align.max(field_align);
34961 }
34962
34963 union_type.flagsPtr(ip).alignment = max_align;
34964 return max_align;
34965}
34966
34967/// This logic must be kept in sync with `Module.getUnionLayout`.
34924fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {34968fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
34925 const mod = sema.mod;34969 const mod = sema.mod;
34926 const ip = &mod.intern_pool;34970 const ip = &mod.intern_pool;
34927 try sema.resolveTypeFields(ty);34971
34928 const union_obj = mod.typeToUnion(ty).?;34972 const union_type = ip.indexToKey(ty.ip_index).union_type;
34973 try sema.resolveTypeFieldsUnion(ty, union_type);
34974
34975 const union_obj = ip.loadUnionType(union_type);
34929 switch (union_obj.flagsPtr(ip).status) {34976 switch (union_obj.flagsPtr(ip).status) {
34930 .none, .have_field_types => {},34977 .none, .have_field_types => {},
34931 .field_types_wip, .layout_wip => {34978 .field_types_wip, .layout_wip => {
...@@ -34939,25 +34986,74 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -34939,25 +34986,74 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
34939 },34986 },
34940 .have_layout, .fully_resolved_wip, .fully_resolved => return,34987 .have_layout, .fully_resolved_wip, .fully_resolved => return,
34941 }34988 }
34989
34942 const prev_status = union_obj.flagsPtr(ip).status;34990 const prev_status = union_obj.flagsPtr(ip).status;
34943 errdefer if (union_obj.flagsPtr(ip).status == .layout_wip) {34991 errdefer if (union_obj.flagsPtr(ip).status == .layout_wip) {
34944 union_obj.flagsPtr(ip).status = prev_status;34992 union_obj.flagsPtr(ip).status = prev_status;
34945 };34993 };
3494634994
34947 union_obj.flagsPtr(ip).status = .layout_wip;34995 union_obj.flagsPtr(ip).status = .layout_wip;
34948 for (0..union_obj.field_types.len) |field_index| {34996
34997 var max_size: u64 = 0;
34998 var max_align: Alignment = .@"1";
34999 for (0..union_obj.field_names.len) |field_index| {
34949 const field_ty = union_obj.field_types.get(ip)[field_index].toType();35000 const field_ty = union_obj.field_types.get(ip)[field_index].toType();
34950 sema.resolveTypeLayout(field_ty) catch |err| switch (err) {35001 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
35002
35003 max_size = @max(max_size, sema.typeAbiSize(field_ty) catch |err| switch (err) {
34951 error.AnalysisFail => {35004 error.AnalysisFail => {
34952 const msg = sema.err orelse return err;35005 const msg = sema.err orelse return err;
34953 try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});35006 try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});
34954 return err;35007 return err;
34955 },35008 },
34956 else => return err,35009 else => return err,
34957 };35010 });
34958 }35011
34959 union_obj.flagsPtr(ip).status = .have_layout;35012 const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index));
34960 _ = try sema.typeRequiresComptime(ty);35013 const field_align = if (explicit_align != .none)
35014 explicit_align
35015 else
35016 try sema.typeAbiAlignment(field_ty);
35017
35018 max_align = max_align.max(field_align);
35019 }
35020
35021 const flags = union_obj.flagsPtr(ip);
35022 const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(union_obj.enum_tag_ty.toType());
35023 const size, const alignment, const padding = if (has_runtime_tag) layout: {
35024 const enum_tag_type = union_obj.enum_tag_ty.toType();
35025 const tag_align = try sema.typeAbiAlignment(enum_tag_type);
35026 const tag_size = try sema.typeAbiSize(enum_tag_type);
35027
35028 // Put the tag before or after the payload depending on which one's
35029 // alignment is greater.
35030 var size: u64 = 0;
35031 var padding: u32 = 0;
35032 if (tag_align.compare(.gte, max_align)) {
35033 // {Tag, Payload}
35034 size += tag_size;
35035 size = max_align.forward(size);
35036 size += max_size;
35037 const prev_size = size;
35038 size = tag_align.forward(size);
35039 padding = @intCast(size - prev_size);
35040 } else {
35041 // {Payload, Tag}
35042 size += max_size;
35043 size = tag_align.forward(size);
35044 size += tag_size;
35045 const prev_size = size;
35046 size = max_align.forward(size);
35047 padding = @intCast(size - prev_size);
35048 }
35049
35050 break :layout .{ size, max_align.max(tag_align), padding };
35051 } else .{ max_align.forward(max_size), max_align, 0 };
35052
35053 union_type.size(ip).* = @intCast(size);
35054 union_type.padding(ip).* = padding;
35055 flags.alignment = alignment;
35056 flags.status = .have_layout;
3496135057
34962 if (union_obj.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {35058 if (union_obj.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
34963 const msg = try Module.ErrorMsg.create(35059 const msg = try Module.ErrorMsg.create(
...@@ -35034,7 +35130,6 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {...@@ -35034,7 +35130,6 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
3503435130
35035fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {35131fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
35036 try sema.resolveUnionLayout(ty);35132 try sema.resolveUnionLayout(ty);
35037 try sema.resolveTypeFields(ty);
3503835133
35039 const mod = sema.mod;35134 const mod = sema.mod;
35040 const ip = &mod.intern_pool;35135 const ip = &mod.intern_pool;
src/type.zig+14-60
...@@ -1034,66 +1034,20 @@ pub const Type = struct {...@@ -1034,66 +1034,20 @@ pub const Type = struct {
1034 }1034 }
1035 return .{ .scalar = big_align };1035 return .{ .scalar = big_align };
1036 },1036 },
1037
1038 .union_type => |union_type| {1037 .union_type => |union_type| {
1039 if (opt_sema) |sema| {1038 const flags = union_type.flagsPtr(ip).*;
1040 if (union_type.flagsPtr(ip).status == .field_types_wip) {1039 if (flags.alignment != .none) return .{ .scalar = flags.alignment };
1041 // We'll guess "pointer-aligned", if the union has an1040
1042 // underaligned pointer field then some allocations1041 if (!union_type.haveLayout(ip)) switch (strat) {
1043 // might require explicit alignment.
1044 return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) };
1045 }
1046 _ = try sema.resolveTypeFields(ty);
1047 }
1048 if (!union_type.haveFieldTypes(ip)) switch (strat) {
1049 .eager => unreachable, // union layout not resolved1042 .eager => unreachable, // union layout not resolved
1050 .sema => unreachable, // handled above1043 .sema => |sema| return .{ .scalar = try sema.resolveUnionAlignment(ty, union_type) },
1051 .lazy => return .{ .val = (try mod.intern(.{ .int = .{1044 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1052 .ty = .comptime_int_type,1045 .ty = .comptime_int_type,
1053 .storage = .{ .lazy_align = ty.toIntern() },1046 .storage = .{ .lazy_align = ty.toIntern() },
1054 } })).toValue() },1047 } })).toValue() },
1055 };1048 };
1056 const union_obj = ip.loadUnionType(union_type);
1057 if (union_obj.field_names.len == 0) {
1058 if (union_obj.hasTag(ip)) {
1059 return abiAlignmentAdvanced(union_obj.enum_tag_ty.toType(), mod, strat);
1060 } else {
1061 return .{ .scalar = .@"1" };
1062 }
1063 }
10641049
1065 var max_align: Alignment = .@"1";1050 return .{ .scalar = union_type.flagsPtr(ip).alignment };
1066 if (union_obj.hasTag(ip)) max_align = union_obj.enum_tag_ty.toType().abiAlignment(mod);
1067 for (0..union_obj.field_names.len) |field_index| {
1068 const field_ty = union_obj.field_types.get(ip)[field_index].toType();
1069 const field_align = if (union_obj.field_aligns.len == 0)
1070 .none
1071 else
1072 union_obj.field_aligns.get(ip)[field_index];
1073 if (!(field_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1074 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1075 .ty = .comptime_int_type,
1076 .storage = .{ .lazy_align = ty.toIntern() },
1077 } })).toValue() },
1078 else => |e| return e,
1079 })) continue;
1080
1081 const field_align_bytes: Alignment = if (field_align != .none)
1082 field_align
1083 else switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
1084 .scalar => |a| a,
1085 .val => switch (strat) {
1086 .eager => unreachable, // struct layout not resolved
1087 .sema => unreachable, // handled above
1088 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1089 .ty = .comptime_int_type,
1090 .storage = .{ .lazy_align = ty.toIntern() },
1091 } })).toValue() },
1092 },
1093 };
1094 max_align = max_align.max(field_align_bytes);
1095 }
1096 return .{ .scalar = max_align };
1097 },1051 },
1098 .opaque_type => return .{ .scalar = .@"1" },1052 .opaque_type => return .{ .scalar = .@"1" },
1099 .enum_type => |enum_type| return .{1053 .enum_type => |enum_type| return .{
...@@ -1451,8 +1405,8 @@ pub const Type = struct {...@@ -1451,8 +1405,8 @@ pub const Type = struct {
1451 },1405 },
1452 .eager => {},1406 .eager => {},
1453 }1407 }
1454 const union_obj = ip.loadUnionType(union_type);1408
1455 return AbiSizeAdvanced{ .scalar = mod.unionAbiSize(union_obj) };1409 return .{ .scalar = union_type.size(ip).* };
1456 },1410 },
1457 .opaque_type => unreachable, // no size available1411 .opaque_type => unreachable, // no size available
1458 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },1412 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },
...@@ -2680,11 +2634,11 @@ pub const Type = struct {...@@ -2680,11 +2634,11 @@ pub const Type = struct {
2680 if (struct_type.flagsPtr(ip).field_types_wip)2634 if (struct_type.flagsPtr(ip).field_types_wip)
2681 return false;2635 return false;
26822636
2683 try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
2684
2685 struct_type.flagsPtr(ip).requires_comptime = .wip;2637 struct_type.flagsPtr(ip).requires_comptime = .wip;
2686 errdefer struct_type.flagsPtr(ip).requires_comptime = .unknown;2638 errdefer struct_type.flagsPtr(ip).requires_comptime = .unknown;
26872639
2640 try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
2641
2688 for (0..struct_type.field_types.len) |i_usize| {2642 for (0..struct_type.field_types.len) |i_usize| {
2689 const i: u32 = @intCast(i_usize);2643 const i: u32 = @intCast(i_usize);
2690 if (struct_type.fieldIsComptime(ip, i)) continue;2644 if (struct_type.fieldIsComptime(ip, i)) continue;
...@@ -2723,12 +2677,12 @@ pub const Type = struct {...@@ -2723,12 +2677,12 @@ pub const Type = struct {
2723 if (union_type.flagsPtr(ip).status == .field_types_wip)2677 if (union_type.flagsPtr(ip).status == .field_types_wip)
2724 return false;2678 return false;
27252679
2726 try sema.resolveTypeFieldsUnion(ty, union_type);2680 union_type.flagsPtr(ip).requires_comptime = .wip;
2727 const union_obj = ip.loadUnionType(union_type);2681 errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
27282682
2729 union_obj.flagsPtr(ip).requires_comptime = .wip;2683 try sema.resolveTypeFieldsUnion(ty, union_type);
2730 errdefer union_obj.flagsPtr(ip).requires_comptime = .unknown;
27312684
2685 const union_obj = ip.loadUnionType(union_type);
2732 for (0..union_obj.field_types.len) |field_idx| {2686 for (0..union_obj.field_types.len) |field_idx| {
2733 const field_ty = union_obj.field_types.get(ip)[field_idx];2687 const field_ty = union_obj.field_types.get(ip)[field_idx];
2734 if (try field_ty.toType().comptimeOnlyAdvanced(mod, opt_sema)) {2688 if (try field_ty.toType().comptimeOnlyAdvanced(mod, opt_sema)) {