authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-10 12:16:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:42:30-07:00
log8297f28546b44afe49bec074733f05e03a3c0e62
treebc0740d17e70cd749bcc94db43f45fefcb642468
parent275652f620541919087bc92da0d2f9e97c66d3c0

stage2: move struct types and aggregate values to InternPool


22 files changed, 1570 insertions(+), 1280 deletions(-)

src/InternPool.zig+225-71
......@@ -1,5 +1,10 @@
11//! All interned objects have both a value and a type.
2//! This data structure is self-contained, with the following exceptions:
3//! * type_struct via Module.Struct.Index
4//! * type_opaque via Module.Namespace.Index and Module.Decl.Index
25
6/// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are
7/// constructed lazily.
38map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
49items: std.MultiArrayList(Item) = .{},
510extra: std.ArrayListUnmanaged(u32) = .{},
......@@ -9,6 +14,13 @@ extra: std.ArrayListUnmanaged(u32) = .{},
914/// violate the above mechanism.
1015limbs: std.ArrayListUnmanaged(u64) = .{},
1116
17/// Struct objects are stored in this data structure because:
18/// * They contain pointers such as the field maps.
19/// * They need to be mutated after creation.
20allocated_structs: std.SegmentedList(Module.Struct, 0) = .{},
21/// When a Struct object is freed from `allocated_structs`, it is pushed into this stack.
22structs_free_list: std.ArrayListUnmanaged(Module.Struct.Index) = .{},
23
1224const std = @import("std");
1325const Allocator = std.mem.Allocator;
1426const assert = std.debug.assert;
......@@ -17,8 +29,7 @@ const BigIntMutable = std.math.big.int.Mutable;
1729const Limb = std.math.big.Limb;
1830
1931const InternPool = @This();
20const DeclIndex = @import("Module.zig").Decl.Index;
21const NamespaceIndex = @import("Module.zig").Namespace.Index;
32const Module = @import("Module.zig");
2233
2334const KeyAdapter = struct {
2435 intern_pool: *const InternPool,
......@@ -45,11 +56,20 @@ pub const Key = union(enum) {
4556 payload_type: Index,
4657 },
4758 simple_type: SimpleType,
59 /// If `empty_struct_type` is handled separately, then this value may be
60 /// safely assumed to never be `none`.
61 struct_type: StructType,
62 union_type: struct {
63 fields_len: u32,
64 // TODO move Module.Union data to InternPool
65 },
66 opaque_type: OpaqueType,
67
4868 simple_value: SimpleValue,
4969 extern_func: struct {
5070 ty: Index,
5171 /// The Decl that corresponds to the function itself.
52 decl: DeclIndex,
72 decl: Module.Decl.Index,
5373 /// Library name if specified.
5474 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
5575 /// Index into the string table bytes.
......@@ -62,13 +82,11 @@ pub const Key = union(enum) {
6282 ty: Index,
6383 tag: BigIntConst,
6484 },
65 struct_type: StructType,
66 opaque_type: OpaqueType,
67
68 union_type: struct {
69 fields_len: u32,
70 // TODO move Module.Union data to InternPool
71 },
85 /// An instance of a struct, array, or vector.
86 /// Each element/field stored as an `Index`.
87 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
88 /// so the slice length will be one more than the type's array length.
89 aggregate: Aggregate,
7290
7391 pub const IntType = std.builtin.Type.Int;
7492
......@@ -113,16 +131,27 @@ pub const Key = union(enum) {
113131 child: Index,
114132 };
115133
116 pub const StructType = struct {
117 fields_len: u32,
118 // TODO move Module.Struct data to InternPool
119 };
120
121134 pub const OpaqueType = struct {
122135 /// The Decl that corresponds to the opaque itself.
123 decl: DeclIndex,
136 decl: Module.Decl.Index,
124137 /// Represents the declarations inside this opaque.
125 namespace: NamespaceIndex,
138 namespace: Module.Namespace.Index,
139 };
140
141 /// There are three possibilities here:
142 /// * `@TypeOf(.{})` (untyped empty struct literal)
143 /// - namespace == .none, index == .none
144 /// * A struct which has a namepace, but no fields.
145 /// - index == .none
146 /// * A struct which has fields as well as a namepace.
147 pub const StructType = struct {
148 /// This will be `none` only in the case of `@TypeOf(.{})`
149 /// (`Index.empty_struct_type`).
150 namespace: Module.Namespace.OptionalIndex,
151 /// The `none` tag is used to represent two cases:
152 /// * `@TypeOf(.{})`, in which case `namespace` will also be `none`.
153 /// * A struct with no fields, in which case `namespace` will be populated.
154 index: Module.Struct.OptionalIndex,
126155 };
127156
128157 pub const Int = struct {
......@@ -156,18 +185,24 @@ pub const Key = union(enum) {
156185 addr: Addr,
157186
158187 pub const Addr = union(enum) {
159 decl: DeclIndex,
188 decl: Module.Decl.Index,
160189 int: Index,
161190 };
162191 };
163192
164193 /// `null` is represented by the `val` field being `none`.
165194 pub const Opt = struct {
195 /// This is the optional type; not the payload type.
166196 ty: Index,
167197 /// This could be `none`, indicating the optional is `null`.
168198 val: Index,
169199 };
170200
201 pub const Aggregate = struct {
202 ty: Index,
203 fields: []const Index,
204 };
205
171206 pub fn hash32(key: Key) u32 {
172207 return @truncate(u32, key.hash64());
173208 }
......@@ -193,8 +228,15 @@ pub const Key = union(enum) {
193228 .simple_value,
194229 .extern_func,
195230 .opt,
231 .struct_type,
196232 => |info| std.hash.autoHash(hasher, info),
197233
234 .union_type => |union_type| {
235 _ = union_type;
236 @panic("TODO");
237 },
238 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
239
198240 .int => |int| {
199241 // Canonicalize all integers by converting them to BigIntConst.
200242 var buffer: Key.Int.Storage.BigIntSpace = undefined;
......@@ -221,16 +263,10 @@ pub const Key = union(enum) {
221263 for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb);
222264 },
223265
224 .struct_type => |struct_type| {
225 if (struct_type.fields_len != 0) {
226 @panic("TODO");
227 }
228 },
229 .union_type => |union_type| {
230 _ = union_type;
231 @panic("TODO");
266 .aggregate => |aggregate| {
267 std.hash.autoHash(hasher, aggregate.ty);
268 for (aggregate.fields) |field| std.hash.autoHash(hasher, field);
232269 },
233 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
234270 }
235271 }
236272
......@@ -280,6 +316,10 @@ pub const Key = union(enum) {
280316 const b_info = b.opt;
281317 return std.meta.eql(a_info, b_info);
282318 },
319 .struct_type => |a_info| {
320 const b_info = b.struct_type;
321 return std.meta.eql(a_info, b_info);
322 },
283323
284324 .ptr => |a_info| {
285325 const b_info = b.ptr;
......@@ -331,16 +371,6 @@ pub const Key = union(enum) {
331371 @panic("TODO");
332372 },
333373
334 .struct_type => |a_info| {
335 const b_info = b.struct_type;
336
337 // TODO: remove this special case for empty_struct
338 if (a_info.fields_len == 0 and b_info.fields_len == 0)
339 return true;
340
341 @panic("TODO");
342 },
343
344374 .union_type => |a_info| {
345375 const b_info = b.union_type;
346376
......@@ -353,6 +383,11 @@ pub const Key = union(enum) {
353383 const b_info = b.opaque_type;
354384 return a_info.decl == b_info.decl;
355385 },
386 .aggregate => |a_info| {
387 const b_info = b.aggregate;
388 if (a_info.ty != b_info.ty) return false;
389 return std.mem.eql(Index, a_info.fields, b_info.fields);
390 },
356391 }
357392 }
358393
......@@ -375,6 +410,7 @@ pub const Key = union(enum) {
375410 .opt,
376411 .extern_func,
377412 .enum_tag,
413 .aggregate,
378414 => |x| return x.ty,
379415
380416 .simple_value => |s| switch (s) {
......@@ -471,6 +507,7 @@ pub const Index = enum(u32) {
471507 anyerror_void_error_union_type,
472508 generic_poison_type,
473509 var_args_param_type,
510 /// `@TypeOf(.{})`
474511 empty_struct_type,
475512
476513 /// `undefined` (untyped)
......@@ -691,7 +728,8 @@ pub const static_keys = [_]Key{
691728
692729 // empty_struct_type
693730 .{ .struct_type = .{
694 .fields_len = 0,
731 .namespace = .none,
732 .index = .none,
695733 } },
696734
697735 .{ .simple_value = .undefined },
......@@ -792,16 +830,18 @@ pub const Tag = enum(u8) {
792830 /// An opaque type.
793831 /// data is index of Key.OpaqueType in extra.
794832 type_opaque,
833 /// A struct type.
834 /// data is Module.Struct.OptionalIndex
835 /// The `none` tag is used to represent `@TypeOf(.{})`.
836 type_struct,
837 /// A struct type that has only a namespace; no fields, and there is no
838 /// Module.Struct object allocated for it.
839 /// data is Module.Namespace.Index.
840 type_struct_ns,
795841
796842 /// A value that can be represented with only an enum tag.
797843 /// data is SimpleValue enum value.
798844 simple_value,
799 /// The SimpleType and SimpleValue enums are exposed via the InternPool API using
800 /// SimpleType and SimpleValue as the Key data themselves.
801 /// This tag is for miscellaneous types and values that can be represented with
802 /// only an enum tag, but will be presented via the API with a different Key.
803 /// data is SimpleInternal enum value.
804 simple_internal,
805845 /// A pointer to an integer value.
806846 /// data is extra index of PtrInt, which contains the type and address.
807847 /// Only pointer types are allowed to have this encoding. Optional types must use
......@@ -809,6 +849,8 @@ pub const Tag = enum(u8) {
809849 ptr_int,
810850 /// An optional value that is non-null.
811851 /// data is Index of the payload value.
852 /// In order to use this encoding, one must ensure that the `InternPool`
853 /// already contains the optional type corresponding to this payload.
812854 opt_payload,
813855 /// An optional value that is null.
814856 /// data is Index of the payload type.
......@@ -859,6 +901,13 @@ pub const Tag = enum(u8) {
859901 extern_func,
860902 /// A regular function.
861903 func,
904 /// This represents the only possible value for *some* types which have
905 /// only one possible value. Not all only-possible-values are encoded this way;
906 /// for example structs which have all comptime fields are not encoded this way.
907 /// The set of values that are encoded this way is:
908 /// * A struct which has 0 fields.
909 /// data is Index of the type, which is known to be zero bits at runtime.
910 only_possible_value,
862911};
863912
864913/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to
......@@ -912,9 +961,12 @@ pub const SimpleType = enum(u32) {
912961};
913962
914963pub const SimpleValue = enum(u32) {
964 /// This is untyped `undefined`.
915965 undefined,
916966 void,
967 /// This is untyped `null`.
917968 null,
969 /// This is the untyped empty struct literal: `.{}`
918970 empty_struct,
919971 true,
920972 false,
......@@ -923,12 +975,6 @@ pub const SimpleValue = enum(u32) {
923975 generic_poison,
924976};
925977
926pub const SimpleInternal = enum(u32) {
927 /// This is the empty struct type. Note that empty_struct value is exposed
928 /// via SimpleValue.
929 type_empty_struct,
930};
931
932978pub const Pointer = struct {
933979 child: Index,
934980 sentinel: Index,
......@@ -1005,7 +1051,7 @@ pub const ErrorUnion = struct {
10051051/// 0. field name: null-terminated string index for each fields_len; declaration order
10061052pub const EnumSimple = struct {
10071053 /// The Decl that corresponds to the enum itself.
1008 decl: DeclIndex,
1054 decl: Module.Decl.Index,
10091055 /// An integer type which is used for the numerical value of the enum. This
10101056 /// is inferred by Zig to be the smallest power of two unsigned int that
10111057 /// fits the number of fields. It is stored here to avoid unnecessary
......@@ -1091,6 +1137,10 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
10911137 ip.items.deinit(gpa);
10921138 ip.extra.deinit(gpa);
10931139 ip.limbs.deinit(gpa);
1140
1141 ip.structs_free_list.deinit(gpa);
1142 ip.allocated_structs.deinit(gpa);
1143
10941144 ip.* = undefined;
10951145}
10961146
......@@ -1167,20 +1217,38 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
11671217 .type_enum_simple => @panic("TODO"),
11681218
11691219 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
1170
1171 .simple_internal => switch (@intToEnum(SimpleInternal, data)) {
1172 .type_empty_struct => .{ .struct_type = .{
1173 .fields_len = 0,
1174 } },
1220 .type_struct => {
1221 const struct_index = @intToEnum(Module.Struct.OptionalIndex, data);
1222 const namespace = if (struct_index.unwrap()) |i|
1223 ip.structPtrConst(i).namespace.toOptional()
1224 else
1225 .none;
1226 return .{ .struct_type = .{
1227 .index = struct_index,
1228 .namespace = namespace,
1229 } };
11751230 },
1231 .type_struct_ns => .{ .struct_type = .{
1232 .index = .none,
1233 .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(),
1234 } },
1235
11761236 .opt_null => .{ .opt = .{
11771237 .ty = @intToEnum(Index, data),
11781238 .val = .none,
11791239 } },
1180 .opt_payload => .{ .opt = .{
1181 .ty = indexToKey(ip, @intToEnum(Index, data)).typeOf(),
1182 .val = @intToEnum(Index, data),
1183 } },
1240 .opt_payload => {
1241 const payload_val = @intToEnum(Index, data);
1242 // The existence of `opt_payload` guarantees that the optional type will be
1243 // stored in the `InternPool`.
1244 const opt_ty = ip.getAssumeExists(.{
1245 .opt_type = indexToKey(ip, payload_val).typeOf(),
1246 });
1247 return .{ .opt = .{
1248 .ty = opt_ty,
1249 .val = payload_val,
1250 } };
1251 },
11841252 .ptr_int => {
11851253 const info = ip.extraData(PtrInt, data);
11861254 return .{ .ptr = .{
......@@ -1225,6 +1293,16 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
12251293 .float_f128 => @panic("TODO"),
12261294 .extern_func => @panic("TODO"),
12271295 .func => @panic("TODO"),
1296 .only_possible_value => {
1297 const ty = @intToEnum(Index, data);
1298 return switch (ip.indexToKey(ty)) {
1299 .struct_type => .{ .aggregate = .{
1300 .ty = ty,
1301 .fields = &.{},
1302 } },
1303 else => unreachable,
1304 };
1305 },
12281306 };
12291307}
12301308
......@@ -1359,12 +1437,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
13591437 },
13601438
13611439 .struct_type => |struct_type| {
1362 if (struct_type.fields_len != 0) {
1363 @panic("TODO"); // handle structs other than empty_struct
1364 }
1365 ip.items.appendAssumeCapacity(.{
1366 .tag = .simple_internal,
1367 .data = @enumToInt(SimpleInternal.type_empty_struct),
1440 ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{
1441 .tag = .type_struct,
1442 .data = @enumToInt(i),
1443 } else if (struct_type.namespace.unwrap()) |i| .{
1444 .tag = .type_struct_ns,
1445 .data = @enumToInt(i),
1446 } else .{
1447 .tag = .type_struct,
1448 .data = @enumToInt(Module.Struct.OptionalIndex.none),
13681449 });
13691450 },
13701451
......@@ -1398,6 +1479,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
13981479
13991480 .opt => |opt| {
14001481 assert(opt.ty != .none);
1482 assert(ip.isOptionalType(opt.ty));
14011483 ip.items.appendAssumeCapacity(if (opt.val == .none) .{
14021484 .tag = .opt_null,
14031485 .data = @enumToInt(opt.ty),
......@@ -1549,10 +1631,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
15491631 const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative;
15501632 try addInt(ip, gpa, enum_tag.ty, tag, enum_tag.tag.limbs);
15511633 },
1634
1635 .aggregate => |aggregate| {
1636 if (aggregate.fields.len == 0) {
1637 ip.items.appendAssumeCapacity(.{
1638 .tag = .only_possible_value,
1639 .data = @enumToInt(aggregate.ty),
1640 });
1641 return @intToEnum(Index, ip.items.len - 1);
1642 }
1643 @panic("TODO");
1644 },
15521645 }
15531646 return @intToEnum(Index, ip.items.len - 1);
15541647}
15551648
1649pub fn getAssumeExists(ip: InternPool, key: Key) Index {
1650 const adapter: KeyAdapter = .{ .intern_pool = &ip };
1651 const index = ip.map.getIndexAdapted(key, adapter).?;
1652 return @intToEnum(Index, index);
1653}
1654
1655/// This operation only happens under compile error conditions.
1656/// Leak the index until the next garbage collection.
1657pub fn remove(ip: *InternPool, index: Index) void {
1658 _ = ip;
1659 _ = index;
1660 @panic("TODO this is a bit problematic to implement, could we maybe just never support a remove() operation on InternPool?");
1661}
1662
15561663fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {
15571664 const limbs_len = @intCast(u32, limbs.len);
15581665 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);
......@@ -1578,8 +1685,8 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
15781685 ip.extra.appendAssumeCapacity(switch (field.type) {
15791686 u32 => @field(extra, field.name),
15801687 Index => @enumToInt(@field(extra, field.name)),
1581 DeclIndex => @enumToInt(@field(extra, field.name)),
1582 NamespaceIndex => @enumToInt(@field(extra, field.name)),
1688 Module.Decl.Index => @enumToInt(@field(extra, field.name)),
1689 Module.Namespace.Index => @enumToInt(@field(extra, field.name)),
15831690 i32 => @bitCast(u32, @field(extra, field.name)),
15841691 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),
15851692 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
......@@ -1635,8 +1742,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {
16351742 @field(result, field.name) = switch (field.type) {
16361743 u32 => int32,
16371744 Index => @intToEnum(Index, int32),
1638 DeclIndex => @intToEnum(DeclIndex, int32),
1639 NamespaceIndex => @intToEnum(NamespaceIndex, int32),
1745 Module.Decl.Index => @intToEnum(Module.Decl.Index, int32),
1746 Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32),
16401747 i32 => @bitCast(i32, int32),
16411748 Pointer.Flags => @bitCast(Pointer.Flags, int32),
16421749 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
......@@ -1808,6 +1915,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
18081915 }
18091916}
18101917
1918pub fn indexToStruct(ip: *InternPool, val: Index) Module.Struct.OptionalIndex {
1919 const tags = ip.items.items(.tag);
1920 if (val == .none) return .none;
1921 if (tags[@enumToInt(val)] != .type_struct) return .none;
1922 const datas = ip.items.items(.data);
1923 return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional();
1924}
1925
1926pub fn isOptionalType(ip: InternPool, ty: Index) bool {
1927 const tags = ip.items.items(.tag);
1928 if (ty == .none) return false;
1929 return tags[@enumToInt(ty)] == .type_optional;
1930}
1931
18111932pub fn dump(ip: InternPool) void {
18121933 dumpFallible(ip, std.heap.page_allocator) catch return;
18131934}
......@@ -1859,9 +1980,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
18591980 .type_error_union => @sizeOf(ErrorUnion),
18601981 .type_enum_simple => @sizeOf(EnumSimple),
18611982 .type_opaque => @sizeOf(Key.OpaqueType),
1983 .type_struct => 0,
1984 .type_struct_ns => 0,
18621985 .simple_type => 0,
18631986 .simple_value => 0,
1864 .simple_internal => 0,
18651987 .ptr_int => @sizeOf(PtrInt),
18661988 .opt_null => 0,
18671989 .opt_payload => 0,
......@@ -1887,6 +2009,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
18872009 .float_f128 => @sizeOf(Float128),
18882010 .extern_func => @panic("TODO"),
18892011 .func => @panic("TODO"),
2012 .only_possible_value => 0,
18902013 });
18912014 }
18922015 const SortContext = struct {
......@@ -1905,3 +2028,34 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
19052028 });
19062029 }
19072030}
2031
2032pub fn structPtr(ip: *InternPool, index: Module.Struct.Index) *Module.Struct {
2033 return ip.allocated_structs.at(@enumToInt(index));
2034}
2035
2036pub fn structPtrConst(ip: InternPool, index: Module.Struct.Index) *const Module.Struct {
2037 return ip.allocated_structs.at(@enumToInt(index));
2038}
2039
2040pub fn structPtrUnwrapConst(ip: InternPool, index: Module.Struct.OptionalIndex) ?*const Module.Struct {
2041 return structPtrConst(ip, index.unwrap() orelse return null);
2042}
2043
2044pub fn createStruct(
2045 ip: *InternPool,
2046 gpa: Allocator,
2047 initialization: Module.Struct,
2048) Allocator.Error!Module.Struct.Index {
2049 if (ip.structs_free_list.popOrNull()) |index| return index;
2050 const ptr = try ip.allocated_structs.addOne(gpa);
2051 ptr.* = initialization;
2052 return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1);
2053}
2054
2055pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void {
2056 ip.structPtr(index).* = undefined;
2057 ip.structs_free_list.append(gpa, index) catch {
2058 // In order to keep `destroyStruct` a non-fallible function, we ignore memory
2059 // allocation failures here, instead leaking the Struct until garbage collection.
2060 };
2061}
src/Module.zig+117-62
......@@ -839,11 +839,14 @@ pub const Decl = struct {
839839
840840 /// If the Decl has a value and it is a struct, return it,
841841 /// otherwise null.
842 pub fn getStruct(decl: *Decl) ?*Struct {
843 if (!decl.owns_tv) return null;
844 const ty = (decl.val.castTag(.ty) orelse return null).data;
845 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;
846 return struct_obj;
842 pub fn getStruct(decl: *Decl, mod: *Module) ?*Struct {
843 return mod.structPtrUnwrap(getStructIndex(decl, mod));
844 }
845
846 pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex {
847 if (!decl.owns_tv) return .none;
848 const ty = (decl.val.castTag(.ty) orelse return .none).data;
849 return mod.intern_pool.indexToStruct(ty.ip_index);
847850 }
848851
849852 /// If the Decl has a value and it is a union, return it,
......@@ -884,32 +887,29 @@ pub const Decl = struct {
884887 /// Only returns it if the Decl is the owner.
885888 pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex {
886889 if (!decl.owns_tv) return .none;
887 if (decl.val.ip_index == .none) {
888 const ty = (decl.val.castTag(.ty) orelse return .none).data;
889 switch (ty.tag()) {
890 .@"struct" => {
891 const struct_obj = ty.castTag(.@"struct").?.data;
892 return struct_obj.namespace.toOptional();
893 },
894 .enum_full, .enum_nonexhaustive => {
895 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;
896 return enum_obj.namespace.toOptional();
897 },
898 .empty_struct => {
899 @panic("TODO");
900 },
901 .@"union", .union_safety_tagged, .union_tagged => {
902 const union_obj = ty.cast(Type.Payload.Union).?.data;
903 return union_obj.namespace.toOptional();
904 },
890 switch (decl.val.ip_index) {
891 .empty_struct_type => return .none,
892 .none => {
893 const ty = (decl.val.castTag(.ty) orelse return .none).data;
894 switch (ty.tag()) {
895 .enum_full, .enum_nonexhaustive => {
896 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;
897 return enum_obj.namespace.toOptional();
898 },
899 .@"union", .union_safety_tagged, .union_tagged => {
900 const union_obj = ty.cast(Type.Payload.Union).?.data;
901 return union_obj.namespace.toOptional();
902 },
905903
906 else => return .none,
907 }
904 else => return .none,
905 }
906 },
907 else => return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
908 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
909 .struct_type => |struct_type| struct_type.namespace,
910 else => .none,
911 },
908912 }
909 return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
910 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
911 else => .none,
912 };
913913 }
914914
915915 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
......@@ -1046,6 +1046,28 @@ pub const Struct = struct {
10461046 is_tuple: bool,
10471047 assumed_runtime_bits: bool = false,
10481048
1049 pub const Index = enum(u32) {
1050 _,
1051
1052 pub fn toOptional(i: Index) OptionalIndex {
1053 return @intToEnum(OptionalIndex, @enumToInt(i));
1054 }
1055 };
1056
1057 pub const OptionalIndex = enum(u32) {
1058 none = std.math.maxInt(u32),
1059 _,
1060
1061 pub fn init(oi: ?Index) OptionalIndex {
1062 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
1063 }
1064
1065 pub fn unwrap(oi: OptionalIndex) ?Index {
1066 if (oi == .none) return null;
1067 return @intToEnum(Index, @enumToInt(oi));
1068 }
1069 };
1070
10491071 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
10501072
10511073 /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.
......@@ -1111,12 +1133,7 @@ pub const Struct = struct {
11111133 }
11121134
11131135 pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {
1114 const owner_decl = mod.declPtr(s.owner_decl);
1115 return .{
1116 .file_scope = owner_decl.getFileScope(mod),
1117 .parent_decl_node = owner_decl.src_node,
1118 .lazy = LazySrcLoc.nodeOffset(0),
1119 };
1136 return mod.declPtr(s.owner_decl).srcLoc(mod);
11201137 }
11211138
11221139 pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc {
......@@ -3622,6 +3639,16 @@ pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {
36223639 return mod.allocated_namespaces.at(@enumToInt(index));
36233640}
36243641
3642pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
3643 return mod.intern_pool.structPtr(index);
3644}
3645
3646/// This one accepts an index from the InternPool and asserts that it is not
3647/// the anonymous empty struct type.
3648pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
3649 return structPtr(mod, index.unwrap() orelse return null);
3650}
3651
36253652/// Returns true if and only if the Decl is the top level struct associated with a File.
36263653pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
36273654 const decl = mod.declPtr(decl_index);
......@@ -4078,7 +4105,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
40784105
40794106 if (!decl.owns_tv) continue;
40804107
4081 if (decl.getStruct()) |struct_obj| {
4108 if (decl.getStruct(mod)) |struct_obj| {
40824109 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {
40834110 try file.deleted_decls.append(gpa, decl_index);
40844111 continue;
......@@ -4597,36 +4624,50 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
45974624 errdefer new_decl_arena.deinit();
45984625 const new_decl_arena_allocator = new_decl_arena.allocator();
45994626
4600 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
4601 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
4602 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
4603 const ty_ty = comptime Type.type;
4604 struct_obj.* = .{
4605 .owner_decl = undefined, // set below
4627 // Because these three things each reference each other, `undefined`
4628 // placeholders are used before being set after the struct type gains an
4629 // InternPool index.
4630 const new_namespace_index = try mod.createNamespace(.{
4631 .parent = .none,
4632 .ty = undefined,
4633 .file_scope = file,
4634 });
4635 const new_namespace = mod.namespacePtr(new_namespace_index);
4636 errdefer mod.destroyNamespace(new_namespace_index);
4637
4638 const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, null);
4639 const new_decl = mod.declPtr(new_decl_index);
4640 errdefer @panic("TODO error handling");
4641
4642 const struct_index = try mod.createStruct(.{
4643 .owner_decl = new_decl_index,
46064644 .fields = .{},
46074645 .zir_index = undefined, // set below
46084646 .layout = .Auto,
46094647 .status = .none,
46104648 .known_non_opv = undefined,
46114649 .is_tuple = undefined, // set below
4612 .namespace = try mod.createNamespace(.{
4613 .parent = .none,
4614 .ty = struct_ty,
4615 .file_scope = file,
4616 }),
4617 };
4618 const new_decl_index = try mod.allocateNewDecl(struct_obj.namespace, 0, null);
4619 const new_decl = mod.declPtr(new_decl_index);
4650 .namespace = new_namespace_index,
4651 });
4652 errdefer mod.destroyStruct(struct_index);
4653
4654 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
4655 .index = struct_index.toOptional(),
4656 .namespace = new_namespace_index.toOptional(),
4657 } });
4658 errdefer mod.intern_pool.remove(struct_ty);
4659
4660 new_namespace.ty = struct_ty.toType();
46204661 file.root_decl = new_decl_index.toOptional();
4621 struct_obj.owner_decl = new_decl_index;
4662
46224663 new_decl.name = try file.fullyQualifiedNameZ(gpa);
46234664 new_decl.src_line = 0;
46244665 new_decl.is_pub = true;
46254666 new_decl.is_exported = false;
46264667 new_decl.has_align = false;
46274668 new_decl.has_linksection_or_addrspace = false;
4628 new_decl.ty = ty_ty;
4629 new_decl.val = struct_val;
4669 new_decl.ty = Type.type;
4670 new_decl.val = struct_ty.toValue();
46304671 new_decl.@"align" = 0;
46314672 new_decl.@"linksection" = null;
46324673 new_decl.has_tv = true;
......@@ -4639,6 +4680,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
46394680 if (file.status == .success_zir) {
46404681 assert(file.zir_loaded);
46414682 const main_struct_inst = Zir.main_struct_inst;
4683 const struct_obj = mod.structPtr(struct_index);
46424684 struct_obj.zir_index = main_struct_inst;
46434685 const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;
46444686 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -4665,7 +4707,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
46654707 var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);
46664708 defer wip_captures.deinit();
46674709
4668 if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
4710 if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_index)) |_| {
46694711 try wip_captures.finalize();
46704712 new_decl.analysis = .complete;
46714713 } else |err| switch (err) {
......@@ -4761,11 +4803,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47614803 if (mod.declIsRoot(decl_index)) {
47624804 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
47634805 const main_struct_inst = Zir.main_struct_inst;
4764 const struct_obj = decl.getStruct().?;
4806 const struct_index = decl.getStructIndex(mod).unwrap().?;
4807 const struct_obj = mod.structPtr(struct_index);
47654808 // This might not have gotten set in `semaFile` if the first time had
47664809 // a ZIR failure, so we set it here in case.
47674810 struct_obj.zir_index = main_struct_inst;
4768 try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);
4811 try sema.analyzeStructDecl(decl, main_struct_inst, struct_index);
47694812 decl.analysis = .complete;
47704813 decl.generation = mod.generation;
47714814 return false;
......@@ -5970,6 +6013,14 @@ pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {
59706013 };
59716014}
59726015
6016pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {
6017 return mod.intern_pool.createStruct(mod.gpa, initialization);
6018}
6019
6020pub fn destroyStruct(mod: *Module, index: Struct.Index) void {
6021 return mod.intern_pool.destroyStruct(mod.gpa, index);
6022}
6023
59736024pub fn allocateNewDecl(
59746025 mod: *Module,
59756026 namespace: Namespace.Index,
......@@ -7202,12 +7253,7 @@ pub fn atomicPtrAlignment(
72027253}
72037254
72047255pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc {
7205 const owner_decl = mod.declPtr(opaque_type.decl);
7206 return .{
7207 .file_scope = owner_decl.getFileScope(mod),
7208 .parent_decl_node = owner_decl.src_node,
7209 .lazy = LazySrcLoc.nodeOffset(0),
7210 };
7256 return mod.declPtr(opaque_type.decl).srcLoc(mod);
72117257}
72127258
72137259pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) ![:0]u8 {
......@@ -7221,3 +7267,12 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
72217267pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index {
72227268 return mod.namespacePtr(namespace_index).getDeclIndex(mod);
72237269}
7270
7271/// Returns null in the following cases:
7272/// * `@TypeOf(.{})`
7273/// * A struct which has no fields (`struct {}`).
7274/// * Not a struct.
7275pub fn typeToStruct(mod: *Module, ty: Type) ?*Struct {
7276 const struct_index = mod.intern_pool.indexToStruct(ty.ip_index).unwrap() orelse return null;
7277 return mod.structPtr(struct_index);
7278}
src/Sema.zig+349-293
......@@ -2090,16 +2090,17 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:
20902090}
20912091
20922092fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError {
2093 const mod = sema.mod;
20932094 const msg = msg: {
20942095 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
20952096 errdefer msg.destroy(sema.gpa);
20962097
2097 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;
2098 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{
2098 const struct_ty = mod.typeToStruct(container_ty) orelse break :msg msg;
2099 const default_value_src = struct_ty.fieldSrcLoc(mod, .{
20992100 .index = field_index,
21002101 .range = .value,
21012102 });
2102 try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
2103 try mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
21032104 break :msg msg;
21042105 };
21052106 return sema.failWithOwnedErrorMsg(msg);
......@@ -2632,8 +2633,10 @@ pub fn analyzeStructDecl(
26322633 sema: *Sema,
26332634 new_decl: *Decl,
26342635 inst: Zir.Inst.Index,
2635 struct_obj: *Module.Struct,
2636 struct_index: Module.Struct.Index,
26362637) SemaError!void {
2638 const mod = sema.mod;
2639 const struct_obj = mod.structPtr(struct_index);
26372640 const extended = sema.code.instructions.items(.data)[inst].extended;
26382641 assert(extended.opcode == .struct_decl);
26392642 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -2662,7 +2665,7 @@ pub fn analyzeStructDecl(
26622665 }
26632666 }
26642667
2665 _ = try sema.mod.scanNamespace(struct_obj.namespace, extra_index, decls_len, new_decl);
2668 _ = try mod.scanNamespace(struct_obj.namespace, extra_index, decls_len, new_decl);
26662669}
26672670
26682671fn zirStructDecl(
......@@ -2671,28 +2674,38 @@ fn zirStructDecl(
26712674 extended: Zir.Inst.Extended.InstData,
26722675 inst: Zir.Inst.Index,
26732676) CompileError!Air.Inst.Ref {
2677 const mod = sema.mod;
2678 const gpa = sema.gpa;
26742679 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
26752680 const src: LazySrcLoc = if (small.has_src_node) blk: {
26762681 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
26772682 break :blk LazySrcLoc.nodeOffset(node_offset);
26782683 } else sema.src;
26792684
2680 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
2685 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
26812686 errdefer new_decl_arena.deinit();
2682 const new_decl_arena_allocator = new_decl_arena.allocator();
26832687
2684 const mod = sema.mod;
2685 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
2686 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
2687 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
2688 // Because these three things each reference each other, `undefined`
2689 // placeholders are used before being set after the struct type gains an
2690 // InternPool index.
2691
26882692 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
26892693 .ty = Type.type,
2690 .val = struct_val,
2694 .val = undefined,
26912695 }, small.name_strategy, "struct", inst);
26922696 const new_decl = mod.declPtr(new_decl_index);
26932697 new_decl.owns_tv = true;
26942698 errdefer mod.abortAnonDecl(new_decl_index);
2695 struct_obj.* = .{
2699
2700 const new_namespace_index = try mod.createNamespace(.{
2701 .parent = block.namespace.toOptional(),
2702 .ty = undefined,
2703 .file_scope = block.getFileScope(mod),
2704 });
2705 const new_namespace = mod.namespacePtr(new_namespace_index);
2706 errdefer mod.destroyNamespace(new_namespace_index);
2707
2708 const struct_index = try mod.createStruct(.{
26962709 .owner_decl = new_decl_index,
26972710 .fields = .{},
26982711 .zir_index = inst,
......@@ -2700,13 +2713,20 @@ fn zirStructDecl(
27002713 .status = .none,
27012714 .known_non_opv = undefined,
27022715 .is_tuple = small.is_tuple,
2703 .namespace = try mod.createNamespace(.{
2704 .parent = block.namespace.toOptional(),
2705 .ty = struct_ty,
2706 .file_scope = block.getFileScope(mod),
2707 }),
2708 };
2709 try sema.analyzeStructDecl(new_decl, inst, struct_obj);
2716 .namespace = new_namespace_index,
2717 });
2718 errdefer mod.destroyStruct(struct_index);
2719
2720 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
2721 .index = struct_index.toOptional(),
2722 .namespace = new_namespace_index.toOptional(),
2723 } });
2724 errdefer mod.intern_pool.remove(struct_ty);
2725
2726 new_decl.val = struct_ty.toValue();
2727 new_namespace.ty = struct_ty.toType();
2728
2729 try sema.analyzeStructDecl(new_decl, inst, struct_index);
27102730 try new_decl.finalizeNewArena(&new_decl_arena);
27112731 return sema.analyzeDeclVal(block, src, new_decl_index);
27122732}
......@@ -2721,6 +2741,7 @@ fn createAnonymousDeclTypeNamed(
27212741 inst: ?Zir.Inst.Index,
27222742) !Decl.Index {
27232743 const mod = sema.mod;
2744 const gpa = sema.gpa;
27242745 const namespace = block.namespace;
27252746 const src_scope = block.wip_capture_scope;
27262747 const src_decl = mod.declPtr(block.src_decl);
......@@ -2736,16 +2757,16 @@ fn createAnonymousDeclTypeNamed(
27362757 // semantically analyzed.
27372758 // This name is also used as the key in the parent namespace so it cannot be
27382759 // renamed.
2739 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{
2760 const name = try std.fmt.allocPrintZ(gpa, "{s}__{s}_{d}", .{
27402761 src_decl.name, anon_prefix, @enumToInt(new_decl_index),
27412762 });
2742 errdefer sema.gpa.free(name);
2763 errdefer gpa.free(name);
27432764 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27442765 return new_decl_index;
27452766 },
27462767 .parent => {
2747 const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
2748 errdefer sema.gpa.free(name);
2768 const name = try gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
2769 errdefer gpa.free(name);
27492770 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27502771 return new_decl_index;
27512772 },
......@@ -2753,7 +2774,7 @@ fn createAnonymousDeclTypeNamed(
27532774 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);
27542775 const zir_tags = sema.code.instructions.items(.tag);
27552776
2756 var buf = std.ArrayList(u8).init(sema.gpa);
2777 var buf = std.ArrayList(u8).init(gpa);
27572778 defer buf.deinit();
27582779 try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
27592780 try buf.appendSlice("(");
......@@ -2781,7 +2802,7 @@ fn createAnonymousDeclTypeNamed(
27812802
27822803 try buf.appendSlice(")");
27832804 const name = try buf.toOwnedSliceSentinel(0);
2784 errdefer sema.gpa.free(name);
2805 errdefer gpa.free(name);
27852806 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27862807 return new_decl_index;
27872808 },
......@@ -2794,10 +2815,10 @@ fn createAnonymousDeclTypeNamed(
27942815 .dbg_var_ptr, .dbg_var_val => {
27952816 if (zir_data[i].str_op.operand != ref) continue;
27962817
2797 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}.{s}", .{
2818 const name = try std.fmt.allocPrintZ(gpa, "{s}.{s}", .{
27982819 src_decl.name, zir_data[i].str_op.getStr(sema.code),
27992820 });
2800 errdefer sema.gpa.free(name);
2821 errdefer gpa.free(name);
28012822
28022823 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
28032824 return new_decl_index;
......@@ -3216,13 +3237,13 @@ fn zirOpaqueDecl(
32163237 .file_scope = block.getFileScope(mod),
32173238 });
32183239 const new_namespace = mod.namespacePtr(new_namespace_index);
3219 errdefer @panic("TODO error handling");
3240 errdefer mod.destroyNamespace(new_namespace_index);
32203241
32213242 const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{
32223243 .decl = new_decl_index,
32233244 .namespace = new_namespace_index,
32243245 } });
3225 errdefer @panic("TODO error handling");
3246 errdefer mod.intern_pool.remove(opaque_ty);
32263247
32273248 new_decl.val = opaque_ty.toValue();
32283249 new_namespace.ty = opaque_ty.toType();
......@@ -3960,7 +3981,7 @@ fn zirArrayBasePtr(
39603981 const elem_ty = sema.typeOf(base_ptr).childType(mod);
39613982 switch (elem_ty.zigTypeTag(mod)) {
39623983 .Array, .Vector => return base_ptr,
3963 .Struct => if (elem_ty.isTuple()) {
3984 .Struct => if (elem_ty.isTuple(mod)) {
39643985 // TODO validate element count
39653986 return base_ptr;
39663987 },
......@@ -4150,7 +4171,7 @@ fn validateArrayInitTy(
41504171 }
41514172 return;
41524173 },
4153 .Struct => if (ty.isTuple()) {
4174 .Struct => if (ty.isTuple(mod)) {
41544175 _ = try sema.resolveTypeFields(ty);
41554176 const array_len = ty.arrayLen(mod);
41564177 if (extra.init_count > array_len) {
......@@ -4358,7 +4379,7 @@ fn validateStructInit(
43584379 const gpa = sema.gpa;
43594380
43604381 // Maps field index to field_ptr index of where it was already initialized.
4361 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount());
4382 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount(mod));
43624383 defer gpa.free(found_fields);
43634384 @memset(found_fields, 0);
43644385
......@@ -4370,7 +4391,7 @@ fn validateStructInit(
43704391 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
43714392 struct_ptr_zir_ref = field_ptr_extra.lhs;
43724393 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
4373 const field_index = if (struct_ty.isTuple())
4394 const field_index = if (struct_ty.isTuple(mod))
43744395 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)
43754396 else
43764397 try sema.structFieldIndex(block, struct_ty, field_name, field_src);
......@@ -4403,9 +4424,9 @@ fn validateStructInit(
44034424 for (found_fields, 0..) |field_ptr, i| {
44044425 if (field_ptr != 0) continue;
44054426
4406 const default_val = struct_ty.structFieldDefaultValue(i);
4427 const default_val = struct_ty.structFieldDefaultValue(i, mod);
44074428 if (default_val.ip_index == .unreachable_value) {
4408 if (struct_ty.isTuple()) {
4429 if (struct_ty.isTuple(mod)) {
44094430 const template = "missing tuple field with index {d}";
44104431 if (root_msg) |msg| {
44114432 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -4414,7 +4435,7 @@ fn validateStructInit(
44144435 }
44154436 continue;
44164437 }
4417 const field_name = struct_ty.structFieldName(i);
4438 const field_name = struct_ty.structFieldName(i, mod);
44184439 const template = "missing struct field: {s}";
44194440 const args = .{field_name};
44204441 if (root_msg) |msg| {
......@@ -4426,7 +4447,7 @@ fn validateStructInit(
44264447 }
44274448
44284449 const field_src = init_src; // TODO better source location
4429 const default_field_ptr = if (struct_ty.isTuple())
4450 const default_field_ptr = if (struct_ty.isTuple(mod))
44304451 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
44314452 else
44324453 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
......@@ -4436,11 +4457,11 @@ fn validateStructInit(
44364457 }
44374458
44384459 if (root_msg) |msg| {
4439 if (struct_ty.castTag(.@"struct")) |struct_obj| {
4440 const fqn = try struct_obj.data.getFullyQualifiedName(mod);
4460 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4461 const fqn = try struct_obj.getFullyQualifiedName(mod);
44414462 defer gpa.free(fqn);
44424463 try mod.errNoteNonLazy(
4443 struct_obj.data.srcLoc(mod),
4464 struct_obj.srcLoc(mod),
44444465 msg,
44454466 "struct '{s}' declared here",
44464467 .{fqn},
......@@ -4463,12 +4484,12 @@ fn validateStructInit(
44634484
44644485 // We collect the comptime field values in case the struct initialization
44654486 // ends up being comptime-known.
4466 const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount());
4487 const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount(mod));
44674488
44684489 field: for (found_fields, 0..) |field_ptr, i| {
44694490 if (field_ptr != 0) {
44704491 // Determine whether the value stored to this pointer is comptime-known.
4471 const field_ty = struct_ty.structFieldType(i);
4492 const field_ty = struct_ty.structFieldType(i, mod);
44724493 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
44734494 field_values[i] = opv;
44744495 continue;
......@@ -4548,9 +4569,9 @@ fn validateStructInit(
45484569 continue :field;
45494570 }
45504571
4551 const default_val = struct_ty.structFieldDefaultValue(i);
4572 const default_val = struct_ty.structFieldDefaultValue(i, mod);
45524573 if (default_val.ip_index == .unreachable_value) {
4553 if (struct_ty.isTuple()) {
4574 if (struct_ty.isTuple(mod)) {
45544575 const template = "missing tuple field with index {d}";
45554576 if (root_msg) |msg| {
45564577 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -4559,7 +4580,7 @@ fn validateStructInit(
45594580 }
45604581 continue;
45614582 }
4562 const field_name = struct_ty.structFieldName(i);
4583 const field_name = struct_ty.structFieldName(i, mod);
45634584 const template = "missing struct field: {s}";
45644585 const args = .{field_name};
45654586 if (root_msg) |msg| {
......@@ -4573,11 +4594,11 @@ fn validateStructInit(
45734594 }
45744595
45754596 if (root_msg) |msg| {
4576 if (struct_ty.castTag(.@"struct")) |struct_obj| {
4577 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
4597 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4598 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
45784599 defer gpa.free(fqn);
45794600 try sema.mod.errNoteNonLazy(
4580 struct_obj.data.srcLoc(sema.mod),
4601 struct_obj.srcLoc(sema.mod),
45814602 msg,
45824603 "struct '{s}' declared here",
45834604 .{fqn},
......@@ -4605,7 +4626,7 @@ fn validateStructInit(
46054626 if (field_ptr != 0) continue;
46064627
46074628 const field_src = init_src; // TODO better source location
4608 const default_field_ptr = if (struct_ty.isTuple())
4629 const default_field_ptr = if (struct_ty.isTuple(mod))
46094630 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
46104631 else
46114632 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
......@@ -4638,7 +4659,7 @@ fn zirValidateArrayInit(
46384659
46394660 var i = instrs.len;
46404661 while (i < array_len) : (i += 1) {
4641 const default_val = array_ty.structFieldDefaultValue(i);
4662 const default_val = array_ty.structFieldDefaultValue(i, mod);
46424663 if (default_val.ip_index == .unreachable_value) {
46434664 const template = "missing tuple field with index {d}";
46444665 if (root_msg) |msg| {
......@@ -4698,7 +4719,7 @@ fn zirValidateArrayInit(
46984719 outer: for (instrs, 0..) |elem_ptr, i| {
46994720 // Determine whether the value stored to this pointer is comptime-known.
47004721
4701 if (array_ty.isTuple()) {
4722 if (array_ty.isTuple(mod)) {
47024723 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
47034724 element_vals[i] = opv;
47044725 continue;
......@@ -7950,7 +7971,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
79507971 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
79517972 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
79527973 if (indexable_ty.zigTypeTag(mod) == .Struct) {
7953 const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs));
7974 const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs), mod);
79547975 return sema.addType(elem_type);
79557976 } else {
79567977 const elem_type = indexable_ty.elemType2(mod);
......@@ -9822,7 +9843,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
98229843 };
98239844 return sema.failWithOwnedErrorMsg(msg);
98249845 },
9825 .Struct, .Union => if (dest_ty.containerLayout() == .Auto) {
9846 .Struct, .Union => if (dest_ty.containerLayout(mod) == .Auto) {
98269847 const container = switch (dest_ty.zigTypeTag(mod)) {
98279848 .Struct => "struct",
98289849 .Union => "union",
......@@ -9885,7 +9906,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
98859906 };
98869907 return sema.failWithOwnedErrorMsg(msg);
98879908 },
9888 .Struct, .Union => if (operand_ty.containerLayout() == .Auto) {
9909 .Struct, .Union => if (operand_ty.containerLayout(mod) == .Auto) {
98899910 const container = switch (operand_ty.zigTypeTag(mod)) {
98909911 .Struct => "struct",
98919912 .Union => "union",
......@@ -12041,12 +12062,12 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1204112062 if (mem.eql(u8, name, field_name)) break true;
1204212063 } else false;
1204312064 }
12044 if (ty.isTuple()) {
12065 if (ty.isTuple(mod)) {
1204512066 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;
12046 break :hf field_index < ty.structFieldCount();
12067 break :hf field_index < ty.structFieldCount(mod);
1204712068 }
1204812069 break :hf switch (ty.zigTypeTag(mod)) {
12049 .Struct => ty.structFields().contains(field_name),
12070 .Struct => ty.structFields(mod).contains(field_name),
1205012071 .Union => ty.unionFields().contains(field_name),
1205112072 .Enum => ty.enumFields().contains(field_name),
1205212073 .Array => mem.eql(u8, field_name, "len"),
......@@ -12601,14 +12622,15 @@ fn analyzeTupleCat(
1260112622 lhs: Air.Inst.Ref,
1260212623 rhs: Air.Inst.Ref,
1260312624) CompileError!Air.Inst.Ref {
12625 const mod = sema.mod;
1260412626 const lhs_ty = sema.typeOf(lhs);
1260512627 const rhs_ty = sema.typeOf(rhs);
1260612628 const src = LazySrcLoc.nodeOffset(src_node);
1260712629 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
1260812630 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1260912631
12610 const lhs_len = lhs_ty.structFieldCount();
12611 const rhs_len = rhs_ty.structFieldCount();
12632 const lhs_len = lhs_ty.structFieldCount(mod);
12633 const rhs_len = rhs_ty.structFieldCount(mod);
1261212634 const dest_fields = lhs_len + rhs_len;
1261312635
1261412636 if (dest_fields == 0) {
......@@ -12629,8 +12651,8 @@ fn analyzeTupleCat(
1262912651 var runtime_src: ?LazySrcLoc = null;
1263012652 var i: u32 = 0;
1263112653 while (i < lhs_len) : (i += 1) {
12632 types[i] = lhs_ty.structFieldType(i);
12633 const default_val = lhs_ty.structFieldDefaultValue(i);
12654 types[i] = lhs_ty.structFieldType(i, mod);
12655 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
1263412656 values[i] = default_val;
1263512657 const operand_src = lhs_src; // TODO better source location
1263612658 if (default_val.ip_index == .unreachable_value) {
......@@ -12639,8 +12661,8 @@ fn analyzeTupleCat(
1263912661 }
1264012662 i = 0;
1264112663 while (i < rhs_len) : (i += 1) {
12642 types[i + lhs_len] = rhs_ty.structFieldType(i);
12643 const default_val = rhs_ty.structFieldDefaultValue(i);
12664 types[i + lhs_len] = rhs_ty.structFieldType(i, mod);
12665 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
1264412666 values[i + lhs_len] = default_val;
1264512667 const operand_src = rhs_src; // TODO better source location
1264612668 if (default_val.ip_index == .unreachable_value) {
......@@ -12691,8 +12713,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1269112713 const rhs_ty = sema.typeOf(rhs);
1269212714 const src = inst_data.src();
1269312715
12694 const lhs_is_tuple = lhs_ty.isTuple();
12695 const rhs_is_tuple = rhs_ty.isTuple();
12716 const lhs_is_tuple = lhs_ty.isTuple(mod);
12717 const rhs_is_tuple = rhs_ty.isTuple(mod);
1269612718 if (lhs_is_tuple and rhs_is_tuple) {
1269712719 return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs);
1269812720 }
......@@ -12800,8 +12822,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1280012822 var elem_i: usize = 0;
1280112823 while (elem_i < lhs_len) : (elem_i += 1) {
1280212824 const lhs_elem_i = elem_i;
12803 const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type;
12804 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.@"unreachable";
12825 const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i, mod) else lhs_info.elem_type;
12826 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
1280512827 const elem_val = if (elem_default_val.ip_index == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
1280612828 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
1280712829 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
......@@ -12810,8 +12832,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1281012832 }
1281112833 while (elem_i < result_len) : (elem_i += 1) {
1281212834 const rhs_elem_i = elem_i - lhs_len;
12813 const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type;
12814 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.@"unreachable";
12835 const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i, mod) else rhs_info.elem_type;
12836 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
1281512837 const elem_val = if (elem_default_val.ip_index == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
1281612838 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
1281712839 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
......@@ -12909,8 +12931,8 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
1290912931 }
1291012932 },
1291112933 .Struct => {
12912 if (operand_ty.isTuple() and peer_ty.isIndexable(mod)) {
12913 assert(!peer_ty.isTuple());
12934 if (operand_ty.isTuple(mod) and peer_ty.isIndexable(mod)) {
12935 assert(!peer_ty.isTuple(mod));
1291412936 return .{
1291512937 .elem_type = peer_ty.elemType2(mod),
1291612938 .sentinel = null,
......@@ -12930,12 +12952,13 @@ fn analyzeTupleMul(
1293012952 operand: Air.Inst.Ref,
1293112953 factor: u64,
1293212954) CompileError!Air.Inst.Ref {
12955 const mod = sema.mod;
1293312956 const operand_ty = sema.typeOf(operand);
1293412957 const src = LazySrcLoc.nodeOffset(src_node);
1293512958 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
1293612959 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1293712960
12938 const tuple_len = operand_ty.structFieldCount();
12961 const tuple_len = operand_ty.structFieldCount(mod);
1293912962 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch
1294012963 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1294112964
......@@ -12951,8 +12974,8 @@ fn analyzeTupleMul(
1295112974 var runtime_src: ?LazySrcLoc = null;
1295212975 var i: u32 = 0;
1295312976 while (i < tuple_len) : (i += 1) {
12954 types[i] = operand_ty.structFieldType(i);
12955 values[i] = operand_ty.structFieldDefaultValue(i);
12977 types[i] = operand_ty.structFieldType(i, mod);
12978 values[i] = operand_ty.structFieldDefaultValue(i, mod);
1295612979 const operand_src = lhs_src; // TODO better source location
1295712980 if (values[i].ip_index == .unreachable_value) {
1295812981 runtime_src = operand_src;
......@@ -13006,7 +13029,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1300613029 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };
1300713030 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
1300813031
13009 if (lhs_ty.isTuple()) {
13032 if (lhs_ty.isTuple(mod)) {
1301013033 // In `**` rhs must be comptime-known, but lhs can be runtime-known
1301113034 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
1301213035 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);
......@@ -14502,7 +14525,7 @@ fn zirOverflowArithmetic(
1450214525
1450314526 const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);
1450414527 element_refs[0] = result.inst;
14505 element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1), result.overflow_bit);
14528 element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1, mod), result.overflow_bit);
1450614529 return block.addAggregateInit(tuple_ty, element_refs);
1450714530}
1450814531
......@@ -16378,7 +16401,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1637816401
1637916402 const union_ty = try sema.resolveTypeFields(ty);
1638016403 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16381 const layout = union_ty.containerLayout();
16404 const layout = union_ty.containerLayout(mod);
1638216405
1638316406 const union_fields = union_ty.unionFields();
1638416407 const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());
......@@ -16484,7 +16507,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1648416507 };
1648516508 const struct_ty = try sema.resolveTypeFields(ty);
1648616509 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16487 const layout = struct_ty.containerLayout();
16510 const layout = struct_ty.containerLayout(mod);
1648816511
1648916512 const struct_field_vals = fv: {
1649016513 if (struct_ty.isSimpleTupleOrAnonStruct()) {
......@@ -16532,7 +16555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1653216555 }
1653316556 break :fv struct_field_vals;
1653416557 }
16535 const struct_fields = struct_ty.structFields();
16558 const struct_fields = struct_ty.structFields(mod);
1653616559 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
1653716560
1653816561 for (struct_field_vals, 0..) |*field_val, i| {
......@@ -16600,7 +16623,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1660016623
1660116624 const backing_integer_val = blk: {
1660216625 if (layout == .Packed) {
16603 const struct_obj = struct_ty.castTag(.@"struct").?.data;
16626 const struct_obj = mod.typeToStruct(struct_ty).?;
1660416627 assert(struct_obj.haveLayout());
1660516628 assert(struct_obj.backing_int_ty.isInt(mod));
1660616629 const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty);
......@@ -16624,7 +16647,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1662416647 // decls: []const Declaration,
1662516648 decls_val,
1662616649 // is_tuple: bool,
16627 Value.makeBool(struct_ty.isTuple()),
16650 Value.makeBool(struct_ty.isTuple(mod)),
1662816651 };
1662916652
1663016653 return sema.addConstant(
......@@ -17801,12 +17824,13 @@ fn structInitEmpty(
1780117824 dest_src: LazySrcLoc,
1780217825 init_src: LazySrcLoc,
1780317826) CompileError!Air.Inst.Ref {
17827 const mod = sema.mod;
1780417828 const gpa = sema.gpa;
1780517829 // This logic must be synchronized with that in `zirStructInit`.
1780617830 const struct_ty = try sema.resolveTypeFields(obj_ty);
1780717831
1780817832 // The init values to use for the struct instance.
17809 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount());
17833 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(mod));
1781017834 defer gpa.free(field_inits);
1781117835 @memset(field_inits, .none);
1781217836
......@@ -17897,18 +17921,18 @@ fn zirStructInit(
1789717921
1789817922 // Maps field index to field_type index of where it was already initialized.
1789917923 // For making sure all fields are accounted for and no fields are duplicated.
17900 const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount());
17924 const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount(mod));
1790117925 defer gpa.free(found_fields);
1790217926
1790317927 // The init values to use for the struct instance.
17904 const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount());
17928 const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount(mod));
1790517929 defer gpa.free(field_inits);
1790617930 @memset(field_inits, .none);
1790717931
1790817932 var field_i: u32 = 0;
1790917933 var extra_index = extra.end;
1791017934
17911 const is_packed = resolved_ty.containerLayout() == .Packed;
17935 const is_packed = resolved_ty.containerLayout(mod) == .Packed;
1791217936 while (field_i < extra.data.fields_len) : (field_i += 1) {
1791317937 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);
1791417938 extra_index = item.end;
......@@ -17917,7 +17941,7 @@ fn zirStructInit(
1791717941 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
1791817942 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
1791917943 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
17920 const field_index = if (resolved_ty.isTuple())
17944 const field_index = if (resolved_ty.isTuple(mod))
1792117945 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)
1792217946 else
1792317947 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
......@@ -17940,7 +17964,7 @@ fn zirStructInit(
1794017964 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
1794117965 };
1794217966
17943 if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index), sema.mod)) {
17967 if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index, mod), sema.mod)) {
1794417968 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);
1794517969 }
1794617970 };
......@@ -18029,13 +18053,13 @@ fn finishStructInit(
1802918053 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
1803018054 }
1803118055 }
18032 } else if (struct_ty.isTuple()) {
18056 } else if (struct_ty.isTuple(mod)) {
1803318057 var i: u32 = 0;
18034 const len = struct_ty.structFieldCount();
18058 const len = struct_ty.structFieldCount(mod);
1803518059 while (i < len) : (i += 1) {
1803618060 if (field_inits[i] != .none) continue;
1803718061
18038 const default_val = struct_ty.structFieldDefaultValue(i);
18062 const default_val = struct_ty.structFieldDefaultValue(i, mod);
1803918063 if (default_val.ip_index == .unreachable_value) {
1804018064 const template = "missing tuple field with index {d}";
1804118065 if (root_msg) |msg| {
......@@ -18044,11 +18068,11 @@ fn finishStructInit(
1804418068 root_msg = try sema.errMsg(block, init_src, template, .{i});
1804518069 }
1804618070 } else {
18047 field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i), default_val);
18071 field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i, mod), default_val);
1804818072 }
1804918073 }
1805018074 } else {
18051 const struct_obj = struct_ty.castTag(.@"struct").?.data;
18075 const struct_obj = mod.typeToStruct(struct_ty).?;
1805218076 for (struct_obj.fields.values(), 0..) |field, i| {
1805318077 if (field_inits[i] != .none) continue;
1805418078
......@@ -18068,11 +18092,11 @@ fn finishStructInit(
1806818092 }
1806918093
1807018094 if (root_msg) |msg| {
18071 if (struct_ty.castTag(.@"struct")) |struct_obj| {
18072 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
18095 if (mod.typeToStruct(struct_ty)) |struct_obj| {
18096 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
1807318097 defer gpa.free(fqn);
1807418098 try sema.mod.errNoteNonLazy(
18075 struct_obj.data.srcLoc(sema.mod),
18099 struct_obj.srcLoc(sema.mod),
1807618100 msg,
1807718101 "struct '{s}' declared here",
1807818102 .{fqn},
......@@ -18277,7 +18301,7 @@ fn zirArrayInit(
1827718301 for (args[1..], 0..) |arg, i| {
1827818302 const resolved_arg = try sema.resolveInst(arg);
1827918303 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)
18280 array_ty.structFieldType(i)
18304 array_ty.structFieldType(i, mod)
1828118305 else
1828218306 array_ty.elemType2(mod);
1828318307 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
......@@ -18331,12 +18355,12 @@ fn zirArrayInit(
1833118355 });
1833218356 const alloc = try block.addTy(.alloc, alloc_ty);
1833318357
18334 if (array_ty.isTuple()) {
18358 if (array_ty.isTuple(mod)) {
1833518359 for (resolved_args, 0..) |arg, i| {
1833618360 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
1833718361 .mutable = true,
1833818362 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18339 .pointee_type = array_ty.structFieldType(i),
18363 .pointee_type = array_ty.structFieldType(i, mod),
1834018364 });
1834118365 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1834218366
......@@ -18514,7 +18538,7 @@ fn fieldType(
1851418538 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
1851518539 return sema.addType(cur_ty.tupleFields().types[field_index]);
1851618540 }
18517 const struct_obj = cur_ty.castTag(.@"struct").?.data;
18541 const struct_obj = mod.typeToStruct(cur_ty).?;
1851818542 const field = struct_obj.fields.get(field_name) orelse
1851918543 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
1852018544 return sema.addType(field.ty);
......@@ -19185,13 +19209,13 @@ fn zirReify(
1918519209 .file_scope = block.getFileScope(mod),
1918619210 });
1918719211 const new_namespace = mod.namespacePtr(new_namespace_index);
19188 errdefer @panic("TODO error handling");
19212 errdefer mod.destroyNamespace(new_namespace_index);
1918919213
1919019214 const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{
1919119215 .decl = new_decl_index,
1919219216 .namespace = new_namespace_index,
1919319217 } });
19194 errdefer @panic("TODO error handling");
19218 errdefer mod.intern_pool.remove(opaque_ty);
1919519219
1919619220 new_decl.val = opaque_ty.toValue();
1919719221 new_namespace.ty = opaque_ty.toType();
......@@ -19493,22 +19517,34 @@ fn reifyStruct(
1949319517 name_strategy: Zir.Inst.NameStrategy,
1949419518 is_tuple: bool,
1949519519) CompileError!Air.Inst.Ref {
19496 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
19520 const mod = sema.mod;
19521 const gpa = sema.gpa;
19522
19523 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
1949719524 errdefer new_decl_arena.deinit();
1949819525 const new_decl_arena_allocator = new_decl_arena.allocator();
1949919526
19500 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
19501 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
19502 const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
19503 const mod = sema.mod;
19527 // Because these three things each reference each other, `undefined`
19528 // placeholders are used before being set after the struct type gains an
19529 // InternPool index.
19530
1950419531 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
1950519532 .ty = Type.type,
19506 .val = new_struct_val,
19533 .val = undefined,
1950719534 }, name_strategy, "struct", inst);
1950819535 const new_decl = mod.declPtr(new_decl_index);
1950919536 new_decl.owns_tv = true;
1951019537 errdefer mod.abortAnonDecl(new_decl_index);
19511 struct_obj.* = .{
19538
19539 const new_namespace_index = try mod.createNamespace(.{
19540 .parent = block.namespace.toOptional(),
19541 .ty = undefined,
19542 .file_scope = block.getFileScope(mod),
19543 });
19544 const new_namespace = mod.namespacePtr(new_namespace_index);
19545 errdefer mod.destroyNamespace(new_namespace_index);
19546
19547 const struct_index = try mod.createStruct(.{
1951219548 .owner_decl = new_decl_index,
1951319549 .fields = .{},
1951419550 .zir_index = inst,
......@@ -19516,12 +19552,19 @@ fn reifyStruct(
1951619552 .status = .have_field_types,
1951719553 .known_non_opv = false,
1951819554 .is_tuple = is_tuple,
19519 .namespace = try mod.createNamespace(.{
19520 .parent = block.namespace.toOptional(),
19521 .ty = struct_ty,
19522 .file_scope = block.getFileScope(mod),
19523 }),
19524 };
19555 .namespace = new_namespace_index,
19556 });
19557 const struct_obj = mod.structPtr(struct_index);
19558 errdefer mod.destroyStruct(struct_index);
19559
19560 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
19561 .index = struct_index.toOptional(),
19562 .namespace = new_namespace_index.toOptional(),
19563 } });
19564 errdefer mod.intern_pool.remove(struct_ty);
19565
19566 new_decl.val = struct_ty.toValue();
19567 new_namespace.ty = struct_ty.toType();
1952519568
1952619569 // Fields
1952719570 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
......@@ -19609,7 +19652,7 @@ fn reifyStruct(
1960919652 if (field_ty.zigTypeTag(mod) == .Opaque) {
1961019653 const msg = msg: {
1961119654 const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
19612 errdefer msg.destroy(sema.gpa);
19655 errdefer msg.destroy(gpa);
1961319656
1961419657 try sema.addDeclaredHereNote(msg, field_ty);
1961519658 break :msg msg;
......@@ -19619,7 +19662,7 @@ fn reifyStruct(
1961919662 if (field_ty.zigTypeTag(mod) == .NoReturn) {
1962019663 const msg = msg: {
1962119664 const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});
19622 errdefer msg.destroy(sema.gpa);
19665 errdefer msg.destroy(gpa);
1962319666
1962419667 try sema.addDeclaredHereNote(msg, field_ty);
1962519668 break :msg msg;
......@@ -19629,7 +19672,7 @@ fn reifyStruct(
1962919672 if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {
1963019673 const msg = msg: {
1963119674 const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
19632 errdefer msg.destroy(sema.gpa);
19675 errdefer msg.destroy(gpa);
1963319676
1963419677 const src_decl = sema.mod.declPtr(block.src_decl);
1963519678 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field);
......@@ -19641,7 +19684,7 @@ fn reifyStruct(
1964119684 } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) {
1964219685 const msg = msg: {
1964319686 const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
19644 errdefer msg.destroy(sema.gpa);
19687 errdefer msg.destroy(gpa);
1964519688
1964619689 const src_decl = sema.mod.declPtr(block.src_decl);
1964719690 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty);
......@@ -19660,7 +19703,7 @@ fn reifyStruct(
1966019703 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
1966119704 error.AnalysisFail => {
1966219705 const msg = sema.err orelse return err;
19663 try sema.addFieldErrNote(struct_ty, index, msg, "while checking this field", .{});
19706 try sema.addFieldErrNote(struct_ty.toType(), index, msg, "while checking this field", .{});
1966419707 return err;
1966519708 },
1966619709 else => return err,
......@@ -20558,21 +20601,21 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2055820601 },
2055920602 }
2056020603
20561 const field_index = if (ty.isTuple()) blk: {
20604 const field_index = if (ty.isTuple(mod)) blk: {
2056220605 if (mem.eql(u8, field_name, "len")) {
2056320606 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
2056420607 }
2056520608 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
2056620609 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
2056720610
20568 if (ty.structFieldIsComptime(field_index)) {
20611 if (ty.structFieldIsComptime(field_index, mod)) {
2056920612 return sema.fail(block, src, "no offset available for comptime field", .{});
2057020613 }
2057120614
20572 switch (ty.containerLayout()) {
20615 switch (ty.containerLayout(mod)) {
2057320616 .Packed => {
2057420617 var bit_sum: u64 = 0;
20575 const fields = ty.structFields();
20618 const fields = ty.structFields(mod);
2057620619 for (fields.values(), 0..) |field, i| {
2057720620 if (i == field_index) {
2057820621 return bit_sum;
......@@ -21810,6 +21853,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2181021853 const tracy = trace(@src());
2181121854 defer tracy.end();
2181221855
21856 const mod = sema.mod;
2181321857 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2181421858 const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2181521859 const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
......@@ -21869,11 +21913,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2186921913 const args = try sema.resolveInst(extra.args);
2187021914
2187121915 const args_ty = sema.typeOf(args);
21872 if (!args_ty.isTuple() and args_ty.ip_index != .empty_struct_type) {
21916 if (!args_ty.isTuple(mod) and args_ty.ip_index != .empty_struct_type) {
2187321917 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});
2187421918 }
2187521919
21876 var resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount());
21920 var resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(mod));
2187721921 for (resolved_args, 0..) |*resolved, i| {
2187821922 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);
2187921923 }
......@@ -21905,7 +21949,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2190521949
2190621950 const field_index = switch (parent_ty.zigTypeTag(mod)) {
2190721951 .Struct => blk: {
21908 if (parent_ty.isTuple()) {
21952 if (parent_ty.isTuple(mod)) {
2190921953 if (mem.eql(u8, field_name, "len")) {
2191021954 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
2191121955 }
......@@ -21918,7 +21962,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2191821962 else => unreachable,
2191921963 };
2192021964
21921 if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index)) {
21965 if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index, mod)) {
2192221966 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
2192321967 }
2192421968
......@@ -21926,17 +21970,17 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2192621970 const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod);
2192721971
2192821972 var ptr_ty_data: Type.Payload.Pointer.Data = .{
21929 .pointee_type = parent_ty.structFieldType(field_index),
21973 .pointee_type = parent_ty.structFieldType(field_index, mod),
2193021974 .mutable = field_ptr_ty_info.mutable,
2193121975 .@"addrspace" = field_ptr_ty_info.@"addrspace",
2193221976 };
2193321977
21934 if (parent_ty.containerLayout() == .Packed) {
21978 if (parent_ty.containerLayout(mod) == .Packed) {
2193521979 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
2193621980 } else {
2193721981 ptr_ty_data.@"align" = blk: {
21938 if (parent_ty.castTag(.@"struct")) |struct_obj| {
21939 break :blk struct_obj.data.fields.values()[field_index].abi_align;
21982 if (mod.typeToStruct(parent_ty)) |struct_obj| {
21983 break :blk struct_obj.fields.values()[field_index].abi_align;
2194021984 } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| {
2194121985 break :blk union_obj.data.fields.values()[field_index].abi_align;
2194221986 } else {
......@@ -23380,8 +23424,7 @@ fn explainWhyTypeIsComptimeInner(
2338023424 .Struct => {
2338123425 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
2338223426
23383 if (ty.castTag(.@"struct")) |payload| {
23384 const struct_obj = payload.data;
23427 if (mod.typeToStruct(ty)) |struct_obj| {
2338523428 for (struct_obj.fields.values(), 0..) |field, i| {
2338623429 const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{
2338723430 .index = i,
......@@ -23472,7 +23515,7 @@ fn validateExternType(
2347223515 .Enum => {
2347323516 return sema.validateExternType(try ty.intTagType(mod), position);
2347423517 },
23475 .Struct, .Union => switch (ty.containerLayout()) {
23518 .Struct, .Union => switch (ty.containerLayout(mod)) {
2347623519 .Extern => return true,
2347723520 .Packed => {
2347823521 const bit_size = try ty.bitSizeAdvanced(mod, sema);
......@@ -23569,7 +23612,7 @@ fn explainWhyTypeIsNotExtern(
2356923612
2357023613/// Returns true if `ty` is allowed in packed types.
2357123614/// Does *NOT* require `ty` to be resolved in any way.
23572fn validatePackedType(ty: Type, mod: *const Module) bool {
23615fn validatePackedType(ty: Type, mod: *Module) bool {
2357323616 switch (ty.zigTypeTag(mod)) {
2357423617 .Type,
2357523618 .ComptimeFloat,
......@@ -23595,7 +23638,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool {
2359523638 .Enum,
2359623639 => return true,
2359723640 .Pointer => return !ty.isSlice(mod),
23598 .Struct, .Union => return ty.containerLayout() == .Packed,
23641 .Struct, .Union => return ty.containerLayout(mod) == .Packed,
2359923642 }
2360023643}
2360123644
......@@ -24419,27 +24462,27 @@ fn fieldCallBind(
2441924462 switch (concrete_ty.zigTypeTag(mod)) {
2442024463 .Struct => {
2442124464 const struct_ty = try sema.resolveTypeFields(concrete_ty);
24422 if (struct_ty.castTag(.@"struct")) |struct_obj| {
24423 const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse
24465 if (mod.typeToStruct(struct_ty)) |struct_obj| {
24466 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
2442424467 break :find_field;
2442524468 const field_index = @intCast(u32, field_index_usize);
24426 const field = struct_obj.data.fields.values()[field_index];
24469 const field = struct_obj.fields.values()[field_index];
2442724470
2442824471 return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr);
24429 } else if (struct_ty.isTuple()) {
24472 } else if (struct_ty.isTuple(mod)) {
2443024473 if (mem.eql(u8, field_name, "len")) {
24431 return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()) };
24474 return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod)) };
2443224475 }
2443324476 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
24434 if (field_index >= struct_ty.structFieldCount()) break :find_field;
24435 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr);
24477 if (field_index >= struct_ty.structFieldCount(mod)) break :find_field;
24478 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index, mod), field_index, object_ptr);
2443624479 } else |_| {}
2443724480 } else {
24438 const max = struct_ty.structFieldCount();
24481 const max = struct_ty.structFieldCount(mod);
2443924482 var i: u32 = 0;
2444024483 while (i < max) : (i += 1) {
24441 if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) {
24442 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr);
24484 if (mem.eql(u8, struct_ty.structFieldName(i, mod), field_name)) {
24485 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i, mod), i, object_ptr);
2444324486 }
2444424487 }
2444524488 }
......@@ -24651,9 +24694,9 @@ fn structFieldPtr(
2465124694 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
2465224695 try sema.resolveStructLayout(struct_ty);
2465324696
24654 if (struct_ty.isTuple()) {
24697 if (struct_ty.isTuple(mod)) {
2465524698 if (mem.eql(u8, field_name, "len")) {
24656 const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount());
24699 const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod));
2465724700 return sema.analyzeRef(block, src, len_inst);
2465824701 }
2465924702 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
......@@ -24663,7 +24706,7 @@ fn structFieldPtr(
2466324706 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
2466424707 }
2466524708
24666 const struct_obj = struct_ty.castTag(.@"struct").?.data;
24709 const struct_obj = mod.typeToStruct(struct_ty).?;
2466724710
2466824711 const field_index_big = struct_obj.fields.getIndex(field_name) orelse
2466924712 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
......@@ -24687,7 +24730,7 @@ fn structFieldPtrByIndex(
2468724730 }
2468824731
2468924732 const mod = sema.mod;
24690 const struct_obj = struct_ty.castTag(.@"struct").?.data;
24733 const struct_obj = mod.typeToStruct(struct_ty).?;
2469124734 const field = struct_obj.fields.values()[field_index];
2469224735 const struct_ptr_ty = sema.typeOf(struct_ptr);
2469324736 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod);
......@@ -24799,8 +24842,11 @@ fn structFieldVal(
2479924842 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
2480024843 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
2480124844 },
24802 .@"struct" => {
24803 const struct_obj = struct_ty.castTag(.@"struct").?.data;
24845 else => unreachable,
24846 },
24847 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
24848 .struct_type => |struct_type| {
24849 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
2480424850 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2480524851
2480624852 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
......@@ -24827,7 +24873,6 @@ fn structFieldVal(
2482724873 },
2482824874 else => unreachable,
2482924875 },
24830 else => unreachable,
2483124876 }
2483224877}
2483324878
......@@ -24840,8 +24885,9 @@ fn tupleFieldVal(
2484024885 field_name_src: LazySrcLoc,
2484124886 tuple_ty: Type,
2484224887) CompileError!Air.Inst.Ref {
24888 const mod = sema.mod;
2484324889 if (mem.eql(u8, field_name, "len")) {
24844 return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount());
24890 return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount(mod));
2484524891 }
2484624892 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src);
2484724893 return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty);
......@@ -24858,7 +24904,7 @@ fn tupleFieldIndex(
2485824904 const mod = sema.mod;
2485924905 assert(!std.mem.eql(u8, field_name, "len"));
2486024906 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
24861 if (field_index < tuple_ty.structFieldCount()) return field_index;
24907 if (field_index < tuple_ty.structFieldCount(mod)) return field_index;
2486224908 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
2486324909 field_name, tuple_ty.fmt(mod),
2486424910 });
......@@ -24878,7 +24924,7 @@ fn tupleFieldValByIndex(
2487824924 tuple_ty: Type,
2487924925) CompileError!Air.Inst.Ref {
2488024926 const mod = sema.mod;
24881 const field_ty = tuple_ty.structFieldType(field_index);
24927 const field_ty = tuple_ty.structFieldType(field_index, mod);
2488224928
2488324929 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
2488424930 return sema.addConstant(field_ty, default_value);
......@@ -25251,7 +25297,7 @@ fn tupleFieldPtr(
2525125297 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
2525225298 const tuple_ty = tuple_ptr_ty.childType(mod);
2525325299 _ = try sema.resolveTypeFields(tuple_ty);
25254 const field_count = tuple_ty.structFieldCount();
25300 const field_count = tuple_ty.structFieldCount(mod);
2525525301
2525625302 if (field_count == 0) {
2525725303 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});
......@@ -25263,7 +25309,7 @@ fn tupleFieldPtr(
2526325309 });
2526425310 }
2526525311
25266 const field_ty = tuple_ty.structFieldType(field_index);
25312 const field_ty = tuple_ty.structFieldType(field_index, mod);
2526725313 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
2526825314 .pointee_type = field_ty,
2526925315 .mutable = tuple_ptr_ty.ptrIsMutable(mod),
......@@ -25308,7 +25354,7 @@ fn tupleField(
2530825354) CompileError!Air.Inst.Ref {
2530925355 const mod = sema.mod;
2531025356 const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple));
25311 const field_count = tuple_ty.structFieldCount();
25357 const field_count = tuple_ty.structFieldCount(mod);
2531225358
2531325359 if (field_count == 0) {
2531425360 return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});
......@@ -25320,7 +25366,7 @@ fn tupleField(
2532025366 });
2532125367 }
2532225368
25323 const field_ty = tuple_ty.structFieldType(field_index);
25369 const field_ty = tuple_ty.structFieldType(field_index, mod);
2532425370
2532525371 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
2532625372 return sema.addConstant(field_ty, default_value); // comptime field
......@@ -25919,7 +25965,7 @@ fn coerceExtra(
2591925965 .Array => {
2592025966 // pointer to tuple to pointer to array
2592125967 if (inst_ty.isSinglePointer(mod) and
25922 inst_ty.childType(mod).isTuple() and
25968 inst_ty.childType(mod).isTuple(mod) and
2592325969 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2592425970 {
2592525971 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
......@@ -25939,11 +25985,11 @@ fn coerceExtra(
2593925985
2594025986 if (!inst_ty.isSinglePointer(mod)) break :to_slice;
2594125987 const inst_child_ty = inst_ty.childType(mod);
25942 if (!inst_child_ty.isTuple()) break :to_slice;
25988 if (!inst_child_ty.isTuple(mod)) break :to_slice;
2594325989
2594425990 // empty tuple to zero-length slice
2594525991 // note that this allows coercing to a mutable slice.
25946 if (inst_child_ty.structFieldCount() == 0) {
25992 if (inst_child_ty.structFieldCount(mod) == 0) {
2594725993 // Optional slice is represented with a null pointer so
2594825994 // we use a dummy pointer value with the required alignment.
2594925995 const slice_val = try Value.Tag.slice.create(sema.arena, .{
......@@ -26213,7 +26259,7 @@ fn coerceExtra(
2621326259 if (inst == .empty_struct) {
2621426260 return sema.arrayInitEmpty(block, inst_src, dest_ty);
2621526261 }
26216 if (inst_ty.isTuple()) {
26262 if (inst_ty.isTuple(mod)) {
2621726263 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
2621826264 }
2621926265 },
......@@ -26225,7 +26271,7 @@ fn coerceExtra(
2622526271 .Vector => switch (inst_ty.zigTypeTag(mod)) {
2622626272 .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
2622726273 .Struct => {
26228 if (inst_ty.isTuple()) {
26274 if (inst_ty.isTuple(mod)) {
2622926275 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
2623026276 }
2623126277 },
......@@ -26238,7 +26284,7 @@ fn coerceExtra(
2623826284 if (inst == .empty_struct) {
2623926285 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);
2624026286 }
26241 if (inst_ty.isTupleOrAnonStruct()) {
26287 if (inst_ty.isTupleOrAnonStruct(mod)) {
2624226288 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
2624326289 error.NotCoercible => break :blk,
2624426290 else => |e| return e,
......@@ -27304,8 +27350,8 @@ fn storePtr2(
2730427350 // this code does not handle tuple-to-struct coercion which requires dealing with missing
2730527351 // fields.
2730627352 const operand_ty = sema.typeOf(uncasted_operand);
27307 if (operand_ty.isTuple() and elem_ty.zigTypeTag(mod) == .Array) {
27308 const field_count = operand_ty.structFieldCount();
27353 if (operand_ty.isTuple(mod) and elem_ty.zigTypeTag(mod) == .Array) {
27354 const field_count = operand_ty.structFieldCount(mod);
2730927355 var i: u32 = 0;
2731027356 while (i < field_count) : (i += 1) {
2731127357 const elem_src = operand_src; // TODO better source location
......@@ -27804,7 +27850,7 @@ fn beginComptimePtrMutation(
2780427850
2780527851 switch (parent.ty.zigTypeTag(mod)) {
2780627852 .Struct => {
27807 const fields = try arena.alloc(Value, parent.ty.structFieldCount());
27853 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
2780827854 @memset(fields, Value.undef);
2780927855
2781027856 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
......@@ -27813,7 +27859,7 @@ fn beginComptimePtrMutation(
2781327859 sema,
2781427860 block,
2781527861 src,
27816 parent.ty.structFieldType(field_index),
27862 parent.ty.structFieldType(field_index, mod),
2781727863 &fields[field_index],
2781827864 ptr_elem_ty,
2781927865 parent.decl_ref_mut,
......@@ -27832,7 +27878,7 @@ fn beginComptimePtrMutation(
2783227878 sema,
2783327879 block,
2783427880 src,
27835 parent.ty.structFieldType(field_index),
27881 parent.ty.structFieldType(field_index, mod),
2783627882 &payload.data.val,
2783727883 ptr_elem_ty,
2783827884 parent.decl_ref_mut,
......@@ -27878,7 +27924,7 @@ fn beginComptimePtrMutation(
2787827924 sema,
2787927925 block,
2788027926 src,
27881 parent.ty.structFieldType(field_index),
27927 parent.ty.structFieldType(field_index, mod),
2788227928 duped,
2788327929 ptr_elem_ty,
2788427930 parent.decl_ref_mut,
......@@ -27889,7 +27935,7 @@ fn beginComptimePtrMutation(
2788927935 sema,
2789027936 block,
2789127937 src,
27892 parent.ty.structFieldType(field_index),
27938 parent.ty.structFieldType(field_index, mod),
2789327939 &val_ptr.castTag(.aggregate).?.data[field_index],
2789427940 ptr_elem_ty,
2789527941 parent.decl_ref_mut,
......@@ -27907,7 +27953,7 @@ fn beginComptimePtrMutation(
2790727953 sema,
2790827954 block,
2790927955 src,
27910 parent.ty.structFieldType(field_index),
27956 parent.ty.structFieldType(field_index, mod),
2791127957 &payload.val,
2791227958 ptr_elem_ty,
2791327959 parent.decl_ref_mut,
......@@ -28269,8 +28315,8 @@ fn beginComptimePtrLoad(
2826928315 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);
2827028316
2827128317 if (field_ptr.container_ty.hasWellDefinedLayout(mod)) {
28272 const struct_ty = field_ptr.container_ty.castTag(.@"struct");
28273 if (struct_ty != null and struct_ty.?.data.layout == .Packed) {
28318 const struct_obj = mod.typeToStruct(field_ptr.container_ty);
28319 if (struct_obj != null and struct_obj.?.layout == .Packed) {
2827428320 // packed structs are not byte addressable
2827528321 deref.parent = null;
2827628322 } else if (deref.parent) |*parent| {
......@@ -28310,7 +28356,7 @@ fn beginComptimePtrLoad(
2831028356 else => unreachable,
2831128357 };
2831228358 } else {
28313 const field_ty = field_ptr.container_ty.structFieldType(field_index);
28359 const field_ty = field_ptr.container_ty.structFieldType(field_index, mod);
2831428360 deref.pointee = TypedValue{
2831528361 .ty = field_ty,
2831628362 .val = try tv.val.fieldValue(tv.ty, mod, field_index),
......@@ -28483,7 +28529,7 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
2848328529 const inst_info = inst_ty.ptrInfo(mod);
2848428530 const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or
2848528531 (inst_info.pointee_type.arrayLen(mod) == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or
28486 (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0);
28532 (inst_info.pointee_type.isTuple(mod) and inst_info.pointee_type.structFieldCount(mod) == 0);
2848728533
2848828534 const ok_cv_qualifiers =
2848928535 ((inst_info.mutable or !dest_info.mutable) or len0) and
......@@ -28714,8 +28760,9 @@ fn coerceAnonStructToUnion(
2871428760 inst: Air.Inst.Ref,
2871528761 inst_src: LazySrcLoc,
2871628762) !Air.Inst.Ref {
28763 const mod = sema.mod;
2871728764 const inst_ty = sema.typeOf(inst);
28718 const field_count = inst_ty.structFieldCount();
28765 const field_count = inst_ty.structFieldCount(mod);
2871928766 if (field_count != 1) {
2872028767 const msg = msg: {
2872128768 const msg = if (field_count > 1) try sema.errMsg(
......@@ -28927,7 +28974,7 @@ fn coerceTupleToSlicePtrs(
2892728974 const tuple_ty = sema.typeOf(ptr_tuple).childType(mod);
2892828975 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);
2892928976 const slice_info = slice_ty.ptrInfo(mod);
28930 const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(), slice_info.sentinel, slice_info.pointee_type, sema.mod);
28977 const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(mod), slice_info.sentinel, slice_info.pointee_type, sema.mod);
2893128978 const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src);
2893228979 if (slice_info.@"align" != 0) {
2893328980 return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{});
......@@ -28966,20 +29013,21 @@ fn coerceTupleToStruct(
2896629013 inst: Air.Inst.Ref,
2896729014 inst_src: LazySrcLoc,
2896829015) !Air.Inst.Ref {
29016 const mod = sema.mod;
2896929017 const struct_ty = try sema.resolveTypeFields(dest_ty);
2897029018
28971 if (struct_ty.isTupleOrAnonStruct()) {
29019 if (struct_ty.isTupleOrAnonStruct(mod)) {
2897229020 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
2897329021 }
2897429022
28975 const fields = struct_ty.structFields();
29023 const fields = struct_ty.structFields(mod);
2897629024 const field_vals = try sema.arena.alloc(Value, fields.count());
2897729025 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
2897829026 @memset(field_refs, .none);
2897929027
2898029028 const inst_ty = sema.typeOf(inst);
2898129029 var runtime_src: ?LazySrcLoc = null;
28982 const field_count = inst_ty.structFieldCount();
29030 const field_count = inst_ty.structFieldCount(mod);
2898329031 var field_i: u32 = 0;
2898429032 while (field_i < field_count) : (field_i += 1) {
2898529033 const field_src = inst_src; // TODO better source location
......@@ -29061,13 +29109,14 @@ fn coerceTupleToTuple(
2906129109 inst: Air.Inst.Ref,
2906229110 inst_src: LazySrcLoc,
2906329111) !Air.Inst.Ref {
29064 const dest_field_count = tuple_ty.structFieldCount();
29112 const mod = sema.mod;
29113 const dest_field_count = tuple_ty.structFieldCount(mod);
2906529114 const field_vals = try sema.arena.alloc(Value, dest_field_count);
2906629115 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
2906729116 @memset(field_refs, .none);
2906829117
2906929118 const inst_ty = sema.typeOf(inst);
29070 const inst_field_count = inst_ty.structFieldCount();
29119 const inst_field_count = inst_ty.structFieldCount(mod);
2907129120 if (inst_field_count > dest_field_count) return error.NotCoercible;
2907229121
2907329122 var runtime_src: ?LazySrcLoc = null;
......@@ -29085,8 +29134,8 @@ fn coerceTupleToTuple(
2908529134
2908629135 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2908729136
29088 const field_ty = tuple_ty.structFieldType(field_i);
29089 const default_val = tuple_ty.structFieldDefaultValue(field_i);
29137 const field_ty = tuple_ty.structFieldType(field_i, mod);
29138 const default_val = tuple_ty.structFieldDefaultValue(field_i, mod);
2909029139 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
2909129140 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
2909229141 field_refs[field_index] = coerced;
......@@ -29115,12 +29164,12 @@ fn coerceTupleToTuple(
2911529164 for (field_refs, 0..) |*field_ref, i| {
2911629165 if (field_ref.* != .none) continue;
2911729166
29118 const default_val = tuple_ty.structFieldDefaultValue(i);
29119 const field_ty = tuple_ty.structFieldType(i);
29167 const default_val = tuple_ty.structFieldDefaultValue(i, mod);
29168 const field_ty = tuple_ty.structFieldType(i, mod);
2912029169
2912129170 const field_src = inst_src; // TODO better source location
2912229171 if (default_val.ip_index == .unreachable_value) {
29123 if (tuple_ty.isTuple()) {
29172 if (tuple_ty.isTuple(mod)) {
2912429173 const template = "missing tuple field: {d}";
2912529174 if (root_msg) |msg| {
2912629175 try sema.errNote(block, field_src, msg, template, .{i});
......@@ -29130,7 +29179,7 @@ fn coerceTupleToTuple(
2913029179 continue;
2913129180 }
2913229181 const template = "missing struct field: {s}";
29133 const args = .{tuple_ty.structFieldName(i)};
29182 const args = .{tuple_ty.structFieldName(i, mod)};
2913429183 if (root_msg) |msg| {
2913529184 try sema.errNote(block, field_src, msg, template, args);
2913629185 } else {
......@@ -31222,17 +31271,17 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3122231271}
3122331272
3122431273fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31274 const mod = sema.mod;
3122531275 const resolved_ty = try sema.resolveTypeFields(ty);
31226 if (resolved_ty.castTag(.@"struct")) |payload| {
31227 const struct_obj = payload.data;
31276 if (mod.typeToStruct(resolved_ty)) |struct_obj| {
3122831277 switch (struct_obj.status) {
3122931278 .none, .have_field_types => {},
3123031279 .field_types_wip, .layout_wip => {
3123131280 const msg = try Module.ErrorMsg.create(
3123231281 sema.gpa,
31233 struct_obj.srcLoc(sema.mod),
31282 struct_obj.srcLoc(mod),
3123431283 "struct '{}' depends on itself",
31235 .{ty.fmt(sema.mod)},
31284 .{ty.fmt(mod)},
3123631285 );
3123731286 return sema.failWithOwnedErrorMsg(msg);
3123831287 },
......@@ -31256,7 +31305,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3125631305 }
3125731306
3125831307 if (struct_obj.layout == .Packed) {
31259 try semaBackingIntType(sema.mod, struct_obj);
31308 try semaBackingIntType(mod, struct_obj);
3126031309 }
3126131310
3126231311 struct_obj.status = .have_layout;
......@@ -31265,20 +31314,20 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3126531314 if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {
3126631315 const msg = try Module.ErrorMsg.create(
3126731316 sema.gpa,
31268 struct_obj.srcLoc(sema.mod),
31317 struct_obj.srcLoc(mod),
3126931318 "struct layout depends on it having runtime bits",
3127031319 .{},
3127131320 );
3127231321 return sema.failWithOwnedErrorMsg(msg);
3127331322 }
3127431323
31275 if (struct_obj.layout == .Auto and sema.mod.backendSupportsFeature(.field_reordering)) {
31324 if (struct_obj.layout == .Auto and mod.backendSupportsFeature(.field_reordering)) {
3127631325 const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index)
3127731326 try sema.perm_arena.alloc(u32, struct_obj.fields.count())
3127831327 else blk: {
31279 const decl = sema.mod.declPtr(struct_obj.owner_decl);
31328 const decl = mod.declPtr(struct_obj.owner_decl);
3128031329 var decl_arena: std.heap.ArenaAllocator = undefined;
31281 const decl_arena_allocator = decl.value_arena.?.acquire(sema.mod.gpa, &decl_arena);
31330 const decl_arena_allocator = decl.value_arena.?.acquire(mod.gpa, &decl_arena);
3128231331 defer decl.value_arena.?.release(&decl_arena);
3128331332 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());
3128431333 };
......@@ -31528,7 +31577,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3152831577 return switch (ty.ip_index) {
3152931578 .empty_struct_type => false,
3153031579 .none => switch (ty.tag()) {
31531 .empty_struct,
3153231580 .error_set,
3153331581 .error_set_single,
3153431582 .error_set_inferred,
......@@ -31569,27 +31617,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3156931617 return false;
3157031618 },
3157131619
31572 .@"struct" => {
31573 const struct_obj = ty.castTag(.@"struct").?.data;
31574 switch (struct_obj.requires_comptime) {
31575 .no, .wip => return false,
31576 .yes => return true,
31577 .unknown => {
31578 var requires_comptime = false;
31579 struct_obj.requires_comptime = .wip;
31580 for (struct_obj.fields.values()) |field| {
31581 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31582 }
31583 if (requires_comptime) {
31584 struct_obj.requires_comptime = .yes;
31585 } else {
31586 struct_obj.requires_comptime = .no;
31587 }
31588 return requires_comptime;
31589 },
31590 }
31591 },
31592
3159331620 .@"union", .union_safety_tagged, .union_tagged => {
3159431621 const union_obj = ty.cast(Type.Payload.Union).?.data;
3159531622 switch (union_obj.requires_comptime) {
......@@ -31686,7 +31713,27 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3168631713 .type_info,
3168731714 => true,
3168831715 },
31689 .struct_type => @panic("TODO"),
31716 .struct_type => |struct_type| {
31717 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
31718 switch (struct_obj.requires_comptime) {
31719 .no, .wip => return false,
31720 .yes => return true,
31721 .unknown => {
31722 var requires_comptime = false;
31723 struct_obj.requires_comptime = .wip;
31724 for (struct_obj.fields.values()) |field| {
31725 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31726 }
31727 if (requires_comptime) {
31728 struct_obj.requires_comptime = .yes;
31729 } else {
31730 struct_obj.requires_comptime = .no;
31731 }
31732 return requires_comptime;
31733 },
31734 }
31735 },
31736
3169031737 .union_type => @panic("TODO"),
3169131738 .opaque_type => false,
3169231739
......@@ -31697,6 +31744,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3169731744 .ptr => unreachable,
3169831745 .opt => unreachable,
3169931746 .enum_tag => unreachable,
31747 .aggregate => unreachable,
3170031748 },
3170131749 };
3170231750}
......@@ -31710,16 +31758,21 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3171031758 const child_ty = try sema.resolveTypeFields(ty.childType(mod));
3171131759 return sema.resolveTypeFully(child_ty);
3171231760 },
31713 .Struct => switch (ty.tag()) {
31714 .@"struct" => return sema.resolveStructFully(ty),
31715 .tuple, .anon_struct => {
31716 const tuple = ty.tupleFields();
31761 .Struct => switch (ty.ip_index) {
31762 .none => switch (ty.tag()) {
31763 .tuple, .anon_struct => {
31764 const tuple = ty.tupleFields();
3171731765
31718 for (tuple.types) |field_ty| {
31719 try sema.resolveTypeFully(field_ty);
31720 }
31766 for (tuple.types) |field_ty| {
31767 try sema.resolveTypeFully(field_ty);
31768 }
31769 },
31770 else => {},
31771 },
31772 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31773 .struct_type => return sema.resolveStructFully(ty),
31774 else => {},
3172131775 },
31722 else => {},
3172331776 },
3172431777 .Union => return sema.resolveUnionFully(ty),
3172531778 .Array => return sema.resolveTypeFully(ty.childType(mod)),
......@@ -31746,9 +31799,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3174631799fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
3174731800 try sema.resolveStructLayout(ty);
3174831801
31802 const mod = sema.mod;
3174931803 const resolved_ty = try sema.resolveTypeFields(ty);
31750 const payload = resolved_ty.castTag(.@"struct").?;
31751 const struct_obj = payload.data;
31804 const struct_obj = mod.typeToStruct(resolved_ty).?;
3175231805
3175331806 switch (struct_obj.status) {
3175431807 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
......@@ -31806,11 +31859,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3180631859
3180731860 switch (ty.ip_index) {
3180831861 .none => switch (ty.tag()) {
31809 .@"struct" => {
31810 const struct_obj = ty.castTag(.@"struct").?.data;
31811 try sema.resolveTypeFieldsStruct(ty, struct_obj);
31812 return ty;
31813 },
3181431862 .@"union", .union_safety_tagged, .union_tagged => {
3181531863 const union_obj = ty.cast(Type.Payload.Union).?.data;
3181631864 try sema.resolveTypeFieldsUnion(ty, union_obj);
......@@ -31904,7 +31952,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3190431952 .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"),
3190531953
3190631954 _ => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31907 .struct_type => @panic("TODO"),
31955 .struct_type => |struct_type| {
31956 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return ty;
31957 try sema.resolveTypeFieldsStruct(ty, struct_obj);
31958 return ty;
31959 },
3190831960 .union_type => @panic("TODO"),
3190931961 else => return ty,
3191031962 },
......@@ -33010,28 +33062,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3301033062 }
3301133063 },
3301233064
33013 .@"struct" => {
33014 const resolved_ty = try sema.resolveTypeFields(ty);
33015 const s = resolved_ty.castTag(.@"struct").?.data;
33016 for (s.fields.values(), 0..) |field, i| {
33017 if (field.is_comptime) continue;
33018 if (field.ty.eql(resolved_ty, sema.mod)) {
33019 const msg = try Module.ErrorMsg.create(
33020 sema.gpa,
33021 s.srcLoc(sema.mod),
33022 "struct '{}' depends on itself",
33023 .{ty.fmt(sema.mod)},
33024 );
33025 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33026 return sema.failWithOwnedErrorMsg(msg);
33027 }
33028 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {
33029 return null;
33030 }
33031 }
33032 return Value.empty_struct;
33033 },
33034
3303533065 .tuple, .anon_struct => {
3303633066 const tuple = ty.tupleFields();
3303733067 for (tuple.values, 0..) |val, i| {
......@@ -33120,8 +33150,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3312033150 });
3312133151 },
3312233152
33123 .empty_struct => return Value.empty_struct,
33124
3312533153 .array => {
3312633154 if (ty.arrayLen(mod) == 0)
3312733155 return Value.initTag(.empty_array);
......@@ -33212,7 +33240,34 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3321233240 .generic_poison => return error.GenericPoison,
3321333241 .var_args_param => unreachable,
3321433242 },
33215 .struct_type => @panic("TODO"),
33243 .struct_type => |struct_type| {
33244 const resolved_ty = try sema.resolveTypeFields(ty);
33245 if (mod.structPtrUnwrap(struct_type.index)) |s| {
33246 for (s.fields.values(), 0..) |field, i| {
33247 if (field.is_comptime) continue;
33248 if (field.ty.eql(resolved_ty, sema.mod)) {
33249 const msg = try Module.ErrorMsg.create(
33250 sema.gpa,
33251 s.srcLoc(sema.mod),
33252 "struct '{}' depends on itself",
33253 .{ty.fmt(sema.mod)},
33254 );
33255 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33256 return sema.failWithOwnedErrorMsg(msg);
33257 }
33258 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {
33259 return null;
33260 }
33261 }
33262 }
33263 // In this case the struct has no fields and therefore has one possible value.
33264 const empty = try mod.intern(.{ .aggregate = .{
33265 .ty = ty.ip_index,
33266 .fields = &.{},
33267 } });
33268 return empty.toValue();
33269 },
33270
3321633271 .union_type => @panic("TODO"),
3321733272 .opaque_type => null,
3321833273
......@@ -33223,6 +33278,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3322333278 .ptr => unreachable,
3322433279 .opt => unreachable,
3322533280 .enum_tag => unreachable,
33281 .aggregate => unreachable,
3322633282 },
3322733283 }
3322833284}
......@@ -33614,7 +33670,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3361433670 .empty_struct_type => false,
3361533671
3361633672 .none => switch (ty.tag()) {
33617 .empty_struct,
3361833673 .error_set,
3361933674 .error_set_single,
3362033675 .error_set_inferred,
......@@ -33655,31 +33710,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3365533710 return false;
3365633711 },
3365733712
33658 .@"struct" => {
33659 const struct_obj = ty.castTag(.@"struct").?.data;
33660 switch (struct_obj.requires_comptime) {
33661 .no, .wip => return false,
33662 .yes => return true,
33663 .unknown => {
33664 if (struct_obj.status == .field_types_wip)
33665 return false;
33666
33667 try sema.resolveTypeFieldsStruct(ty, struct_obj);
33668
33669 struct_obj.requires_comptime = .wip;
33670 for (struct_obj.fields.values()) |field| {
33671 if (field.is_comptime) continue;
33672 if (try sema.typeRequiresComptime(field.ty)) {
33673 struct_obj.requires_comptime = .yes;
33674 return true;
33675 }
33676 }
33677 struct_obj.requires_comptime = .no;
33678 return false;
33679 },
33680 }
33681 },
33682
3368333713 .@"union", .union_safety_tagged, .union_tagged => {
3368433714 const union_obj = ty.cast(Type.Payload.Union).?.data;
3368533715 switch (union_obj.requires_comptime) {
......@@ -33782,7 +33812,31 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3378233812
3378333813 .var_args_param => unreachable,
3378433814 },
33785 .struct_type => @panic("TODO"),
33815 .struct_type => |struct_type| {
33816 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
33817 switch (struct_obj.requires_comptime) {
33818 .no, .wip => return false,
33819 .yes => return true,
33820 .unknown => {
33821 if (struct_obj.status == .field_types_wip)
33822 return false;
33823
33824 try sema.resolveTypeFieldsStruct(ty, struct_obj);
33825
33826 struct_obj.requires_comptime = .wip;
33827 for (struct_obj.fields.values()) |field| {
33828 if (field.is_comptime) continue;
33829 if (try sema.typeRequiresComptime(field.ty)) {
33830 struct_obj.requires_comptime = .yes;
33831 return true;
33832 }
33833 }
33834 struct_obj.requires_comptime = .no;
33835 return false;
33836 },
33837 }
33838 },
33839
3378633840 .union_type => @panic("TODO"),
3378733841 .opaque_type => false,
3378833842
......@@ -33793,6 +33847,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3379333847 .ptr => unreachable,
3379433848 .opt => unreachable,
3379533849 .enum_tag => unreachable,
33850 .aggregate => unreachable,
3379633851 },
3379733852 };
3379833853}
......@@ -33864,11 +33919,12 @@ fn structFieldIndex(
3386433919 field_name: []const u8,
3386533920 field_src: LazySrcLoc,
3386633921) !u32 {
33922 const mod = sema.mod;
3386733923 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
3386833924 if (struct_ty.isAnonStruct()) {
3386933925 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
3387033926 } else {
33871 const struct_obj = struct_ty.castTag(.@"struct").?.data;
33927 const struct_obj = mod.typeToStruct(struct_ty).?;
3387233928 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
3387333929 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
3387433930 return @intCast(u32, field_index_usize);
src/TypedValue.zig+13-7
......@@ -180,7 +180,7 @@ pub fn print(
180180 switch (field_ptr.container_ty.tag()) {
181181 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),
182182 else => {
183 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index);
183 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod);
184184 return writer.print(".{s}", .{field_name});
185185 },
186186 }
......@@ -381,21 +381,27 @@ fn printAggregate(
381381 }
382382 if (ty.zigTypeTag(mod) == .Struct) {
383383 try writer.writeAll(".{");
384 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
384 const max_len = std.math.min(ty.structFieldCount(mod), max_aggregate_items);
385385
386386 var i: u32 = 0;
387387 while (i < max_len) : (i += 1) {
388388 if (i != 0) try writer.writeAll(", ");
389 switch (ty.tag()) {
390 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
391 else => {},
389 switch (ty.ip_index) {
390 .none => switch (ty.tag()) {
391 .anon_struct => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
392 else => {},
393 },
394 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
395 .struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
396 else => {},
397 },
392398 }
393399 try print(.{
394 .ty = ty.structFieldType(i),
400 .ty = ty.structFieldType(i, mod),
395401 .val = try val.fieldValue(ty, mod, i),
396402 }, writer, level - 1, mod);
397403 }
398 if (ty.structFieldCount() > max_aggregate_items) {
404 if (ty.structFieldCount(mod) > max_aggregate_items) {
399405 try writer.writeAll(", ...");
400406 }
401407 return writer.writeAll("}");
src/arch/aarch64/CodeGen.zig+3-3
......@@ -4119,7 +4119,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
41194119 const mod = self.bin_file.options.module.?;
41204120 const mcv = try self.resolveInst(operand);
41214121 const struct_ty = self.typeOf(operand);
4122 const struct_field_ty = struct_ty.structFieldType(index);
4122 const struct_field_ty = struct_ty.structFieldType(index, mod);
41234123 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
41244124
41254125 switch (mcv) {
......@@ -5466,10 +5466,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54665466 const reg_lock = self.register_manager.lockReg(rwo.reg);
54675467 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
54685468
5469 const wrapped_ty = ty.structFieldType(0);
5469 const wrapped_ty = ty.structFieldType(0, mod);
54705470 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });
54715471
5472 const overflow_bit_ty = ty.structFieldType(1);
5472 const overflow_bit_ty = ty.structFieldType(1, mod);
54735473 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
54745474 const raw_cond_reg = try self.register_manager.allocReg(null, gp);
54755475 const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty);
src/arch/aarch64/abi.zig+6-6
......@@ -21,7 +21,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
2121 var maybe_float_bits: ?u16 = null;
2222 switch (ty.zigTypeTag(mod)) {
2323 .Struct => {
24 if (ty.containerLayout() == .Packed) return .byval;
24 if (ty.containerLayout(mod) == .Packed) return .byval;
2525 const float_count = countFloats(ty, mod, &maybe_float_bits);
2626 if (float_count <= sret_float_count) return .{ .float_array = float_count };
2727
......@@ -31,7 +31,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
3131 return .integer;
3232 },
3333 .Union => {
34 if (ty.containerLayout() == .Packed) return .byval;
34 if (ty.containerLayout(mod) == .Packed) return .byval;
3535 const float_count = countFloats(ty, mod, &maybe_float_bits);
3636 if (float_count <= sret_float_count) return .{ .float_array = float_count };
3737
......@@ -90,11 +90,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 {
9090 return max_count;
9191 },
9292 .Struct => {
93 const fields_len = ty.structFieldCount();
93 const fields_len = ty.structFieldCount(mod);
9494 var count: u8 = 0;
9595 var i: u32 = 0;
9696 while (i < fields_len) : (i += 1) {
97 const field_ty = ty.structFieldType(i);
97 const field_ty = ty.structFieldType(i, mod);
9898 const field_count = countFloats(field_ty, mod, maybe_float_bits);
9999 if (field_count == invalid) return invalid;
100100 count += field_count;
......@@ -125,10 +125,10 @@ pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type {
125125 return null;
126126 },
127127 .Struct => {
128 const fields_len = ty.structFieldCount();
128 const fields_len = ty.structFieldCount(mod);
129129 var i: u32 = 0;
130130 while (i < fields_len) : (i += 1) {
131 const field_ty = ty.structFieldType(i);
131 const field_ty = ty.structFieldType(i, mod);
132132 if (getFloatArrayType(field_ty, mod)) |some| return some;
133133 }
134134 return null;
src/arch/arm/CodeGen.zig+3-3
......@@ -2910,7 +2910,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
29102910 const mcv = try self.resolveInst(operand);
29112911 const struct_ty = self.typeOf(operand);
29122912 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
2913 const struct_field_ty = struct_ty.structFieldType(index);
2913 const struct_field_ty = struct_ty.structFieldType(index, mod);
29142914
29152915 switch (mcv) {
29162916 .dead, .unreach => unreachable,
......@@ -5404,10 +5404,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54045404 const reg_lock = self.register_manager.lockReg(reg);
54055405 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
54065406
5407 const wrapped_ty = ty.structFieldType(0);
5407 const wrapped_ty = ty.structFieldType(0, mod);
54085408 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });
54095409
5410 const overflow_bit_ty = ty.structFieldType(1);
5410 const overflow_bit_ty = ty.structFieldType(1, mod);
54115411 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
54125412 const cond_reg = try self.register_manager.allocReg(null, gp);
54135413
src/arch/arm/abi.zig+6-6
......@@ -32,7 +32,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
3232 switch (ty.zigTypeTag(mod)) {
3333 .Struct => {
3434 const bit_size = ty.bitSize(mod);
35 if (ty.containerLayout() == .Packed) {
35 if (ty.containerLayout(mod) == .Packed) {
3636 if (bit_size > 64) return .memory;
3737 return .byval;
3838 }
......@@ -40,10 +40,10 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
4040 const float_count = countFloats(ty, mod, &maybe_float_bits);
4141 if (float_count <= byval_float_count) return .byval;
4242
43 const fields = ty.structFieldCount();
43 const fields = ty.structFieldCount(mod);
4444 var i: u32 = 0;
4545 while (i < fields) : (i += 1) {
46 const field_ty = ty.structFieldType(i);
46 const field_ty = ty.structFieldType(i, mod);
4747 const field_alignment = ty.structFieldAlign(i, mod);
4848 const field_size = field_ty.bitSize(mod);
4949 if (field_size > 32 or field_alignment > 32) {
......@@ -54,7 +54,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
5454 },
5555 .Union => {
5656 const bit_size = ty.bitSize(mod);
57 if (ty.containerLayout() == .Packed) {
57 if (ty.containerLayout(mod) == .Packed) {
5858 if (bit_size > 64) return .memory;
5959 return .byval;
6060 }
......@@ -132,11 +132,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 {
132132 return max_count;
133133 },
134134 .Struct => {
135 const fields_len = ty.structFieldCount();
135 const fields_len = ty.structFieldCount(mod);
136136 var count: u32 = 0;
137137 var i: u32 = 0;
138138 while (i < fields_len) : (i += 1) {
139 const field_ty = ty.structFieldType(i);
139 const field_ty = ty.structFieldType(i, mod);
140140 const field_count = countFloats(field_ty, mod, maybe_float_bits);
141141 if (field_count == invalid) return invalid;
142142 count += field_count;
src/arch/riscv64/abi.zig+2-2
......@@ -15,7 +15,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
1515 switch (ty.zigTypeTag(mod)) {
1616 .Struct => {
1717 const bit_size = ty.bitSize(mod);
18 if (ty.containerLayout() == .Packed) {
18 if (ty.containerLayout(mod) == .Packed) {
1919 if (bit_size > max_byval_size) return .memory;
2020 return .byval;
2121 }
......@@ -26,7 +26,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
2626 },
2727 .Union => {
2828 const bit_size = ty.bitSize(mod);
29 if (ty.containerLayout() == .Packed) {
29 if (ty.containerLayout(mod) == .Packed) {
3030 if (bit_size > max_byval_size) return .memory;
3131 return .byval;
3232 }
src/arch/sparc64/CodeGen.zig+2-2
......@@ -3993,10 +3993,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
39933993 const reg_lock = self.register_manager.lockReg(rwo.reg);
39943994 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
39953995
3996 const wrapped_ty = ty.structFieldType(0);
3996 const wrapped_ty = ty.structFieldType(0, mod);
39973997 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });
39983998
3999 const overflow_bit_ty = ty.structFieldType(1);
3999 const overflow_bit_ty = ty.structFieldType(1, mod);
40004000 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
40014001 const cond_reg = try self.register_manager.allocReg(null, gp);
40024002
src/arch/wasm/CodeGen.zig+15-16
......@@ -1006,9 +1006,9 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
10061006 if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64;
10071007 break :blk wasm.Valtype.i32; // represented as pointer to stack
10081008 },
1009 .Struct => switch (ty.containerLayout()) {
1009 .Struct => switch (ty.containerLayout(mod)) {
10101010 .Packed => {
1011 const struct_obj = ty.castTag(.@"struct").?.data;
1011 const struct_obj = mod.typeToStruct(ty).?;
10121012 return typeToValtype(struct_obj.backing_int_ty, mod);
10131013 },
10141014 else => wasm.Valtype.i32,
......@@ -1017,7 +1017,7 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
10171017 .direct => wasm.Valtype.v128,
10181018 .unrolled => wasm.Valtype.i32,
10191019 },
1020 .Union => switch (ty.containerLayout()) {
1020 .Union => switch (ty.containerLayout(mod)) {
10211021 .Packed => {
10221022 const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory");
10231023 return typeToValtype(int_ty, mod);
......@@ -1747,8 +1747,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
17471747 return ty.hasRuntimeBitsIgnoreComptime(mod);
17481748 },
17491749 .Struct => {
1750 if (ty.castTag(.@"struct")) |struct_ty| {
1751 const struct_obj = struct_ty.data;
1750 if (mod.typeToStruct(ty)) |struct_obj| {
17521751 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
17531752 return isByRef(struct_obj.backing_int_ty, mod);
17541753 }
......@@ -2954,11 +2953,11 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
29542953 const parent_ty = field_ptr.container_ty;
29552954
29562955 const field_offset = switch (parent_ty.zigTypeTag(mod)) {
2957 .Struct => switch (parent_ty.containerLayout()) {
2956 .Struct => switch (parent_ty.containerLayout(mod)) {
29582957 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod),
29592958 else => parent_ty.structFieldOffset(field_ptr.field_index, mod),
29602959 },
2961 .Union => switch (parent_ty.containerLayout()) {
2960 .Union => switch (parent_ty.containerLayout(mod)) {
29622961 .Packed => 0,
29632962 else => blk: {
29642963 const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod);
......@@ -3158,7 +3157,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
31583157 return WValue{ .imm32 = @boolToInt(is_pl) };
31593158 },
31603159 .Struct => {
3161 const struct_obj = ty.castTag(.@"struct").?.data;
3160 const struct_obj = mod.typeToStruct(ty).?;
31623161 assert(struct_obj.layout == .Packed);
31633162 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
31643163 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
......@@ -3225,7 +3224,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
32253224 return WValue{ .imm32 = 0xaaaaaaaa };
32263225 },
32273226 .Struct => {
3228 const struct_obj = ty.castTag(.@"struct").?.data;
3227 const struct_obj = mod.typeToStruct(ty).?;
32293228 assert(struct_obj.layout == .Packed);
32303229 return func.emitUndefined(struct_obj.backing_int_ty);
32313230 },
......@@ -3635,7 +3634,7 @@ fn structFieldPtr(
36353634) InnerError!WValue {
36363635 const mod = func.bin_file.base.options.module.?;
36373636 const result_ty = func.typeOfIndex(inst);
3638 const offset = switch (struct_ty.containerLayout()) {
3637 const offset = switch (struct_ty.containerLayout(mod)) {
36393638 .Packed => switch (struct_ty.zigTypeTag(mod)) {
36403639 .Struct => offset: {
36413640 if (result_ty.ptrInfo(mod).host_size != 0) {
......@@ -3668,13 +3667,13 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
36683667 const struct_ty = func.typeOf(struct_field.struct_operand);
36693668 const operand = try func.resolveInst(struct_field.struct_operand);
36703669 const field_index = struct_field.field_index;
3671 const field_ty = struct_ty.structFieldType(field_index);
3670 const field_ty = struct_ty.structFieldType(field_index, mod);
36723671 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand});
36733672
3674 const result = switch (struct_ty.containerLayout()) {
3673 const result = switch (struct_ty.containerLayout(mod)) {
36753674 .Packed => switch (struct_ty.zigTypeTag(mod)) {
36763675 .Struct => result: {
3677 const struct_obj = struct_ty.castTag(.@"struct").?.data;
3676 const struct_obj = mod.typeToStruct(struct_ty).?;
36783677 const offset = struct_obj.packedFieldBitOffset(mod, field_index);
36793678 const backing_ty = struct_obj.backing_int_ty;
36803679 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {
......@@ -4998,12 +4997,12 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
49984997 }
49994998 break :result_value result;
50004999 },
5001 .Struct => switch (result_ty.containerLayout()) {
5000 .Struct => switch (result_ty.containerLayout(mod)) {
50025001 .Packed => {
50035002 if (isByRef(result_ty, mod)) {
50045003 return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{});
50055004 }
5006 const struct_obj = result_ty.castTag(.@"struct").?.data;
5005 const struct_obj = mod.typeToStruct(result_ty).?;
50075006 const fields = struct_obj.fields.values();
50085007 const backing_type = struct_obj.backing_int_ty;
50095008
......@@ -5051,7 +5050,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
50515050 for (elements, 0..) |elem, elem_index| {
50525051 if ((try result_ty.structFieldValueComptime(mod, elem_index)) != null) continue;
50535052
5054 const elem_ty = result_ty.structFieldType(elem_index);
5053 const elem_ty = result_ty.structFieldType(elem_index, mod);
50555054 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
50565055 const value = try func.resolveInst(elem);
50575056 try func.store(offset, value, elem_ty, 0);
src/arch/wasm/abi.zig+9-9
......@@ -26,14 +26,14 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
2626 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none;
2727 switch (ty.zigTypeTag(mod)) {
2828 .Struct => {
29 if (ty.containerLayout() == .Packed) {
29 if (ty.containerLayout(mod) == .Packed) {
3030 if (ty.bitSize(mod) <= 64) return direct;
3131 return .{ .direct, .direct };
3232 }
3333 // When the struct type is non-scalar
34 if (ty.structFieldCount() > 1) return memory;
34 if (ty.structFieldCount(mod) > 1) return memory;
3535 // When the struct's alignment is non-natural
36 const field = ty.structFields().values()[0];
36 const field = ty.structFields(mod).values()[0];
3737 if (field.abi_align != 0) {
3838 if (field.abi_align > field.ty.abiAlignment(mod)) {
3939 return memory;
......@@ -64,7 +64,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
6464 return direct;
6565 },
6666 .Union => {
67 if (ty.containerLayout() == .Packed) {
67 if (ty.containerLayout(mod) == .Packed) {
6868 if (ty.bitSize(mod) <= 64) return direct;
6969 return .{ .direct, .direct };
7070 }
......@@ -96,19 +96,19 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
9696pub fn scalarType(ty: Type, mod: *Module) Type {
9797 switch (ty.zigTypeTag(mod)) {
9898 .Struct => {
99 switch (ty.containerLayout()) {
99 switch (ty.containerLayout(mod)) {
100100 .Packed => {
101 const struct_obj = ty.castTag(.@"struct").?.data;
101 const struct_obj = mod.typeToStruct(ty).?;
102102 return scalarType(struct_obj.backing_int_ty, mod);
103103 },
104104 else => {
105 std.debug.assert(ty.structFieldCount() == 1);
106 return scalarType(ty.structFieldType(0), mod);
105 std.debug.assert(ty.structFieldCount(mod) == 1);
106 return scalarType(ty.structFieldType(0, mod), mod);
107107 },
108108 }
109109 },
110110 .Union => {
111 if (ty.containerLayout() != .Packed) {
111 if (ty.containerLayout(mod) != .Packed) {
112112 const layout = ty.unionGetLayout(mod);
113113 if (layout.payload_size == 0 and layout.tag_size != 0) {
114114 return scalarType(ty.unionTagTypeSafety().?, mod);
src/arch/x86_64/CodeGen.zig+17-17
......@@ -3252,13 +3252,13 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
32523252 try self.genSetMem(
32533253 .{ .frame = frame_index },
32543254 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3255 tuple_ty.structFieldType(1),
3255 tuple_ty.structFieldType(1, mod),
32563256 .{ .eflags = cc },
32573257 );
32583258 try self.genSetMem(
32593259 .{ .frame = frame_index },
32603260 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3261 tuple_ty.structFieldType(0),
3261 tuple_ty.structFieldType(0, mod),
32623262 partial_mcv,
32633263 );
32643264 break :result .{ .load_frame = .{ .index = frame_index } };
......@@ -3289,7 +3289,7 @@ fn genSetFrameTruncatedOverflowCompare(
32893289 };
32903290 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
32913291
3292 const ty = tuple_ty.structFieldType(0);
3292 const ty = tuple_ty.structFieldType(0, mod);
32933293 const int_info = ty.intInfo(mod);
32943294
32953295 const hi_limb_bits = (int_info.bits - 1) % 64 + 1;
......@@ -3336,7 +3336,7 @@ fn genSetFrameTruncatedOverflowCompare(
33363336 try self.genSetMem(
33373337 .{ .frame = frame_index },
33383338 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3339 tuple_ty.structFieldType(1),
3339 tuple_ty.structFieldType(1, mod),
33403340 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },
33413341 );
33423342}
......@@ -3393,13 +3393,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
33933393 try self.genSetMem(
33943394 .{ .frame = frame_index },
33953395 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3396 tuple_ty.structFieldType(0),
3396 tuple_ty.structFieldType(0, mod),
33973397 partial_mcv,
33983398 );
33993399 try self.genSetMem(
34003400 .{ .frame = frame_index },
34013401 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3402 tuple_ty.structFieldType(1),
3402 tuple_ty.structFieldType(1, mod),
34033403 .{ .immediate = 0 }, // cc being set is impossible
34043404 );
34053405 } else try self.genSetFrameTruncatedOverflowCompare(
......@@ -5563,7 +5563,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
55635563 const ptr_field_ty = self.typeOfIndex(inst);
55645564 const ptr_container_ty = self.typeOf(operand);
55655565 const container_ty = ptr_container_ty.childType(mod);
5566 const field_offset = @intCast(i32, switch (container_ty.containerLayout()) {
5566 const field_offset = @intCast(i32, switch (container_ty.containerLayout(mod)) {
55675567 .Auto, .Extern => container_ty.structFieldOffset(index, mod),
55685568 .Packed => if (container_ty.zigTypeTag(mod) == .Struct and
55695569 ptr_field_ty.ptrInfo(mod).host_size == 0)
......@@ -5591,16 +5591,16 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
55915591
55925592 const container_ty = self.typeOf(operand);
55935593 const container_rc = regClassForType(container_ty, mod);
5594 const field_ty = container_ty.structFieldType(index);
5594 const field_ty = container_ty.structFieldType(index, mod);
55955595 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
55965596 const field_rc = regClassForType(field_ty, mod);
55975597 const field_is_gp = field_rc.supersetOf(gp);
55985598
55995599 const src_mcv = try self.resolveInst(operand);
5600 const field_off = switch (container_ty.containerLayout()) {
5600 const field_off = switch (container_ty.containerLayout(mod)) {
56015601 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8),
5602 .Packed => if (container_ty.castTag(.@"struct")) |struct_obj|
5603 struct_obj.data.packedFieldBitOffset(mod, index)
5602 .Packed => if (mod.typeToStruct(container_ty)) |struct_obj|
5603 struct_obj.packedFieldBitOffset(mod, index)
56045604 else
56055605 0,
56065606 };
......@@ -10036,13 +10036,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1003610036 try self.genSetMem(
1003710037 base,
1003810038 disp + @intCast(i32, ty.structFieldOffset(0, mod)),
10039 ty.structFieldType(0),
10039 ty.structFieldType(0, mod),
1004010040 .{ .register = ro.reg },
1004110041 );
1004210042 try self.genSetMem(
1004310043 base,
1004410044 disp + @intCast(i32, ty.structFieldOffset(1, mod)),
10045 ty.structFieldType(1),
10045 ty.structFieldType(1, mod),
1004610046 .{ .eflags = ro.eflags },
1004710047 );
1004810048 },
......@@ -11259,8 +11259,8 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1125911259 .Struct => {
1126011260 const frame_index =
1126111261 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
11262 if (result_ty.containerLayout() == .Packed) {
11263 const struct_obj = result_ty.castTag(.@"struct").?.data;
11262 if (result_ty.containerLayout(mod) == .Packed) {
11263 const struct_obj = mod.typeToStruct(result_ty).?;
1126411264 try self.genInlineMemset(
1126511265 .{ .lea_frame = .{ .index = frame_index } },
1126611266 .{ .immediate = 0 },
......@@ -11269,7 +11269,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1126911269 for (elements, 0..) |elem, elem_i| {
1127011270 if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;
1127111271
11272 const elem_ty = result_ty.structFieldType(elem_i);
11272 const elem_ty = result_ty.structFieldType(elem_i, mod);
1127311273 const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));
1127411274 if (elem_bit_size > 64) {
1127511275 return self.fail(
......@@ -11341,7 +11341,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1134111341 } else for (elements, 0..) |elem, elem_i| {
1134211342 if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;
1134311343
11344 const elem_ty = result_ty.structFieldType(elem_i);
11344 const elem_ty = result_ty.structFieldType(elem_i, mod);
1134511345 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));
1134611346 const elem_mcv = try self.resolveInst(elem);
1134711347 const mat_elem_mcv = switch (elem_mcv) {
src/arch/x86_64/abi.zig+4-4
......@@ -41,7 +41,7 @@ pub fn classifyWindows(ty: Type, mod: *Module) Class {
4141 1, 2, 4, 8 => return .integer,
4242 else => switch (ty.zigTypeTag(mod)) {
4343 .Int => return .win_i128,
44 .Struct, .Union => if (ty.containerLayout() == .Packed) {
44 .Struct, .Union => if (ty.containerLayout(mod) == .Packed) {
4545 return .win_i128;
4646 } else {
4747 return .memory;
......@@ -210,7 +210,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
210210 // "If the size of the aggregate exceeds a single eightbyte, each is classified
211211 // separately.".
212212 const ty_size = ty.abiSize(mod);
213 if (ty.containerLayout() == .Packed) {
213 if (ty.containerLayout(mod) == .Packed) {
214214 assert(ty_size <= 128);
215215 result[0] = .integer;
216216 if (ty_size > 64) result[1] = .integer;
......@@ -221,7 +221,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
221221
222222 var result_i: usize = 0; // out of 8
223223 var byte_i: usize = 0; // out of 8
224 const fields = ty.structFields();
224 const fields = ty.structFields(mod);
225225 for (fields.values()) |field| {
226226 if (field.abi_align != 0) {
227227 if (field.abi_align < field.ty.abiAlignment(mod)) {
......@@ -329,7 +329,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
329329 // "If the size of the aggregate exceeds a single eightbyte, each is classified
330330 // separately.".
331331 const ty_size = ty.abiSize(mod);
332 if (ty.containerLayout() == .Packed) {
332 if (ty.containerLayout(mod) == .Packed) {
333333 assert(ty_size <= 128);
334334 result[0] = .integer;
335335 if (ty_size > 64) result[1] = .integer;
src/codegen.zig+3-3
......@@ -503,8 +503,8 @@ pub fn generateSymbol(
503503 return Result.ok;
504504 },
505505 .Struct => {
506 if (typed_value.ty.containerLayout() == .Packed) {
507 const struct_obj = typed_value.ty.castTag(.@"struct").?.data;
506 if (typed_value.ty.containerLayout(mod) == .Packed) {
507 const struct_obj = mod.typeToStruct(typed_value.ty).?;
508508 const fields = struct_obj.fields.values();
509509 const field_vals = typed_value.val.castTag(.aggregate).?.data;
510510 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
......@@ -539,7 +539,7 @@ pub fn generateSymbol(
539539 const struct_begin = code.items.len;
540540 const field_vals = typed_value.val.castTag(.aggregate).?.data;
541541 for (field_vals, 0..) |field_val, index| {
542 const field_ty = typed_value.ty.structFieldType(index);
542 const field_ty = typed_value.ty.structFieldType(index, mod);
543543 if (!field_ty.hasRuntimeBits(mod)) continue;
544544
545545 switch (try generateSymbol(bin_file, src_loc, .{
src/codegen/c.zig+119-109
......@@ -820,7 +820,7 @@ pub const DeclGen = struct {
820820 try dg.renderValue(writer, Type.bool, val, initializer_type);
821821 return writer.writeAll(" }");
822822 },
823 .Struct => switch (ty.containerLayout()) {
823 .Struct => switch (ty.containerLayout(mod)) {
824824 .Auto, .Extern => {
825825 if (!location.isInitializer()) {
826826 try writer.writeByte('(');
......@@ -830,9 +830,9 @@ pub const DeclGen = struct {
830830
831831 try writer.writeByte('{');
832832 var empty = true;
833 for (0..ty.structFieldCount()) |field_i| {
834 if (ty.structFieldIsComptime(field_i)) continue;
835 const field_ty = ty.structFieldType(field_i);
833 for (0..ty.structFieldCount(mod)) |field_i| {
834 if (ty.structFieldIsComptime(field_i, mod)) continue;
835 const field_ty = ty.structFieldType(field_i, mod);
836836 if (!field_ty.hasRuntimeBits(mod)) continue;
837837
838838 if (!empty) try writer.writeByte(',');
......@@ -1328,7 +1328,7 @@ pub const DeclGen = struct {
13281328 },
13291329 else => unreachable,
13301330 },
1331 .Struct => switch (ty.containerLayout()) {
1331 .Struct => switch (ty.containerLayout(mod)) {
13321332 .Auto, .Extern => {
13331333 const field_vals = val.castTag(.aggregate).?.data;
13341334
......@@ -1341,8 +1341,8 @@ pub const DeclGen = struct {
13411341 try writer.writeByte('{');
13421342 var empty = true;
13431343 for (field_vals, 0..) |field_val, field_i| {
1344 if (ty.structFieldIsComptime(field_i)) continue;
1345 const field_ty = ty.structFieldType(field_i);
1344 if (ty.structFieldIsComptime(field_i, mod)) continue;
1345 const field_ty = ty.structFieldType(field_i, mod);
13461346 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13471347
13481348 if (!empty) try writer.writeByte(',');
......@@ -1363,8 +1363,8 @@ pub const DeclGen = struct {
13631363
13641364 var eff_num_fields: usize = 0;
13651365 for (0..field_vals.len) |field_i| {
1366 if (ty.structFieldIsComptime(field_i)) continue;
1367 const field_ty = ty.structFieldType(field_i);
1366 if (ty.structFieldIsComptime(field_i, mod)) continue;
1367 const field_ty = ty.structFieldType(field_i, mod);
13681368 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13691369
13701370 eff_num_fields += 1;
......@@ -1386,8 +1386,8 @@ pub const DeclGen = struct {
13861386 var eff_index: usize = 0;
13871387 var needs_closing_paren = false;
13881388 for (field_vals, 0..) |field_val, field_i| {
1389 if (ty.structFieldIsComptime(field_i)) continue;
1390 const field_ty = ty.structFieldType(field_i);
1389 if (ty.structFieldIsComptime(field_i, mod)) continue;
1390 const field_ty = ty.structFieldType(field_i, mod);
13911391 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13921392
13931393 const cast_context = IntCastContext{ .value = .{ .value = field_val } };
......@@ -1416,8 +1416,8 @@ pub const DeclGen = struct {
14161416 // a << a_off | b << b_off | c << c_off
14171417 var empty = true;
14181418 for (field_vals, 0..) |field_val, field_i| {
1419 if (ty.structFieldIsComptime(field_i)) continue;
1420 const field_ty = ty.structFieldType(field_i);
1419 if (ty.structFieldIsComptime(field_i, mod)) continue;
1420 const field_ty = ty.structFieldType(field_i, mod);
14211421 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14221422
14231423 if (!empty) try writer.writeAll(" | ");
......@@ -1453,7 +1453,7 @@ pub const DeclGen = struct {
14531453 const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?;
14541454 const field_ty = ty.unionFields().values()[field_i].ty;
14551455 const field_name = ty.unionFields().keys()[field_i];
1456 if (ty.containerLayout() == .Packed) {
1456 if (ty.containerLayout(mod) == .Packed) {
14571457 if (field_ty.hasRuntimeBits(mod)) {
14581458 if (field_ty.isPtrAtRuntime(mod)) {
14591459 try writer.writeByte('(');
......@@ -5218,25 +5218,25 @@ fn fieldLocation(
52185218 end: void,
52195219} {
52205220 return switch (container_ty.zigTypeTag(mod)) {
5221 .Struct => switch (container_ty.containerLayout()) {
5222 .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| {
5223 if (container_ty.structFieldIsComptime(next_field_index)) continue;
5224 const field_ty = container_ty.structFieldType(next_field_index);
5221 .Struct => switch (container_ty.containerLayout(mod)) {
5222 .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| {
5223 if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
5224 const field_ty = container_ty.structFieldType(next_field_index, mod);
52255225 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
52265226
52275227 break .{ .field = if (container_ty.isSimpleTuple())
52285228 .{ .field = next_field_index }
52295229 else
5230 .{ .identifier = container_ty.structFieldName(next_field_index) } };
5230 .{ .identifier = container_ty.structFieldName(next_field_index, mod) } };
52315231 } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,
52325232 .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0)
52335233 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) }
52345234 else
52355235 .begin,
52365236 },
5237 .Union => switch (container_ty.containerLayout()) {
5237 .Union => switch (container_ty.containerLayout(mod)) {
52385238 .Auto, .Extern => {
5239 const field_ty = container_ty.structFieldType(field_index);
5239 const field_ty = container_ty.structFieldType(field_index, mod);
52405240 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))
52415241 return if (container_ty.unionTagTypeSafety() != null and
52425242 !container_ty.unionHasAllZeroBitFieldTypes(mod))
......@@ -5417,101 +5417,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
54175417 // Ensure complete type definition is visible before accessing fields.
54185418 _ = try f.typeToIndex(struct_ty, .complete);
54195419
5420 const field_name: CValue = switch (struct_ty.tag()) {
5421 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {
5422 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5420 const field_name: CValue = switch (struct_ty.ip_index) {
5421 .none => switch (struct_ty.tag()) {
5422 .tuple, .anon_struct => if (struct_ty.isSimpleTuple())
54235423 .{ .field = extra.field_index }
54245424 else
5425 .{ .identifier = struct_ty.structFieldName(extra.field_index) },
5426 .Packed => {
5427 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5428 const int_info = struct_ty.intInfo(mod);
5429
5430 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
5431
5432 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);
5433 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
5425 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
54345426
5435 const field_int_signedness = if (inst_ty.isAbiInt(mod))
5436 inst_ty.intInfo(mod).signedness
5437 else
5438 .unsigned;
5439 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
5440
5441 const temp_local = try f.allocLocal(inst, field_int_ty);
5442 try f.writeCValue(writer, temp_local, .Other);
5443 try writer.writeAll(" = zig_wrap_");
5444 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
5445 try writer.writeAll("((");
5446 try f.renderType(writer, field_int_ty);
5447 try writer.writeByte(')');
5448 const cant_cast = int_info.bits > 64;
5449 if (cant_cast) {
5450 if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
5451 try writer.writeAll("zig_lo_");
5452 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5453 try writer.writeByte('(');
5454 }
5455 if (bit_offset > 0) {
5456 try writer.writeAll("zig_shr_");
5457 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5458 try writer.writeByte('(');
5459 }
5460 try f.writeCValue(writer, struct_byval, .Other);
5461 if (bit_offset > 0) {
5462 try writer.writeAll(", ");
5463 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
5464 try writer.writeByte(')');
5465 }
5466 if (cant_cast) try writer.writeByte(')');
5467 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
5468 try writer.writeAll(");\n");
5469 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
5427 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout(mod) == .Packed) {
5428 const operand_lval = if (struct_byval == .constant) blk: {
5429 const operand_local = try f.allocLocal(inst, struct_ty);
5430 try f.writeCValue(writer, operand_local, .Other);
5431 try writer.writeAll(" = ");
5432 try f.writeCValue(writer, struct_byval, .Initializer);
5433 try writer.writeAll(";\n");
5434 break :blk operand_local;
5435 } else struct_byval;
54705436
54715437 const local = try f.allocLocal(inst, inst_ty);
5472 try writer.writeAll("memcpy(");
5473 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
5474 try writer.writeAll(", ");
5475 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
5438 try writer.writeAll("memcpy(&");
5439 try f.writeCValue(writer, local, .Other);
5440 try writer.writeAll(", &");
5441 try f.writeCValue(writer, operand_lval, .Other);
54765442 try writer.writeAll(", sizeof(");
54775443 try f.renderType(writer, inst_ty);
54785444 try writer.writeAll("));\n");
5479 try freeLocal(f, inst, temp_local.new_local, 0);
5445
5446 if (struct_byval == .constant) {
5447 try freeLocal(f, inst, operand_lval.new_local, 0);
5448 }
5449
54805450 return local;
5451 } else field_name: {
5452 const name = struct_ty.unionFields().keys()[extra.field_index];
5453 break :field_name if (struct_ty.unionTagTypeSafety()) |_|
5454 .{ .payload_identifier = name }
5455 else
5456 .{ .identifier = name };
54815457 },
5458 else => unreachable,
54825459 },
5483 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
5484 const operand_lval = if (struct_byval == .constant) blk: {
5485 const operand_local = try f.allocLocal(inst, struct_ty);
5486 try f.writeCValue(writer, operand_local, .Other);
5487 try writer.writeAll(" = ");
5488 try f.writeCValue(writer, struct_byval, .Initializer);
5489 try writer.writeAll(";\n");
5490 break :blk operand_local;
5491 } else struct_byval;
5460 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
5461 .struct_type => switch (struct_ty.containerLayout(mod)) {
5462 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5463 .{ .field = extra.field_index }
5464 else
5465 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5466 .Packed => {
5467 const struct_obj = mod.typeToStruct(struct_ty).?;
5468 const int_info = struct_ty.intInfo(mod);
54925469
5493 const local = try f.allocLocal(inst, inst_ty);
5494 try writer.writeAll("memcpy(&");
5495 try f.writeCValue(writer, local, .Other);
5496 try writer.writeAll(", &");
5497 try f.writeCValue(writer, operand_lval, .Other);
5498 try writer.writeAll(", sizeof(");
5499 try f.renderType(writer, inst_ty);
5500 try writer.writeAll("));\n");
5470 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
55015471
5502 if (struct_byval == .constant) {
5503 try freeLocal(f, inst, operand_lval.new_local, 0);
5504 }
5472 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);
5473 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
55055474
5506 return local;
5507 } else field_name: {
5508 const name = struct_ty.unionFields().keys()[extra.field_index];
5509 break :field_name if (struct_ty.unionTagTypeSafety()) |_|
5510 .{ .payload_identifier = name }
5511 else
5512 .{ .identifier = name };
5475 const field_int_signedness = if (inst_ty.isAbiInt(mod))
5476 inst_ty.intInfo(mod).signedness
5477 else
5478 .unsigned;
5479 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
5480
5481 const temp_local = try f.allocLocal(inst, field_int_ty);
5482 try f.writeCValue(writer, temp_local, .Other);
5483 try writer.writeAll(" = zig_wrap_");
5484 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
5485 try writer.writeAll("((");
5486 try f.renderType(writer, field_int_ty);
5487 try writer.writeByte(')');
5488 const cant_cast = int_info.bits > 64;
5489 if (cant_cast) {
5490 if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
5491 try writer.writeAll("zig_lo_");
5492 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5493 try writer.writeByte('(');
5494 }
5495 if (bit_offset > 0) {
5496 try writer.writeAll("zig_shr_");
5497 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5498 try writer.writeByte('(');
5499 }
5500 try f.writeCValue(writer, struct_byval, .Other);
5501 if (bit_offset > 0) {
5502 try writer.writeAll(", ");
5503 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
5504 try writer.writeByte(')');
5505 }
5506 if (cant_cast) try writer.writeByte(')');
5507 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
5508 try writer.writeAll(");\n");
5509 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
5510
5511 const local = try f.allocLocal(inst, inst_ty);
5512 try writer.writeAll("memcpy(");
5513 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
5514 try writer.writeAll(", ");
5515 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
5516 try writer.writeAll(", sizeof(");
5517 try f.renderType(writer, inst_ty);
5518 try writer.writeAll("));\n");
5519 try freeLocal(f, inst, temp_local.new_local, 0);
5520 return local;
5521 },
5522 },
5523 else => unreachable,
55135524 },
5514 else => unreachable,
55155525 };
55165526
55175527 const local = try f.allocLocal(inst, inst_ty);
......@@ -6805,17 +6815,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68056815 try a.end(f, writer);
68066816 }
68076817 },
6808 .Struct => switch (inst_ty.containerLayout()) {
6818 .Struct => switch (inst_ty.containerLayout(mod)) {
68096819 .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {
6810 if (inst_ty.structFieldIsComptime(field_i)) continue;
6811 const field_ty = inst_ty.structFieldType(field_i);
6820 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6821 const field_ty = inst_ty.structFieldType(field_i, mod);
68126822 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68136823
68146824 const a = try Assignment.start(f, writer, field_ty);
68156825 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())
68166826 .{ .field = field_i }
68176827 else
6818 .{ .identifier = inst_ty.structFieldName(field_i) });
6828 .{ .identifier = inst_ty.structFieldName(field_i, mod) });
68196829 try a.assign(f, writer);
68206830 try f.writeCValue(writer, element, .Other);
68216831 try a.end(f, writer);
......@@ -6831,8 +6841,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68316841
68326842 var empty = true;
68336843 for (0..elements.len) |field_i| {
6834 if (inst_ty.structFieldIsComptime(field_i)) continue;
6835 const field_ty = inst_ty.structFieldType(field_i);
6844 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6845 const field_ty = inst_ty.structFieldType(field_i, mod);
68366846 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68376847
68386848 if (!empty) {
......@@ -6844,8 +6854,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68446854 }
68456855 empty = true;
68466856 for (resolved_elements, 0..) |element, field_i| {
6847 if (inst_ty.structFieldIsComptime(field_i)) continue;
6848 const field_ty = inst_ty.structFieldType(field_i);
6857 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6858 const field_ty = inst_ty.structFieldType(field_i, mod);
68496859 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68506860
68516861 if (!empty) try writer.writeAll(", ");
src/codegen/c/type.zig+25-25
......@@ -299,7 +299,7 @@ pub const CType = extern union {
299299 pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs {
300300 return init(
301301 struct_ty.structFieldAlign(field_i, mod),
302 struct_ty.structFieldType(field_i).abiAlignment(mod),
302 struct_ty.structFieldType(field_i, mod).abiAlignment(mod),
303303 );
304304 }
305305 pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs {
......@@ -1486,23 +1486,23 @@ pub const CType = extern union {
14861486 }
14871487 },
14881488
1489 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout() == .Packed) {
1490 if (ty.castTag(.@"struct")) |struct_obj| {
1491 try self.initType(struct_obj.data.backing_int_ty, kind, lookup);
1489 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .Packed) {
1490 if (mod.typeToStruct(ty)) |struct_obj| {
1491 try self.initType(struct_obj.backing_int_ty, kind, lookup);
14921492 } else {
14931493 const bits = @intCast(u16, ty.bitSize(mod));
14941494 const int_ty = try mod.intType(.unsigned, bits);
14951495 try self.initType(int_ty, kind, lookup);
14961496 }
1497 } else if (ty.isTupleOrAnonStruct()) {
1497 } else if (ty.isTupleOrAnonStruct(mod)) {
14981498 if (lookup.isMutable()) {
14991499 for (0..switch (zig_ty_tag) {
1500 .Struct => ty.structFieldCount(),
1500 .Struct => ty.structFieldCount(mod),
15011501 .Union => ty.unionFields().count(),
15021502 else => unreachable,
15031503 }) |field_i| {
1504 const field_ty = ty.structFieldType(field_i);
1505 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
1504 const field_ty = ty.structFieldType(field_i, mod);
1505 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
15061506 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
15071507 _ = try lookup.typeToIndex(field_ty, switch (kind) {
15081508 .forward, .forward_parameter => .forward,
......@@ -1579,11 +1579,11 @@ pub const CType = extern union {
15791579 } else {
15801580 var is_packed = false;
15811581 for (0..switch (zig_ty_tag) {
1582 .Struct => ty.structFieldCount(),
1582 .Struct => ty.structFieldCount(mod),
15831583 .Union => ty.unionFields().count(),
15841584 else => unreachable,
15851585 }) |field_i| {
1586 const field_ty = ty.structFieldType(field_i);
1586 const field_ty = ty.structFieldType(field_i, mod);
15871587 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
15881588
15891589 const field_align = AlignAs.fieldAlign(ty, field_i, mod);
......@@ -1929,15 +1929,15 @@ pub const CType = extern union {
19291929 => {
19301930 const zig_ty_tag = ty.zigTypeTag(mod);
19311931 const fields_len = switch (zig_ty_tag) {
1932 .Struct => ty.structFieldCount(),
1932 .Struct => ty.structFieldCount(mod),
19331933 .Union => ty.unionFields().count(),
19341934 else => unreachable,
19351935 };
19361936
19371937 var c_fields_len: usize = 0;
19381938 for (0..fields_len) |field_i| {
1939 const field_ty = ty.structFieldType(field_i);
1940 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
1939 const field_ty = ty.structFieldType(field_i, mod);
1940 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
19411941 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
19421942 c_fields_len += 1;
19431943 }
......@@ -1945,8 +1945,8 @@ pub const CType = extern union {
19451945 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
19461946 var c_field_i: usize = 0;
19471947 for (0..fields_len) |field_i| {
1948 const field_ty = ty.structFieldType(field_i);
1949 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
1948 const field_ty = ty.structFieldType(field_i, mod);
1949 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
19501950 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
19511951
19521952 defer c_field_i += 1;
......@@ -1955,7 +1955,7 @@ pub const CType = extern union {
19551955 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
19561956 else
19571957 arena.dupeZ(u8, switch (zig_ty_tag) {
1958 .Struct => ty.structFieldName(field_i),
1958 .Struct => ty.structFieldName(field_i, mod),
19591959 .Union => ty.unionFields().keys()[field_i],
19601960 else => unreachable,
19611961 }),
......@@ -2074,7 +2074,7 @@ pub const CType = extern union {
20742074 .fwd_anon_struct,
20752075 .fwd_anon_union,
20762076 => {
2077 if (!ty.isTupleOrAnonStruct()) return false;
2077 if (!ty.isTupleOrAnonStruct(mod)) return false;
20782078
20792079 var name_buf: [
20802080 std.fmt.count("f{}", .{std.math.maxInt(usize)})
......@@ -2084,12 +2084,12 @@ pub const CType = extern union {
20842084 const zig_ty_tag = ty.zigTypeTag(mod);
20852085 var c_field_i: usize = 0;
20862086 for (0..switch (zig_ty_tag) {
2087 .Struct => ty.structFieldCount(),
2087 .Struct => ty.structFieldCount(mod),
20882088 .Union => ty.unionFields().count(),
20892089 else => unreachable,
20902090 }) |field_i| {
2091 const field_ty = ty.structFieldType(field_i);
2092 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
2091 const field_ty = ty.structFieldType(field_i, mod);
2092 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
20932093 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
20942094
20952095 defer c_field_i += 1;
......@@ -2105,7 +2105,7 @@ pub const CType = extern union {
21052105 if (ty.isSimpleTuple())
21062106 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
21072107 else switch (zig_ty_tag) {
2108 .Struct => ty.structFieldName(field_i),
2108 .Struct => ty.structFieldName(field_i, mod),
21092109 .Union => ty.unionFields().keys()[field_i],
21102110 else => unreachable,
21112111 },
......@@ -2210,12 +2210,12 @@ pub const CType = extern union {
22102210
22112211 const zig_ty_tag = ty.zigTypeTag(mod);
22122212 for (0..switch (ty.zigTypeTag(mod)) {
2213 .Struct => ty.structFieldCount(),
2213 .Struct => ty.structFieldCount(mod),
22142214 .Union => ty.unionFields().count(),
22152215 else => unreachable,
22162216 }) |field_i| {
2217 const field_ty = ty.structFieldType(field_i);
2218 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
2217 const field_ty = ty.structFieldType(field_i, mod);
2218 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
22192219 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22202220
22212221 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {
......@@ -2227,7 +2227,7 @@ pub const CType = extern union {
22272227 hasher.update(if (ty.isSimpleTuple())
22282228 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
22292229 else switch (zig_ty_tag) {
2230 .Struct => ty.structFieldName(field_i),
2230 .Struct => ty.structFieldName(field_i, mod),
22312231 .Union => ty.unionFields().keys()[field_i],
22322232 else => unreachable,
22332233 });
src/codegen/llvm.zig+26-28
......@@ -1986,8 +1986,7 @@ pub const Object = struct {
19861986 const name = try ty.nameAlloc(gpa, o.module);
19871987 defer gpa.free(name);
19881988
1989 if (ty.castTag(.@"struct")) |payload| {
1990 const struct_obj = payload.data;
1989 if (mod.typeToStruct(ty)) |struct_obj| {
19911990 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
19921991 assert(struct_obj.haveLayout());
19931992 const info = struct_obj.backing_int_ty.intInfo(mod);
......@@ -2075,8 +2074,7 @@ pub const Object = struct {
20752074 return full_di_ty;
20762075 }
20772076
2078 if (ty.castTag(.@"struct")) |payload| {
2079 const struct_obj = payload.data;
2077 if (mod.typeToStruct(ty)) |struct_obj| {
20802078 if (!struct_obj.haveFieldTypes()) {
20812079 // This can happen if a struct type makes it all the way to
20822080 // flush() without ever being instantiated or referenced (even
......@@ -2105,8 +2103,8 @@ pub const Object = struct {
21052103 return struct_di_ty;
21062104 }
21072105
2108 const fields = ty.structFields();
2109 const layout = ty.containerLayout();
2106 const fields = ty.structFields(mod);
2107 const layout = ty.containerLayout(mod);
21102108
21112109 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
21122110 defer di_fields.deinit(gpa);
......@@ -2116,7 +2114,7 @@ pub const Object = struct {
21162114 comptime assert(struct_layout_version == 2);
21172115 var offset: u64 = 0;
21182116
2119 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod);
2117 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
21202118 while (it.next()) |field_and_index| {
21212119 const field = field_and_index.field;
21222120 const field_size = field.ty.abiSize(mod);
......@@ -2990,7 +2988,7 @@ pub const DeclGen = struct {
29902988 return llvm_struct_ty;
29912989 }
29922990
2993 const struct_obj = t.castTag(.@"struct").?.data;
2991 const struct_obj = mod.typeToStruct(t).?;
29942992
29952993 if (struct_obj.layout == .Packed) {
29962994 assert(struct_obj.haveLayout());
......@@ -3696,7 +3694,7 @@ pub const DeclGen = struct {
36963694 }
36973695 }
36983696
3699 const struct_obj = tv.ty.castTag(.@"struct").?.data;
3697 const struct_obj = mod.typeToStruct(tv.ty).?;
37003698
37013699 if (struct_obj.layout == .Packed) {
37023700 assert(struct_obj.haveLayout());
......@@ -4043,7 +4041,7 @@ pub const DeclGen = struct {
40434041 const llvm_u32 = dg.context.intType(32);
40444042 switch (parent_ty.zigTypeTag(mod)) {
40454043 .Union => {
4046 if (parent_ty.containerLayout() == .Packed) {
4044 if (parent_ty.containerLayout(mod) == .Packed) {
40474045 return parent_llvm_ptr;
40484046 }
40494047
......@@ -4065,14 +4063,14 @@ pub const DeclGen = struct {
40654063 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
40664064 },
40674065 .Struct => {
4068 if (parent_ty.containerLayout() == .Packed) {
4066 if (parent_ty.containerLayout(mod) == .Packed) {
40694067 if (!byte_aligned) return parent_llvm_ptr;
40704068 const llvm_usize = dg.context.intType(target.ptrBitWidth());
40714069 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
40724070 // count bits of fields before this one
40734071 const prev_bits = b: {
40744072 var b: usize = 0;
4075 for (parent_ty.structFields().values()[0..field_index]) |field| {
4073 for (parent_ty.structFields(mod).values()[0..field_index]) |field| {
40764074 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
40774075 b += @intCast(usize, field.ty.bitSize(mod));
40784076 }
......@@ -5983,7 +5981,7 @@ pub const FuncGen = struct {
59835981 const struct_ty = self.typeOf(struct_field.struct_operand);
59845982 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
59855983 const field_index = struct_field.field_index;
5986 const field_ty = struct_ty.structFieldType(field_index);
5984 const field_ty = struct_ty.structFieldType(field_index, mod);
59875985 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
59885986 return null;
59895987 }
......@@ -5991,9 +5989,9 @@ pub const FuncGen = struct {
59915989 if (!isByRef(struct_ty, mod)) {
59925990 assert(!isByRef(field_ty, mod));
59935991 switch (struct_ty.zigTypeTag(mod)) {
5994 .Struct => switch (struct_ty.containerLayout()) {
5992 .Struct => switch (struct_ty.containerLayout(mod)) {
59955993 .Packed => {
5996 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5994 const struct_obj = mod.typeToStruct(struct_ty).?;
59975995 const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index);
59985996 const containing_int = struct_llvm_val;
59995997 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);
......@@ -6019,7 +6017,7 @@ pub const FuncGen = struct {
60196017 },
60206018 },
60216019 .Union => {
6022 assert(struct_ty.containerLayout() == .Packed);
6020 assert(struct_ty.containerLayout(mod) == .Packed);
60236021 const containing_int = struct_llvm_val;
60246022 const elem_llvm_ty = try self.dg.lowerType(field_ty);
60256023 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
......@@ -6041,7 +6039,7 @@ pub const FuncGen = struct {
60416039
60426040 switch (struct_ty.zigTypeTag(mod)) {
60436041 .Struct => {
6044 assert(struct_ty.containerLayout() != .Packed);
6042 assert(struct_ty.containerLayout(mod) != .Packed);
60456043 var ptr_ty_buf: Type.Payload.Pointer = undefined;
60466044 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
60476045 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
......@@ -9289,8 +9287,8 @@ pub const FuncGen = struct {
92899287 return vector;
92909288 },
92919289 .Struct => {
9292 if (result_ty.containerLayout() == .Packed) {
9293 const struct_obj = result_ty.castTag(.@"struct").?.data;
9290 if (result_ty.containerLayout(mod) == .Packed) {
9291 const struct_obj = mod.typeToStruct(result_ty).?;
92949292 assert(struct_obj.haveLayout());
92959293 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
92969294 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));
......@@ -9795,7 +9793,7 @@ pub const FuncGen = struct {
97959793 const mod = self.dg.module;
97969794 const struct_ty = struct_ptr_ty.childType(mod);
97979795 switch (struct_ty.zigTypeTag(mod)) {
9798 .Struct => switch (struct_ty.containerLayout()) {
9796 .Struct => switch (struct_ty.containerLayout(mod)) {
97999797 .Packed => {
98009798 const result_ty = self.typeOfIndex(inst);
98019799 const result_ty_info = result_ty.ptrInfo(mod);
......@@ -9838,7 +9836,7 @@ pub const FuncGen = struct {
98389836 },
98399837 .Union => {
98409838 const layout = struct_ty.unionGetLayout(mod);
9841 if (layout.payload_size == 0 or struct_ty.containerLayout() == .Packed) return struct_ptr;
9839 if (layout.payload_size == 0 or struct_ty.containerLayout(mod) == .Packed) return struct_ptr;
98429840 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
98439841 const union_llvm_ty = try self.dg.lowerType(struct_ty);
98449842 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");
......@@ -10530,11 +10528,11 @@ fn llvmFieldIndex(
1053010528 }
1053110529 return null;
1053210530 }
10533 const layout = ty.containerLayout();
10531 const layout = ty.containerLayout(mod);
1053410532 assert(layout != .Packed);
1053510533
1053610534 var llvm_field_index: c_uint = 0;
10537 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod);
10535 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
1053810536 while (it.next()) |field_and_index| {
1053910537 const field = field_and_index.field;
1054010538 const field_align = field.alignment(mod, layout);
......@@ -11113,7 +11111,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
1111311111 .Array, .Frame => return ty.hasRuntimeBits(mod),
1111411112 .Struct => {
1111511113 // Packed structs are represented to LLVM as integers.
11116 if (ty.containerLayout() == .Packed) return false;
11114 if (ty.containerLayout(mod) == .Packed) return false;
1111711115 if (ty.isSimpleTupleOrAnonStruct()) {
1111811116 const tuple = ty.tupleFields();
1111911117 var count: usize = 0;
......@@ -11127,7 +11125,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
1112711125 return false;
1112811126 }
1112911127 var count: usize = 0;
11130 const fields = ty.structFields();
11128 const fields = ty.structFields(mod);
1113111129 for (fields.values()) |field| {
1113211130 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
1113311131
......@@ -11137,7 +11135,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
1113711135 }
1113811136 return false;
1113911137 },
11140 .Union => switch (ty.containerLayout()) {
11138 .Union => switch (ty.containerLayout(mod)) {
1114111139 .Packed => return false,
1114211140 else => return ty.hasRuntimeBits(mod),
1114311141 },
......@@ -11176,8 +11174,8 @@ fn isScalar(mod: *Module, ty: Type) bool {
1117611174 .Vector,
1117711175 => true,
1117811176
11179 .Struct => ty.containerLayout() == .Packed,
11180 .Union => ty.containerLayout() == .Packed,
11177 .Struct => ty.containerLayout(mod) == .Packed,
11178 .Union => ty.containerLayout(mod) == .Packed,
1118111179 else => false,
1118211180 };
1118311181}
src/codegen/spirv.zig+4-4
......@@ -685,7 +685,7 @@ pub const DeclGen = struct {
685685 if (ty.isSimpleTupleOrAnonStruct()) {
686686 unreachable; // TODO
687687 } else {
688 const struct_ty = ty.castTag(.@"struct").?.data;
688 const struct_ty = mod.typeToStruct(ty).?;
689689
690690 if (struct_ty.layout == .Packed) {
691691 return dg.todo("packed struct constants", .{});
......@@ -1306,7 +1306,7 @@ pub const DeclGen = struct {
13061306 } });
13071307 }
13081308
1309 const struct_ty = ty.castTag(.@"struct").?.data;
1309 const struct_ty = mod.typeToStruct(ty).?;
13101310
13111311 if (struct_ty.layout == .Packed) {
13121312 return try self.resolveType(struct_ty.backing_int_ty, .direct);
......@@ -2576,7 +2576,7 @@ pub const DeclGen = struct {
25762576 const struct_ty = self.typeOf(struct_field.struct_operand);
25772577 const object_id = try self.resolve(struct_field.struct_operand);
25782578 const field_index = struct_field.field_index;
2579 const field_ty = struct_ty.structFieldType(field_index);
2579 const field_ty = struct_ty.structFieldType(field_index, mod);
25802580
25812581 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
25822582
......@@ -2595,7 +2595,7 @@ pub const DeclGen = struct {
25952595 const mod = self.module;
25962596 const object_ty = object_ptr_ty.childType(mod);
25972597 switch (object_ty.zigTypeTag(mod)) {
2598 .Struct => switch (object_ty.containerLayout()) {
2598 .Struct => switch (object_ty.containerLayout(mod)) {
25992599 .Packed => unreachable, // TODO
26002600 else => {
26012601 const field_index_ty_ref = try self.intType(.unsigned, 32);
src/link/Dwarf.zig+2-2
......@@ -360,13 +360,13 @@ pub const DeclState = struct {
360360 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
361361 dbg_info_buffer.appendAssumeCapacity(0);
362362
363 const struct_obj = ty.castTag(.@"struct").?.data;
363 const struct_obj = mod.typeToStruct(ty).?;
364364 if (struct_obj.layout == .Packed) {
365365 log.debug("TODO implement .debug_info for packed structs", .{});
366366 break :blk;
367367 }
368368
369 const fields = ty.structFields();
369 const fields = ty.structFields(mod);
370370 for (fields.keys(), 0..) |field_name, field_index| {
371371 const field = fields.get(field_name).?;
372372 if (!field.ty.hasRuntimeBits(mod)) continue;
src/type.zig+601-582
......@@ -59,8 +59,6 @@ pub const Type = struct {
5959
6060 .anyframe_T => return .AnyFrame,
6161
62 .empty_struct,
63 .@"struct",
6462 .tuple,
6563 .anon_struct,
6664 => return .Struct,
......@@ -148,6 +146,7 @@ pub const Type = struct {
148146 .opt => unreachable,
149147 .enum_tag => unreachable,
150148 .simple_value => unreachable,
149 .aggregate => unreachable,
151150 },
152151 }
153152 }
......@@ -501,16 +500,6 @@ pub const Type = struct {
501500 return a.elemType2(mod).eql(b.elemType2(mod), mod);
502501 },
503502
504 .empty_struct => {
505 const a_namespace = a.castTag(.empty_struct).?.data;
506 const b_namespace = (b.castTag(.empty_struct) orelse return false).data;
507 return a_namespace == b_namespace;
508 },
509 .@"struct" => {
510 const a_struct_obj = a.castTag(.@"struct").?.data;
511 const b_struct_obj = (b.castTag(.@"struct") orelse return false).data;
512 return a_struct_obj == b_struct_obj;
513 },
514503 .tuple => {
515504 if (!b.isSimpleTuple()) return false;
516505
......@@ -720,15 +709,6 @@ pub const Type = struct {
720709 hashWithHasher(ty.childType(mod), hasher, mod);
721710 },
722711
723 .empty_struct => {
724 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
725 const namespace: *const Module.Namespace = ty.castTag(.empty_struct).?.data;
726 std.hash.autoHash(hasher, namespace);
727 },
728 .@"struct" => {
729 const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data;
730 std.hash.autoHash(hasher, struct_obj);
731 },
732712 .tuple => {
733713 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
734714
......@@ -955,8 +935,6 @@ pub const Type = struct {
955935 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
956936 .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred),
957937 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
958 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
959 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
960938 .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union),
961939 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),
962940 .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered),
......@@ -1033,14 +1011,6 @@ pub const Type = struct {
10331011 while (true) {
10341012 const t = ty.tag();
10351013 switch (t) {
1036 .empty_struct => return writer.writeAll("struct {}"),
1037
1038 .@"struct" => {
1039 const struct_obj = ty.castTag(.@"struct").?.data;
1040 return writer.print("({s} decl={d})", .{
1041 @tagName(t), struct_obj.owner_decl,
1042 });
1043 },
10441014 .@"union", .union_safety_tagged, .union_tagged => {
10451015 const union_obj = ty.cast(Payload.Union).?.data;
10461016 return writer.print("({s} decl={d})", .{
......@@ -1247,22 +1217,10 @@ pub const Type = struct {
12471217 /// Prints a name suitable for `@typeName`.
12481218 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
12491219 switch (ty.ip_index) {
1250 .empty_struct_type => try writer.writeAll("@TypeOf(.{})"),
1251
12521220 .none => switch (ty.tag()) {
12531221 .inferred_alloc_const => unreachable,
12541222 .inferred_alloc_mut => unreachable,
12551223
1256 .empty_struct => {
1257 const namespace = ty.castTag(.empty_struct).?.data;
1258 try namespace.renderFullyQualifiedName(mod, "", writer);
1259 },
1260
1261 .@"struct" => {
1262 const struct_obj = ty.castTag(.@"struct").?.data;
1263 const decl = mod.declPtr(struct_obj.owner_decl);
1264 try decl.renderFullyQualifiedName(mod, writer);
1265 },
12661224 .@"union", .union_safety_tagged, .union_tagged => {
12671225 const union_obj = ty.cast(Payload.Union).?.data;
12681226 const decl = mod.declPtr(union_obj.owner_decl);
......@@ -1548,7 +1506,18 @@ pub const Type = struct {
15481506 return;
15491507 },
15501508 .simple_type => |s| return writer.writeAll(@tagName(s)),
1551 .struct_type => @panic("TODO"),
1509 .struct_type => |struct_type| {
1510 if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
1511 const decl = mod.declPtr(struct_obj.owner_decl);
1512 try decl.renderFullyQualifiedName(mod, writer);
1513 } else if (struct_type.namespace.unwrap()) |namespace_index| {
1514 const namespace = mod.namespacePtr(namespace_index);
1515 try namespace.renderFullyQualifiedName(mod, "", writer);
1516 } else {
1517 try writer.writeAll("@TypeOf(.{})");
1518 }
1519 },
1520
15521521 .union_type => @panic("TODO"),
15531522 .opaque_type => |opaque_type| {
15541523 const decl = mod.declPtr(opaque_type.decl);
......@@ -1562,6 +1531,7 @@ pub const Type = struct {
15621531 .ptr => unreachable,
15631532 .opt => unreachable,
15641533 .enum_tag => unreachable,
1534 .aggregate => unreachable,
15651535 },
15661536 }
15671537 }
......@@ -1624,12 +1594,10 @@ pub const Type = struct {
16241594 },
16251595
16261596 // These are false because they are comptime-only types.
1627 .empty_struct,
16281597 // These are function *bodies*, not pointers.
16291598 // Special exceptions have to be made when emitting functions due to
16301599 // this returning false.
1631 .function,
1632 => return false,
1600 .function => return false,
16331601
16341602 .optional => {
16351603 const child_ty = ty.optionalChild(mod);
......@@ -1646,28 +1614,6 @@ pub const Type = struct {
16461614 }
16471615 },
16481616
1649 .@"struct" => {
1650 const struct_obj = ty.castTag(.@"struct").?.data;
1651 if (struct_obj.status == .field_types_wip) {
1652 // In this case, we guess that hasRuntimeBits() for this type is true,
1653 // and then later if our guess was incorrect, we emit a compile error.
1654 struct_obj.assumed_runtime_bits = true;
1655 return true;
1656 }
1657 switch (strat) {
1658 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1659 .eager => assert(struct_obj.haveFieldTypes()),
1660 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
1661 }
1662 for (struct_obj.fields.values()) |field| {
1663 if (field.is_comptime) continue;
1664 if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1665 return true;
1666 } else {
1667 return false;
1668 }
1669 },
1670
16711617 .enum_full => {
16721618 const enum_full = ty.castTag(.enum_full).?.data;
16731619 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
......@@ -1824,7 +1770,31 @@ pub const Type = struct {
18241770 .generic_poison => unreachable,
18251771 .var_args_param => unreachable,
18261772 },
1827 .struct_type => @panic("TODO"),
1773 .struct_type => |struct_type| {
1774 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
1775 // This struct has no fields.
1776 return false;
1777 };
1778 if (struct_obj.status == .field_types_wip) {
1779 // In this case, we guess that hasRuntimeBits() for this type is true,
1780 // and then later if our guess was incorrect, we emit a compile error.
1781 struct_obj.assumed_runtime_bits = true;
1782 return true;
1783 }
1784 switch (strat) {
1785 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1786 .eager => assert(struct_obj.haveFieldTypes()),
1787 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
1788 }
1789 for (struct_obj.fields.values()) |field| {
1790 if (field.is_comptime) continue;
1791 if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1792 return true;
1793 } else {
1794 return false;
1795 }
1796 },
1797
18281798 .union_type => @panic("TODO"),
18291799 .opaque_type => true,
18301800
......@@ -1835,6 +1805,7 @@ pub const Type = struct {
18351805 .ptr => unreachable,
18361806 .opt => unreachable,
18371807 .enum_tag => unreachable,
1808 .aggregate => unreachable,
18381809 },
18391810 }
18401811 }
......@@ -1862,7 +1833,6 @@ pub const Type = struct {
18621833 .anyframe_T,
18631834 .tuple,
18641835 .anon_struct,
1865 .empty_struct,
18661836 => false,
18671837
18681838 .enum_full,
......@@ -1877,7 +1847,6 @@ pub const Type = struct {
18771847 => ty.childType(mod).hasWellDefinedLayout(mod),
18781848
18791849 .optional => ty.isPtrLikeOptional(mod),
1880 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,
18811850 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,
18821851 .union_tagged => false,
18831852 },
......@@ -1936,7 +1905,13 @@ pub const Type = struct {
19361905
19371906 .var_args_param => unreachable,
19381907 },
1939 .struct_type => @panic("TODO"),
1908 .struct_type => |struct_type| {
1909 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
1910 // Struct with no fields has a well-defined layout of no bits.
1911 return true;
1912 };
1913 return struct_obj.layout != .Auto;
1914 },
19401915 .union_type => @panic("TODO"),
19411916 .opaque_type => false,
19421917
......@@ -1947,6 +1922,7 @@ pub const Type = struct {
19471922 .ptr => unreachable,
19481923 .opt => unreachable,
19491924 .enum_tag => unreachable,
1925 .aggregate => unreachable,
19501926 },
19511927 };
19521928 }
......@@ -2146,68 +2122,6 @@ pub const Type = struct {
21462122 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
21472123 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
21482124
2149 .@"struct" => {
2150 const struct_obj = ty.castTag(.@"struct").?.data;
2151 if (opt_sema) |sema| {
2152 if (struct_obj.status == .field_types_wip) {
2153 // We'll guess "pointer-aligned", if the struct has an
2154 // underaligned pointer field then some allocations
2155 // might require explicit alignment.
2156 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2157 }
2158 _ = try sema.resolveTypeFields(ty);
2159 }
2160 if (!struct_obj.haveFieldTypes()) switch (strat) {
2161 .eager => unreachable, // struct layout not resolved
2162 .sema => unreachable, // handled above
2163 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2164 };
2165 if (struct_obj.layout == .Packed) {
2166 switch (strat) {
2167 .sema => |sema| try sema.resolveTypeLayout(ty),
2168 .lazy => |arena| {
2169 if (!struct_obj.haveLayout()) {
2170 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
2171 }
2172 },
2173 .eager => {},
2174 }
2175 assert(struct_obj.haveLayout());
2176 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
2177 }
2178
2179 const fields = ty.structFields();
2180 var big_align: u32 = 0;
2181 for (fields.values()) |field| {
2182 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2183 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
2184 else => |e| return e,
2185 })) continue;
2186
2187 const field_align = if (field.abi_align != 0)
2188 field.abi_align
2189 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
2190 .scalar => |a| a,
2191 .val => switch (strat) {
2192 .eager => unreachable, // struct layout not resolved
2193 .sema => unreachable, // handled above
2194 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2195 },
2196 };
2197 big_align = @max(big_align, field_align);
2198
2199 // This logic is duplicated in Module.Struct.Field.alignment.
2200 if (struct_obj.layout == .Extern or target.ofmt == .c) {
2201 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
2202 // The C ABI requires 128 bit integer fields of structs
2203 // to be 16-bytes aligned.
2204 big_align = @max(big_align, 16);
2205 }
2206 }
2207 }
2208 return AbiAlignmentAdvanced{ .scalar = big_align };
2209 },
2210
22112125 .tuple, .anon_struct => {
22122126 const tuple = ty.tupleFields();
22132127 var big_align: u32 = 0;
......@@ -2241,8 +2155,6 @@ pub const Type = struct {
22412155 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true);
22422156 },
22432157
2244 .empty_struct => return AbiAlignmentAdvanced{ .scalar = 0 },
2245
22462158 .inferred_alloc_const,
22472159 .inferred_alloc_mut,
22482160 => unreachable,
......@@ -2337,7 +2249,69 @@ pub const Type = struct {
23372249 .generic_poison => unreachable,
23382250 .var_args_param => unreachable,
23392251 },
2340 .struct_type => @panic("TODO"),
2252 .struct_type => |struct_type| {
2253 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
2254 return AbiAlignmentAdvanced{ .scalar = 0 };
2255
2256 if (opt_sema) |sema| {
2257 if (struct_obj.status == .field_types_wip) {
2258 // We'll guess "pointer-aligned", if the struct has an
2259 // underaligned pointer field then some allocations
2260 // might require explicit alignment.
2261 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2262 }
2263 _ = try sema.resolveTypeFields(ty);
2264 }
2265 if (!struct_obj.haveFieldTypes()) switch (strat) {
2266 .eager => unreachable, // struct layout not resolved
2267 .sema => unreachable, // handled above
2268 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2269 };
2270 if (struct_obj.layout == .Packed) {
2271 switch (strat) {
2272 .sema => |sema| try sema.resolveTypeLayout(ty),
2273 .lazy => |arena| {
2274 if (!struct_obj.haveLayout()) {
2275 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
2276 }
2277 },
2278 .eager => {},
2279 }
2280 assert(struct_obj.haveLayout());
2281 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
2282 }
2283
2284 const fields = ty.structFields(mod);
2285 var big_align: u32 = 0;
2286 for (fields.values()) |field| {
2287 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2288 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
2289 else => |e| return e,
2290 })) continue;
2291
2292 const field_align = if (field.abi_align != 0)
2293 field.abi_align
2294 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
2295 .scalar => |a| a,
2296 .val => switch (strat) {
2297 .eager => unreachable, // struct layout not resolved
2298 .sema => unreachable, // handled above
2299 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2300 },
2301 };
2302 big_align = @max(big_align, field_align);
2303
2304 // This logic is duplicated in Module.Struct.Field.alignment.
2305 if (struct_obj.layout == .Extern or target.ofmt == .c) {
2306 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
2307 // The C ABI requires 128 bit integer fields of structs
2308 // to be 16-bytes aligned.
2309 big_align = @max(big_align, 16);
2310 }
2311 }
2312 }
2313 return AbiAlignmentAdvanced{ .scalar = big_align };
2314 },
23412315 .union_type => @panic("TODO"),
23422316 .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 },
23432317
......@@ -2348,6 +2322,7 @@ pub const Type = struct {
23482322 .ptr => unreachable,
23492323 .opt => unreachable,
23502324 .enum_tag => unreachable,
2325 .aggregate => unreachable,
23512326 },
23522327 }
23532328 }
......@@ -2517,42 +2492,16 @@ pub const Type = struct {
25172492 .inferred_alloc_const => unreachable,
25182493 .inferred_alloc_mut => unreachable,
25192494
2520 .empty_struct => return AbiSizeAdvanced{ .scalar = 0 },
2521
2522 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
2523 .Packed => {
2524 const struct_obj = ty.castTag(.@"struct").?.data;
2525 switch (strat) {
2526 .sema => |sema| try sema.resolveTypeLayout(ty),
2527 .lazy => |arena| {
2528 if (!struct_obj.haveLayout()) {
2529 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2530 }
2531 },
2532 .eager => {},
2533 }
2534 assert(struct_obj.haveLayout());
2535 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
2536 },
2537 else => {
2538 switch (strat) {
2539 .sema => |sema| try sema.resolveTypeLayout(ty),
2540 .lazy => |arena| {
2541 if (ty.castTag(.@"struct")) |payload| {
2542 const struct_obj = payload.data;
2543 if (!struct_obj.haveLayout()) {
2544 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2545 }
2546 }
2547 },
2548 .eager => {},
2549 }
2550 const field_count = ty.structFieldCount();
2551 if (field_count == 0) {
2552 return AbiSizeAdvanced{ .scalar = 0 };
2553 }
2554 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2555 },
2495 .tuple, .anon_struct => {
2496 switch (strat) {
2497 .sema => |sema| try sema.resolveTypeLayout(ty),
2498 .lazy, .eager => {},
2499 }
2500 const field_count = ty.structFieldCount(mod);
2501 if (field_count == 0) {
2502 return AbiSizeAdvanced{ .scalar = 0 };
2503 }
2504 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
25562505 },
25572506
25582507 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
......@@ -2752,7 +2701,42 @@ pub const Type = struct {
27522701 .generic_poison => unreachable,
27532702 .var_args_param => unreachable,
27542703 },
2755 .struct_type => @panic("TODO"),
2704 .struct_type => |struct_type| switch (ty.containerLayout(mod)) {
2705 .Packed => {
2706 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
2707 return AbiSizeAdvanced{ .scalar = 0 };
2708
2709 switch (strat) {
2710 .sema => |sema| try sema.resolveTypeLayout(ty),
2711 .lazy => |arena| {
2712 if (!struct_obj.haveLayout()) {
2713 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2714 }
2715 },
2716 .eager => {},
2717 }
2718 assert(struct_obj.haveLayout());
2719 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
2720 },
2721 else => {
2722 switch (strat) {
2723 .sema => |sema| try sema.resolveTypeLayout(ty),
2724 .lazy => |arena| {
2725 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
2726 return AbiSizeAdvanced{ .scalar = 0 };
2727 if (!struct_obj.haveLayout()) {
2728 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2729 }
2730 },
2731 .eager => {},
2732 }
2733 const field_count = ty.structFieldCount(mod);
2734 if (field_count == 0) {
2735 return AbiSizeAdvanced{ .scalar = 0 };
2736 }
2737 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2738 },
2739 },
27562740 .union_type => @panic("TODO"),
27572741 .opaque_type => unreachable, // no size available
27582742
......@@ -2763,6 +2747,7 @@ pub const Type = struct {
27632747 .ptr => unreachable,
27642748 .opt => unreachable,
27652749 .enum_tag => unreachable,
2750 .aggregate => unreachable,
27662751 },
27672752 }
27682753 }
......@@ -2850,189 +2835,189 @@ pub const Type = struct {
28502835 ) Module.CompileError!u64 {
28512836 const target = mod.getTarget();
28522837
2853 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2854 .int_type => |int_type| return int_type.bits,
2855 .ptr_type => |ptr_type| switch (ptr_type.size) {
2856 .Slice => return target.ptrBitWidth() * 2,
2857 else => return target.ptrBitWidth() * 2,
2858 },
2859 .array_type => |array_type| {
2860 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
2861 if (len == 0) return 0;
2862 const elem_ty = array_type.child.toType();
2863 const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod));
2864 if (elem_size == 0) return 0;
2865 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema);
2866 return (len - 1) * 8 * elem_size + elem_bit_size;
2867 },
2868 .vector_type => |vector_type| {
2869 const child_ty = vector_type.child.toType();
2870 const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema);
2871 return elem_bit_size * vector_type.len;
2872 },
2873 .opt_type => @panic("TODO"),
2874 .error_union_type => @panic("TODO"),
2875 .simple_type => |t| switch (t) {
2876 .f16 => return 16,
2877 .f32 => return 32,
2878 .f64 => return 64,
2879 .f80 => return 80,
2880 .f128 => return 128,
2881
2882 .usize,
2883 .isize,
2884 .@"anyframe",
2885 => return target.ptrBitWidth(),
2886
2887 .c_char => return target.c_type_bit_size(.char),
2888 .c_short => return target.c_type_bit_size(.short),
2889 .c_ushort => return target.c_type_bit_size(.ushort),
2890 .c_int => return target.c_type_bit_size(.int),
2891 .c_uint => return target.c_type_bit_size(.uint),
2892 .c_long => return target.c_type_bit_size(.long),
2893 .c_ulong => return target.c_type_bit_size(.ulong),
2894 .c_longlong => return target.c_type_bit_size(.longlong),
2895 .c_ulonglong => return target.c_type_bit_size(.ulonglong),
2896 .c_longdouble => return target.c_type_bit_size(.longdouble),
2897
2898 .bool => return 1,
2899 .void => return 0,
2900
2901 // TODO revisit this when we have the concept of the error tag type
2902 .anyerror => return 16,
2903
2904 .anyopaque => unreachable,
2905 .type => unreachable,
2906 .comptime_int => unreachable,
2907 .comptime_float => unreachable,
2908 .noreturn => unreachable,
2909 .null => unreachable,
2910 .undefined => unreachable,
2911 .enum_literal => unreachable,
2912 .generic_poison => unreachable,
2913 .var_args_param => unreachable,
2914
2915 .atomic_order => unreachable, // missing call to resolveTypeFields
2916 .atomic_rmw_op => unreachable, // missing call to resolveTypeFields
2917 .calling_convention => unreachable, // missing call to resolveTypeFields
2918 .address_space => unreachable, // missing call to resolveTypeFields
2919 .float_mode => unreachable, // missing call to resolveTypeFields
2920 .reduce_op => unreachable, // missing call to resolveTypeFields
2921 .call_modifier => unreachable, // missing call to resolveTypeFields
2922 .prefetch_options => unreachable, // missing call to resolveTypeFields
2923 .export_options => unreachable, // missing call to resolveTypeFields
2924 .extern_options => unreachable, // missing call to resolveTypeFields
2925 .type_info => unreachable, // missing call to resolveTypeFields
2926 },
2927 .struct_type => @panic("TODO"),
2928 .union_type => @panic("TODO"),
2929 .opaque_type => unreachable,
2930
2931 // values, not types
2932 .simple_value => unreachable,
2933 .extern_func => unreachable,
2934 .int => unreachable,
2935 .ptr => unreachable,
2936 .opt => unreachable,
2937 .enum_tag => unreachable,
2938 };
2939
29402838 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
29412839
2942 switch (ty.tag()) {
2943 .function => unreachable, // represents machine code; not a pointer
2944 .empty_struct => unreachable,
2945 .inferred_alloc_const => unreachable,
2946 .inferred_alloc_mut => unreachable,
2947
2948 .@"struct" => {
2949 const struct_obj = ty.castTag(.@"struct").?.data;
2950 if (struct_obj.layout != .Packed) {
2951 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2952 }
2953 if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty);
2954 assert(struct_obj.haveLayout());
2955 return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema);
2956 },
2957
2958 .tuple, .anon_struct => {
2959 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2960 if (ty.containerLayout() != .Packed) {
2961 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2962 }
2963 var total: u64 = 0;
2964 for (ty.tupleFields().types) |field_ty| {
2965 total += try bitSizeAdvanced(field_ty, mod, opt_sema);
2966 }
2967 return total;
2968 },
2840 switch (ty.ip_index) {
2841 .none => switch (ty.tag()) {
2842 .function => unreachable, // represents machine code; not a pointer
2843 .inferred_alloc_const => unreachable,
2844 .inferred_alloc_mut => unreachable,
29692845
2970 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
2971 const int_tag_ty = try ty.intTagType(mod);
2972 return try bitSizeAdvanced(int_tag_ty, mod, opt_sema);
2973 },
2846 .tuple, .anon_struct => {
2847 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2848 if (ty.containerLayout(mod) != .Packed) {
2849 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2850 }
2851 var total: u64 = 0;
2852 for (ty.tupleFields().types) |field_ty| {
2853 total += try bitSizeAdvanced(field_ty, mod, opt_sema);
2854 }
2855 return total;
2856 },
29742857
2975 .@"union", .union_safety_tagged, .union_tagged => {
2976 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2977 if (ty.containerLayout() != .Packed) {
2978 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2979 }
2980 const union_obj = ty.cast(Payload.Union).?.data;
2981 assert(union_obj.haveFieldTypes());
2858 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
2859 const int_tag_ty = try ty.intTagType(mod);
2860 return try bitSizeAdvanced(int_tag_ty, mod, opt_sema);
2861 },
29822862
2983 var size: u64 = 0;
2984 for (union_obj.fields.values()) |field| {
2985 size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema));
2986 }
2987 return size;
2988 },
2863 .@"union", .union_safety_tagged, .union_tagged => {
2864 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2865 if (ty.containerLayout(mod) != .Packed) {
2866 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2867 }
2868 const union_obj = ty.cast(Payload.Union).?.data;
2869 assert(union_obj.haveFieldTypes());
29892870
2990 .array => {
2991 const payload = ty.castTag(.array).?.data;
2992 const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod));
2993 if (elem_size == 0 or payload.len == 0)
2994 return @as(u64, 0);
2995 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);
2996 return (payload.len - 1) * 8 * elem_size + elem_bit_size;
2997 },
2998 .array_sentinel => {
2999 const payload = ty.castTag(.array_sentinel).?.data;
3000 const elem_size = std.math.max(
3001 payload.elem_type.abiAlignment(mod),
3002 payload.elem_type.abiSize(mod),
3003 );
3004 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);
3005 return payload.len * 8 * elem_size + elem_bit_size;
3006 },
2871 var size: u64 = 0;
2872 for (union_obj.fields.values()) |field| {
2873 size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema));
2874 }
2875 return size;
2876 },
2877
2878 .array => {
2879 const payload = ty.castTag(.array).?.data;
2880 const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod));
2881 if (elem_size == 0 or payload.len == 0)
2882 return @as(u64, 0);
2883 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);
2884 return (payload.len - 1) * 8 * elem_size + elem_bit_size;
2885 },
2886 .array_sentinel => {
2887 const payload = ty.castTag(.array_sentinel).?.data;
2888 const elem_size = std.math.max(
2889 payload.elem_type.abiAlignment(mod),
2890 payload.elem_type.abiSize(mod),
2891 );
2892 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);
2893 return payload.len * 8 * elem_size + elem_bit_size;
2894 },
30072895
3008 .anyframe_T => return target.ptrBitWidth(),
2896 .anyframe_T => return target.ptrBitWidth(),
30092897
3010 .pointer => switch (ty.castTag(.pointer).?.data.size) {
3011 .Slice => return target.ptrBitWidth() * 2,
3012 else => return target.ptrBitWidth(),
2898 .pointer => switch (ty.castTag(.pointer).?.data.size) {
2899 .Slice => return target.ptrBitWidth() * 2,
2900 else => return target.ptrBitWidth(),
2901 },
2902
2903 .error_set,
2904 .error_set_single,
2905 .error_set_inferred,
2906 .error_set_merged,
2907 => return 16, // TODO revisit this when we have the concept of the error tag type
2908
2909 .optional, .error_union => {
2910 // Optionals and error unions are not packed so their bitsize
2911 // includes padding bits.
2912 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
2913 },
30132914 },
2915 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2916 .int_type => |int_type| return int_type.bits,
2917 .ptr_type => |ptr_type| switch (ptr_type.size) {
2918 .Slice => return target.ptrBitWidth() * 2,
2919 else => return target.ptrBitWidth() * 2,
2920 },
2921 .array_type => |array_type| {
2922 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
2923 if (len == 0) return 0;
2924 const elem_ty = array_type.child.toType();
2925 const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod));
2926 if (elem_size == 0) return 0;
2927 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema);
2928 return (len - 1) * 8 * elem_size + elem_bit_size;
2929 },
2930 .vector_type => |vector_type| {
2931 const child_ty = vector_type.child.toType();
2932 const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema);
2933 return elem_bit_size * vector_type.len;
2934 },
2935 .opt_type => @panic("TODO"),
2936 .error_union_type => @panic("TODO"),
2937 .simple_type => |t| switch (t) {
2938 .f16 => return 16,
2939 .f32 => return 32,
2940 .f64 => return 64,
2941 .f80 => return 80,
2942 .f128 => return 128,
30142943
3015 .error_set,
3016 .error_set_single,
3017 .error_set_inferred,
3018 .error_set_merged,
3019 => return 16, // TODO revisit this when we have the concept of the error tag type
2944 .usize,
2945 .isize,
2946 .@"anyframe",
2947 => return target.ptrBitWidth(),
2948
2949 .c_char => return target.c_type_bit_size(.char),
2950 .c_short => return target.c_type_bit_size(.short),
2951 .c_ushort => return target.c_type_bit_size(.ushort),
2952 .c_int => return target.c_type_bit_size(.int),
2953 .c_uint => return target.c_type_bit_size(.uint),
2954 .c_long => return target.c_type_bit_size(.long),
2955 .c_ulong => return target.c_type_bit_size(.ulong),
2956 .c_longlong => return target.c_type_bit_size(.longlong),
2957 .c_ulonglong => return target.c_type_bit_size(.ulonglong),
2958 .c_longdouble => return target.c_type_bit_size(.longdouble),
2959
2960 .bool => return 1,
2961 .void => return 0,
2962
2963 // TODO revisit this when we have the concept of the error tag type
2964 .anyerror => return 16,
2965
2966 .anyopaque => unreachable,
2967 .type => unreachable,
2968 .comptime_int => unreachable,
2969 .comptime_float => unreachable,
2970 .noreturn => unreachable,
2971 .null => unreachable,
2972 .undefined => unreachable,
2973 .enum_literal => unreachable,
2974 .generic_poison => unreachable,
2975 .var_args_param => unreachable,
2976
2977 .atomic_order => unreachable, // missing call to resolveTypeFields
2978 .atomic_rmw_op => unreachable, // missing call to resolveTypeFields
2979 .calling_convention => unreachable, // missing call to resolveTypeFields
2980 .address_space => unreachable, // missing call to resolveTypeFields
2981 .float_mode => unreachable, // missing call to resolveTypeFields
2982 .reduce_op => unreachable, // missing call to resolveTypeFields
2983 .call_modifier => unreachable, // missing call to resolveTypeFields
2984 .prefetch_options => unreachable, // missing call to resolveTypeFields
2985 .export_options => unreachable, // missing call to resolveTypeFields
2986 .extern_options => unreachable, // missing call to resolveTypeFields
2987 .type_info => unreachable, // missing call to resolveTypeFields
2988 },
2989 .struct_type => |struct_type| {
2990 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
2991 if (struct_obj.layout != .Packed) {
2992 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2993 }
2994 if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty);
2995 assert(struct_obj.haveLayout());
2996 return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema);
2997 },
2998
2999 .union_type => @panic("TODO"),
3000 .opaque_type => unreachable,
30203001
3021 .optional, .error_union => {
3022 // Optionals and error unions are not packed so their bitsize
3023 // includes padding bits.
3024 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
3002 // values, not types
3003 .simple_value => unreachable,
3004 .extern_func => unreachable,
3005 .int => unreachable,
3006 .ptr => unreachable,
3007 .opt => unreachable,
3008 .enum_tag => unreachable,
3009 .aggregate => unreachable,
30253010 },
30263011 }
30273012 }
30283013
30293014 /// Returns true if the type's layout is already resolved and it is safe
30303015 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
3031 pub fn layoutIsResolved(ty: Type, mod: *const Module) bool {
3016 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
30323017 switch (ty.zigTypeTag(mod)) {
30333018 .Struct => {
3034 if (ty.castTag(.@"struct")) |struct_ty| {
3035 return struct_ty.data.haveLayout();
3019 if (mod.typeToStruct(ty)) |struct_obj| {
3020 return struct_obj.haveLayout();
30363021 }
30373022 return true;
30383023 },
......@@ -3500,18 +3485,23 @@ pub const Type = struct {
35003485 }
35013486 }
35023487
3503 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {
3488 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
35043489 return switch (ty.ip_index) {
35053490 .empty_struct_type => .Auto,
35063491 .none => switch (ty.tag()) {
35073492 .tuple, .anon_struct => .Auto,
3508 .@"struct" => ty.castTag(.@"struct").?.data.layout,
35093493 .@"union" => ty.castTag(.@"union").?.data.layout,
35103494 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,
35113495 .union_tagged => ty.castTag(.union_tagged).?.data.layout,
35123496 else => unreachable,
35133497 },
3514 else => unreachable,
3498 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3499 .struct_type => |struct_type| {
3500 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;
3501 return struct_obj.layout;
3502 },
3503 else => unreachable,
3504 },
35153505 };
35163506 }
35173507
......@@ -3631,14 +3621,16 @@ pub const Type = struct {
36313621 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,
36323622 .tuple => ty.castTag(.tuple).?.data.types.len,
36333623 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
3634 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
3635 .empty_struct => 0,
36363624
36373625 else => unreachable,
36383626 },
36393627 else => switch (ip.indexToKey(ty.ip_index)) {
36403628 .vector_type => |vector_type| vector_type.len,
36413629 .array_type => |array_type| array_type.len,
3630 .struct_type => |struct_type| {
3631 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
3632 return struct_obj.fields.count();
3633 },
36423634 else => unreachable,
36433635 },
36443636 };
......@@ -3665,11 +3657,9 @@ pub const Type = struct {
36653657 /// Asserts the type is an array, pointer or vector.
36663658 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
36673659 return switch (ty.ip_index) {
3668 .empty_struct_type => null,
36693660 .none => switch (ty.tag()) {
36703661 .array,
36713662 .tuple,
3672 .@"struct",
36733663 => null,
36743664
36753665 .pointer => ty.castTag(.pointer).?.data.sentinel,
......@@ -3721,16 +3711,16 @@ pub const Type = struct {
37213711
37223712 /// Returns true for integers, enums, error sets, and packed structs.
37233713 /// If this function returns true, then intInfo() can be called on the type.
3724 pub fn isAbiInt(ty: Type, mod: *const Module) bool {
3714 pub fn isAbiInt(ty: Type, mod: *Module) bool {
37253715 return switch (ty.zigTypeTag(mod)) {
37263716 .Int, .Enum, .ErrorSet => true,
3727 .Struct => ty.containerLayout() == .Packed,
3717 .Struct => ty.containerLayout(mod) == .Packed,
37283718 else => false,
37293719 };
37303720 }
37313721
37323722 /// Asserts the type is an integer, enum, error set, or vector of one of them.
3733 pub fn intInfo(starting_ty: Type, mod: *const Module) InternPool.Key.IntType {
3723 pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType {
37343724 const target = mod.getTarget();
37353725 var ty = starting_ty;
37363726
......@@ -3750,12 +3740,6 @@ pub const Type = struct {
37503740 return .{ .signedness = .unsigned, .bits = 16 };
37513741 },
37523742
3753 .@"struct" => {
3754 const struct_obj = ty.castTag(.@"struct").?.data;
3755 assert(struct_obj.layout == .Packed);
3756 ty = struct_obj.backing_int_ty;
3757 },
3758
37593743 else => unreachable,
37603744 },
37613745 .anyerror_type => {
......@@ -3775,6 +3759,12 @@ pub const Type = struct {
37753759 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
37763760 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
37773761 .int_type => |int_type| return int_type,
3762 .struct_type => |struct_type| {
3763 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3764 assert(struct_obj.layout == .Packed);
3765 ty = struct_obj.backing_int_ty;
3766 },
3767
37783768 .ptr_type => unreachable,
37793769 .array_type => unreachable,
37803770 .vector_type => |vector_type| ty = vector_type.child.toType(),
......@@ -3782,7 +3772,7 @@ pub const Type = struct {
37823772 .opt_type => unreachable,
37833773 .error_union_type => unreachable,
37843774 .simple_type => unreachable, // handled via Index enum tag above
3785 .struct_type => @panic("TODO"),
3775
37863776 .union_type => unreachable,
37873777 .opaque_type => unreachable,
37883778
......@@ -3793,6 +3783,7 @@ pub const Type = struct {
37933783 .ptr => unreachable,
37943784 .opt => unreachable,
37953785 .enum_tag => unreachable,
3786 .aggregate => unreachable,
37963787 },
37973788 };
37983789 }
......@@ -3996,17 +3987,6 @@ pub const Type = struct {
39963987 }
39973988 },
39983989
3999 .@"struct" => {
4000 const s = ty.castTag(.@"struct").?.data;
4001 assert(s.haveFieldTypes());
4002 for (s.fields.values()) |field| {
4003 if (field.is_comptime) continue;
4004 if ((try field.ty.onePossibleValue(mod)) != null) continue;
4005 return null;
4006 }
4007 return Value.empty_struct;
4008 },
4009
40103990 .tuple, .anon_struct => {
40113991 const tuple = ty.tupleFields();
40123992 for (tuple.values, 0..) |val, i| {
......@@ -4069,8 +4049,6 @@ pub const Type = struct {
40694049 return Value.empty_struct;
40704050 },
40714051
4072 .empty_struct => return Value.empty_struct,
4073
40744052 .array => {
40754053 if (ty.arrayLen(mod) == 0)
40764054 return Value.initTag(.empty_array);
......@@ -4158,7 +4136,23 @@ pub const Type = struct {
41584136 .generic_poison => unreachable,
41594137 .var_args_param => unreachable,
41604138 },
4161 .struct_type => @panic("TODO"),
4139 .struct_type => |struct_type| {
4140 if (mod.structPtrUnwrap(struct_type.index)) |s| {
4141 assert(s.haveFieldTypes());
4142 for (s.fields.values()) |field| {
4143 if (field.is_comptime) continue;
4144 if ((try field.ty.onePossibleValue(mod)) != null) continue;
4145 return null;
4146 }
4147 }
4148 // In this case the struct has no fields and therefore has one possible value.
4149 const empty = try mod.intern(.{ .aggregate = .{
4150 .ty = ty.ip_index,
4151 .fields = &.{},
4152 } });
4153 return empty.toValue();
4154 },
4155
41624156 .union_type => @panic("TODO"),
41634157 .opaque_type => return null,
41644158
......@@ -4169,6 +4163,7 @@ pub const Type = struct {
41694163 .ptr => unreachable,
41704164 .opt => unreachable,
41714165 .enum_tag => unreachable,
4166 .aggregate => unreachable,
41724167 },
41734168 };
41744169 }
......@@ -4177,12 +4172,11 @@ pub const Type = struct {
41774172 /// resolves field types rather than asserting they are already resolved.
41784173 /// TODO merge these implementations together with the "advanced" pattern seen
41794174 /// elsewhere in this file.
4180 pub fn comptimeOnly(ty: Type, mod: *const Module) bool {
4175 pub fn comptimeOnly(ty: Type, mod: *Module) bool {
41814176 return switch (ty.ip_index) {
41824177 .empty_struct_type => false,
41834178
41844179 .none => switch (ty.tag()) {
4185 .empty_struct,
41864180 .error_set,
41874181 .error_set_single,
41884182 .error_set_inferred,
......@@ -4222,20 +4216,6 @@ pub const Type = struct {
42224216 return false;
42234217 },
42244218
4225 .@"struct" => {
4226 const struct_obj = ty.castTag(.@"struct").?.data;
4227 switch (struct_obj.requires_comptime) {
4228 .wip, .unknown => {
4229 // Return false to avoid incorrect dependency loops.
4230 // This will be handled correctly once merged with
4231 // `Sema.typeRequiresComptime`.
4232 return false;
4233 },
4234 .no => return false,
4235 .yes => return true,
4236 }
4237 },
4238
42394219 .@"union", .union_safety_tagged, .union_tagged => {
42404220 const union_obj = ty.cast(Type.Payload.Union).?.data;
42414221 switch (union_obj.requires_comptime) {
......@@ -4326,7 +4306,21 @@ pub const Type = struct {
43264306
43274307 .var_args_param => unreachable,
43284308 },
4329 .struct_type => @panic("TODO"),
4309 .struct_type => |struct_type| {
4310 // A struct with no fields is not comptime-only.
4311 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
4312 switch (struct_obj.requires_comptime) {
4313 .wip, .unknown => {
4314 // Return false to avoid incorrect dependency loops.
4315 // This will be handled correctly once merged with
4316 // `Sema.typeRequiresComptime`.
4317 return false;
4318 },
4319 .no => return false,
4320 .yes => return true,
4321 }
4322 },
4323
43304324 .union_type => @panic("TODO"),
43314325 .opaque_type => false,
43324326
......@@ -4337,6 +4331,7 @@ pub const Type = struct {
43374331 .ptr => unreachable,
43384332 .opt => unreachable,
43394333 .enum_tag => unreachable,
4334 .aggregate => unreachable,
43404335 },
43414336 };
43424337 }
......@@ -4352,19 +4347,19 @@ pub const Type = struct {
43524347 };
43534348 }
43544349
4355 pub fn isIndexable(ty: Type, mod: *const Module) bool {
4350 pub fn isIndexable(ty: Type, mod: *Module) bool {
43564351 return switch (ty.zigTypeTag(mod)) {
43574352 .Array, .Vector => true,
43584353 .Pointer => switch (ty.ptrSize(mod)) {
43594354 .Slice, .Many, .C => true,
43604355 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
43614356 },
4362 .Struct => ty.isTuple(),
4357 .Struct => ty.isTuple(mod),
43634358 else => false,
43644359 };
43654360 }
43664361
4367 pub fn indexableHasLen(ty: Type, mod: *const Module) bool {
4362 pub fn indexableHasLen(ty: Type, mod: *Module) bool {
43684363 return switch (ty.zigTypeTag(mod)) {
43694364 .Array, .Vector => true,
43704365 .Pointer => switch (ty.ptrSize(mod)) {
......@@ -4372,7 +4367,7 @@ pub const Type = struct {
43724367 .Slice => true,
43734368 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
43744369 },
4375 .Struct => ty.isTuple(),
4370 .Struct => ty.isTuple(mod),
43764371 else => false,
43774372 };
43784373 }
......@@ -4381,10 +4376,8 @@ pub const Type = struct {
43814376 pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex {
43824377 return switch (ty.ip_index) {
43834378 .none => switch (ty.tag()) {
4384 .@"struct" => ty.castTag(.@"struct").?.data.namespace.toOptional(),
43854379 .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(),
43864380 .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(),
4387 .empty_struct => @panic("TODO"),
43884381 .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(),
43894382 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(),
43904383 .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(),
......@@ -4393,6 +4386,7 @@ pub const Type = struct {
43934386 },
43944387 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
43954388 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
4389 .struct_type => |struct_type| struct_type.namespace,
43964390 else => .none,
43974391 },
43984392 };
......@@ -4618,161 +4612,188 @@ pub const Type = struct {
46184612 }
46194613 }
46204614
4621 pub fn structFields(ty: Type) Module.Struct.Fields {
4622 return switch (ty.ip_index) {
4623 .empty_struct_type => .{},
4624 .none => switch (ty.tag()) {
4625 .empty_struct => .{},
4626 .@"struct" => {
4627 const struct_obj = ty.castTag(.@"struct").?.data;
4628 assert(struct_obj.haveFieldTypes());
4629 return struct_obj.fields;
4630 },
4631 else => unreachable,
4615 pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields {
4616 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4617 .struct_type => |struct_type| {
4618 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .{};
4619 assert(struct_obj.haveFieldTypes());
4620 return struct_obj.fields;
46324621 },
46334622 else => unreachable,
4634 };
4623 }
46354624 }
46364625
4637 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {
4638 switch (ty.tag()) {
4639 .@"struct" => {
4640 const struct_obj = ty.castTag(.@"struct").?.data;
4641 assert(struct_obj.haveFieldTypes());
4642 return struct_obj.fields.keys()[field_index];
4626 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 {
4627 switch (ty.ip_index) {
4628 .none => switch (ty.tag()) {
4629 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],
4630 else => unreachable,
4631 },
4632 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4633 .struct_type => |struct_type| {
4634 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4635 assert(struct_obj.haveFieldTypes());
4636 return struct_obj.fields.keys()[field_index];
4637 },
4638 else => unreachable,
46434639 },
4644 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],
4645 else => unreachable,
46464640 }
46474641 }
46484642
4649 pub fn structFieldCount(ty: Type) usize {
4643 pub fn structFieldCount(ty: Type, mod: *Module) usize {
46504644 return switch (ty.ip_index) {
46514645 .empty_struct_type => 0,
46524646 .none => switch (ty.tag()) {
4653 .@"struct" => {
4654 const struct_obj = ty.castTag(.@"struct").?.data;
4647 .tuple => ty.castTag(.tuple).?.data.types.len,
4648 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
4649 else => unreachable,
4650 },
4651 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4652 .struct_type => |struct_type| {
4653 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
46554654 assert(struct_obj.haveFieldTypes());
46564655 return struct_obj.fields.count();
46574656 },
4658 .empty_struct => 0,
4659 .tuple => ty.castTag(.tuple).?.data.types.len,
4660 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
46614657 else => unreachable,
46624658 },
4663 else => unreachable,
46644659 };
46654660 }
46664661
46674662 /// Supports structs and unions.
4668 pub fn structFieldType(ty: Type, index: usize) Type {
4669 switch (ty.tag()) {
4670 .@"struct" => {
4671 const struct_obj = ty.castTag(.@"struct").?.data;
4672 return struct_obj.fields.values()[index].ty;
4663 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
4664 return switch (ty.ip_index) {
4665 .none => switch (ty.tag()) {
4666 .@"union", .union_safety_tagged, .union_tagged => {
4667 const union_obj = ty.cast(Payload.Union).?.data;
4668 return union_obj.fields.values()[index].ty;
4669 },
4670 .tuple => return ty.castTag(.tuple).?.data.types[index],
4671 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
4672 else => unreachable,
46734673 },
4674 .@"union", .union_safety_tagged, .union_tagged => {
4675 const union_obj = ty.cast(Payload.Union).?.data;
4676 return union_obj.fields.values()[index].ty;
4674 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4675 .struct_type => |struct_type| {
4676 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4677 return struct_obj.fields.values()[index].ty;
4678 },
4679 else => unreachable,
46774680 },
4678 .tuple => return ty.castTag(.tuple).?.data.types[index],
4679 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
4680 else => unreachable,
4681 }
4681 };
46824682 }
46834683
46844684 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {
4685 switch (ty.tag()) {
4686 .@"struct" => {
4687 const struct_obj = ty.castTag(.@"struct").?.data;
4688 assert(struct_obj.layout != .Packed);
4689 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
4685 switch (ty.ip_index) {
4686 .none => switch (ty.tag()) {
4687 .@"union", .union_safety_tagged, .union_tagged => {
4688 const union_obj = ty.cast(Payload.Union).?.data;
4689 return union_obj.fields.values()[index].normalAlignment(mod);
4690 },
4691 .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod),
4692 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod),
4693 else => unreachable,
46904694 },
4691 .@"union", .union_safety_tagged, .union_tagged => {
4692 const union_obj = ty.cast(Payload.Union).?.data;
4693 return union_obj.fields.values()[index].normalAlignment(mod);
4695 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4696 .struct_type => |struct_type| {
4697 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4698 assert(struct_obj.layout != .Packed);
4699 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
4700 },
4701 else => unreachable,
46944702 },
4695 .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod),
4696 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod),
4697 else => unreachable,
46984703 }
46994704 }
47004705
4701 pub fn structFieldDefaultValue(ty: Type, index: usize) Value {
4702 switch (ty.tag()) {
4703 .@"struct" => {
4704 const struct_obj = ty.castTag(.@"struct").?.data;
4705 return struct_obj.fields.values()[index].default_val;
4706 },
4707 .tuple => {
4708 const tuple = ty.castTag(.tuple).?.data;
4709 return tuple.values[index];
4706 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
4707 switch (ty.ip_index) {
4708 .none => switch (ty.tag()) {
4709 .tuple => {
4710 const tuple = ty.castTag(.tuple).?.data;
4711 return tuple.values[index];
4712 },
4713 .anon_struct => {
4714 const struct_obj = ty.castTag(.anon_struct).?.data;
4715 return struct_obj.values[index];
4716 },
4717 else => unreachable,
47104718 },
4711 .anon_struct => {
4712 const struct_obj = ty.castTag(.anon_struct).?.data;
4713 return struct_obj.values[index];
4719 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4720 .struct_type => |struct_type| {
4721 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4722 return struct_obj.fields.values()[index].default_val;
4723 },
4724 else => unreachable,
47144725 },
4715 else => unreachable,
47164726 }
47174727 }
47184728
47194729 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
4720 switch (ty.tag()) {
4721 .@"struct" => {
4722 const struct_obj = ty.castTag(.@"struct").?.data;
4723 const field = struct_obj.fields.values()[index];
4724 if (field.is_comptime) {
4725 return field.default_val;
4726 } else {
4727 return field.ty.onePossibleValue(mod);
4728 }
4729 },
4730 .tuple => {
4731 const tuple = ty.castTag(.tuple).?.data;
4732 const val = tuple.values[index];
4733 if (val.ip_index == .unreachable_value) {
4734 return tuple.types[index].onePossibleValue(mod);
4735 } else {
4736 return val;
4737 }
4730 switch (ty.ip_index) {
4731 .none => switch (ty.tag()) {
4732 .tuple => {
4733 const tuple = ty.castTag(.tuple).?.data;
4734 const val = tuple.values[index];
4735 if (val.ip_index == .unreachable_value) {
4736 return tuple.types[index].onePossibleValue(mod);
4737 } else {
4738 return val;
4739 }
4740 },
4741 .anon_struct => {
4742 const anon_struct = ty.castTag(.anon_struct).?.data;
4743 const val = anon_struct.values[index];
4744 if (val.ip_index == .unreachable_value) {
4745 return anon_struct.types[index].onePossibleValue(mod);
4746 } else {
4747 return val;
4748 }
4749 },
4750 else => unreachable,
47384751 },
4739 .anon_struct => {
4740 const anon_struct = ty.castTag(.anon_struct).?.data;
4741 const val = anon_struct.values[index];
4742 if (val.ip_index == .unreachable_value) {
4743 return anon_struct.types[index].onePossibleValue(mod);
4744 } else {
4745 return val;
4746 }
4752 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4753 .struct_type => |struct_type| {
4754 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4755 const field = struct_obj.fields.values()[index];
4756 if (field.is_comptime) {
4757 return field.default_val;
4758 } else {
4759 return field.ty.onePossibleValue(mod);
4760 }
4761 },
4762 else => unreachable,
47474763 },
4748 else => unreachable,
47494764 }
47504765 }
47514766
4752 pub fn structFieldIsComptime(ty: Type, index: usize) bool {
4753 switch (ty.tag()) {
4754 .@"struct" => {
4755 const struct_obj = ty.castTag(.@"struct").?.data;
4756 if (struct_obj.layout == .Packed) return false;
4757 const field = struct_obj.fields.values()[index];
4758 return field.is_comptime;
4759 },
4760 .tuple => {
4761 const tuple = ty.castTag(.tuple).?.data;
4762 const val = tuple.values[index];
4763 return val.ip_index != .unreachable_value;
4767 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
4768 switch (ty.ip_index) {
4769 .none => switch (ty.tag()) {
4770 .tuple => {
4771 const tuple = ty.castTag(.tuple).?.data;
4772 const val = tuple.values[index];
4773 return val.ip_index != .unreachable_value;
4774 },
4775 .anon_struct => {
4776 const anon_struct = ty.castTag(.anon_struct).?.data;
4777 const val = anon_struct.values[index];
4778 return val.ip_index != .unreachable_value;
4779 },
4780 else => unreachable,
47644781 },
4765 .anon_struct => {
4766 const anon_struct = ty.castTag(.anon_struct).?.data;
4767 const val = anon_struct.values[index];
4768 return val.ip_index != .unreachable_value;
4782 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4783 .struct_type => |struct_type| {
4784 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4785 if (struct_obj.layout == .Packed) return false;
4786 const field = struct_obj.fields.values()[index];
4787 return field.is_comptime;
4788 },
4789 else => unreachable,
47694790 },
4770 else => unreachable,
47714791 }
47724792 }
47734793
47744794 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
4775 const struct_obj = ty.castTag(.@"struct").?.data;
4795 const struct_type = mod.intern_pool.indexToKey(ty.ip_index).struct_type;
4796 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
47764797 assert(struct_obj.layout == .Packed);
47774798 comptime assert(Type.packed_struct_layout_version == 2);
47784799
......@@ -4833,7 +4854,8 @@ pub const Type = struct {
48334854 /// Get an iterator that iterates over all the struct field, returning the field and
48344855 /// offset of that field. Asserts that the type is a non-packed struct.
48354856 pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator {
4836 const struct_obj = ty.castTag(.@"struct").?.data;
4857 const struct_type = mod.intern_pool.indexToKey(ty.ip_index).struct_type;
4858 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
48374859 assert(struct_obj.haveLayout());
48384860 assert(struct_obj.layout != .Packed);
48394861 return .{ .struct_obj = struct_obj, .module = mod };
......@@ -4841,57 +4863,62 @@ pub const Type = struct {
48414863
48424864 /// Supports structs and unions.
48434865 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
4844 switch (ty.tag()) {
4845 .@"struct" => {
4846 const struct_obj = ty.castTag(.@"struct").?.data;
4847 assert(struct_obj.haveLayout());
4848 assert(struct_obj.layout != .Packed);
4849 var it = ty.iterateStructOffsets(mod);
4850 while (it.next()) |field_offset| {
4851 if (index == field_offset.field)
4852 return field_offset.offset;
4853 }
4854
4855 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4856 },
4866 switch (ty.ip_index) {
4867 .none => switch (ty.tag()) {
4868 .tuple, .anon_struct => {
4869 const tuple = ty.tupleFields();
48574870
4858 .tuple, .anon_struct => {
4859 const tuple = ty.tupleFields();
4871 var offset: u64 = 0;
4872 var big_align: u32 = 0;
48604873
4861 var offset: u64 = 0;
4862 var big_align: u32 = 0;
4874 for (tuple.types, 0..) |field_ty, i| {
4875 const field_val = tuple.values[i];
4876 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) {
4877 // comptime field
4878 if (i == index) return offset;
4879 continue;
4880 }
48634881
4864 for (tuple.types, 0..) |field_ty, i| {
4865 const field_val = tuple.values[i];
4866 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) {
4867 // comptime field
4882 const field_align = field_ty.abiAlignment(mod);
4883 big_align = @max(big_align, field_align);
4884 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
48684885 if (i == index) return offset;
4869 continue;
4886 offset += field_ty.abiSize(mod);
48704887 }
4888 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
4889 return offset;
4890 },
48714891
4872 const field_align = field_ty.abiAlignment(mod);
4873 big_align = @max(big_align, field_align);
4874 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
4875 if (i == index) return offset;
4876 offset += field_ty.abiSize(mod);
4877 }
4878 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
4879 return offset;
4892 .@"union" => return 0,
4893 .union_safety_tagged, .union_tagged => {
4894 const union_obj = ty.cast(Payload.Union).?.data;
4895 const layout = union_obj.getLayout(mod, true);
4896 if (layout.tag_align >= layout.payload_align) {
4897 // {Tag, Payload}
4898 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
4899 } else {
4900 // {Payload, Tag}
4901 return 0;
4902 }
4903 },
4904 else => unreachable,
48804905 },
4906 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4907 .struct_type => |struct_type| {
4908 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4909 assert(struct_obj.haveLayout());
4910 assert(struct_obj.layout != .Packed);
4911 var it = ty.iterateStructOffsets(mod);
4912 while (it.next()) |field_offset| {
4913 if (index == field_offset.field)
4914 return field_offset.offset;
4915 }
48814916
4882 .@"union" => return 0,
4883 .union_safety_tagged, .union_tagged => {
4884 const union_obj = ty.cast(Payload.Union).?.data;
4885 const layout = union_obj.getLayout(mod, true);
4886 if (layout.tag_align >= layout.payload_align) {
4887 // {Tag, Payload}
4888 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
4889 } else {
4890 // {Payload, Tag}
4891 return 0;
4892 }
4917 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4918 },
4919
4920 else => unreachable,
48934921 },
4894 else => unreachable,
48954922 }
48964923 }
48974924
......@@ -4901,6 +4928,7 @@ pub const Type = struct {
49014928
49024929 pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {
49034930 switch (ty.ip_index) {
4931 .empty_struct_type => return null,
49044932 .none => switch (ty.tag()) {
49054933 .enum_full, .enum_nonexhaustive => {
49064934 const enum_full = ty.cast(Payload.EnumFull).?.data;
......@@ -4914,10 +4942,6 @@ pub const Type = struct {
49144942 const enum_simple = ty.castTag(.enum_simple).?.data;
49154943 return enum_simple.srcLoc(mod);
49164944 },
4917 .@"struct" => {
4918 const struct_obj = ty.castTag(.@"struct").?.data;
4919 return struct_obj.srcLoc(mod);
4920 },
49214945 .error_set => {
49224946 const error_set = ty.castTag(.error_set).?.data;
49234947 return error_set.srcLoc(mod);
......@@ -4930,7 +4954,10 @@ pub const Type = struct {
49304954 else => return null,
49314955 },
49324956 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4933 .struct_type => @panic("TODO"),
4957 .struct_type => |struct_type| {
4958 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4959 return struct_obj.srcLoc(mod);
4960 },
49344961 .union_type => @panic("TODO"),
49354962 .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type),
49364963 else => null,
......@@ -4954,10 +4981,6 @@ pub const Type = struct {
49544981 const enum_simple = ty.castTag(.enum_simple).?.data;
49554982 return enum_simple.owner_decl;
49564983 },
4957 .@"struct" => {
4958 const struct_obj = ty.castTag(.@"struct").?.data;
4959 return struct_obj.owner_decl;
4960 },
49614984 .error_set => {
49624985 const error_set = ty.castTag(.error_set).?.data;
49634986 return error_set.owner_decl;
......@@ -4970,7 +4993,10 @@ pub const Type = struct {
49704993 else => return null,
49714994 },
49724995 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4973 .struct_type => @panic("TODO"),
4996 .struct_type => |struct_type| {
4997 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return null;
4998 return struct_obj.owner_decl;
4999 },
49745000 .union_type => @panic("TODO"),
49755001 .opaque_type => |opaque_type| opaque_type.decl,
49765002 else => null,
......@@ -5013,8 +5039,6 @@ pub const Type = struct {
50135039 /// The type is the inferred error set of a specific function.
50145040 error_set_inferred,
50155041 error_set_merged,
5016 empty_struct,
5017 @"struct",
50185042 @"union",
50195043 union_safety_tagged,
50205044 union_tagged,
......@@ -5046,12 +5070,10 @@ pub const Type = struct {
50465070 .function => Payload.Function,
50475071 .error_union => Payload.ErrorUnion,
50485072 .error_set_single => Payload.Name,
5049 .@"struct" => Payload.Struct,
50505073 .@"union", .union_safety_tagged, .union_tagged => Payload.Union,
50515074 .enum_full, .enum_nonexhaustive => Payload.EnumFull,
50525075 .enum_simple => Payload.EnumSimple,
50535076 .enum_numbered => Payload.EnumNumbered,
5054 .empty_struct => Payload.ContainerScope,
50555077 .tuple => Payload.Tuple,
50565078 .anon_struct => Payload.AnonStruct,
50575079 };
......@@ -5082,15 +5104,19 @@ pub const Type = struct {
50825104 }
50835105 };
50845106
5085 pub fn isTuple(ty: Type) bool {
5107 pub fn isTuple(ty: Type, mod: *Module) bool {
50865108 return switch (ty.ip_index) {
5087 .empty_struct_type => true,
50885109 .none => switch (ty.tag()) {
50895110 .tuple => true,
5090 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
50915111 else => false,
50925112 },
5093 else => false, // TODO struct
5113 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
5114 .struct_type => |struct_type| {
5115 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
5116 return struct_obj.is_tuple;
5117 },
5118 else => false,
5119 },
50945120 };
50955121 }
50965122
......@@ -5101,36 +5127,41 @@ pub const Type = struct {
51015127 .anon_struct => true,
51025128 else => false,
51035129 },
5104 else => false, // TODO struct
5130 else => false,
51055131 };
51065132 }
51075133
5108 pub fn isTupleOrAnonStruct(ty: Type) bool {
5134 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
51095135 return switch (ty.ip_index) {
51105136 .empty_struct_type => true,
51115137 .none => switch (ty.tag()) {
51125138 .tuple, .anon_struct => true,
5113 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
51145139 else => false,
51155140 },
5116 else => false, // TODO struct
5141 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
5142 .struct_type => |struct_type| {
5143 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
5144 return struct_obj.is_tuple;
5145 },
5146 else => false,
5147 },
51175148 };
51185149 }
51195150
51205151 pub fn isSimpleTuple(ty: Type) bool {
51215152 return switch (ty.ip_index) {
5122 .empty_struct => true,
5153 .empty_struct_type => true,
51235154 .none => switch (ty.tag()) {
51245155 .tuple => true,
51255156 else => false,
51265157 },
5127 else => false, // TODO
5158 else => false,
51285159 };
51295160 }
51305161
51315162 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {
51325163 return switch (ty.ip_index) {
5133 .empty_struct => true,
5164 .empty_struct_type => true,
51345165 .none => switch (ty.tag()) {
51355166 .tuple, .anon_struct => true,
51365167 else => false,
......@@ -5142,7 +5173,7 @@ pub const Type = struct {
51425173 // Only allowed for simple tuple types
51435174 pub fn tupleFields(ty: Type) Payload.Tuple.Data {
51445175 return switch (ty.ip_index) {
5145 .empty_struct => .{ .types = &.{}, .values = &.{} },
5176 .empty_struct_type => .{ .types = &.{}, .values = &.{} },
51465177 .none => switch (ty.tag()) {
51475178 .tuple => ty.castTag(.tuple).?.data,
51485179 .anon_struct => .{
......@@ -5319,18 +5350,6 @@ pub const Type = struct {
53195350 data: []const u8,
53205351 };
53215352
5322 /// Mostly used for namespace like structs with zero fields.
5323 /// Most commonly used for files.
5324 pub const ContainerScope = struct {
5325 base: Payload,
5326 data: *Module.Namespace,
5327 };
5328
5329 pub const Struct = struct {
5330 base: Payload = .{ .tag = .@"struct" },
5331 data: *Module.Struct,
5332 };
5333
53345353 pub const Tuple = struct {
53355354 base: Payload = .{ .tag = .tuple },
53365355 data: Data,
src/value.zig+19-26
......@@ -996,10 +996,10 @@ pub const Value = struct {
996996 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
997997 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
998998 },
999 .Struct => switch (ty.containerLayout()) {
999 .Struct => switch (ty.containerLayout(mod)) {
10001000 .Auto => return error.IllDefinedMemoryLayout,
10011001 .Extern => {
1002 const fields = ty.structFields().values();
1002 const fields = ty.structFields(mod).values();
10031003 const field_vals = val.castTag(.aggregate).?.data;
10041004 for (fields, 0..) |field, i| {
10051005 const off = @intCast(usize, ty.structFieldOffset(i, mod));
......@@ -1017,7 +1017,7 @@ pub const Value = struct {
10171017 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
10181018 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
10191019 },
1020 .Union => switch (ty.containerLayout()) {
1020 .Union => switch (ty.containerLayout(mod)) {
10211021 .Auto => return error.IllDefinedMemoryLayout,
10221022 .Extern => return error.Unimplemented,
10231023 .Packed => {
......@@ -1119,12 +1119,12 @@ pub const Value = struct {
11191119 bits += elem_bit_size;
11201120 }
11211121 },
1122 .Struct => switch (ty.containerLayout()) {
1122 .Struct => switch (ty.containerLayout(mod)) {
11231123 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
11241124 .Extern => unreachable, // Handled in non-packed writeToMemory
11251125 .Packed => {
11261126 var bits: u16 = 0;
1127 const fields = ty.structFields().values();
1127 const fields = ty.structFields(mod).values();
11281128 const field_vals = val.castTag(.aggregate).?.data;
11291129 for (fields, 0..) |field, i| {
11301130 const field_bits = @intCast(u16, field.ty.bitSize(mod));
......@@ -1133,7 +1133,7 @@ pub const Value = struct {
11331133 }
11341134 },
11351135 },
1136 .Union => switch (ty.containerLayout()) {
1136 .Union => switch (ty.containerLayout(mod)) {
11371137 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
11381138 .Extern => unreachable, // Handled in non-packed writeToMemory
11391139 .Packed => {
......@@ -1236,14 +1236,14 @@ pub const Value = struct {
12361236 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
12371237 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);
12381238 },
1239 .Struct => switch (ty.containerLayout()) {
1239 .Struct => switch (ty.containerLayout(mod)) {
12401240 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
12411241 .Extern => {
1242 const fields = ty.structFields().values();
1242 const fields = ty.structFields(mod).values();
12431243 const field_vals = try arena.alloc(Value, fields.len);
12441244 for (fields, 0..) |field, i| {
12451245 const off = @intCast(usize, ty.structFieldOffset(i, mod));
1246 const sz = @intCast(usize, ty.structFieldType(i).abiSize(mod));
1246 const sz = @intCast(usize, ty.structFieldType(i, mod).abiSize(mod));
12471247 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena);
12481248 }
12491249 return Tag.aggregate.create(arena, field_vals);
......@@ -1346,12 +1346,12 @@ pub const Value = struct {
13461346 }
13471347 return Tag.aggregate.create(arena, elems);
13481348 },
1349 .Struct => switch (ty.containerLayout()) {
1349 .Struct => switch (ty.containerLayout(mod)) {
13501350 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
13511351 .Extern => unreachable, // Handled by non-packed readFromMemory
13521352 .Packed => {
13531353 var bits: u16 = 0;
1354 const fields = ty.structFields().values();
1354 const fields = ty.structFields(mod).values();
13551355 const field_vals = try arena.alloc(Value, fields.len);
13561356 for (fields, 0..) |field, i| {
13571357 const field_bits = @intCast(u16, field.ty.bitSize(mod));
......@@ -1996,7 +1996,7 @@ pub const Value = struct {
19961996 }
19971997
19981998 if (ty.zigTypeTag(mod) == .Struct) {
1999 const fields = ty.structFields().values();
1999 const fields = ty.structFields(mod).values();
20002000 assert(fields.len == a_field_vals.len);
20012001 for (fields, 0..) |field, i| {
20022002 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
......@@ -2019,7 +2019,7 @@ pub const Value = struct {
20192019 .@"union" => {
20202020 const a_union = a.castTag(.@"union").?.data;
20212021 const b_union = b.castTag(.@"union").?.data;
2022 switch (ty.containerLayout()) {
2022 switch (ty.containerLayout(mod)) {
20232023 .Packed, .Extern => {
20242024 const tag_ty = ty.unionTagTypeHypothetical();
20252025 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {
......@@ -2252,7 +2252,7 @@ pub const Value = struct {
22522252 .aggregate => {
22532253 const field_values = val.castTag(.aggregate).?.data;
22542254 for (field_values, 0..) |field_val, i| {
2255 const field_ty = ty.structFieldType(i);
2255 const field_ty = ty.structFieldType(i, mod);
22562256 field_val.hash(field_ty, hasher, mod);
22572257 }
22582258 },
......@@ -2623,7 +2623,7 @@ pub const Value = struct {
26232623 const data = val.castTag(.field_ptr).?.data;
26242624 if (data.container_ptr.pointerDecl()) |decl_index| {
26252625 const container_decl = mod.declPtr(decl_index);
2626 const field_type = data.container_ty.structFieldType(data.field_index);
2626 const field_type = data.container_ty.structFieldType(data.field_index, mod);
26272627 const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index);
26282628 return field_val.elemValue(mod, index);
26292629 } else unreachable;
......@@ -2758,16 +2758,6 @@ pub const Value = struct {
27582758 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
27592759 switch (val.ip_index) {
27602760 .undef => return Value.undef,
2761 .empty_struct => {
2762 if (ty.isSimpleTupleOrAnonStruct()) {
2763 const tuple = ty.tupleFields();
2764 return tuple.values[index];
2765 }
2766 if (try ty.structFieldValueComptime(mod, index)) |some| {
2767 return some;
2768 }
2769 unreachable;
2770 },
27712761
27722762 .none => switch (val.tag()) {
27732763 .aggregate => {
......@@ -2784,7 +2774,10 @@ pub const Value = struct {
27842774
27852775 else => unreachable,
27862776 },
2787 else => unreachable,
2777 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2778 .aggregate => |aggregate| aggregate.fields[index].toValue(),
2779 else => unreachable,
2780 },
27882781 }
27892782 }
27902783