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 @@...@@ -1,5 +1,10 @@
1//! All interned objects have both a value and a type.1//! 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.
3map: std.AutoArrayHashMapUnmanaged(void, void) = .{},8map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
4items: std.MultiArrayList(Item) = .{},9items: std.MultiArrayList(Item) = .{},
5extra: std.ArrayListUnmanaged(u32) = .{},10extra: std.ArrayListUnmanaged(u32) = .{},
...@@ -9,6 +14,13 @@ extra: std.ArrayListUnmanaged(u32) = .{},...@@ -9,6 +14,13 @@ extra: std.ArrayListUnmanaged(u32) = .{},
9/// violate the above mechanism.14/// violate the above mechanism.
10limbs: std.ArrayListUnmanaged(u64) = .{},15limbs: 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
12const std = @import("std");24const std = @import("std");
13const Allocator = std.mem.Allocator;25const Allocator = std.mem.Allocator;
14const assert = std.debug.assert;26const assert = std.debug.assert;
...@@ -17,8 +29,7 @@ const BigIntMutable = std.math.big.int.Mutable;...@@ -17,8 +29,7 @@ const BigIntMutable = std.math.big.int.Mutable;
17const Limb = std.math.big.Limb;29const Limb = std.math.big.Limb;
1830
19const InternPool = @This();31const InternPool = @This();
20const DeclIndex = @import("Module.zig").Decl.Index;32const Module = @import("Module.zig");
21const NamespaceIndex = @import("Module.zig").Namespace.Index;
2233
23const KeyAdapter = struct {34const KeyAdapter = struct {
24 intern_pool: *const InternPool,35 intern_pool: *const InternPool,
...@@ -45,11 +56,20 @@ pub const Key = union(enum) {...@@ -45,11 +56,20 @@ pub const Key = union(enum) {
45 payload_type: Index,56 payload_type: Index,
46 },57 },
47 simple_type: SimpleType,58 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
48 simple_value: SimpleValue,68 simple_value: SimpleValue,
49 extern_func: struct {69 extern_func: struct {
50 ty: Index,70 ty: Index,
51 /// The Decl that corresponds to the function itself.71 /// The Decl that corresponds to the function itself.
52 decl: DeclIndex,72 decl: Module.Decl.Index,
53 /// Library name if specified.73 /// Library name if specified.
54 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.74 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
55 /// Index into the string table bytes.75 /// Index into the string table bytes.
...@@ -62,13 +82,11 @@ pub const Key = union(enum) {...@@ -62,13 +82,11 @@ pub const Key = union(enum) {
62 ty: Index,82 ty: Index,
63 tag: BigIntConst,83 tag: BigIntConst,
64 },84 },
65 struct_type: StructType,85 /// An instance of a struct, array, or vector.
66 opaque_type: OpaqueType,86 /// Each element/field stored as an `Index`.
6787 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
68 union_type: struct {88 /// so the slice length will be one more than the type's array length.
69 fields_len: u32,89 aggregate: Aggregate,
70 // TODO move Module.Union data to InternPool
71 },
7290
73 pub const IntType = std.builtin.Type.Int;91 pub const IntType = std.builtin.Type.Int;
7492
...@@ -113,16 +131,27 @@ pub const Key = union(enum) {...@@ -113,16 +131,27 @@ pub const Key = union(enum) {
113 child: Index,131 child: Index,
114 };132 };
115133
116 pub const StructType = struct {
117 fields_len: u32,
118 // TODO move Module.Struct data to InternPool
119 };
120
121 pub const OpaqueType = struct {134 pub const OpaqueType = struct {
122 /// The Decl that corresponds to the opaque itself.135 /// The Decl that corresponds to the opaque itself.
123 decl: DeclIndex,136 decl: Module.Decl.Index,
124 /// Represents the declarations inside this opaque.137 /// 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,
126 };155 };
127156
128 pub const Int = struct {157 pub const Int = struct {
...@@ -156,18 +185,24 @@ pub const Key = union(enum) {...@@ -156,18 +185,24 @@ pub const Key = union(enum) {
156 addr: Addr,185 addr: Addr,
157186
158 pub const Addr = union(enum) {187 pub const Addr = union(enum) {
159 decl: DeclIndex,188 decl: Module.Decl.Index,
160 int: Index,189 int: Index,
161 };190 };
162 };191 };
163192
164 /// `null` is represented by the `val` field being `none`.193 /// `null` is represented by the `val` field being `none`.
165 pub const Opt = struct {194 pub const Opt = struct {
195 /// This is the optional type; not the payload type.
166 ty: Index,196 ty: Index,
167 /// This could be `none`, indicating the optional is `null`.197 /// This could be `none`, indicating the optional is `null`.
168 val: Index,198 val: Index,
169 };199 };
170200
201 pub const Aggregate = struct {
202 ty: Index,
203 fields: []const Index,
204 };
205
171 pub fn hash32(key: Key) u32 {206 pub fn hash32(key: Key) u32 {
172 return @truncate(u32, key.hash64());207 return @truncate(u32, key.hash64());
173 }208 }
...@@ -193,8 +228,15 @@ pub const Key = union(enum) {...@@ -193,8 +228,15 @@ pub const Key = union(enum) {
193 .simple_value,228 .simple_value,
194 .extern_func,229 .extern_func,
195 .opt,230 .opt,
231 .struct_type,
196 => |info| std.hash.autoHash(hasher, info),232 => |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
198 .int => |int| {240 .int => |int| {
199 // Canonicalize all integers by converting them to BigIntConst.241 // Canonicalize all integers by converting them to BigIntConst.
200 var buffer: Key.Int.Storage.BigIntSpace = undefined;242 var buffer: Key.Int.Storage.BigIntSpace = undefined;
...@@ -221,16 +263,10 @@ pub const Key = union(enum) {...@@ -221,16 +263,10 @@ pub const Key = union(enum) {
221 for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb);263 for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb);
222 },264 },
223265
224 .struct_type => |struct_type| {266 .aggregate => |aggregate| {
225 if (struct_type.fields_len != 0) {267 std.hash.autoHash(hasher, aggregate.ty);
226 @panic("TODO");268 for (aggregate.fields) |field| std.hash.autoHash(hasher, field);
227 }
228 },
229 .union_type => |union_type| {
230 _ = union_type;
231 @panic("TODO");
232 },269 },
233 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
234 }270 }
235 }271 }
236272
...@@ -280,6 +316,10 @@ pub const Key = union(enum) {...@@ -280,6 +316,10 @@ pub const Key = union(enum) {
280 const b_info = b.opt;316 const b_info = b.opt;
281 return std.meta.eql(a_info, b_info);317 return std.meta.eql(a_info, b_info);
282 },318 },
319 .struct_type => |a_info| {
320 const b_info = b.struct_type;
321 return std.meta.eql(a_info, b_info);
322 },
283323
284 .ptr => |a_info| {324 .ptr => |a_info| {
285 const b_info = b.ptr;325 const b_info = b.ptr;
...@@ -331,16 +371,6 @@ pub const Key = union(enum) {...@@ -331,16 +371,6 @@ pub const Key = union(enum) {
331 @panic("TODO");371 @panic("TODO");
332 },372 },
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
344 .union_type => |a_info| {374 .union_type => |a_info| {
345 const b_info = b.union_type;375 const b_info = b.union_type;
346376
...@@ -353,6 +383,11 @@ pub const Key = union(enum) {...@@ -353,6 +383,11 @@ pub const Key = union(enum) {
353 const b_info = b.opaque_type;383 const b_info = b.opaque_type;
354 return a_info.decl == b_info.decl;384 return a_info.decl == b_info.decl;
355 },385 },
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 },
356 }391 }
357 }392 }
358393
...@@ -375,6 +410,7 @@ pub const Key = union(enum) {...@@ -375,6 +410,7 @@ pub const Key = union(enum) {
375 .opt,410 .opt,
376 .extern_func,411 .extern_func,
377 .enum_tag,412 .enum_tag,
413 .aggregate,
378 => |x| return x.ty,414 => |x| return x.ty,
379415
380 .simple_value => |s| switch (s) {416 .simple_value => |s| switch (s) {
...@@ -471,6 +507,7 @@ pub const Index = enum(u32) {...@@ -471,6 +507,7 @@ pub const Index = enum(u32) {
471 anyerror_void_error_union_type,507 anyerror_void_error_union_type,
472 generic_poison_type,508 generic_poison_type,
473 var_args_param_type,509 var_args_param_type,
510 /// `@TypeOf(.{})`
474 empty_struct_type,511 empty_struct_type,
475512
476 /// `undefined` (untyped)513 /// `undefined` (untyped)
...@@ -691,7 +728,8 @@ pub const static_keys = [_]Key{...@@ -691,7 +728,8 @@ pub const static_keys = [_]Key{
691728
692 // empty_struct_type729 // empty_struct_type
693 .{ .struct_type = .{730 .{ .struct_type = .{
694 .fields_len = 0,731 .namespace = .none,
732 .index = .none,
695 } },733 } },
696734
697 .{ .simple_value = .undefined },735 .{ .simple_value = .undefined },
...@@ -792,16 +830,18 @@ pub const Tag = enum(u8) {...@@ -792,16 +830,18 @@ pub const Tag = enum(u8) {
792 /// An opaque type.830 /// An opaque type.
793 /// data is index of Key.OpaqueType in extra.831 /// data is index of Key.OpaqueType in extra.
794 type_opaque,832 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
796 /// A value that can be represented with only an enum tag.842 /// A value that can be represented with only an enum tag.
797 /// data is SimpleValue enum value.843 /// data is SimpleValue enum value.
798 simple_value,844 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,
805 /// A pointer to an integer value.845 /// A pointer to an integer value.
806 /// data is extra index of PtrInt, which contains the type and address.846 /// data is extra index of PtrInt, which contains the type and address.
807 /// Only pointer types are allowed to have this encoding. Optional types must use847 /// Only pointer types are allowed to have this encoding. Optional types must use
...@@ -809,6 +849,8 @@ pub const Tag = enum(u8) {...@@ -809,6 +849,8 @@ pub const Tag = enum(u8) {
809 ptr_int,849 ptr_int,
810 /// An optional value that is non-null.850 /// An optional value that is non-null.
811 /// data is Index of the payload value.851 /// 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.
812 opt_payload,854 opt_payload,
813 /// An optional value that is null.855 /// An optional value that is null.
814 /// data is Index of the payload type.856 /// data is Index of the payload type.
...@@ -859,6 +901,13 @@ pub const Tag = enum(u8) {...@@ -859,6 +901,13 @@ pub const Tag = enum(u8) {
859 extern_func,901 extern_func,
860 /// A regular function.902 /// A regular function.
861 func,903 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,
862};911};
863912
864/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to913/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to
...@@ -912,9 +961,12 @@ pub const SimpleType = enum(u32) {...@@ -912,9 +961,12 @@ pub const SimpleType = enum(u32) {
912};961};
913962
914pub const SimpleValue = enum(u32) {963pub const SimpleValue = enum(u32) {
964 /// This is untyped `undefined`.
915 undefined,965 undefined,
916 void,966 void,
967 /// This is untyped `null`.
917 null,968 null,
969 /// This is the untyped empty struct literal: `.{}`
918 empty_struct,970 empty_struct,
919 true,971 true,
920 false,972 false,
...@@ -923,12 +975,6 @@ pub const SimpleValue = enum(u32) {...@@ -923,12 +975,6 @@ pub const SimpleValue = enum(u32) {
923 generic_poison,975 generic_poison,
924};976};
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
932pub const Pointer = struct {978pub const Pointer = struct {
933 child: Index,979 child: Index,
934 sentinel: Index,980 sentinel: Index,
...@@ -1005,7 +1051,7 @@ pub const ErrorUnion = struct {...@@ -1005,7 +1051,7 @@ pub const ErrorUnion = struct {
1005/// 0. field name: null-terminated string index for each fields_len; declaration order1051/// 0. field name: null-terminated string index for each fields_len; declaration order
1006pub const EnumSimple = struct {1052pub const EnumSimple = struct {
1007 /// The Decl that corresponds to the enum itself.1053 /// The Decl that corresponds to the enum itself.
1008 decl: DeclIndex,1054 decl: Module.Decl.Index,
1009 /// An integer type which is used for the numerical value of the enum. This1055 /// An integer type which is used for the numerical value of the enum. This
1010 /// is inferred by Zig to be the smallest power of two unsigned int that1056 /// is inferred by Zig to be the smallest power of two unsigned int that
1011 /// fits the number of fields. It is stored here to avoid unnecessary1057 /// fits the number of fields. It is stored here to avoid unnecessary
...@@ -1091,6 +1137,10 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -1091,6 +1137,10 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
1091 ip.items.deinit(gpa);1137 ip.items.deinit(gpa);
1092 ip.extra.deinit(gpa);1138 ip.extra.deinit(gpa);
1093 ip.limbs.deinit(gpa);1139 ip.limbs.deinit(gpa);
1140
1141 ip.structs_free_list.deinit(gpa);
1142 ip.allocated_structs.deinit(gpa);
1143
1094 ip.* = undefined;1144 ip.* = undefined;
1095}1145}
10961146
...@@ -1167,20 +1217,38 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1167,20 +1217,38 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1167 .type_enum_simple => @panic("TODO"),1217 .type_enum_simple => @panic("TODO"),
11681218
1169 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },1219 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
11701220 .type_struct => {
1171 .simple_internal => switch (@intToEnum(SimpleInternal, data)) {1221 const struct_index = @intToEnum(Module.Struct.OptionalIndex, data);
1172 .type_empty_struct => .{ .struct_type = .{1222 const namespace = if (struct_index.unwrap()) |i|
1173 .fields_len = 0,1223 ip.structPtrConst(i).namespace.toOptional()
1174 } },1224 else
1225 .none;
1226 return .{ .struct_type = .{
1227 .index = struct_index,
1228 .namespace = namespace,
1229 } };
1175 },1230 },
1231 .type_struct_ns => .{ .struct_type = .{
1232 .index = .none,
1233 .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(),
1234 } },
1235
1176 .opt_null => .{ .opt = .{1236 .opt_null => .{ .opt = .{
1177 .ty = @intToEnum(Index, data),1237 .ty = @intToEnum(Index, data),
1178 .val = .none,1238 .val = .none,
1179 } },1239 } },
1180 .opt_payload => .{ .opt = .{1240 .opt_payload => {
1181 .ty = indexToKey(ip, @intToEnum(Index, data)).typeOf(),1241 const payload_val = @intToEnum(Index, data);
1182 .val = @intToEnum(Index, data),1242 // The existence of `opt_payload` guarantees that the optional type will be
1183 } },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 },
1184 .ptr_int => {1252 .ptr_int => {
1185 const info = ip.extraData(PtrInt, data);1253 const info = ip.extraData(PtrInt, data);
1186 return .{ .ptr = .{1254 return .{ .ptr = .{
...@@ -1225,6 +1293,16 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1225,6 +1293,16 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1225 .float_f128 => @panic("TODO"),1293 .float_f128 => @panic("TODO"),
1226 .extern_func => @panic("TODO"),1294 .extern_func => @panic("TODO"),
1227 .func => @panic("TODO"),1295 .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 },
1228 };1306 };
1229}1307}
12301308
...@@ -1359,12 +1437,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1359,12 +1437,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1359 },1437 },
13601438
1361 .struct_type => |struct_type| {1439 .struct_type => |struct_type| {
1362 if (struct_type.fields_len != 0) {1440 ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{
1363 @panic("TODO"); // handle structs other than empty_struct1441 .tag = .type_struct,
1364 }1442 .data = @enumToInt(i),
1365 ip.items.appendAssumeCapacity(.{1443 } else if (struct_type.namespace.unwrap()) |i| .{
1366 .tag = .simple_internal,1444 .tag = .type_struct_ns,
1367 .data = @enumToInt(SimpleInternal.type_empty_struct),1445 .data = @enumToInt(i),
1446 } else .{
1447 .tag = .type_struct,
1448 .data = @enumToInt(Module.Struct.OptionalIndex.none),
1368 });1449 });
1369 },1450 },
13701451
...@@ -1398,6 +1479,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1398,6 +1479,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
13981479
1399 .opt => |opt| {1480 .opt => |opt| {
1400 assert(opt.ty != .none);1481 assert(opt.ty != .none);
1482 assert(ip.isOptionalType(opt.ty));
1401 ip.items.appendAssumeCapacity(if (opt.val == .none) .{1483 ip.items.appendAssumeCapacity(if (opt.val == .none) .{
1402 .tag = .opt_null,1484 .tag = .opt_null,
1403 .data = @enumToInt(opt.ty),1485 .data = @enumToInt(opt.ty),
...@@ -1549,10 +1631,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1549,10 +1631,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1549 const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative;1631 const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative;
1550 try addInt(ip, gpa, enum_tag.ty, tag, enum_tag.tag.limbs);1632 try addInt(ip, gpa, enum_tag.ty, tag, enum_tag.tag.limbs);
1551 },1633 },
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 },
1552 }1645 }
1553 return @intToEnum(Index, ip.items.len - 1);1646 return @intToEnum(Index, ip.items.len - 1);
1554}1647}
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
1556fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {1663fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {
1557 const limbs_len = @intCast(u32, limbs.len);1664 const limbs_len = @intCast(u32, limbs.len);
1558 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);1665 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);
...@@ -1578,8 +1685,8 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -1578,8 +1685,8 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
1578 ip.extra.appendAssumeCapacity(switch (field.type) {1685 ip.extra.appendAssumeCapacity(switch (field.type) {
1579 u32 => @field(extra, field.name),1686 u32 => @field(extra, field.name),
1580 Index => @enumToInt(@field(extra, field.name)),1687 Index => @enumToInt(@field(extra, field.name)),
1581 DeclIndex => @enumToInt(@field(extra, field.name)),1688 Module.Decl.Index => @enumToInt(@field(extra, field.name)),
1582 NamespaceIndex => @enumToInt(@field(extra, field.name)),1689 Module.Namespace.Index => @enumToInt(@field(extra, field.name)),
1583 i32 => @bitCast(u32, @field(extra, field.name)),1690 i32 => @bitCast(u32, @field(extra, field.name)),
1584 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),1691 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),
1585 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),1692 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
...@@ -1635,8 +1742,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {...@@ -1635,8 +1742,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {
1635 @field(result, field.name) = switch (field.type) {1742 @field(result, field.name) = switch (field.type) {
1636 u32 => int32,1743 u32 => int32,
1637 Index => @intToEnum(Index, int32),1744 Index => @intToEnum(Index, int32),
1638 DeclIndex => @intToEnum(DeclIndex, int32),1745 Module.Decl.Index => @intToEnum(Module.Decl.Index, int32),
1639 NamespaceIndex => @intToEnum(NamespaceIndex, int32),1746 Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32),
1640 i32 => @bitCast(i32, int32),1747 i32 => @bitCast(i32, int32),
1641 Pointer.Flags => @bitCast(Pointer.Flags, int32),1748 Pointer.Flags => @bitCast(Pointer.Flags, int32),
1642 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),1749 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
...@@ -1808,6 +1915,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -1808,6 +1915,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
1808 }1915 }
1809}1916}
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
1811pub fn dump(ip: InternPool) void {1932pub fn dump(ip: InternPool) void {
1812 dumpFallible(ip, std.heap.page_allocator) catch return;1933 dumpFallible(ip, std.heap.page_allocator) catch return;
1813}1934}
...@@ -1859,9 +1980,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -1859,9 +1980,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
1859 .type_error_union => @sizeOf(ErrorUnion),1980 .type_error_union => @sizeOf(ErrorUnion),
1860 .type_enum_simple => @sizeOf(EnumSimple),1981 .type_enum_simple => @sizeOf(EnumSimple),
1861 .type_opaque => @sizeOf(Key.OpaqueType),1982 .type_opaque => @sizeOf(Key.OpaqueType),
1983 .type_struct => 0,
1984 .type_struct_ns => 0,
1862 .simple_type => 0,1985 .simple_type => 0,
1863 .simple_value => 0,1986 .simple_value => 0,
1864 .simple_internal => 0,
1865 .ptr_int => @sizeOf(PtrInt),1987 .ptr_int => @sizeOf(PtrInt),
1866 .opt_null => 0,1988 .opt_null => 0,
1867 .opt_payload => 0,1989 .opt_payload => 0,
...@@ -1887,6 +2009,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -1887,6 +2009,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
1887 .float_f128 => @sizeOf(Float128),2009 .float_f128 => @sizeOf(Float128),
1888 .extern_func => @panic("TODO"),2010 .extern_func => @panic("TODO"),
1889 .func => @panic("TODO"),2011 .func => @panic("TODO"),
2012 .only_possible_value => 0,
1890 });2013 });
1891 }2014 }
1892 const SortContext = struct {2015 const SortContext = struct {
...@@ -1905,3 +2028,34 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -1905,3 +2028,34 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
1905 });2028 });
1906 }2029 }
1907}2030}
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 {...@@ -839,11 +839,14 @@ pub const Decl = struct {
839839
840 /// If the Decl has a value and it is a struct, return it,840 /// If the Decl has a value and it is a struct, return it,
841 /// otherwise null.841 /// otherwise null.
842 pub fn getStruct(decl: *Decl) ?*Struct {842 pub fn getStruct(decl: *Decl, mod: *Module) ?*Struct {
843 if (!decl.owns_tv) return null;843 return mod.structPtrUnwrap(getStructIndex(decl, mod));
844 const ty = (decl.val.castTag(.ty) orelse return null).data;844 }
845 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;845
846 return struct_obj;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);
847 }850 }
848851
849 /// If the Decl has a value and it is a union, return it,852 /// If the Decl has a value and it is a union, return it,
...@@ -884,32 +887,29 @@ pub const Decl = struct {...@@ -884,32 +887,29 @@ pub const Decl = struct {
884 /// Only returns it if the Decl is the owner.887 /// Only returns it if the Decl is the owner.
885 pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex {888 pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex {
886 if (!decl.owns_tv) return .none;889 if (!decl.owns_tv) return .none;
887 if (decl.val.ip_index == .none) {890 switch (decl.val.ip_index) {
888 const ty = (decl.val.castTag(.ty) orelse return .none).data;891 .empty_struct_type => return .none,
889 switch (ty.tag()) {892 .none => {
890 .@"struct" => {893 const ty = (decl.val.castTag(.ty) orelse return .none).data;
891 const struct_obj = ty.castTag(.@"struct").?.data;894 switch (ty.tag()) {
892 return struct_obj.namespace.toOptional();895 .enum_full, .enum_nonexhaustive => {
893 },896 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;
894 .enum_full, .enum_nonexhaustive => {897 return enum_obj.namespace.toOptional();
895 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;898 },
896 return enum_obj.namespace.toOptional();899 .@"union", .union_safety_tagged, .union_tagged => {
897 },900 const union_obj = ty.cast(Type.Payload.Union).?.data;
898 .empty_struct => {901 return union_obj.namespace.toOptional();
899 @panic("TODO");902 },
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 },
905903
906 else => return .none,904 else => return .none,
907 }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 },
908 }912 }
909 return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
910 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
911 else => .none,
912 };
913 }913 }
914914
915 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.915 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
...@@ -1046,6 +1046,28 @@ pub const Struct = struct {...@@ -1046,6 +1046,28 @@ pub const Struct = struct {
1046 is_tuple: bool,1046 is_tuple: bool,
1047 assumed_runtime_bits: bool = false,1047 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
1049 pub const Fields = std.StringArrayHashMapUnmanaged(Field);1071 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
10501072
1051 /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.1073 /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.
...@@ -1111,12 +1133,7 @@ pub const Struct = struct {...@@ -1111,12 +1133,7 @@ pub const Struct = struct {
1111 }1133 }
11121134
1113 pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {1135 pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {
1114 const owner_decl = mod.declPtr(s.owner_decl);1136 return mod.declPtr(s.owner_decl).srcLoc(mod);
1115 return .{
1116 .file_scope = owner_decl.getFileScope(mod),
1117 .parent_decl_node = owner_decl.src_node,
1118 .lazy = LazySrcLoc.nodeOffset(0),
1119 };
1120 }1137 }
11211138
1122 pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc {1139 pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc {
...@@ -3622,6 +3639,16 @@ pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {...@@ -3622,6 +3639,16 @@ pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {
3622 return mod.allocated_namespaces.at(@enumToInt(index));3639 return mod.allocated_namespaces.at(@enumToInt(index));
3623}3640}
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
3625/// Returns true if and only if the Decl is the top level struct associated with a File.3652/// Returns true if and only if the Decl is the top level struct associated with a File.
3626pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {3653pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
3627 const decl = mod.declPtr(decl_index);3654 const decl = mod.declPtr(decl_index);
...@@ -4078,7 +4105,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -4078,7 +4105,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
40784105
4079 if (!decl.owns_tv) continue;4106 if (!decl.owns_tv) continue;
40804107
4081 if (decl.getStruct()) |struct_obj| {4108 if (decl.getStruct(mod)) |struct_obj| {
4082 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {4109 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {
4083 try file.deleted_decls.append(gpa, decl_index);4110 try file.deleted_decls.append(gpa, decl_index);
4084 continue;4111 continue;
...@@ -4597,36 +4624,50 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4597,36 +4624,50 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4597 errdefer new_decl_arena.deinit();4624 errdefer new_decl_arena.deinit();
4598 const new_decl_arena_allocator = new_decl_arena.allocator();4625 const new_decl_arena_allocator = new_decl_arena.allocator();
45994626
4600 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);4627 // Because these three things each reference each other, `undefined`
4601 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);4628 // placeholders are used before being set after the struct type gains an
4602 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);4629 // InternPool index.
4603 const ty_ty = comptime Type.type;4630 const new_namespace_index = try mod.createNamespace(.{
4604 struct_obj.* = .{4631 .parent = .none,
4605 .owner_decl = undefined, // set below4632 .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,
4606 .fields = .{},4644 .fields = .{},
4607 .zir_index = undefined, // set below4645 .zir_index = undefined, // set below
4608 .layout = .Auto,4646 .layout = .Auto,
4609 .status = .none,4647 .status = .none,
4610 .known_non_opv = undefined,4648 .known_non_opv = undefined,
4611 .is_tuple = undefined, // set below4649 .is_tuple = undefined, // set below
4612 .namespace = try mod.createNamespace(.{4650 .namespace = new_namespace_index,
4613 .parent = .none,4651 });
4614 .ty = struct_ty,4652 errdefer mod.destroyStruct(struct_index);
4615 .file_scope = file,4653
4616 }),4654 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
4617 };4655 .index = struct_index.toOptional(),
4618 const new_decl_index = try mod.allocateNewDecl(struct_obj.namespace, 0, null);4656 .namespace = new_namespace_index.toOptional(),
4619 const new_decl = mod.declPtr(new_decl_index);4657 } });
4658 errdefer mod.intern_pool.remove(struct_ty);
4659
4660 new_namespace.ty = struct_ty.toType();
4620 file.root_decl = new_decl_index.toOptional();4661 file.root_decl = new_decl_index.toOptional();
4621 struct_obj.owner_decl = new_decl_index;4662
4622 new_decl.name = try file.fullyQualifiedNameZ(gpa);4663 new_decl.name = try file.fullyQualifiedNameZ(gpa);
4623 new_decl.src_line = 0;4664 new_decl.src_line = 0;
4624 new_decl.is_pub = true;4665 new_decl.is_pub = true;
4625 new_decl.is_exported = false;4666 new_decl.is_exported = false;
4626 new_decl.has_align = false;4667 new_decl.has_align = false;
4627 new_decl.has_linksection_or_addrspace = false;4668 new_decl.has_linksection_or_addrspace = false;
4628 new_decl.ty = ty_ty;4669 new_decl.ty = Type.type;
4629 new_decl.val = struct_val;4670 new_decl.val = struct_ty.toValue();
4630 new_decl.@"align" = 0;4671 new_decl.@"align" = 0;
4631 new_decl.@"linksection" = null;4672 new_decl.@"linksection" = null;
4632 new_decl.has_tv = true;4673 new_decl.has_tv = true;
...@@ -4639,6 +4680,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4639,6 +4680,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4639 if (file.status == .success_zir) {4680 if (file.status == .success_zir) {
4640 assert(file.zir_loaded);4681 assert(file.zir_loaded);
4641 const main_struct_inst = Zir.main_struct_inst;4682 const main_struct_inst = Zir.main_struct_inst;
4683 const struct_obj = mod.structPtr(struct_index);
4642 struct_obj.zir_index = main_struct_inst;4684 struct_obj.zir_index = main_struct_inst;
4643 const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;4685 const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;
4644 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);4686 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
...@@ -4665,7 +4707,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4665,7 +4707,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4665 var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);4707 var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);
4666 defer wip_captures.deinit();4708 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)) |_| {
4669 try wip_captures.finalize();4711 try wip_captures.finalize();
4670 new_decl.analysis = .complete;4712 new_decl.analysis = .complete;
4671 } else |err| switch (err) {4713 } else |err| switch (err) {
...@@ -4761,11 +4803,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4761,11 +4803,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4761 if (mod.declIsRoot(decl_index)) {4803 if (mod.declIsRoot(decl_index)) {
4762 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });4804 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
4763 const main_struct_inst = Zir.main_struct_inst;4805 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);
4765 // This might not have gotten set in `semaFile` if the first time had4808 // This might not have gotten set in `semaFile` if the first time had
4766 // a ZIR failure, so we set it here in case.4809 // a ZIR failure, so we set it here in case.
4767 struct_obj.zir_index = main_struct_inst;4810 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);
4769 decl.analysis = .complete;4812 decl.analysis = .complete;
4770 decl.generation = mod.generation;4813 decl.generation = mod.generation;
4771 return false;4814 return false;
...@@ -5970,6 +6013,14 @@ pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {...@@ -5970,6 +6013,14 @@ pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {
5970 };6013 };
5971}6014}
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
5973pub fn allocateNewDecl(6024pub fn allocateNewDecl(
5974 mod: *Module,6025 mod: *Module,
5975 namespace: Namespace.Index,6026 namespace: Namespace.Index,
...@@ -7202,12 +7253,7 @@ pub fn atomicPtrAlignment(...@@ -7202,12 +7253,7 @@ pub fn atomicPtrAlignment(
7202}7253}
72037254
7204pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc {7255pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc {
7205 const owner_decl = mod.declPtr(opaque_type.decl);7256 return mod.declPtr(opaque_type.decl).srcLoc(mod);
7206 return .{
7207 .file_scope = owner_decl.getFileScope(mod),
7208 .parent_decl_node = owner_decl.src_node,
7209 .lazy = LazySrcLoc.nodeOffset(0),
7210 };
7211}7257}
72127258
7213pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) ![:0]u8 {7259pub 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 {...@@ -7221,3 +7267,12 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
7221pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index {7267pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index {
7222 return mod.namespacePtr(namespace_index).getDeclIndex(mod);7268 return mod.namespacePtr(namespace_index).getDeclIndex(mod);
7223}7269}
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:...@@ -2090,16 +2090,17 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:
2090}2090}
20912091
2092fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError {2092fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError {
2093 const mod = sema.mod;
2093 const msg = msg: {2094 const msg = msg: {
2094 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});2095 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
2095 errdefer msg.destroy(sema.gpa);2096 errdefer msg.destroy(sema.gpa);
20962097
2097 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;2098 const struct_ty = mod.typeToStruct(container_ty) orelse break :msg msg;
2098 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{2099 const default_value_src = struct_ty.fieldSrcLoc(mod, .{
2099 .index = field_index,2100 .index = field_index,
2100 .range = .value,2101 .range = .value,
2101 });2102 });
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", .{});
2103 break :msg msg;2104 break :msg msg;
2104 };2105 };
2105 return sema.failWithOwnedErrorMsg(msg);2106 return sema.failWithOwnedErrorMsg(msg);
...@@ -2632,8 +2633,10 @@ pub fn analyzeStructDecl(...@@ -2632,8 +2633,10 @@ pub fn analyzeStructDecl(
2632 sema: *Sema,2633 sema: *Sema,
2633 new_decl: *Decl,2634 new_decl: *Decl,
2634 inst: Zir.Inst.Index,2635 inst: Zir.Inst.Index,
2635 struct_obj: *Module.Struct,2636 struct_index: Module.Struct.Index,
2636) SemaError!void {2637) SemaError!void {
2638 const mod = sema.mod;
2639 const struct_obj = mod.structPtr(struct_index);
2637 const extended = sema.code.instructions.items(.data)[inst].extended;2640 const extended = sema.code.instructions.items(.data)[inst].extended;
2638 assert(extended.opcode == .struct_decl);2641 assert(extended.opcode == .struct_decl);
2639 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);2642 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
...@@ -2662,7 +2665,7 @@ pub fn analyzeStructDecl(...@@ -2662,7 +2665,7 @@ pub fn analyzeStructDecl(
2662 }2665 }
2663 }2666 }
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);
2666}2669}
26672670
2668fn zirStructDecl(2671fn zirStructDecl(
...@@ -2671,28 +2674,38 @@ fn zirStructDecl(...@@ -2671,28 +2674,38 @@ fn zirStructDecl(
2671 extended: Zir.Inst.Extended.InstData,2674 extended: Zir.Inst.Extended.InstData,
2672 inst: Zir.Inst.Index,2675 inst: Zir.Inst.Index,
2673) CompileError!Air.Inst.Ref {2676) CompileError!Air.Inst.Ref {
2677 const mod = sema.mod;
2678 const gpa = sema.gpa;
2674 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);2679 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
2675 const src: LazySrcLoc = if (small.has_src_node) blk: {2680 const src: LazySrcLoc = if (small.has_src_node) blk: {
2676 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);2681 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
2677 break :blk LazySrcLoc.nodeOffset(node_offset);2682 break :blk LazySrcLoc.nodeOffset(node_offset);
2678 } else sema.src;2683 } 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);
2681 errdefer new_decl_arena.deinit();2686 errdefer new_decl_arena.deinit();
2682 const new_decl_arena_allocator = new_decl_arena.allocator();
26832687
2684 const mod = sema.mod;2688 // Because these three things each reference each other, `undefined`
2685 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);2689 // placeholders are used before being set after the struct type gains an
2686 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);2690 // InternPool index.
2687 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);2691
2688 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{2692 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
2689 .ty = Type.type,2693 .ty = Type.type,
2690 .val = struct_val,2694 .val = undefined,
2691 }, small.name_strategy, "struct", inst);2695 }, small.name_strategy, "struct", inst);
2692 const new_decl = mod.declPtr(new_decl_index);2696 const new_decl = mod.declPtr(new_decl_index);
2693 new_decl.owns_tv = true;2697 new_decl.owns_tv = true;
2694 errdefer mod.abortAnonDecl(new_decl_index);2698 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(.{
2696 .owner_decl = new_decl_index,2709 .owner_decl = new_decl_index,
2697 .fields = .{},2710 .fields = .{},
2698 .zir_index = inst,2711 .zir_index = inst,
...@@ -2700,13 +2713,20 @@ fn zirStructDecl(...@@ -2700,13 +2713,20 @@ fn zirStructDecl(
2700 .status = .none,2713 .status = .none,
2701 .known_non_opv = undefined,2714 .known_non_opv = undefined,
2702 .is_tuple = small.is_tuple,2715 .is_tuple = small.is_tuple,
2703 .namespace = try mod.createNamespace(.{2716 .namespace = new_namespace_index,
2704 .parent = block.namespace.toOptional(),2717 });
2705 .ty = struct_ty,2718 errdefer mod.destroyStruct(struct_index);
2706 .file_scope = block.getFileScope(mod),2719
2707 }),2720 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
2708 };2721 .index = struct_index.toOptional(),
2709 try sema.analyzeStructDecl(new_decl, inst, struct_obj);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);
2710 try new_decl.finalizeNewArena(&new_decl_arena);2730 try new_decl.finalizeNewArena(&new_decl_arena);
2711 return sema.analyzeDeclVal(block, src, new_decl_index);2731 return sema.analyzeDeclVal(block, src, new_decl_index);
2712}2732}
...@@ -2721,6 +2741,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2721,6 +2741,7 @@ fn createAnonymousDeclTypeNamed(
2721 inst: ?Zir.Inst.Index,2741 inst: ?Zir.Inst.Index,
2722) !Decl.Index {2742) !Decl.Index {
2723 const mod = sema.mod;2743 const mod = sema.mod;
2744 const gpa = sema.gpa;
2724 const namespace = block.namespace;2745 const namespace = block.namespace;
2725 const src_scope = block.wip_capture_scope;2746 const src_scope = block.wip_capture_scope;
2726 const src_decl = mod.declPtr(block.src_decl);2747 const src_decl = mod.declPtr(block.src_decl);
...@@ -2736,16 +2757,16 @@ fn createAnonymousDeclTypeNamed(...@@ -2736,16 +2757,16 @@ fn createAnonymousDeclTypeNamed(
2736 // semantically analyzed.2757 // semantically analyzed.
2737 // This name is also used as the key in the parent namespace so it cannot be2758 // This name is also used as the key in the parent namespace so it cannot be
2738 // renamed.2759 // renamed.
2739 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{2760 const name = try std.fmt.allocPrintZ(gpa, "{s}__{s}_{d}", .{
2740 src_decl.name, anon_prefix, @enumToInt(new_decl_index),2761 src_decl.name, anon_prefix, @enumToInt(new_decl_index),
2741 });2762 });
2742 errdefer sema.gpa.free(name);2763 errdefer gpa.free(name);
2743 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2764 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2744 return new_decl_index;2765 return new_decl_index;
2745 },2766 },
2746 .parent => {2767 .parent => {
2747 const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));2768 const name = try gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
2748 errdefer sema.gpa.free(name);2769 errdefer gpa.free(name);
2749 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2770 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2750 return new_decl_index;2771 return new_decl_index;
2751 },2772 },
...@@ -2753,7 +2774,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2753,7 +2774,7 @@ fn createAnonymousDeclTypeNamed(
2753 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);2774 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);
2754 const zir_tags = sema.code.instructions.items(.tag);2775 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);
2757 defer buf.deinit();2778 defer buf.deinit();
2758 try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));2779 try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
2759 try buf.appendSlice("(");2780 try buf.appendSlice("(");
...@@ -2781,7 +2802,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2781,7 +2802,7 @@ fn createAnonymousDeclTypeNamed(
27812802
2782 try buf.appendSlice(")");2803 try buf.appendSlice(")");
2783 const name = try buf.toOwnedSliceSentinel(0);2804 const name = try buf.toOwnedSliceSentinel(0);
2784 errdefer sema.gpa.free(name);2805 errdefer gpa.free(name);
2785 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2806 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2786 return new_decl_index;2807 return new_decl_index;
2787 },2808 },
...@@ -2794,10 +2815,10 @@ fn createAnonymousDeclTypeNamed(...@@ -2794,10 +2815,10 @@ fn createAnonymousDeclTypeNamed(
2794 .dbg_var_ptr, .dbg_var_val => {2815 .dbg_var_ptr, .dbg_var_val => {
2795 if (zir_data[i].str_op.operand != ref) continue;2816 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}", .{
2798 src_decl.name, zir_data[i].str_op.getStr(sema.code),2819 src_decl.name, zir_data[i].str_op.getStr(sema.code),
2799 });2820 });
2800 errdefer sema.gpa.free(name);2821 errdefer gpa.free(name);
28012822
2802 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);2823 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2803 return new_decl_index;2824 return new_decl_index;
...@@ -3216,13 +3237,13 @@ fn zirOpaqueDecl(...@@ -3216,13 +3237,13 @@ fn zirOpaqueDecl(
3216 .file_scope = block.getFileScope(mod),3237 .file_scope = block.getFileScope(mod),
3217 });3238 });
3218 const new_namespace = mod.namespacePtr(new_namespace_index);3239 const new_namespace = mod.namespacePtr(new_namespace_index);
3219 errdefer @panic("TODO error handling");3240 errdefer mod.destroyNamespace(new_namespace_index);
32203241
3221 const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{3242 const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{
3222 .decl = new_decl_index,3243 .decl = new_decl_index,
3223 .namespace = new_namespace_index,3244 .namespace = new_namespace_index,
3224 } });3245 } });
3225 errdefer @panic("TODO error handling");3246 errdefer mod.intern_pool.remove(opaque_ty);
32263247
3227 new_decl.val = opaque_ty.toValue();3248 new_decl.val = opaque_ty.toValue();
3228 new_namespace.ty = opaque_ty.toType();3249 new_namespace.ty = opaque_ty.toType();
...@@ -3960,7 +3981,7 @@ fn zirArrayBasePtr(...@@ -3960,7 +3981,7 @@ fn zirArrayBasePtr(
3960 const elem_ty = sema.typeOf(base_ptr).childType(mod);3981 const elem_ty = sema.typeOf(base_ptr).childType(mod);
3961 switch (elem_ty.zigTypeTag(mod)) {3982 switch (elem_ty.zigTypeTag(mod)) {
3962 .Array, .Vector => return base_ptr,3983 .Array, .Vector => return base_ptr,
3963 .Struct => if (elem_ty.isTuple()) {3984 .Struct => if (elem_ty.isTuple(mod)) {
3964 // TODO validate element count3985 // TODO validate element count
3965 return base_ptr;3986 return base_ptr;
3966 },3987 },
...@@ -4150,7 +4171,7 @@ fn validateArrayInitTy(...@@ -4150,7 +4171,7 @@ fn validateArrayInitTy(
4150 }4171 }
4151 return;4172 return;
4152 },4173 },
4153 .Struct => if (ty.isTuple()) {4174 .Struct => if (ty.isTuple(mod)) {
4154 _ = try sema.resolveTypeFields(ty);4175 _ = try sema.resolveTypeFields(ty);
4155 const array_len = ty.arrayLen(mod);4176 const array_len = ty.arrayLen(mod);
4156 if (extra.init_count > array_len) {4177 if (extra.init_count > array_len) {
...@@ -4358,7 +4379,7 @@ fn validateStructInit(...@@ -4358,7 +4379,7 @@ fn validateStructInit(
4358 const gpa = sema.gpa;4379 const gpa = sema.gpa;
43594380
4360 // Maps field index to field_ptr index of where it was already initialized.4381 // 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));
4362 defer gpa.free(found_fields);4383 defer gpa.free(found_fields);
4363 @memset(found_fields, 0);4384 @memset(found_fields, 0);
43644385
...@@ -4370,7 +4391,7 @@ fn validateStructInit(...@@ -4370,7 +4391,7 @@ fn validateStructInit(
4370 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;4391 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
4371 struct_ptr_zir_ref = field_ptr_extra.lhs;4392 struct_ptr_zir_ref = field_ptr_extra.lhs;
4372 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);4393 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))
4374 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)4395 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)
4375 else4396 else
4376 try sema.structFieldIndex(block, struct_ty, field_name, field_src);4397 try sema.structFieldIndex(block, struct_ty, field_name, field_src);
...@@ -4403,9 +4424,9 @@ fn validateStructInit(...@@ -4403,9 +4424,9 @@ fn validateStructInit(
4403 for (found_fields, 0..) |field_ptr, i| {4424 for (found_fields, 0..) |field_ptr, i| {
4404 if (field_ptr != 0) continue;4425 if (field_ptr != 0) continue;
44054426
4406 const default_val = struct_ty.structFieldDefaultValue(i);4427 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4407 if (default_val.ip_index == .unreachable_value) {4428 if (default_val.ip_index == .unreachable_value) {
4408 if (struct_ty.isTuple()) {4429 if (struct_ty.isTuple(mod)) {
4409 const template = "missing tuple field with index {d}";4430 const template = "missing tuple field with index {d}";
4410 if (root_msg) |msg| {4431 if (root_msg) |msg| {
4411 try sema.errNote(block, init_src, msg, template, .{i});4432 try sema.errNote(block, init_src, msg, template, .{i});
...@@ -4414,7 +4435,7 @@ fn validateStructInit(...@@ -4414,7 +4435,7 @@ fn validateStructInit(
4414 }4435 }
4415 continue;4436 continue;
4416 }4437 }
4417 const field_name = struct_ty.structFieldName(i);4438 const field_name = struct_ty.structFieldName(i, mod);
4418 const template = "missing struct field: {s}";4439 const template = "missing struct field: {s}";
4419 const args = .{field_name};4440 const args = .{field_name};
4420 if (root_msg) |msg| {4441 if (root_msg) |msg| {
...@@ -4426,7 +4447,7 @@ fn validateStructInit(...@@ -4426,7 +4447,7 @@ fn validateStructInit(
4426 }4447 }
44274448
4428 const field_src = init_src; // TODO better source location4449 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))
4430 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)4451 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
4431 else4452 else
4432 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);4453 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
...@@ -4436,11 +4457,11 @@ fn validateStructInit(...@@ -4436,11 +4457,11 @@ fn validateStructInit(
4436 }4457 }
44374458
4438 if (root_msg) |msg| {4459 if (root_msg) |msg| {
4439 if (struct_ty.castTag(.@"struct")) |struct_obj| {4460 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4440 const fqn = try struct_obj.data.getFullyQualifiedName(mod);4461 const fqn = try struct_obj.getFullyQualifiedName(mod);
4441 defer gpa.free(fqn);4462 defer gpa.free(fqn);
4442 try mod.errNoteNonLazy(4463 try mod.errNoteNonLazy(
4443 struct_obj.data.srcLoc(mod),4464 struct_obj.srcLoc(mod),
4444 msg,4465 msg,
4445 "struct '{s}' declared here",4466 "struct '{s}' declared here",
4446 .{fqn},4467 .{fqn},
...@@ -4463,12 +4484,12 @@ fn validateStructInit(...@@ -4463,12 +4484,12 @@ fn validateStructInit(
44634484
4464 // We collect the comptime field values in case the struct initialization4485 // We collect the comptime field values in case the struct initialization
4465 // ends up being comptime-known.4486 // 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
4468 field: for (found_fields, 0..) |field_ptr, i| {4489 field: for (found_fields, 0..) |field_ptr, i| {
4469 if (field_ptr != 0) {4490 if (field_ptr != 0) {
4470 // Determine whether the value stored to this pointer is comptime-known.4491 // 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);
4472 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {4493 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
4473 field_values[i] = opv;4494 field_values[i] = opv;
4474 continue;4495 continue;
...@@ -4548,9 +4569,9 @@ fn validateStructInit(...@@ -4548,9 +4569,9 @@ fn validateStructInit(
4548 continue :field;4569 continue :field;
4549 }4570 }
45504571
4551 const default_val = struct_ty.structFieldDefaultValue(i);4572 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4552 if (default_val.ip_index == .unreachable_value) {4573 if (default_val.ip_index == .unreachable_value) {
4553 if (struct_ty.isTuple()) {4574 if (struct_ty.isTuple(mod)) {
4554 const template = "missing tuple field with index {d}";4575 const template = "missing tuple field with index {d}";
4555 if (root_msg) |msg| {4576 if (root_msg) |msg| {
4556 try sema.errNote(block, init_src, msg, template, .{i});4577 try sema.errNote(block, init_src, msg, template, .{i});
...@@ -4559,7 +4580,7 @@ fn validateStructInit(...@@ -4559,7 +4580,7 @@ fn validateStructInit(
4559 }4580 }
4560 continue;4581 continue;
4561 }4582 }
4562 const field_name = struct_ty.structFieldName(i);4583 const field_name = struct_ty.structFieldName(i, mod);
4563 const template = "missing struct field: {s}";4584 const template = "missing struct field: {s}";
4564 const args = .{field_name};4585 const args = .{field_name};
4565 if (root_msg) |msg| {4586 if (root_msg) |msg| {
...@@ -4573,11 +4594,11 @@ fn validateStructInit(...@@ -4573,11 +4594,11 @@ fn validateStructInit(
4573 }4594 }
45744595
4575 if (root_msg) |msg| {4596 if (root_msg) |msg| {
4576 if (struct_ty.castTag(.@"struct")) |struct_obj| {4597 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4577 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);4598 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
4578 defer gpa.free(fqn);4599 defer gpa.free(fqn);
4579 try sema.mod.errNoteNonLazy(4600 try sema.mod.errNoteNonLazy(
4580 struct_obj.data.srcLoc(sema.mod),4601 struct_obj.srcLoc(sema.mod),
4581 msg,4602 msg,
4582 "struct '{s}' declared here",4603 "struct '{s}' declared here",
4583 .{fqn},4604 .{fqn},
...@@ -4605,7 +4626,7 @@ fn validateStructInit(...@@ -4605,7 +4626,7 @@ fn validateStructInit(
4605 if (field_ptr != 0) continue;4626 if (field_ptr != 0) continue;
46064627
4607 const field_src = init_src; // TODO better source location4628 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))
4609 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)4630 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
4610 else4631 else
4611 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);4632 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
...@@ -4638,7 +4659,7 @@ fn zirValidateArrayInit(...@@ -4638,7 +4659,7 @@ fn zirValidateArrayInit(
46384659
4639 var i = instrs.len;4660 var i = instrs.len;
4640 while (i < array_len) : (i += 1) {4661 while (i < array_len) : (i += 1) {
4641 const default_val = array_ty.structFieldDefaultValue(i);4662 const default_val = array_ty.structFieldDefaultValue(i, mod);
4642 if (default_val.ip_index == .unreachable_value) {4663 if (default_val.ip_index == .unreachable_value) {
4643 const template = "missing tuple field with index {d}";4664 const template = "missing tuple field with index {d}";
4644 if (root_msg) |msg| {4665 if (root_msg) |msg| {
...@@ -4698,7 +4719,7 @@ fn zirValidateArrayInit(...@@ -4698,7 +4719,7 @@ fn zirValidateArrayInit(
4698 outer: for (instrs, 0..) |elem_ptr, i| {4719 outer: for (instrs, 0..) |elem_ptr, i| {
4699 // Determine whether the value stored to this pointer is comptime-known.4720 // Determine whether the value stored to this pointer is comptime-known.
47004721
4701 if (array_ty.isTuple()) {4722 if (array_ty.isTuple(mod)) {
4702 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {4723 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
4703 element_vals[i] = opv;4724 element_vals[i] = opv;
4704 continue;4725 continue;
...@@ -7950,7 +7971,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -7950,7 +7971,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
7950 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);7971 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
7951 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction7972 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
7952 if (indexable_ty.zigTypeTag(mod) == .Struct) {7973 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);
7954 return sema.addType(elem_type);7975 return sema.addType(elem_type);
7955 } else {7976 } else {
7956 const elem_type = indexable_ty.elemType2(mod);7977 const elem_type = indexable_ty.elemType2(mod);
...@@ -9822,7 +9843,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9822,7 +9843,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9822 };9843 };
9823 return sema.failWithOwnedErrorMsg(msg);9844 return sema.failWithOwnedErrorMsg(msg);
9824 },9845 },
9825 .Struct, .Union => if (dest_ty.containerLayout() == .Auto) {9846 .Struct, .Union => if (dest_ty.containerLayout(mod) == .Auto) {
9826 const container = switch (dest_ty.zigTypeTag(mod)) {9847 const container = switch (dest_ty.zigTypeTag(mod)) {
9827 .Struct => "struct",9848 .Struct => "struct",
9828 .Union => "union",9849 .Union => "union",
...@@ -9885,7 +9906,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9885,7 +9906,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9885 };9906 };
9886 return sema.failWithOwnedErrorMsg(msg);9907 return sema.failWithOwnedErrorMsg(msg);
9887 },9908 },
9888 .Struct, .Union => if (operand_ty.containerLayout() == .Auto) {9909 .Struct, .Union => if (operand_ty.containerLayout(mod) == .Auto) {
9889 const container = switch (operand_ty.zigTypeTag(mod)) {9910 const container = switch (operand_ty.zigTypeTag(mod)) {
9890 .Struct => "struct",9911 .Struct => "struct",
9891 .Union => "union",9912 .Union => "union",
...@@ -12041,12 +12062,12 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12041,12 +12062,12 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12041 if (mem.eql(u8, name, field_name)) break true;12062 if (mem.eql(u8, name, field_name)) break true;
12042 } else false;12063 } else false;
12043 }12064 }
12044 if (ty.isTuple()) {12065 if (ty.isTuple(mod)) {
12045 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;12066 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);
12047 }12068 }
12048 break :hf switch (ty.zigTypeTag(mod)) {12069 break :hf switch (ty.zigTypeTag(mod)) {
12049 .Struct => ty.structFields().contains(field_name),12070 .Struct => ty.structFields(mod).contains(field_name),
12050 .Union => ty.unionFields().contains(field_name),12071 .Union => ty.unionFields().contains(field_name),
12051 .Enum => ty.enumFields().contains(field_name),12072 .Enum => ty.enumFields().contains(field_name),
12052 .Array => mem.eql(u8, field_name, "len"),12073 .Array => mem.eql(u8, field_name, "len"),
...@@ -12601,14 +12622,15 @@ fn analyzeTupleCat(...@@ -12601,14 +12622,15 @@ fn analyzeTupleCat(
12601 lhs: Air.Inst.Ref,12622 lhs: Air.Inst.Ref,
12602 rhs: Air.Inst.Ref,12623 rhs: Air.Inst.Ref,
12603) CompileError!Air.Inst.Ref {12624) CompileError!Air.Inst.Ref {
12625 const mod = sema.mod;
12604 const lhs_ty = sema.typeOf(lhs);12626 const lhs_ty = sema.typeOf(lhs);
12605 const rhs_ty = sema.typeOf(rhs);12627 const rhs_ty = sema.typeOf(rhs);
12606 const src = LazySrcLoc.nodeOffset(src_node);12628 const src = LazySrcLoc.nodeOffset(src_node);
12607 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };12629 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
12608 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };12630 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1260912631
12610 const lhs_len = lhs_ty.structFieldCount();12632 const lhs_len = lhs_ty.structFieldCount(mod);
12611 const rhs_len = rhs_ty.structFieldCount();12633 const rhs_len = rhs_ty.structFieldCount(mod);
12612 const dest_fields = lhs_len + rhs_len;12634 const dest_fields = lhs_len + rhs_len;
1261312635
12614 if (dest_fields == 0) {12636 if (dest_fields == 0) {
...@@ -12629,8 +12651,8 @@ fn analyzeTupleCat(...@@ -12629,8 +12651,8 @@ fn analyzeTupleCat(
12629 var runtime_src: ?LazySrcLoc = null;12651 var runtime_src: ?LazySrcLoc = null;
12630 var i: u32 = 0;12652 var i: u32 = 0;
12631 while (i < lhs_len) : (i += 1) {12653 while (i < lhs_len) : (i += 1) {
12632 types[i] = lhs_ty.structFieldType(i);12654 types[i] = lhs_ty.structFieldType(i, mod);
12633 const default_val = lhs_ty.structFieldDefaultValue(i);12655 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
12634 values[i] = default_val;12656 values[i] = default_val;
12635 const operand_src = lhs_src; // TODO better source location12657 const operand_src = lhs_src; // TODO better source location
12636 if (default_val.ip_index == .unreachable_value) {12658 if (default_val.ip_index == .unreachable_value) {
...@@ -12639,8 +12661,8 @@ fn analyzeTupleCat(...@@ -12639,8 +12661,8 @@ fn analyzeTupleCat(
12639 }12661 }
12640 i = 0;12662 i = 0;
12641 while (i < rhs_len) : (i += 1) {12663 while (i < rhs_len) : (i += 1) {
12642 types[i + lhs_len] = rhs_ty.structFieldType(i);12664 types[i + lhs_len] = rhs_ty.structFieldType(i, mod);
12643 const default_val = rhs_ty.structFieldDefaultValue(i);12665 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
12644 values[i + lhs_len] = default_val;12666 values[i + lhs_len] = default_val;
12645 const operand_src = rhs_src; // TODO better source location12667 const operand_src = rhs_src; // TODO better source location
12646 if (default_val.ip_index == .unreachable_value) {12668 if (default_val.ip_index == .unreachable_value) {
...@@ -12691,8 +12713,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12691,8 +12713,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12691 const rhs_ty = sema.typeOf(rhs);12713 const rhs_ty = sema.typeOf(rhs);
12692 const src = inst_data.src();12714 const src = inst_data.src();
1269312715
12694 const lhs_is_tuple = lhs_ty.isTuple();12716 const lhs_is_tuple = lhs_ty.isTuple(mod);
12695 const rhs_is_tuple = rhs_ty.isTuple();12717 const rhs_is_tuple = rhs_ty.isTuple(mod);
12696 if (lhs_is_tuple and rhs_is_tuple) {12718 if (lhs_is_tuple and rhs_is_tuple) {
12697 return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs);12719 return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs);
12698 }12720 }
...@@ -12800,8 +12822,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12800,8 +12822,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12800 var elem_i: usize = 0;12822 var elem_i: usize = 0;
12801 while (elem_i < lhs_len) : (elem_i += 1) {12823 while (elem_i < lhs_len) : (elem_i += 1) {
12802 const lhs_elem_i = elem_i;12824 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;12825 const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i, mod) else lhs_info.elem_type;
12804 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.@"unreachable";12826 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
12805 const elem_val = if (elem_default_val.ip_index == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;12827 const elem_val = if (elem_default_val.ip_index == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
12806 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);12828 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
12807 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);12829 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...@@ -12810,8 +12832,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12810 }12832 }
12811 while (elem_i < result_len) : (elem_i += 1) {12833 while (elem_i < result_len) : (elem_i += 1) {
12812 const rhs_elem_i = elem_i - lhs_len;12834 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;12835 const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i, mod) else rhs_info.elem_type;
12814 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.@"unreachable";12836 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
12815 const elem_val = if (elem_default_val.ip_index == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;12837 const elem_val = if (elem_default_val.ip_index == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
12816 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);12838 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
12817 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);12839 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...@@ -12909,8 +12931,8 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
12909 }12931 }
12910 },12932 },
12911 .Struct => {12933 .Struct => {
12912 if (operand_ty.isTuple() and peer_ty.isIndexable(mod)) {12934 if (operand_ty.isTuple(mod) and peer_ty.isIndexable(mod)) {
12913 assert(!peer_ty.isTuple());12935 assert(!peer_ty.isTuple(mod));
12914 return .{12936 return .{
12915 .elem_type = peer_ty.elemType2(mod),12937 .elem_type = peer_ty.elemType2(mod),
12916 .sentinel = null,12938 .sentinel = null,
...@@ -12930,12 +12952,13 @@ fn analyzeTupleMul(...@@ -12930,12 +12952,13 @@ fn analyzeTupleMul(
12930 operand: Air.Inst.Ref,12952 operand: Air.Inst.Ref,
12931 factor: u64,12953 factor: u64,
12932) CompileError!Air.Inst.Ref {12954) CompileError!Air.Inst.Ref {
12955 const mod = sema.mod;
12933 const operand_ty = sema.typeOf(operand);12956 const operand_ty = sema.typeOf(operand);
12934 const src = LazySrcLoc.nodeOffset(src_node);12957 const src = LazySrcLoc.nodeOffset(src_node);
12935 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };12958 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
12936 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };12959 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);
12939 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch12962 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch
12940 return sema.fail(block, rhs_src, "operation results in overflow", .{});12963 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1294112964
...@@ -12951,8 +12974,8 @@ fn analyzeTupleMul(...@@ -12951,8 +12974,8 @@ fn analyzeTupleMul(
12951 var runtime_src: ?LazySrcLoc = null;12974 var runtime_src: ?LazySrcLoc = null;
12952 var i: u32 = 0;12975 var i: u32 = 0;
12953 while (i < tuple_len) : (i += 1) {12976 while (i < tuple_len) : (i += 1) {
12954 types[i] = operand_ty.structFieldType(i);12977 types[i] = operand_ty.structFieldType(i, mod);
12955 values[i] = operand_ty.structFieldDefaultValue(i);12978 values[i] = operand_ty.structFieldDefaultValue(i, mod);
12956 const operand_src = lhs_src; // TODO better source location12979 const operand_src = lhs_src; // TODO better source location
12957 if (values[i].ip_index == .unreachable_value) {12980 if (values[i].ip_index == .unreachable_value) {
12958 runtime_src = operand_src;12981 runtime_src = operand_src;
...@@ -13006,7 +13029,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13006,7 +13029,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13006 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };13029 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };
13007 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };13030 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
1300813031
13009 if (lhs_ty.isTuple()) {13032 if (lhs_ty.isTuple(mod)) {
13010 // In `**` rhs must be comptime-known, but lhs can be runtime-known13033 // In `**` rhs must be comptime-known, but lhs can be runtime-known
13011 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");13034 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
13012 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);13035 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);
...@@ -14502,7 +14525,7 @@ fn zirOverflowArithmetic(...@@ -14502,7 +14525,7 @@ fn zirOverflowArithmetic(
1450214525
14503 const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);14526 const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);
14504 element_refs[0] = result.inst;14527 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);
14506 return block.addAggregateInit(tuple_ty, element_refs);14529 return block.addAggregateInit(tuple_ty, element_refs);
14507}14530}
1450814531
...@@ -16378,7 +16401,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16378,7 +16401,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1637816401
16379 const union_ty = try sema.resolveTypeFields(ty);16402 const union_ty = try sema.resolveTypeFields(ty);
16380 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout16403 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16381 const layout = union_ty.containerLayout();16404 const layout = union_ty.containerLayout(mod);
1638216405
16383 const union_fields = union_ty.unionFields();16406 const union_fields = union_ty.unionFields();
16384 const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());16407 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...@@ -16484,7 +16507,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16484 };16507 };
16485 const struct_ty = try sema.resolveTypeFields(ty);16508 const struct_ty = try sema.resolveTypeFields(ty);
16486 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout16509 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16487 const layout = struct_ty.containerLayout();16510 const layout = struct_ty.containerLayout(mod);
1648816511
16489 const struct_field_vals = fv: {16512 const struct_field_vals = fv: {
16490 if (struct_ty.isSimpleTupleOrAnonStruct()) {16513 if (struct_ty.isSimpleTupleOrAnonStruct()) {
...@@ -16532,7 +16555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16532,7 +16555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16532 }16555 }
16533 break :fv struct_field_vals;16556 break :fv struct_field_vals;
16534 }16557 }
16535 const struct_fields = struct_ty.structFields();16558 const struct_fields = struct_ty.structFields(mod);
16536 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());16559 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
1653716560
16538 for (struct_field_vals, 0..) |*field_val, i| {16561 for (struct_field_vals, 0..) |*field_val, i| {
...@@ -16600,7 +16623,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16600,7 +16623,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1660016623
16601 const backing_integer_val = blk: {16624 const backing_integer_val = blk: {
16602 if (layout == .Packed) {16625 if (layout == .Packed) {
16603 const struct_obj = struct_ty.castTag(.@"struct").?.data;16626 const struct_obj = mod.typeToStruct(struct_ty).?;
16604 assert(struct_obj.haveLayout());16627 assert(struct_obj.haveLayout());
16605 assert(struct_obj.backing_int_ty.isInt(mod));16628 assert(struct_obj.backing_int_ty.isInt(mod));
16606 const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty);16629 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...@@ -16624,7 +16647,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16624 // decls: []const Declaration,16647 // decls: []const Declaration,
16625 decls_val,16648 decls_val,
16626 // is_tuple: bool,16649 // is_tuple: bool,
16627 Value.makeBool(struct_ty.isTuple()),16650 Value.makeBool(struct_ty.isTuple(mod)),
16628 };16651 };
1662916652
16630 return sema.addConstant(16653 return sema.addConstant(
...@@ -17801,12 +17824,13 @@ fn structInitEmpty(...@@ -17801,12 +17824,13 @@ fn structInitEmpty(
17801 dest_src: LazySrcLoc,17824 dest_src: LazySrcLoc,
17802 init_src: LazySrcLoc,17825 init_src: LazySrcLoc,
17803) CompileError!Air.Inst.Ref {17826) CompileError!Air.Inst.Ref {
17827 const mod = sema.mod;
17804 const gpa = sema.gpa;17828 const gpa = sema.gpa;
17805 // This logic must be synchronized with that in `zirStructInit`.17829 // This logic must be synchronized with that in `zirStructInit`.
17806 const struct_ty = try sema.resolveTypeFields(obj_ty);17830 const struct_ty = try sema.resolveTypeFields(obj_ty);
1780717831
17808 // The init values to use for the struct instance.17832 // 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));
17810 defer gpa.free(field_inits);17834 defer gpa.free(field_inits);
17811 @memset(field_inits, .none);17835 @memset(field_inits, .none);
1781217836
...@@ -17897,18 +17921,18 @@ fn zirStructInit(...@@ -17897,18 +17921,18 @@ fn zirStructInit(
1789717921
17898 // Maps field index to field_type index of where it was already initialized.17922 // Maps field index to field_type index of where it was already initialized.
17899 // For making sure all fields are accounted for and no fields are duplicated.17923 // 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));
17901 defer gpa.free(found_fields);17925 defer gpa.free(found_fields);
1790217926
17903 // The init values to use for the struct instance.17927 // 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));
17905 defer gpa.free(field_inits);17929 defer gpa.free(field_inits);
17906 @memset(field_inits, .none);17930 @memset(field_inits, .none);
1790717931
17908 var field_i: u32 = 0;17932 var field_i: u32 = 0;
17909 var extra_index = extra.end;17933 var extra_index = extra.end;
1791017934
17911 const is_packed = resolved_ty.containerLayout() == .Packed;17935 const is_packed = resolved_ty.containerLayout(mod) == .Packed;
17912 while (field_i < extra.data.fields_len) : (field_i += 1) {17936 while (field_i < extra.data.fields_len) : (field_i += 1) {
17913 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);17937 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);
17914 extra_index = item.end;17938 extra_index = item.end;
...@@ -17917,7 +17941,7 @@ fn zirStructInit(...@@ -17917,7 +17941,7 @@ fn zirStructInit(
17917 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };17941 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
17918 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;17942 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
17919 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);17943 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))
17921 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)17945 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)
17922 else17946 else
17923 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);17947 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
...@@ -17940,7 +17964,7 @@ fn zirStructInit(...@@ -17940,7 +17964,7 @@ fn zirStructInit(
17940 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");17964 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
17941 };17965 };
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)) {
17944 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);17968 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);
17945 }17969 }
17946 };17970 };
...@@ -18029,13 +18053,13 @@ fn finishStructInit(...@@ -18029,13 +18053,13 @@ fn finishStructInit(
18029 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);18053 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
18030 }18054 }
18031 }18055 }
18032 } else if (struct_ty.isTuple()) {18056 } else if (struct_ty.isTuple(mod)) {
18033 var i: u32 = 0;18057 var i: u32 = 0;
18034 const len = struct_ty.structFieldCount();18058 const len = struct_ty.structFieldCount(mod);
18035 while (i < len) : (i += 1) {18059 while (i < len) : (i += 1) {
18036 if (field_inits[i] != .none) continue;18060 if (field_inits[i] != .none) continue;
1803718061
18038 const default_val = struct_ty.structFieldDefaultValue(i);18062 const default_val = struct_ty.structFieldDefaultValue(i, mod);
18039 if (default_val.ip_index == .unreachable_value) {18063 if (default_val.ip_index == .unreachable_value) {
18040 const template = "missing tuple field with index {d}";18064 const template = "missing tuple field with index {d}";
18041 if (root_msg) |msg| {18065 if (root_msg) |msg| {
...@@ -18044,11 +18068,11 @@ fn finishStructInit(...@@ -18044,11 +18068,11 @@ fn finishStructInit(
18044 root_msg = try sema.errMsg(block, init_src, template, .{i});18068 root_msg = try sema.errMsg(block, init_src, template, .{i});
18045 }18069 }
18046 } else {18070 } 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);
18048 }18072 }
18049 }18073 }
18050 } else {18074 } else {
18051 const struct_obj = struct_ty.castTag(.@"struct").?.data;18075 const struct_obj = mod.typeToStruct(struct_ty).?;
18052 for (struct_obj.fields.values(), 0..) |field, i| {18076 for (struct_obj.fields.values(), 0..) |field, i| {
18053 if (field_inits[i] != .none) continue;18077 if (field_inits[i] != .none) continue;
1805418078
...@@ -18068,11 +18092,11 @@ fn finishStructInit(...@@ -18068,11 +18092,11 @@ fn finishStructInit(
18068 }18092 }
1806918093
18070 if (root_msg) |msg| {18094 if (root_msg) |msg| {
18071 if (struct_ty.castTag(.@"struct")) |struct_obj| {18095 if (mod.typeToStruct(struct_ty)) |struct_obj| {
18072 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);18096 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
18073 defer gpa.free(fqn);18097 defer gpa.free(fqn);
18074 try sema.mod.errNoteNonLazy(18098 try sema.mod.errNoteNonLazy(
18075 struct_obj.data.srcLoc(sema.mod),18099 struct_obj.srcLoc(sema.mod),
18076 msg,18100 msg,
18077 "struct '{s}' declared here",18101 "struct '{s}' declared here",
18078 .{fqn},18102 .{fqn},
...@@ -18277,7 +18301,7 @@ fn zirArrayInit(...@@ -18277,7 +18301,7 @@ fn zirArrayInit(
18277 for (args[1..], 0..) |arg, i| {18301 for (args[1..], 0..) |arg, i| {
18278 const resolved_arg = try sema.resolveInst(arg);18302 const resolved_arg = try sema.resolveInst(arg);
18279 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)18303 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)
18280 array_ty.structFieldType(i)18304 array_ty.structFieldType(i, mod)
18281 else18305 else
18282 array_ty.elemType2(mod);18306 array_ty.elemType2(mod);
18283 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {18307 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
...@@ -18331,12 +18355,12 @@ fn zirArrayInit(...@@ -18331,12 +18355,12 @@ fn zirArrayInit(
18331 });18355 });
18332 const alloc = try block.addTy(.alloc, alloc_ty);18356 const alloc = try block.addTy(.alloc, alloc_ty);
1833318357
18334 if (array_ty.isTuple()) {18358 if (array_ty.isTuple(mod)) {
18335 for (resolved_args, 0..) |arg, i| {18359 for (resolved_args, 0..) |arg, i| {
18336 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{18360 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18337 .mutable = true,18361 .mutable = true,
18338 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18362 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18339 .pointee_type = array_ty.structFieldType(i),18363 .pointee_type = array_ty.structFieldType(i, mod),
18340 });18364 });
18341 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);18365 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1834218366
...@@ -18514,7 +18538,7 @@ fn fieldType(...@@ -18514,7 +18538,7 @@ fn fieldType(
18514 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);18538 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
18515 return sema.addType(cur_ty.tupleFields().types[field_index]);18539 return sema.addType(cur_ty.tupleFields().types[field_index]);
18516 }18540 }
18517 const struct_obj = cur_ty.castTag(.@"struct").?.data;18541 const struct_obj = mod.typeToStruct(cur_ty).?;
18518 const field = struct_obj.fields.get(field_name) orelse18542 const field = struct_obj.fields.get(field_name) orelse
18519 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);18543 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18520 return sema.addType(field.ty);18544 return sema.addType(field.ty);
...@@ -19185,13 +19209,13 @@ fn zirReify(...@@ -19185,13 +19209,13 @@ fn zirReify(
19185 .file_scope = block.getFileScope(mod),19209 .file_scope = block.getFileScope(mod),
19186 });19210 });
19187 const new_namespace = mod.namespacePtr(new_namespace_index);19211 const new_namespace = mod.namespacePtr(new_namespace_index);
19188 errdefer @panic("TODO error handling");19212 errdefer mod.destroyNamespace(new_namespace_index);
1918919213
19190 const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{19214 const opaque_ty = try mod.intern_pool.get(gpa, .{ .opaque_type = .{
19191 .decl = new_decl_index,19215 .decl = new_decl_index,
19192 .namespace = new_namespace_index,19216 .namespace = new_namespace_index,
19193 } });19217 } });
19194 errdefer @panic("TODO error handling");19218 errdefer mod.intern_pool.remove(opaque_ty);
1919519219
19196 new_decl.val = opaque_ty.toValue();19220 new_decl.val = opaque_ty.toValue();
19197 new_namespace.ty = opaque_ty.toType();19221 new_namespace.ty = opaque_ty.toType();
...@@ -19493,22 +19517,34 @@ fn reifyStruct(...@@ -19493,22 +19517,34 @@ fn reifyStruct(
19493 name_strategy: Zir.Inst.NameStrategy,19517 name_strategy: Zir.Inst.NameStrategy,
19494 is_tuple: bool,19518 is_tuple: bool,
19495) CompileError!Air.Inst.Ref {19519) 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);
19497 errdefer new_decl_arena.deinit();19524 errdefer new_decl_arena.deinit();
19498 const new_decl_arena_allocator = new_decl_arena.allocator();19525 const new_decl_arena_allocator = new_decl_arena.allocator();
1949919526
19500 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);19527 // Because these three things each reference each other, `undefined`
19501 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);19528 // placeholders are used before being set after the struct type gains an
19502 const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);19529 // InternPool index.
19503 const mod = sema.mod;19530
19504 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{19531 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19505 .ty = Type.type,19532 .ty = Type.type,
19506 .val = new_struct_val,19533 .val = undefined,
19507 }, name_strategy, "struct", inst);19534 }, name_strategy, "struct", inst);
19508 const new_decl = mod.declPtr(new_decl_index);19535 const new_decl = mod.declPtr(new_decl_index);
19509 new_decl.owns_tv = true;19536 new_decl.owns_tv = true;
19510 errdefer mod.abortAnonDecl(new_decl_index);19537 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(.{
19512 .owner_decl = new_decl_index,19548 .owner_decl = new_decl_index,
19513 .fields = .{},19549 .fields = .{},
19514 .zir_index = inst,19550 .zir_index = inst,
...@@ -19516,12 +19552,19 @@ fn reifyStruct(...@@ -19516,12 +19552,19 @@ fn reifyStruct(
19516 .status = .have_field_types,19552 .status = .have_field_types,
19517 .known_non_opv = false,19553 .known_non_opv = false,
19518 .is_tuple = is_tuple,19554 .is_tuple = is_tuple,
19519 .namespace = try mod.createNamespace(.{19555 .namespace = new_namespace_index,
19520 .parent = block.namespace.toOptional(),19556 });
19521 .ty = struct_ty,19557 const struct_obj = mod.structPtr(struct_index);
19522 .file_scope = block.getFileScope(mod),19558 errdefer mod.destroyStruct(struct_index);
19523 }),19559
19524 };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
19526 // Fields19569 // Fields
19527 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));19570 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
...@@ -19609,7 +19652,7 @@ fn reifyStruct(...@@ -19609,7 +19652,7 @@ fn reifyStruct(
19609 if (field_ty.zigTypeTag(mod) == .Opaque) {19652 if (field_ty.zigTypeTag(mod) == .Opaque) {
19610 const msg = msg: {19653 const msg = msg: {
19611 const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});19654 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
19614 try sema.addDeclaredHereNote(msg, field_ty);19657 try sema.addDeclaredHereNote(msg, field_ty);
19615 break :msg msg;19658 break :msg msg;
...@@ -19619,7 +19662,7 @@ fn reifyStruct(...@@ -19619,7 +19662,7 @@ fn reifyStruct(
19619 if (field_ty.zigTypeTag(mod) == .NoReturn) {19662 if (field_ty.zigTypeTag(mod) == .NoReturn) {
19620 const msg = msg: {19663 const msg = msg: {
19621 const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});19664 const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});
19622 errdefer msg.destroy(sema.gpa);19665 errdefer msg.destroy(gpa);
1962319666
19624 try sema.addDeclaredHereNote(msg, field_ty);19667 try sema.addDeclaredHereNote(msg, field_ty);
19625 break :msg msg;19668 break :msg msg;
...@@ -19629,7 +19672,7 @@ fn reifyStruct(...@@ -19629,7 +19672,7 @@ fn reifyStruct(
19629 if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {19672 if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {
19630 const msg = msg: {19673 const msg = msg: {
19631 const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});19674 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
19634 const src_decl = sema.mod.declPtr(block.src_decl);19677 const src_decl = sema.mod.declPtr(block.src_decl);
19635 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field);19678 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field);
...@@ -19641,7 +19684,7 @@ fn reifyStruct(...@@ -19641,7 +19684,7 @@ fn reifyStruct(
19641 } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) {19684 } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) {
19642 const msg = msg: {19685 const msg = msg: {
19643 const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});19686 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
19646 const src_decl = sema.mod.declPtr(block.src_decl);19689 const src_decl = sema.mod.declPtr(block.src_decl);
19647 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty);19690 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty);
...@@ -19660,7 +19703,7 @@ fn reifyStruct(...@@ -19660,7 +19703,7 @@ fn reifyStruct(
19660 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {19703 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
19661 error.AnalysisFail => {19704 error.AnalysisFail => {
19662 const msg = sema.err orelse return err;19705 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", .{});
19664 return err;19707 return err;
19665 },19708 },
19666 else => return err,19709 else => return err,
...@@ -20558,21 +20601,21 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -20558,21 +20601,21 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
20558 },20601 },
20559 }20602 }
2056020603
20561 const field_index = if (ty.isTuple()) blk: {20604 const field_index = if (ty.isTuple(mod)) blk: {
20562 if (mem.eql(u8, field_name, "len")) {20605 if (mem.eql(u8, field_name, "len")) {
20563 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});20606 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
20564 }20607 }
20565 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);20608 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
20566 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);20609 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
2056720610
20568 if (ty.structFieldIsComptime(field_index)) {20611 if (ty.structFieldIsComptime(field_index, mod)) {
20569 return sema.fail(block, src, "no offset available for comptime field", .{});20612 return sema.fail(block, src, "no offset available for comptime field", .{});
20570 }20613 }
2057120614
20572 switch (ty.containerLayout()) {20615 switch (ty.containerLayout(mod)) {
20573 .Packed => {20616 .Packed => {
20574 var bit_sum: u64 = 0;20617 var bit_sum: u64 = 0;
20575 const fields = ty.structFields();20618 const fields = ty.structFields(mod);
20576 for (fields.values(), 0..) |field, i| {20619 for (fields.values(), 0..) |field, i| {
20577 if (i == field_index) {20620 if (i == field_index) {
20578 return bit_sum;20621 return bit_sum;
...@@ -21810,6 +21853,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -21810,6 +21853,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21810 const tracy = trace(@src());21853 const tracy = trace(@src());
21811 defer tracy.end();21854 defer tracy.end();
2181221855
21856 const mod = sema.mod;
21813 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;21857 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
21814 const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };21858 const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
21815 const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };21859 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...@@ -21869,11 +21913,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21869 const args = try sema.resolveInst(extra.args);21913 const args = try sema.resolveInst(extra.args);
2187021914
21871 const args_ty = sema.typeOf(args);21915 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) {
21873 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});21917 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});
21874 }21918 }
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));
21877 for (resolved_args, 0..) |*resolved, i| {21921 for (resolved_args, 0..) |*resolved, i| {
21878 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);21922 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);
21879 }21923 }
...@@ -21905,7 +21949,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -21905,7 +21949,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2190521949
21906 const field_index = switch (parent_ty.zigTypeTag(mod)) {21950 const field_index = switch (parent_ty.zigTypeTag(mod)) {
21907 .Struct => blk: {21951 .Struct => blk: {
21908 if (parent_ty.isTuple()) {21952 if (parent_ty.isTuple(mod)) {
21909 if (mem.eql(u8, field_name, "len")) {21953 if (mem.eql(u8, field_name, "len")) {
21910 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});21954 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
21911 }21955 }
...@@ -21918,7 +21962,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -21918,7 +21962,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
21918 else => unreachable,21962 else => unreachable,
21919 };21963 };
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)) {
21922 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});21966 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
21923 }21967 }
2192421968
...@@ -21926,17 +21970,17 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -21926,17 +21970,17 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
21926 const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod);21970 const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod);
2192721971
21928 var ptr_ty_data: Type.Payload.Pointer.Data = .{21972 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),
21930 .mutable = field_ptr_ty_info.mutable,21974 .mutable = field_ptr_ty_info.mutable,
21931 .@"addrspace" = field_ptr_ty_info.@"addrspace",21975 .@"addrspace" = field_ptr_ty_info.@"addrspace",
21932 };21976 };
2193321977
21934 if (parent_ty.containerLayout() == .Packed) {21978 if (parent_ty.containerLayout(mod) == .Packed) {
21935 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});21979 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
21936 } else {21980 } else {
21937 ptr_ty_data.@"align" = blk: {21981 ptr_ty_data.@"align" = blk: {
21938 if (parent_ty.castTag(.@"struct")) |struct_obj| {21982 if (mod.typeToStruct(parent_ty)) |struct_obj| {
21939 break :blk struct_obj.data.fields.values()[field_index].abi_align;21983 break :blk struct_obj.fields.values()[field_index].abi_align;
21940 } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| {21984 } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| {
21941 break :blk union_obj.data.fields.values()[field_index].abi_align;21985 break :blk union_obj.data.fields.values()[field_index].abi_align;
21942 } else {21986 } else {
...@@ -23380,8 +23424,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -23380,8 +23424,7 @@ fn explainWhyTypeIsComptimeInner(
23380 .Struct => {23424 .Struct => {
23381 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;23425 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
2338223426
23383 if (ty.castTag(.@"struct")) |payload| {23427 if (mod.typeToStruct(ty)) |struct_obj| {
23384 const struct_obj = payload.data;
23385 for (struct_obj.fields.values(), 0..) |field, i| {23428 for (struct_obj.fields.values(), 0..) |field, i| {
23386 const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{23429 const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{
23387 .index = i,23430 .index = i,
...@@ -23472,7 +23515,7 @@ fn validateExternType(...@@ -23472,7 +23515,7 @@ fn validateExternType(
23472 .Enum => {23515 .Enum => {
23473 return sema.validateExternType(try ty.intTagType(mod), position);23516 return sema.validateExternType(try ty.intTagType(mod), position);
23474 },23517 },
23475 .Struct, .Union => switch (ty.containerLayout()) {23518 .Struct, .Union => switch (ty.containerLayout(mod)) {
23476 .Extern => return true,23519 .Extern => return true,
23477 .Packed => {23520 .Packed => {
23478 const bit_size = try ty.bitSizeAdvanced(mod, sema);23521 const bit_size = try ty.bitSizeAdvanced(mod, sema);
...@@ -23569,7 +23612,7 @@ fn explainWhyTypeIsNotExtern(...@@ -23569,7 +23612,7 @@ fn explainWhyTypeIsNotExtern(
2356923612
23570/// Returns true if `ty` is allowed in packed types.23613/// Returns true if `ty` is allowed in packed types.
23571/// Does *NOT* require `ty` to be resolved in any way.23614/// 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 {
23573 switch (ty.zigTypeTag(mod)) {23616 switch (ty.zigTypeTag(mod)) {
23574 .Type,23617 .Type,
23575 .ComptimeFloat,23618 .ComptimeFloat,
...@@ -23595,7 +23638,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool {...@@ -23595,7 +23638,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool {
23595 .Enum,23638 .Enum,
23596 => return true,23639 => return true,
23597 .Pointer => return !ty.isSlice(mod),23640 .Pointer => return !ty.isSlice(mod),
23598 .Struct, .Union => return ty.containerLayout() == .Packed,23641 .Struct, .Union => return ty.containerLayout(mod) == .Packed,
23599 }23642 }
23600}23643}
2360123644
...@@ -24419,27 +24462,27 @@ fn fieldCallBind(...@@ -24419,27 +24462,27 @@ fn fieldCallBind(
24419 switch (concrete_ty.zigTypeTag(mod)) {24462 switch (concrete_ty.zigTypeTag(mod)) {
24420 .Struct => {24463 .Struct => {
24421 const struct_ty = try sema.resolveTypeFields(concrete_ty);24464 const struct_ty = try sema.resolveTypeFields(concrete_ty);
24422 if (struct_ty.castTag(.@"struct")) |struct_obj| {24465 if (mod.typeToStruct(struct_ty)) |struct_obj| {
24423 const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse24466 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24424 break :find_field;24467 break :find_field;
24425 const field_index = @intCast(u32, field_index_usize);24468 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
24428 return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr);24471 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)) {
24430 if (mem.eql(u8, field_name, "len")) {24473 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)) };
24432 }24475 }
24433 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {24476 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
24434 if (field_index >= struct_ty.structFieldCount()) break :find_field;24477 if (field_index >= struct_ty.structFieldCount(mod)) break :find_field;
24435 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr);24478 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index, mod), field_index, object_ptr);
24436 } else |_| {}24479 } else |_| {}
24437 } else {24480 } else {
24438 const max = struct_ty.structFieldCount();24481 const max = struct_ty.structFieldCount(mod);
24439 var i: u32 = 0;24482 var i: u32 = 0;
24440 while (i < max) : (i += 1) {24483 while (i < max) : (i += 1) {
24441 if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) {24484 if (mem.eql(u8, struct_ty.structFieldName(i, mod), field_name)) {
24442 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr);24485 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i, mod), i, object_ptr);
24443 }24486 }
24444 }24487 }
24445 }24488 }
...@@ -24651,9 +24694,9 @@ fn structFieldPtr(...@@ -24651,9 +24694,9 @@ fn structFieldPtr(
24651 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);24694 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24652 try sema.resolveStructLayout(struct_ty);24695 try sema.resolveStructLayout(struct_ty);
2465324696
24654 if (struct_ty.isTuple()) {24697 if (struct_ty.isTuple(mod)) {
24655 if (mem.eql(u8, field_name, "len")) {24698 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));
24657 return sema.analyzeRef(block, src, len_inst);24700 return sema.analyzeRef(block, src, len_inst);
24658 }24701 }
24659 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);24702 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
...@@ -24663,7 +24706,7 @@ fn structFieldPtr(...@@ -24663,7 +24706,7 @@ fn structFieldPtr(
24663 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);24706 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
24664 }24707 }
2466524708
24666 const struct_obj = struct_ty.castTag(.@"struct").?.data;24709 const struct_obj = mod.typeToStruct(struct_ty).?;
2466724710
24668 const field_index_big = struct_obj.fields.getIndex(field_name) orelse24711 const field_index_big = struct_obj.fields.getIndex(field_name) orelse
24669 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);24712 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
...@@ -24687,7 +24730,7 @@ fn structFieldPtrByIndex(...@@ -24687,7 +24730,7 @@ fn structFieldPtrByIndex(
24687 }24730 }
2468824731
24689 const mod = sema.mod;24732 const mod = sema.mod;
24690 const struct_obj = struct_ty.castTag(.@"struct").?.data;24733 const struct_obj = mod.typeToStruct(struct_ty).?;
24691 const field = struct_obj.fields.values()[field_index];24734 const field = struct_obj.fields.values()[field_index];
24692 const struct_ptr_ty = sema.typeOf(struct_ptr);24735 const struct_ptr_ty = sema.typeOf(struct_ptr);
24693 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod);24736 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod);
...@@ -24799,8 +24842,11 @@ fn structFieldVal(...@@ -24799,8 +24842,11 @@ fn structFieldVal(
24799 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);24842 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24800 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);24843 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24801 },24844 },
24802 .@"struct" => {24845 else => unreachable,
24803 const struct_obj = struct_ty.castTag(.@"struct").?.data;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).?;
24804 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);24850 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2480524851
24806 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse24852 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
...@@ -24827,7 +24873,6 @@ fn structFieldVal(...@@ -24827,7 +24873,6 @@ fn structFieldVal(
24827 },24873 },
24828 else => unreachable,24874 else => unreachable,
24829 },24875 },
24830 else => unreachable,
24831 }24876 }
24832}24877}
2483324878
...@@ -24840,8 +24885,9 @@ fn tupleFieldVal(...@@ -24840,8 +24885,9 @@ fn tupleFieldVal(
24840 field_name_src: LazySrcLoc,24885 field_name_src: LazySrcLoc,
24841 tuple_ty: Type,24886 tuple_ty: Type,
24842) CompileError!Air.Inst.Ref {24887) CompileError!Air.Inst.Ref {
24888 const mod = sema.mod;
24843 if (mem.eql(u8, field_name, "len")) {24889 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));
24845 }24891 }
24846 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src);24892 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src);
24847 return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty);24893 return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty);
...@@ -24858,7 +24904,7 @@ fn tupleFieldIndex(...@@ -24858,7 +24904,7 @@ fn tupleFieldIndex(
24858 const mod = sema.mod;24904 const mod = sema.mod;
24859 assert(!std.mem.eql(u8, field_name, "len"));24905 assert(!std.mem.eql(u8, field_name, "len"));
24860 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {24906 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;
24862 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{24908 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
24863 field_name, tuple_ty.fmt(mod),24909 field_name, tuple_ty.fmt(mod),
24864 });24910 });
...@@ -24878,7 +24924,7 @@ fn tupleFieldValByIndex(...@@ -24878,7 +24924,7 @@ fn tupleFieldValByIndex(
24878 tuple_ty: Type,24924 tuple_ty: Type,
24879) CompileError!Air.Inst.Ref {24925) CompileError!Air.Inst.Ref {
24880 const mod = sema.mod;24926 const mod = sema.mod;
24881 const field_ty = tuple_ty.structFieldType(field_index);24927 const field_ty = tuple_ty.structFieldType(field_index, mod);
2488224928
24883 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {24929 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
24884 return sema.addConstant(field_ty, default_value);24930 return sema.addConstant(field_ty, default_value);
...@@ -25251,7 +25297,7 @@ fn tupleFieldPtr(...@@ -25251,7 +25297,7 @@ fn tupleFieldPtr(
25251 const tuple_ptr_ty = sema.typeOf(tuple_ptr);25297 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
25252 const tuple_ty = tuple_ptr_ty.childType(mod);25298 const tuple_ty = tuple_ptr_ty.childType(mod);
25253 _ = try sema.resolveTypeFields(tuple_ty);25299 _ = try sema.resolveTypeFields(tuple_ty);
25254 const field_count = tuple_ty.structFieldCount();25300 const field_count = tuple_ty.structFieldCount(mod);
2525525301
25256 if (field_count == 0) {25302 if (field_count == 0) {
25257 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});25303 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});
...@@ -25263,7 +25309,7 @@ fn tupleFieldPtr(...@@ -25263,7 +25309,7 @@ fn tupleFieldPtr(
25263 });25309 });
25264 }25310 }
2526525311
25266 const field_ty = tuple_ty.structFieldType(field_index);25312 const field_ty = tuple_ty.structFieldType(field_index, mod);
25267 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{25313 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
25268 .pointee_type = field_ty,25314 .pointee_type = field_ty,
25269 .mutable = tuple_ptr_ty.ptrIsMutable(mod),25315 .mutable = tuple_ptr_ty.ptrIsMutable(mod),
...@@ -25308,7 +25354,7 @@ fn tupleField(...@@ -25308,7 +25354,7 @@ fn tupleField(
25308) CompileError!Air.Inst.Ref {25354) CompileError!Air.Inst.Ref {
25309 const mod = sema.mod;25355 const mod = sema.mod;
25310 const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple));25356 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
25313 if (field_count == 0) {25359 if (field_count == 0) {
25314 return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});25360 return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});
...@@ -25320,7 +25366,7 @@ fn tupleField(...@@ -25320,7 +25366,7 @@ fn tupleField(
25320 });25366 });
25321 }25367 }
2532225368
25323 const field_ty = tuple_ty.structFieldType(field_index);25369 const field_ty = tuple_ty.structFieldType(field_index, mod);
2532425370
25325 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {25371 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
25326 return sema.addConstant(field_ty, default_value); // comptime field25372 return sema.addConstant(field_ty, default_value); // comptime field
...@@ -25919,7 +25965,7 @@ fn coerceExtra(...@@ -25919,7 +25965,7 @@ fn coerceExtra(
25919 .Array => {25965 .Array => {
25920 // pointer to tuple to pointer to array25966 // pointer to tuple to pointer to array
25921 if (inst_ty.isSinglePointer(mod) and25967 if (inst_ty.isSinglePointer(mod) and
25922 inst_ty.childType(mod).isTuple() and25968 inst_ty.childType(mod).isTuple(mod) and
25923 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))25969 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
25924 {25970 {
25925 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);25971 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
...@@ -25939,11 +25985,11 @@ fn coerceExtra(...@@ -25939,11 +25985,11 @@ fn coerceExtra(
2593925985
25940 if (!inst_ty.isSinglePointer(mod)) break :to_slice;25986 if (!inst_ty.isSinglePointer(mod)) break :to_slice;
25941 const inst_child_ty = inst_ty.childType(mod);25987 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
25944 // empty tuple to zero-length slice25990 // empty tuple to zero-length slice
25945 // note that this allows coercing to a mutable slice.25991 // note that this allows coercing to a mutable slice.
25946 if (inst_child_ty.structFieldCount() == 0) {25992 if (inst_child_ty.structFieldCount(mod) == 0) {
25947 // Optional slice is represented with a null pointer so25993 // Optional slice is represented with a null pointer so
25948 // we use a dummy pointer value with the required alignment.25994 // we use a dummy pointer value with the required alignment.
25949 const slice_val = try Value.Tag.slice.create(sema.arena, .{25995 const slice_val = try Value.Tag.slice.create(sema.arena, .{
...@@ -26213,7 +26259,7 @@ fn coerceExtra(...@@ -26213,7 +26259,7 @@ fn coerceExtra(
26213 if (inst == .empty_struct) {26259 if (inst == .empty_struct) {
26214 return sema.arrayInitEmpty(block, inst_src, dest_ty);26260 return sema.arrayInitEmpty(block, inst_src, dest_ty);
26215 }26261 }
26216 if (inst_ty.isTuple()) {26262 if (inst_ty.isTuple(mod)) {
26217 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);26263 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
26218 }26264 }
26219 },26265 },
...@@ -26225,7 +26271,7 @@ fn coerceExtra(...@@ -26225,7 +26271,7 @@ fn coerceExtra(
26225 .Vector => switch (inst_ty.zigTypeTag(mod)) {26271 .Vector => switch (inst_ty.zigTypeTag(mod)) {
26226 .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),26272 .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
26227 .Struct => {26273 .Struct => {
26228 if (inst_ty.isTuple()) {26274 if (inst_ty.isTuple(mod)) {
26229 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);26275 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
26230 }26276 }
26231 },26277 },
...@@ -26238,7 +26284,7 @@ fn coerceExtra(...@@ -26238,7 +26284,7 @@ fn coerceExtra(
26238 if (inst == .empty_struct) {26284 if (inst == .empty_struct) {
26239 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);26285 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);
26240 }26286 }
26241 if (inst_ty.isTupleOrAnonStruct()) {26287 if (inst_ty.isTupleOrAnonStruct(mod)) {
26242 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {26288 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
26243 error.NotCoercible => break :blk,26289 error.NotCoercible => break :blk,
26244 else => |e| return e,26290 else => |e| return e,
...@@ -27304,8 +27350,8 @@ fn storePtr2(...@@ -27304,8 +27350,8 @@ fn storePtr2(
27304 // this code does not handle tuple-to-struct coercion which requires dealing with missing27350 // this code does not handle tuple-to-struct coercion which requires dealing with missing
27305 // fields.27351 // fields.
27306 const operand_ty = sema.typeOf(uncasted_operand);27352 const operand_ty = sema.typeOf(uncasted_operand);
27307 if (operand_ty.isTuple() and elem_ty.zigTypeTag(mod) == .Array) {27353 if (operand_ty.isTuple(mod) and elem_ty.zigTypeTag(mod) == .Array) {
27308 const field_count = operand_ty.structFieldCount();27354 const field_count = operand_ty.structFieldCount(mod);
27309 var i: u32 = 0;27355 var i: u32 = 0;
27310 while (i < field_count) : (i += 1) {27356 while (i < field_count) : (i += 1) {
27311 const elem_src = operand_src; // TODO better source location27357 const elem_src = operand_src; // TODO better source location
...@@ -27804,7 +27850,7 @@ fn beginComptimePtrMutation(...@@ -27804,7 +27850,7 @@ fn beginComptimePtrMutation(
2780427850
27805 switch (parent.ty.zigTypeTag(mod)) {27851 switch (parent.ty.zigTypeTag(mod)) {
27806 .Struct => {27852 .Struct => {
27807 const fields = try arena.alloc(Value, parent.ty.structFieldCount());27853 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
27808 @memset(fields, Value.undef);27854 @memset(fields, Value.undef);
2780927855
27810 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);27856 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
...@@ -27813,7 +27859,7 @@ fn beginComptimePtrMutation(...@@ -27813,7 +27859,7 @@ fn beginComptimePtrMutation(
27813 sema,27859 sema,
27814 block,27860 block,
27815 src,27861 src,
27816 parent.ty.structFieldType(field_index),27862 parent.ty.structFieldType(field_index, mod),
27817 &fields[field_index],27863 &fields[field_index],
27818 ptr_elem_ty,27864 ptr_elem_ty,
27819 parent.decl_ref_mut,27865 parent.decl_ref_mut,
...@@ -27832,7 +27878,7 @@ fn beginComptimePtrMutation(...@@ -27832,7 +27878,7 @@ fn beginComptimePtrMutation(
27832 sema,27878 sema,
27833 block,27879 block,
27834 src,27880 src,
27835 parent.ty.structFieldType(field_index),27881 parent.ty.structFieldType(field_index, mod),
27836 &payload.data.val,27882 &payload.data.val,
27837 ptr_elem_ty,27883 ptr_elem_ty,
27838 parent.decl_ref_mut,27884 parent.decl_ref_mut,
...@@ -27878,7 +27924,7 @@ fn beginComptimePtrMutation(...@@ -27878,7 +27924,7 @@ fn beginComptimePtrMutation(
27878 sema,27924 sema,
27879 block,27925 block,
27880 src,27926 src,
27881 parent.ty.structFieldType(field_index),27927 parent.ty.structFieldType(field_index, mod),
27882 duped,27928 duped,
27883 ptr_elem_ty,27929 ptr_elem_ty,
27884 parent.decl_ref_mut,27930 parent.decl_ref_mut,
...@@ -27889,7 +27935,7 @@ fn beginComptimePtrMutation(...@@ -27889,7 +27935,7 @@ fn beginComptimePtrMutation(
27889 sema,27935 sema,
27890 block,27936 block,
27891 src,27937 src,
27892 parent.ty.structFieldType(field_index),27938 parent.ty.structFieldType(field_index, mod),
27893 &val_ptr.castTag(.aggregate).?.data[field_index],27939 &val_ptr.castTag(.aggregate).?.data[field_index],
27894 ptr_elem_ty,27940 ptr_elem_ty,
27895 parent.decl_ref_mut,27941 parent.decl_ref_mut,
...@@ -27907,7 +27953,7 @@ fn beginComptimePtrMutation(...@@ -27907,7 +27953,7 @@ fn beginComptimePtrMutation(
27907 sema,27953 sema,
27908 block,27954 block,
27909 src,27955 src,
27910 parent.ty.structFieldType(field_index),27956 parent.ty.structFieldType(field_index, mod),
27911 &payload.val,27957 &payload.val,
27912 ptr_elem_ty,27958 ptr_elem_ty,
27913 parent.decl_ref_mut,27959 parent.decl_ref_mut,
...@@ -28269,8 +28315,8 @@ fn beginComptimePtrLoad(...@@ -28269,8 +28315,8 @@ fn beginComptimePtrLoad(
28269 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);28315 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);
2827028316
28271 if (field_ptr.container_ty.hasWellDefinedLayout(mod)) {28317 if (field_ptr.container_ty.hasWellDefinedLayout(mod)) {
28272 const struct_ty = field_ptr.container_ty.castTag(.@"struct");28318 const struct_obj = mod.typeToStruct(field_ptr.container_ty);
28273 if (struct_ty != null and struct_ty.?.data.layout == .Packed) {28319 if (struct_obj != null and struct_obj.?.layout == .Packed) {
28274 // packed structs are not byte addressable28320 // packed structs are not byte addressable
28275 deref.parent = null;28321 deref.parent = null;
28276 } else if (deref.parent) |*parent| {28322 } else if (deref.parent) |*parent| {
...@@ -28310,7 +28356,7 @@ fn beginComptimePtrLoad(...@@ -28310,7 +28356,7 @@ fn beginComptimePtrLoad(
28310 else => unreachable,28356 else => unreachable,
28311 };28357 };
28312 } else {28358 } else {
28313 const field_ty = field_ptr.container_ty.structFieldType(field_index);28359 const field_ty = field_ptr.container_ty.structFieldType(field_index, mod);
28314 deref.pointee = TypedValue{28360 deref.pointee = TypedValue{
28315 .ty = field_ty,28361 .ty = field_ty,
28316 .val = try tv.val.fieldValue(tv.ty, mod, field_index),28362 .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...@@ -28483,7 +28529,7 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
28483 const inst_info = inst_ty.ptrInfo(mod);28529 const inst_info = inst_ty.ptrInfo(mod);
28484 const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or28530 const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or
28485 (inst_info.pointee_type.arrayLen(mod) == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or28531 (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
28488 const ok_cv_qualifiers =28534 const ok_cv_qualifiers =
28489 ((inst_info.mutable or !dest_info.mutable) or len0) and28535 ((inst_info.mutable or !dest_info.mutable) or len0) and
...@@ -28714,8 +28760,9 @@ fn coerceAnonStructToUnion(...@@ -28714,8 +28760,9 @@ fn coerceAnonStructToUnion(
28714 inst: Air.Inst.Ref,28760 inst: Air.Inst.Ref,
28715 inst_src: LazySrcLoc,28761 inst_src: LazySrcLoc,
28716) !Air.Inst.Ref {28762) !Air.Inst.Ref {
28763 const mod = sema.mod;
28717 const inst_ty = sema.typeOf(inst);28764 const inst_ty = sema.typeOf(inst);
28718 const field_count = inst_ty.structFieldCount();28765 const field_count = inst_ty.structFieldCount(mod);
28719 if (field_count != 1) {28766 if (field_count != 1) {
28720 const msg = msg: {28767 const msg = msg: {
28721 const msg = if (field_count > 1) try sema.errMsg(28768 const msg = if (field_count > 1) try sema.errMsg(
...@@ -28927,7 +28974,7 @@ fn coerceTupleToSlicePtrs(...@@ -28927,7 +28974,7 @@ fn coerceTupleToSlicePtrs(
28927 const tuple_ty = sema.typeOf(ptr_tuple).childType(mod);28974 const tuple_ty = sema.typeOf(ptr_tuple).childType(mod);
28928 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);28975 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);
28929 const slice_info = slice_ty.ptrInfo(mod);28976 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);
28931 const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src);28978 const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src);
28932 if (slice_info.@"align" != 0) {28979 if (slice_info.@"align" != 0) {
28933 return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{});28980 return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{});
...@@ -28966,20 +29013,21 @@ fn coerceTupleToStruct(...@@ -28966,20 +29013,21 @@ fn coerceTupleToStruct(
28966 inst: Air.Inst.Ref,29013 inst: Air.Inst.Ref,
28967 inst_src: LazySrcLoc,29014 inst_src: LazySrcLoc,
28968) !Air.Inst.Ref {29015) !Air.Inst.Ref {
29016 const mod = sema.mod;
28969 const struct_ty = try sema.resolveTypeFields(dest_ty);29017 const struct_ty = try sema.resolveTypeFields(dest_ty);
2897029018
28971 if (struct_ty.isTupleOrAnonStruct()) {29019 if (struct_ty.isTupleOrAnonStruct(mod)) {
28972 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);29020 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
28973 }29021 }
2897429022
28975 const fields = struct_ty.structFields();29023 const fields = struct_ty.structFields(mod);
28976 const field_vals = try sema.arena.alloc(Value, fields.count());29024 const field_vals = try sema.arena.alloc(Value, fields.count());
28977 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);29025 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
28978 @memset(field_refs, .none);29026 @memset(field_refs, .none);
2897929027
28980 const inst_ty = sema.typeOf(inst);29028 const inst_ty = sema.typeOf(inst);
28981 var runtime_src: ?LazySrcLoc = null;29029 var runtime_src: ?LazySrcLoc = null;
28982 const field_count = inst_ty.structFieldCount();29030 const field_count = inst_ty.structFieldCount(mod);
28983 var field_i: u32 = 0;29031 var field_i: u32 = 0;
28984 while (field_i < field_count) : (field_i += 1) {29032 while (field_i < field_count) : (field_i += 1) {
28985 const field_src = inst_src; // TODO better source location29033 const field_src = inst_src; // TODO better source location
...@@ -29061,13 +29109,14 @@ fn coerceTupleToTuple(...@@ -29061,13 +29109,14 @@ fn coerceTupleToTuple(
29061 inst: Air.Inst.Ref,29109 inst: Air.Inst.Ref,
29062 inst_src: LazySrcLoc,29110 inst_src: LazySrcLoc,
29063) !Air.Inst.Ref {29111) !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);
29065 const field_vals = try sema.arena.alloc(Value, dest_field_count);29114 const field_vals = try sema.arena.alloc(Value, dest_field_count);
29066 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);29115 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
29067 @memset(field_refs, .none);29116 @memset(field_refs, .none);
2906829117
29069 const inst_ty = sema.typeOf(inst);29118 const inst_ty = sema.typeOf(inst);
29070 const inst_field_count = inst_ty.structFieldCount();29119 const inst_field_count = inst_ty.structFieldCount(mod);
29071 if (inst_field_count > dest_field_count) return error.NotCoercible;29120 if (inst_field_count > dest_field_count) return error.NotCoercible;
2907229121
29073 var runtime_src: ?LazySrcLoc = null;29122 var runtime_src: ?LazySrcLoc = null;
...@@ -29085,8 +29134,8 @@ fn coerceTupleToTuple(...@@ -29085,8 +29134,8 @@ fn coerceTupleToTuple(
2908529134
29086 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);29135 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2908729136
29088 const field_ty = tuple_ty.structFieldType(field_i);29137 const field_ty = tuple_ty.structFieldType(field_i, mod);
29089 const default_val = tuple_ty.structFieldDefaultValue(field_i);29138 const default_val = tuple_ty.structFieldDefaultValue(field_i, mod);
29090 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);29139 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
29091 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);29140 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
29092 field_refs[field_index] = coerced;29141 field_refs[field_index] = coerced;
...@@ -29115,12 +29164,12 @@ fn coerceTupleToTuple(...@@ -29115,12 +29164,12 @@ fn coerceTupleToTuple(
29115 for (field_refs, 0..) |*field_ref, i| {29164 for (field_refs, 0..) |*field_ref, i| {
29116 if (field_ref.* != .none) continue;29165 if (field_ref.* != .none) continue;
2911729166
29118 const default_val = tuple_ty.structFieldDefaultValue(i);29167 const default_val = tuple_ty.structFieldDefaultValue(i, mod);
29119 const field_ty = tuple_ty.structFieldType(i);29168 const field_ty = tuple_ty.structFieldType(i, mod);
2912029169
29121 const field_src = inst_src; // TODO better source location29170 const field_src = inst_src; // TODO better source location
29122 if (default_val.ip_index == .unreachable_value) {29171 if (default_val.ip_index == .unreachable_value) {
29123 if (tuple_ty.isTuple()) {29172 if (tuple_ty.isTuple(mod)) {
29124 const template = "missing tuple field: {d}";29173 const template = "missing tuple field: {d}";
29125 if (root_msg) |msg| {29174 if (root_msg) |msg| {
29126 try sema.errNote(block, field_src, msg, template, .{i});29175 try sema.errNote(block, field_src, msg, template, .{i});
...@@ -29130,7 +29179,7 @@ fn coerceTupleToTuple(...@@ -29130,7 +29179,7 @@ fn coerceTupleToTuple(
29130 continue;29179 continue;
29131 }29180 }
29132 const template = "missing struct field: {s}";29181 const template = "missing struct field: {s}";
29133 const args = .{tuple_ty.structFieldName(i)};29182 const args = .{tuple_ty.structFieldName(i, mod)};
29134 if (root_msg) |msg| {29183 if (root_msg) |msg| {
29135 try sema.errNote(block, field_src, msg, template, args);29184 try sema.errNote(block, field_src, msg, template, args);
29136 } else {29185 } else {
...@@ -31222,17 +31271,17 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31222,17 +31271,17 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
31222}31271}
3122331272
31224fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {31273fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31274 const mod = sema.mod;
31225 const resolved_ty = try sema.resolveTypeFields(ty);31275 const resolved_ty = try sema.resolveTypeFields(ty);
31226 if (resolved_ty.castTag(.@"struct")) |payload| {31276 if (mod.typeToStruct(resolved_ty)) |struct_obj| {
31227 const struct_obj = payload.data;
31228 switch (struct_obj.status) {31277 switch (struct_obj.status) {
31229 .none, .have_field_types => {},31278 .none, .have_field_types => {},
31230 .field_types_wip, .layout_wip => {31279 .field_types_wip, .layout_wip => {
31231 const msg = try Module.ErrorMsg.create(31280 const msg = try Module.ErrorMsg.create(
31232 sema.gpa,31281 sema.gpa,
31233 struct_obj.srcLoc(sema.mod),31282 struct_obj.srcLoc(mod),
31234 "struct '{}' depends on itself",31283 "struct '{}' depends on itself",
31235 .{ty.fmt(sema.mod)},31284 .{ty.fmt(mod)},
31236 );31285 );
31237 return sema.failWithOwnedErrorMsg(msg);31286 return sema.failWithOwnedErrorMsg(msg);
31238 },31287 },
...@@ -31256,7 +31305,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31256,7 +31305,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31256 }31305 }
3125731306
31258 if (struct_obj.layout == .Packed) {31307 if (struct_obj.layout == .Packed) {
31259 try semaBackingIntType(sema.mod, struct_obj);31308 try semaBackingIntType(mod, struct_obj);
31260 }31309 }
3126131310
31262 struct_obj.status = .have_layout;31311 struct_obj.status = .have_layout;
...@@ -31265,20 +31314,20 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31265,20 +31314,20 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31265 if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {31314 if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {
31266 const msg = try Module.ErrorMsg.create(31315 const msg = try Module.ErrorMsg.create(
31267 sema.gpa,31316 sema.gpa,
31268 struct_obj.srcLoc(sema.mod),31317 struct_obj.srcLoc(mod),
31269 "struct layout depends on it having runtime bits",31318 "struct layout depends on it having runtime bits",
31270 .{},31319 .{},
31271 );31320 );
31272 return sema.failWithOwnedErrorMsg(msg);31321 return sema.failWithOwnedErrorMsg(msg);
31273 }31322 }
3127431323
31275 if (struct_obj.layout == .Auto and sema.mod.backendSupportsFeature(.field_reordering)) {31324 if (struct_obj.layout == .Auto and mod.backendSupportsFeature(.field_reordering)) {
31276 const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index)31325 const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index)
31277 try sema.perm_arena.alloc(u32, struct_obj.fields.count())31326 try sema.perm_arena.alloc(u32, struct_obj.fields.count())
31278 else blk: {31327 else blk: {
31279 const decl = sema.mod.declPtr(struct_obj.owner_decl);31328 const decl = mod.declPtr(struct_obj.owner_decl);
31280 var decl_arena: std.heap.ArenaAllocator = undefined;31329 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);
31282 defer decl.value_arena.?.release(&decl_arena);31331 defer decl.value_arena.?.release(&decl_arena);
31283 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());31332 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());
31284 };31333 };
...@@ -31528,7 +31577,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31528,7 +31577,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31528 return switch (ty.ip_index) {31577 return switch (ty.ip_index) {
31529 .empty_struct_type => false,31578 .empty_struct_type => false,
31530 .none => switch (ty.tag()) {31579 .none => switch (ty.tag()) {
31531 .empty_struct,
31532 .error_set,31580 .error_set,
31533 .error_set_single,31581 .error_set_single,
31534 .error_set_inferred,31582 .error_set_inferred,
...@@ -31569,27 +31617,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31569,27 +31617,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31569 return false;31617 return false;
31570 },31618 },
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
31593 .@"union", .union_safety_tagged, .union_tagged => {31620 .@"union", .union_safety_tagged, .union_tagged => {
31594 const union_obj = ty.cast(Type.Payload.Union).?.data;31621 const union_obj = ty.cast(Type.Payload.Union).?.data;
31595 switch (union_obj.requires_comptime) {31622 switch (union_obj.requires_comptime) {
...@@ -31686,7 +31713,27 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31686,7 +31713,27 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31686 .type_info,31713 .type_info,
31687 => true,31714 => true,
31688 },31715 },
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
31690 .union_type => @panic("TODO"),31737 .union_type => @panic("TODO"),
31691 .opaque_type => false,31738 .opaque_type => false,
3169231739
...@@ -31697,6 +31744,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31697,6 +31744,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31697 .ptr => unreachable,31744 .ptr => unreachable,
31698 .opt => unreachable,31745 .opt => unreachable,
31699 .enum_tag => unreachable,31746 .enum_tag => unreachable,
31747 .aggregate => unreachable,
31700 },31748 },
31701 };31749 };
31702}31750}
...@@ -31710,16 +31758,21 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31710,16 +31758,21 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31710 const child_ty = try sema.resolveTypeFields(ty.childType(mod));31758 const child_ty = try sema.resolveTypeFields(ty.childType(mod));
31711 return sema.resolveTypeFully(child_ty);31759 return sema.resolveTypeFully(child_ty);
31712 },31760 },
31713 .Struct => switch (ty.tag()) {31761 .Struct => switch (ty.ip_index) {
31714 .@"struct" => return sema.resolveStructFully(ty),31762 .none => switch (ty.tag()) {
31715 .tuple, .anon_struct => {31763 .tuple, .anon_struct => {
31716 const tuple = ty.tupleFields();31764 const tuple = ty.tupleFields();
3171731765
31718 for (tuple.types) |field_ty| {31766 for (tuple.types) |field_ty| {
31719 try sema.resolveTypeFully(field_ty);31767 try sema.resolveTypeFully(field_ty);
31720 }31768 }
31769 },
31770 else => {},
31771 },
31772 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31773 .struct_type => return sema.resolveStructFully(ty),
31774 else => {},
31721 },31775 },
31722 else => {},
31723 },31776 },
31724 .Union => return sema.resolveUnionFully(ty),31777 .Union => return sema.resolveUnionFully(ty),
31725 .Array => return sema.resolveTypeFully(ty.childType(mod)),31778 .Array => return sema.resolveTypeFully(ty.childType(mod)),
...@@ -31746,9 +31799,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31746,9 +31799,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31746fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {31799fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
31747 try sema.resolveStructLayout(ty);31800 try sema.resolveStructLayout(ty);
3174831801
31802 const mod = sema.mod;
31749 const resolved_ty = try sema.resolveTypeFields(ty);31803 const resolved_ty = try sema.resolveTypeFields(ty);
31750 const payload = resolved_ty.castTag(.@"struct").?;31804 const struct_obj = mod.typeToStruct(resolved_ty).?;
31751 const struct_obj = payload.data;
3175231805
31753 switch (struct_obj.status) {31806 switch (struct_obj.status) {
31754 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},31807 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
...@@ -31806,11 +31859,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -31806,11 +31859,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3180631859
31807 switch (ty.ip_index) {31860 switch (ty.ip_index) {
31808 .none => switch (ty.tag()) {31861 .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 },
31814 .@"union", .union_safety_tagged, .union_tagged => {31862 .@"union", .union_safety_tagged, .union_tagged => {
31815 const union_obj = ty.cast(Type.Payload.Union).?.data;31863 const union_obj = ty.cast(Type.Payload.Union).?.data;
31816 try sema.resolveTypeFieldsUnion(ty, union_obj);31864 try sema.resolveTypeFieldsUnion(ty, union_obj);
...@@ -31904,7 +31952,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -31904,7 +31952,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
31904 .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"),31952 .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"),
3190531953
31906 _ => switch (mod.intern_pool.indexToKey(ty.ip_index)) {31954 _ => 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 },
31908 .union_type => @panic("TODO"),31960 .union_type => @panic("TODO"),
31909 else => return ty,31961 else => return ty,
31910 },31962 },
...@@ -33010,28 +33062,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33010,28 +33062,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33010 }33062 }
33011 },33063 },
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
33035 .tuple, .anon_struct => {33065 .tuple, .anon_struct => {
33036 const tuple = ty.tupleFields();33066 const tuple = ty.tupleFields();
33037 for (tuple.values, 0..) |val, i| {33067 for (tuple.values, 0..) |val, i| {
...@@ -33120,8 +33150,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33120,8 +33150,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33120 });33150 });
33121 },33151 },
3312233152
33123 .empty_struct => return Value.empty_struct,
33124
33125 .array => {33153 .array => {
33126 if (ty.arrayLen(mod) == 0)33154 if (ty.arrayLen(mod) == 0)
33127 return Value.initTag(.empty_array);33155 return Value.initTag(.empty_array);
...@@ -33212,7 +33240,34 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33212,7 +33240,34 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33212 .generic_poison => return error.GenericPoison,33240 .generic_poison => return error.GenericPoison,
33213 .var_args_param => unreachable,33241 .var_args_param => unreachable,
33214 },33242 },
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
33216 .union_type => @panic("TODO"),33271 .union_type => @panic("TODO"),
33217 .opaque_type => null,33272 .opaque_type => null,
3321833273
...@@ -33223,6 +33278,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33223,6 +33278,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33223 .ptr => unreachable,33278 .ptr => unreachable,
33224 .opt => unreachable,33279 .opt => unreachable,
33225 .enum_tag => unreachable,33280 .enum_tag => unreachable,
33281 .aggregate => unreachable,
33226 },33282 },
33227 }33283 }
33228}33284}
...@@ -33614,7 +33670,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33614,7 +33670,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33614 .empty_struct_type => false,33670 .empty_struct_type => false,
3361533671
33616 .none => switch (ty.tag()) {33672 .none => switch (ty.tag()) {
33617 .empty_struct,
33618 .error_set,33673 .error_set,
33619 .error_set_single,33674 .error_set_single,
33620 .error_set_inferred,33675 .error_set_inferred,
...@@ -33655,31 +33710,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33655,31 +33710,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33655 return false;33710 return false;
33656 },33711 },
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
33683 .@"union", .union_safety_tagged, .union_tagged => {33713 .@"union", .union_safety_tagged, .union_tagged => {
33684 const union_obj = ty.cast(Type.Payload.Union).?.data;33714 const union_obj = ty.cast(Type.Payload.Union).?.data;
33685 switch (union_obj.requires_comptime) {33715 switch (union_obj.requires_comptime) {
...@@ -33782,7 +33812,31 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33782,7 +33812,31 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3378233812
33783 .var_args_param => unreachable,33813 .var_args_param => unreachable,
33784 },33814 },
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
33786 .union_type => @panic("TODO"),33840 .union_type => @panic("TODO"),
33787 .opaque_type => false,33841 .opaque_type => false,
3378833842
...@@ -33793,6 +33847,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33793,6 +33847,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33793 .ptr => unreachable,33847 .ptr => unreachable,
33794 .opt => unreachable,33848 .opt => unreachable,
33795 .enum_tag => unreachable,33849 .enum_tag => unreachable,
33850 .aggregate => unreachable,
33796 },33851 },
33797 };33852 };
33798}33853}
...@@ -33864,11 +33919,12 @@ fn structFieldIndex(...@@ -33864,11 +33919,12 @@ fn structFieldIndex(
33864 field_name: []const u8,33919 field_name: []const u8,
33865 field_src: LazySrcLoc,33920 field_src: LazySrcLoc,
33866) !u32 {33921) !u32 {
33922 const mod = sema.mod;
33867 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);33923 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
33868 if (struct_ty.isAnonStruct()) {33924 if (struct_ty.isAnonStruct()) {
33869 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);33925 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
33870 } else {33926 } else {
33871 const struct_obj = struct_ty.castTag(.@"struct").?.data;33927 const struct_obj = mod.typeToStruct(struct_ty).?;
33872 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse33928 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
33873 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);33929 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
33874 return @intCast(u32, field_index_usize);33930 return @intCast(u32, field_index_usize);
src/TypedValue.zig+13-7
...@@ -180,7 +180,7 @@ pub fn print(...@@ -180,7 +180,7 @@ pub fn print(
180 switch (field_ptr.container_ty.tag()) {180 switch (field_ptr.container_ty.tag()) {
181 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),181 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),
182 else => {182 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);
184 return writer.print(".{s}", .{field_name});184 return writer.print(".{s}", .{field_name});
185 },185 },
186 }186 }
...@@ -381,21 +381,27 @@ fn printAggregate(...@@ -381,21 +381,27 @@ fn printAggregate(
381 }381 }
382 if (ty.zigTypeTag(mod) == .Struct) {382 if (ty.zigTypeTag(mod) == .Struct) {
383 try writer.writeAll(".{");383 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
386 var i: u32 = 0;386 var i: u32 = 0;
387 while (i < max_len) : (i += 1) {387 while (i < max_len) : (i += 1) {
388 if (i != 0) try writer.writeAll(", ");388 if (i != 0) try writer.writeAll(", ");
389 switch (ty.tag()) {389 switch (ty.ip_index) {
390 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),390 .none => switch (ty.tag()) {
391 else => {},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 },
392 }398 }
393 try print(.{399 try print(.{
394 .ty = ty.structFieldType(i),400 .ty = ty.structFieldType(i, mod),
395 .val = try val.fieldValue(ty, mod, i),401 .val = try val.fieldValue(ty, mod, i),
396 }, writer, level - 1, mod);402 }, writer, level - 1, mod);
397 }403 }
398 if (ty.structFieldCount() > max_aggregate_items) {404 if (ty.structFieldCount(mod) > max_aggregate_items) {
399 try writer.writeAll(", ...");405 try writer.writeAll(", ...");
400 }406 }
401 return writer.writeAll("}");407 return writer.writeAll("}");
src/arch/aarch64/CodeGen.zig+3-3
...@@ -4119,7 +4119,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4119,7 +4119,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
4119 const mod = self.bin_file.options.module.?;4119 const mod = self.bin_file.options.module.?;
4120 const mcv = try self.resolveInst(operand);4120 const mcv = try self.resolveInst(operand);
4121 const struct_ty = self.typeOf(operand);4121 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);
4123 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));4123 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
41244124
4125 switch (mcv) {4125 switch (mcv) {
...@@ -5466,10 +5466,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5466,10 +5466,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5466 const reg_lock = self.register_manager.lockReg(rwo.reg);5466 const reg_lock = self.register_manager.lockReg(rwo.reg);
5467 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);5467 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);
5470 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });5470 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);
5473 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));5473 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
5474 const raw_cond_reg = try self.register_manager.allocReg(null, gp);5474 const raw_cond_reg = try self.register_manager.allocReg(null, gp);
5475 const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty);5475 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 {...@@ -21,7 +21,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
21 var maybe_float_bits: ?u16 = null;21 var maybe_float_bits: ?u16 = null;
22 switch (ty.zigTypeTag(mod)) {22 switch (ty.zigTypeTag(mod)) {
23 .Struct => {23 .Struct => {
24 if (ty.containerLayout() == .Packed) return .byval;24 if (ty.containerLayout(mod) == .Packed) return .byval;
25 const float_count = countFloats(ty, mod, &maybe_float_bits);25 const float_count = countFloats(ty, mod, &maybe_float_bits);
26 if (float_count <= sret_float_count) return .{ .float_array = float_count };26 if (float_count <= sret_float_count) return .{ .float_array = float_count };
2727
...@@ -31,7 +31,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {...@@ -31,7 +31,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
31 return .integer;31 return .integer;
32 },32 },
33 .Union => {33 .Union => {
34 if (ty.containerLayout() == .Packed) return .byval;34 if (ty.containerLayout(mod) == .Packed) return .byval;
35 const float_count = countFloats(ty, mod, &maybe_float_bits);35 const float_count = countFloats(ty, mod, &maybe_float_bits);
36 if (float_count <= sret_float_count) return .{ .float_array = float_count };36 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 {...@@ -90,11 +90,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 {
90 return max_count;90 return max_count;
91 },91 },
92 .Struct => {92 .Struct => {
93 const fields_len = ty.structFieldCount();93 const fields_len = ty.structFieldCount(mod);
94 var count: u8 = 0;94 var count: u8 = 0;
95 var i: u32 = 0;95 var i: u32 = 0;
96 while (i < fields_len) : (i += 1) {96 while (i < fields_len) : (i += 1) {
97 const field_ty = ty.structFieldType(i);97 const field_ty = ty.structFieldType(i, mod);
98 const field_count = countFloats(field_ty, mod, maybe_float_bits);98 const field_count = countFloats(field_ty, mod, maybe_float_bits);
99 if (field_count == invalid) return invalid;99 if (field_count == invalid) return invalid;
100 count += field_count;100 count += field_count;
...@@ -125,10 +125,10 @@ pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type {...@@ -125,10 +125,10 @@ pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type {
125 return null;125 return null;
126 },126 },
127 .Struct => {127 .Struct => {
128 const fields_len = ty.structFieldCount();128 const fields_len = ty.structFieldCount(mod);
129 var i: u32 = 0;129 var i: u32 = 0;
130 while (i < fields_len) : (i += 1) {130 while (i < fields_len) : (i += 1) {
131 const field_ty = ty.structFieldType(i);131 const field_ty = ty.structFieldType(i, mod);
132 if (getFloatArrayType(field_ty, mod)) |some| return some;132 if (getFloatArrayType(field_ty, mod)) |some| return some;
133 }133 }
134 return null;134 return null;
src/arch/arm/CodeGen.zig+3-3
...@@ -2910,7 +2910,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2910,7 +2910,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2910 const mcv = try self.resolveInst(operand);2910 const mcv = try self.resolveInst(operand);
2911 const struct_ty = self.typeOf(operand);2911 const struct_ty = self.typeOf(operand);
2912 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));2912 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
2915 switch (mcv) {2915 switch (mcv) {
2916 .dead, .unreach => unreachable,2916 .dead, .unreach => unreachable,
...@@ -5404,10 +5404,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5404,10 +5404,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5404 const reg_lock = self.register_manager.lockReg(reg);5404 const reg_lock = self.register_manager.lockReg(reg);
5405 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);5405 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);
5408 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });5408 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);
5411 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));5411 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
5412 const cond_reg = try self.register_manager.allocReg(null, gp);5412 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 {...@@ -32,7 +32,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
32 switch (ty.zigTypeTag(mod)) {32 switch (ty.zigTypeTag(mod)) {
33 .Struct => {33 .Struct => {
34 const bit_size = ty.bitSize(mod);34 const bit_size = ty.bitSize(mod);
35 if (ty.containerLayout() == .Packed) {35 if (ty.containerLayout(mod) == .Packed) {
36 if (bit_size > 64) return .memory;36 if (bit_size > 64) return .memory;
37 return .byval;37 return .byval;
38 }38 }
...@@ -40,10 +40,10 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {...@@ -40,10 +40,10 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
40 const float_count = countFloats(ty, mod, &maybe_float_bits);40 const float_count = countFloats(ty, mod, &maybe_float_bits);
41 if (float_count <= byval_float_count) return .byval;41 if (float_count <= byval_float_count) return .byval;
4242
43 const fields = ty.structFieldCount();43 const fields = ty.structFieldCount(mod);
44 var i: u32 = 0;44 var i: u32 = 0;
45 while (i < fields) : (i += 1) {45 while (i < fields) : (i += 1) {
46 const field_ty = ty.structFieldType(i);46 const field_ty = ty.structFieldType(i, mod);
47 const field_alignment = ty.structFieldAlign(i, mod);47 const field_alignment = ty.structFieldAlign(i, mod);
48 const field_size = field_ty.bitSize(mod);48 const field_size = field_ty.bitSize(mod);
49 if (field_size > 32 or field_alignment > 32) {49 if (field_size > 32 or field_alignment > 32) {
...@@ -54,7 +54,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {...@@ -54,7 +54,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
54 },54 },
55 .Union => {55 .Union => {
56 const bit_size = ty.bitSize(mod);56 const bit_size = ty.bitSize(mod);
57 if (ty.containerLayout() == .Packed) {57 if (ty.containerLayout(mod) == .Packed) {
58 if (bit_size > 64) return .memory;58 if (bit_size > 64) return .memory;
59 return .byval;59 return .byval;
60 }60 }
...@@ -132,11 +132,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 {...@@ -132,11 +132,11 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 {
132 return max_count;132 return max_count;
133 },133 },
134 .Struct => {134 .Struct => {
135 const fields_len = ty.structFieldCount();135 const fields_len = ty.structFieldCount(mod);
136 var count: u32 = 0;136 var count: u32 = 0;
137 var i: u32 = 0;137 var i: u32 = 0;
138 while (i < fields_len) : (i += 1) {138 while (i < fields_len) : (i += 1) {
139 const field_ty = ty.structFieldType(i);139 const field_ty = ty.structFieldType(i, mod);
140 const field_count = countFloats(field_ty, mod, maybe_float_bits);140 const field_count = countFloats(field_ty, mod, maybe_float_bits);
141 if (field_count == invalid) return invalid;141 if (field_count == invalid) return invalid;
142 count += field_count;142 count += field_count;
src/arch/riscv64/abi.zig+2-2
...@@ -15,7 +15,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {...@@ -15,7 +15,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
15 switch (ty.zigTypeTag(mod)) {15 switch (ty.zigTypeTag(mod)) {
16 .Struct => {16 .Struct => {
17 const bit_size = ty.bitSize(mod);17 const bit_size = ty.bitSize(mod);
18 if (ty.containerLayout() == .Packed) {18 if (ty.containerLayout(mod) == .Packed) {
19 if (bit_size > max_byval_size) return .memory;19 if (bit_size > max_byval_size) return .memory;
20 return .byval;20 return .byval;
21 }21 }
...@@ -26,7 +26,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {...@@ -26,7 +26,7 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
26 },26 },
27 .Union => {27 .Union => {
28 const bit_size = ty.bitSize(mod);28 const bit_size = ty.bitSize(mod);
29 if (ty.containerLayout() == .Packed) {29 if (ty.containerLayout(mod) == .Packed) {
30 if (bit_size > max_byval_size) return .memory;30 if (bit_size > max_byval_size) return .memory;
31 return .byval;31 return .byval;
32 }32 }
src/arch/sparc64/CodeGen.zig+2-2
...@@ -3993,10 +3993,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3993,10 +3993,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3993 const reg_lock = self.register_manager.lockReg(rwo.reg);3993 const reg_lock = self.register_manager.lockReg(rwo.reg);
3994 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);3994 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);
3997 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });3997 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);
4000 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));4000 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
4001 const cond_reg = try self.register_manager.allocReg(null, gp);4001 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 {...@@ -1006,9 +1006,9 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
1006 if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64;1006 if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64;
1007 break :blk wasm.Valtype.i32; // represented as pointer to stack1007 break :blk wasm.Valtype.i32; // represented as pointer to stack
1008 },1008 },
1009 .Struct => switch (ty.containerLayout()) {1009 .Struct => switch (ty.containerLayout(mod)) {
1010 .Packed => {1010 .Packed => {
1011 const struct_obj = ty.castTag(.@"struct").?.data;1011 const struct_obj = mod.typeToStruct(ty).?;
1012 return typeToValtype(struct_obj.backing_int_ty, mod);1012 return typeToValtype(struct_obj.backing_int_ty, mod);
1013 },1013 },
1014 else => wasm.Valtype.i32,1014 else => wasm.Valtype.i32,
...@@ -1017,7 +1017,7 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {...@@ -1017,7 +1017,7 @@ fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
1017 .direct => wasm.Valtype.v128,1017 .direct => wasm.Valtype.v128,
1018 .unrolled => wasm.Valtype.i32,1018 .unrolled => wasm.Valtype.i32,
1019 },1019 },
1020 .Union => switch (ty.containerLayout()) {1020 .Union => switch (ty.containerLayout(mod)) {
1021 .Packed => {1021 .Packed => {
1022 const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory");1022 const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory");
1023 return typeToValtype(int_ty, mod);1023 return typeToValtype(int_ty, mod);
...@@ -1747,8 +1747,7 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -1747,8 +1747,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
1747 return ty.hasRuntimeBitsIgnoreComptime(mod);1747 return ty.hasRuntimeBitsIgnoreComptime(mod);
1748 },1748 },
1749 .Struct => {1749 .Struct => {
1750 if (ty.castTag(.@"struct")) |struct_ty| {1750 if (mod.typeToStruct(ty)) |struct_obj| {
1751 const struct_obj = struct_ty.data;
1752 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {1751 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
1753 return isByRef(struct_obj.backing_int_ty, mod);1752 return isByRef(struct_obj.backing_int_ty, mod);
1754 }1753 }
...@@ -2954,11 +2953,11 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue...@@ -2954,11 +2953,11 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
2954 const parent_ty = field_ptr.container_ty;2953 const parent_ty = field_ptr.container_ty;
29552954
2956 const field_offset = switch (parent_ty.zigTypeTag(mod)) {2955 const field_offset = switch (parent_ty.zigTypeTag(mod)) {
2957 .Struct => switch (parent_ty.containerLayout()) {2956 .Struct => switch (parent_ty.containerLayout(mod)) {
2958 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod),2957 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod),
2959 else => parent_ty.structFieldOffset(field_ptr.field_index, mod),2958 else => parent_ty.structFieldOffset(field_ptr.field_index, mod),
2960 },2959 },
2961 .Union => switch (parent_ty.containerLayout()) {2960 .Union => switch (parent_ty.containerLayout(mod)) {
2962 .Packed => 0,2961 .Packed => 0,
2963 else => blk: {2962 else => blk: {
2964 const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod);2963 const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod);
...@@ -3158,7 +3157,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -3158,7 +3157,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3158 return WValue{ .imm32 = @boolToInt(is_pl) };3157 return WValue{ .imm32 = @boolToInt(is_pl) };
3159 },3158 },
3160 .Struct => {3159 .Struct => {
3161 const struct_obj = ty.castTag(.@"struct").?.data;3160 const struct_obj = mod.typeToStruct(ty).?;
3162 assert(struct_obj.layout == .Packed);3161 assert(struct_obj.layout == .Packed);
3163 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer3162 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3164 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;3163 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 {...@@ -3225,7 +3224,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3225 return WValue{ .imm32 = 0xaaaaaaaa };3224 return WValue{ .imm32 = 0xaaaaaaaa };
3226 },3225 },
3227 .Struct => {3226 .Struct => {
3228 const struct_obj = ty.castTag(.@"struct").?.data;3227 const struct_obj = mod.typeToStruct(ty).?;
3229 assert(struct_obj.layout == .Packed);3228 assert(struct_obj.layout == .Packed);
3230 return func.emitUndefined(struct_obj.backing_int_ty);3229 return func.emitUndefined(struct_obj.backing_int_ty);
3231 },3230 },
...@@ -3635,7 +3634,7 @@ fn structFieldPtr(...@@ -3635,7 +3634,7 @@ fn structFieldPtr(
3635) InnerError!WValue {3634) InnerError!WValue {
3636 const mod = func.bin_file.base.options.module.?;3635 const mod = func.bin_file.base.options.module.?;
3637 const result_ty = func.typeOfIndex(inst);3636 const result_ty = func.typeOfIndex(inst);
3638 const offset = switch (struct_ty.containerLayout()) {3637 const offset = switch (struct_ty.containerLayout(mod)) {
3639 .Packed => switch (struct_ty.zigTypeTag(mod)) {3638 .Packed => switch (struct_ty.zigTypeTag(mod)) {
3640 .Struct => offset: {3639 .Struct => offset: {
3641 if (result_ty.ptrInfo(mod).host_size != 0) {3640 if (result_ty.ptrInfo(mod).host_size != 0) {
...@@ -3668,13 +3667,13 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3668,13 +3667,13 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3668 const struct_ty = func.typeOf(struct_field.struct_operand);3667 const struct_ty = func.typeOf(struct_field.struct_operand);
3669 const operand = try func.resolveInst(struct_field.struct_operand);3668 const operand = try func.resolveInst(struct_field.struct_operand);
3670 const field_index = struct_field.field_index;3669 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);
3672 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand});3671 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)) {
3675 .Packed => switch (struct_ty.zigTypeTag(mod)) {3674 .Packed => switch (struct_ty.zigTypeTag(mod)) {
3676 .Struct => result: {3675 .Struct => result: {
3677 const struct_obj = struct_ty.castTag(.@"struct").?.data;3676 const struct_obj = mod.typeToStruct(struct_ty).?;
3678 const offset = struct_obj.packedFieldBitOffset(mod, field_index);3677 const offset = struct_obj.packedFieldBitOffset(mod, field_index);
3679 const backing_ty = struct_obj.backing_int_ty;3678 const backing_ty = struct_obj.backing_int_ty;
3680 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {3679 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {
...@@ -4998,12 +4997,12 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4998,12 +4997,12 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4998 }4997 }
4999 break :result_value result;4998 break :result_value result;
5000 },4999 },
5001 .Struct => switch (result_ty.containerLayout()) {5000 .Struct => switch (result_ty.containerLayout(mod)) {
5002 .Packed => {5001 .Packed => {
5003 if (isByRef(result_ty, mod)) {5002 if (isByRef(result_ty, mod)) {
5004 return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{});5003 return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{});
5005 }5004 }
5006 const struct_obj = result_ty.castTag(.@"struct").?.data;5005 const struct_obj = mod.typeToStruct(result_ty).?;
5007 const fields = struct_obj.fields.values();5006 const fields = struct_obj.fields.values();
5008 const backing_type = struct_obj.backing_int_ty;5007 const backing_type = struct_obj.backing_int_ty;
50095008
...@@ -5051,7 +5050,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5051,7 +5050,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5051 for (elements, 0..) |elem, elem_index| {5050 for (elements, 0..) |elem, elem_index| {
5052 if ((try result_ty.structFieldValueComptime(mod, elem_index)) != null) continue;5051 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);
5055 const elem_size = @intCast(u32, elem_ty.abiSize(mod));5054 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
5056 const value = try func.resolveInst(elem);5055 const value = try func.resolveInst(elem);
5057 try func.store(offset, value, elem_ty, 0);5056 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 {...@@ -26,14 +26,14 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
26 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none;26 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none;
27 switch (ty.zigTypeTag(mod)) {27 switch (ty.zigTypeTag(mod)) {
28 .Struct => {28 .Struct => {
29 if (ty.containerLayout() == .Packed) {29 if (ty.containerLayout(mod) == .Packed) {
30 if (ty.bitSize(mod) <= 64) return direct;30 if (ty.bitSize(mod) <= 64) return direct;
31 return .{ .direct, .direct };31 return .{ .direct, .direct };
32 }32 }
33 // When the struct type is non-scalar33 // When the struct type is non-scalar
34 if (ty.structFieldCount() > 1) return memory;34 if (ty.structFieldCount(mod) > 1) return memory;
35 // When the struct's alignment is non-natural35 // When the struct's alignment is non-natural
36 const field = ty.structFields().values()[0];36 const field = ty.structFields(mod).values()[0];
37 if (field.abi_align != 0) {37 if (field.abi_align != 0) {
38 if (field.abi_align > field.ty.abiAlignment(mod)) {38 if (field.abi_align > field.ty.abiAlignment(mod)) {
39 return memory;39 return memory;
...@@ -64,7 +64,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {...@@ -64,7 +64,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
64 return direct;64 return direct;
65 },65 },
66 .Union => {66 .Union => {
67 if (ty.containerLayout() == .Packed) {67 if (ty.containerLayout(mod) == .Packed) {
68 if (ty.bitSize(mod) <= 64) return direct;68 if (ty.bitSize(mod) <= 64) return direct;
69 return .{ .direct, .direct };69 return .{ .direct, .direct };
70 }70 }
...@@ -96,19 +96,19 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {...@@ -96,19 +96,19 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
96pub fn scalarType(ty: Type, mod: *Module) Type {96pub fn scalarType(ty: Type, mod: *Module) Type {
97 switch (ty.zigTypeTag(mod)) {97 switch (ty.zigTypeTag(mod)) {
98 .Struct => {98 .Struct => {
99 switch (ty.containerLayout()) {99 switch (ty.containerLayout(mod)) {
100 .Packed => {100 .Packed => {
101 const struct_obj = ty.castTag(.@"struct").?.data;101 const struct_obj = mod.typeToStruct(ty).?;
102 return scalarType(struct_obj.backing_int_ty, mod);102 return scalarType(struct_obj.backing_int_ty, mod);
103 },103 },
104 else => {104 else => {
105 std.debug.assert(ty.structFieldCount() == 1);105 std.debug.assert(ty.structFieldCount(mod) == 1);
106 return scalarType(ty.structFieldType(0), mod);106 return scalarType(ty.structFieldType(0, mod), mod);
107 },107 },
108 }108 }
109 },109 },
110 .Union => {110 .Union => {
111 if (ty.containerLayout() != .Packed) {111 if (ty.containerLayout(mod) != .Packed) {
112 const layout = ty.unionGetLayout(mod);112 const layout = ty.unionGetLayout(mod);
113 if (layout.payload_size == 0 and layout.tag_size != 0) {113 if (layout.payload_size == 0 and layout.tag_size != 0) {
114 return scalarType(ty.unionTagTypeSafety().?, mod);114 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 {...@@ -3252,13 +3252,13 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3252 try self.genSetMem(3252 try self.genSetMem(
3253 .{ .frame = frame_index },3253 .{ .frame = frame_index },
3254 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),3254 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3255 tuple_ty.structFieldType(1),3255 tuple_ty.structFieldType(1, mod),
3256 .{ .eflags = cc },3256 .{ .eflags = cc },
3257 );3257 );
3258 try self.genSetMem(3258 try self.genSetMem(
3259 .{ .frame = frame_index },3259 .{ .frame = frame_index },
3260 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),3260 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3261 tuple_ty.structFieldType(0),3261 tuple_ty.structFieldType(0, mod),
3262 partial_mcv,3262 partial_mcv,
3263 );3263 );
3264 break :result .{ .load_frame = .{ .index = frame_index } };3264 break :result .{ .load_frame = .{ .index = frame_index } };
...@@ -3289,7 +3289,7 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3289,7 +3289,7 @@ fn genSetFrameTruncatedOverflowCompare(
3289 };3289 };
3290 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);3290 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);
3293 const int_info = ty.intInfo(mod);3293 const int_info = ty.intInfo(mod);
32943294
3295 const hi_limb_bits = (int_info.bits - 1) % 64 + 1;3295 const hi_limb_bits = (int_info.bits - 1) % 64 + 1;
...@@ -3336,7 +3336,7 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -3336,7 +3336,7 @@ fn genSetFrameTruncatedOverflowCompare(
3336 try self.genSetMem(3336 try self.genSetMem(
3337 .{ .frame = frame_index },3337 .{ .frame = frame_index },
3338 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),3338 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3339 tuple_ty.structFieldType(1),3339 tuple_ty.structFieldType(1, mod),
3340 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },3340 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },
3341 );3341 );
3342}3342}
...@@ -3393,13 +3393,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3393,13 +3393,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3393 try self.genSetMem(3393 try self.genSetMem(
3394 .{ .frame = frame_index },3394 .{ .frame = frame_index },
3395 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),3395 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3396 tuple_ty.structFieldType(0),3396 tuple_ty.structFieldType(0, mod),
3397 partial_mcv,3397 partial_mcv,
3398 );3398 );
3399 try self.genSetMem(3399 try self.genSetMem(
3400 .{ .frame = frame_index },3400 .{ .frame = frame_index },
3401 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),3401 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3402 tuple_ty.structFieldType(1),3402 tuple_ty.structFieldType(1, mod),
3403 .{ .immediate = 0 }, // cc being set is impossible3403 .{ .immediate = 0 }, // cc being set is impossible
3404 );3404 );
3405 } else try self.genSetFrameTruncatedOverflowCompare(3405 } else try self.genSetFrameTruncatedOverflowCompare(
...@@ -5563,7 +5563,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32...@@ -5563,7 +5563,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
5563 const ptr_field_ty = self.typeOfIndex(inst);5563 const ptr_field_ty = self.typeOfIndex(inst);
5564 const ptr_container_ty = self.typeOf(operand);5564 const ptr_container_ty = self.typeOf(operand);
5565 const container_ty = ptr_container_ty.childType(mod);5565 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)) {
5567 .Auto, .Extern => container_ty.structFieldOffset(index, mod),5567 .Auto, .Extern => container_ty.structFieldOffset(index, mod),
5568 .Packed => if (container_ty.zigTypeTag(mod) == .Struct and5568 .Packed => if (container_ty.zigTypeTag(mod) == .Struct and
5569 ptr_field_ty.ptrInfo(mod).host_size == 0)5569 ptr_field_ty.ptrInfo(mod).host_size == 0)
...@@ -5591,16 +5591,16 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5591,16 +5591,16 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
55915591
5592 const container_ty = self.typeOf(operand);5592 const container_ty = self.typeOf(operand);
5593 const container_rc = regClassForType(container_ty, mod);5593 const container_rc = regClassForType(container_ty, mod);
5594 const field_ty = container_ty.structFieldType(index);5594 const field_ty = container_ty.structFieldType(index, mod);
5595 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;5595 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
5596 const field_rc = regClassForType(field_ty, mod);5596 const field_rc = regClassForType(field_ty, mod);
5597 const field_is_gp = field_rc.supersetOf(gp);5597 const field_is_gp = field_rc.supersetOf(gp);
55985598
5599 const src_mcv = try self.resolveInst(operand);5599 const src_mcv = try self.resolveInst(operand);
5600 const field_off = switch (container_ty.containerLayout()) {5600 const field_off = switch (container_ty.containerLayout(mod)) {
5601 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8),5601 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8),
5602 .Packed => if (container_ty.castTag(.@"struct")) |struct_obj|5602 .Packed => if (mod.typeToStruct(container_ty)) |struct_obj|
5603 struct_obj.data.packedFieldBitOffset(mod, index)5603 struct_obj.packedFieldBitOffset(mod, index)
5604 else5604 else
5605 0,5605 0,
5606 };5606 };
...@@ -10036,13 +10036,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -10036,13 +10036,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
10036 try self.genSetMem(10036 try self.genSetMem(
10037 base,10037 base,
10038 disp + @intCast(i32, ty.structFieldOffset(0, mod)),10038 disp + @intCast(i32, ty.structFieldOffset(0, mod)),
10039 ty.structFieldType(0),10039 ty.structFieldType(0, mod),
10040 .{ .register = ro.reg },10040 .{ .register = ro.reg },
10041 );10041 );
10042 try self.genSetMem(10042 try self.genSetMem(
10043 base,10043 base,
10044 disp + @intCast(i32, ty.structFieldOffset(1, mod)),10044 disp + @intCast(i32, ty.structFieldOffset(1, mod)),
10045 ty.structFieldType(1),10045 ty.structFieldType(1, mod),
10046 .{ .eflags = ro.eflags },10046 .{ .eflags = ro.eflags },
10047 );10047 );
10048 },10048 },
...@@ -11259,8 +11259,8 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11259,8 +11259,8 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11259 .Struct => {11259 .Struct => {
11260 const frame_index =11260 const frame_index =
11261 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));11261 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
11262 if (result_ty.containerLayout() == .Packed) {11262 if (result_ty.containerLayout(mod) == .Packed) {
11263 const struct_obj = result_ty.castTag(.@"struct").?.data;11263 const struct_obj = mod.typeToStruct(result_ty).?;
11264 try self.genInlineMemset(11264 try self.genInlineMemset(
11265 .{ .lea_frame = .{ .index = frame_index } },11265 .{ .lea_frame = .{ .index = frame_index } },
11266 .{ .immediate = 0 },11266 .{ .immediate = 0 },
...@@ -11269,7 +11269,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11269,7 +11269,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11269 for (elements, 0..) |elem, elem_i| {11269 for (elements, 0..) |elem, elem_i| {
11270 if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;11270 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);
11273 const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));11273 const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));
11274 if (elem_bit_size > 64) {11274 if (elem_bit_size > 64) {
11275 return self.fail(11275 return self.fail(
...@@ -11341,7 +11341,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11341,7 +11341,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11341 } else for (elements, 0..) |elem, elem_i| {11341 } else for (elements, 0..) |elem, elem_i| {
11342 if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;11342 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);
11345 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));11345 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));
11346 const elem_mcv = try self.resolveInst(elem);11346 const elem_mcv = try self.resolveInst(elem);
11347 const mat_elem_mcv = switch (elem_mcv) {11347 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 {...@@ -41,7 +41,7 @@ pub fn classifyWindows(ty: Type, mod: *Module) Class {
41 1, 2, 4, 8 => return .integer,41 1, 2, 4, 8 => return .integer,
42 else => switch (ty.zigTypeTag(mod)) {42 else => switch (ty.zigTypeTag(mod)) {
43 .Int => return .win_i128,43 .Int => return .win_i128,
44 .Struct, .Union => if (ty.containerLayout() == .Packed) {44 .Struct, .Union => if (ty.containerLayout(mod) == .Packed) {
45 return .win_i128;45 return .win_i128;
46 } else {46 } else {
47 return .memory;47 return .memory;
...@@ -210,7 +210,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {...@@ -210,7 +210,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
210 // "If the size of the aggregate exceeds a single eightbyte, each is classified210 // "If the size of the aggregate exceeds a single eightbyte, each is classified
211 // separately.".211 // separately.".
212 const ty_size = ty.abiSize(mod);212 const ty_size = ty.abiSize(mod);
213 if (ty.containerLayout() == .Packed) {213 if (ty.containerLayout(mod) == .Packed) {
214 assert(ty_size <= 128);214 assert(ty_size <= 128);
215 result[0] = .integer;215 result[0] = .integer;
216 if (ty_size > 64) result[1] = .integer;216 if (ty_size > 64) result[1] = .integer;
...@@ -221,7 +221,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {...@@ -221,7 +221,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
221221
222 var result_i: usize = 0; // out of 8222 var result_i: usize = 0; // out of 8
223 var byte_i: usize = 0; // out of 8223 var byte_i: usize = 0; // out of 8
224 const fields = ty.structFields();224 const fields = ty.structFields(mod);
225 for (fields.values()) |field| {225 for (fields.values()) |field| {
226 if (field.abi_align != 0) {226 if (field.abi_align != 0) {
227 if (field.abi_align < field.ty.abiAlignment(mod)) {227 if (field.abi_align < field.ty.abiAlignment(mod)) {
...@@ -329,7 +329,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {...@@ -329,7 +329,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
329 // "If the size of the aggregate exceeds a single eightbyte, each is classified329 // "If the size of the aggregate exceeds a single eightbyte, each is classified
330 // separately.".330 // separately.".
331 const ty_size = ty.abiSize(mod);331 const ty_size = ty.abiSize(mod);
332 if (ty.containerLayout() == .Packed) {332 if (ty.containerLayout(mod) == .Packed) {
333 assert(ty_size <= 128);333 assert(ty_size <= 128);
334 result[0] = .integer;334 result[0] = .integer;
335 if (ty_size > 64) result[1] = .integer;335 if (ty_size > 64) result[1] = .integer;
src/codegen.zig+3-3
...@@ -503,8 +503,8 @@ pub fn generateSymbol(...@@ -503,8 +503,8 @@ pub fn generateSymbol(
503 return Result.ok;503 return Result.ok;
504 },504 },
505 .Struct => {505 .Struct => {
506 if (typed_value.ty.containerLayout() == .Packed) {506 if (typed_value.ty.containerLayout(mod) == .Packed) {
507 const struct_obj = typed_value.ty.castTag(.@"struct").?.data;507 const struct_obj = mod.typeToStruct(typed_value.ty).?;
508 const fields = struct_obj.fields.values();508 const fields = struct_obj.fields.values();
509 const field_vals = typed_value.val.castTag(.aggregate).?.data;509 const field_vals = typed_value.val.castTag(.aggregate).?.data;
510 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;510 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
...@@ -539,7 +539,7 @@ pub fn generateSymbol(...@@ -539,7 +539,7 @@ pub fn generateSymbol(
539 const struct_begin = code.items.len;539 const struct_begin = code.items.len;
540 const field_vals = typed_value.val.castTag(.aggregate).?.data;540 const field_vals = typed_value.val.castTag(.aggregate).?.data;
541 for (field_vals, 0..) |field_val, index| {541 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);
543 if (!field_ty.hasRuntimeBits(mod)) continue;543 if (!field_ty.hasRuntimeBits(mod)) continue;
544544
545 switch (try generateSymbol(bin_file, src_loc, .{545 switch (try generateSymbol(bin_file, src_loc, .{
src/codegen/c.zig+119-109
...@@ -820,7 +820,7 @@ pub const DeclGen = struct {...@@ -820,7 +820,7 @@ pub const DeclGen = struct {
820 try dg.renderValue(writer, Type.bool, val, initializer_type);820 try dg.renderValue(writer, Type.bool, val, initializer_type);
821 return writer.writeAll(" }");821 return writer.writeAll(" }");
822 },822 },
823 .Struct => switch (ty.containerLayout()) {823 .Struct => switch (ty.containerLayout(mod)) {
824 .Auto, .Extern => {824 .Auto, .Extern => {
825 if (!location.isInitializer()) {825 if (!location.isInitializer()) {
826 try writer.writeByte('(');826 try writer.writeByte('(');
...@@ -830,9 +830,9 @@ pub const DeclGen = struct {...@@ -830,9 +830,9 @@ pub const DeclGen = struct {
830830
831 try writer.writeByte('{');831 try writer.writeByte('{');
832 var empty = true;832 var empty = true;
833 for (0..ty.structFieldCount()) |field_i| {833 for (0..ty.structFieldCount(mod)) |field_i| {
834 if (ty.structFieldIsComptime(field_i)) continue;834 if (ty.structFieldIsComptime(field_i, mod)) continue;
835 const field_ty = ty.structFieldType(field_i);835 const field_ty = ty.structFieldType(field_i, mod);
836 if (!field_ty.hasRuntimeBits(mod)) continue;836 if (!field_ty.hasRuntimeBits(mod)) continue;
837837
838 if (!empty) try writer.writeByte(',');838 if (!empty) try writer.writeByte(',');
...@@ -1328,7 +1328,7 @@ pub const DeclGen = struct {...@@ -1328,7 +1328,7 @@ pub const DeclGen = struct {
1328 },1328 },
1329 else => unreachable,1329 else => unreachable,
1330 },1330 },
1331 .Struct => switch (ty.containerLayout()) {1331 .Struct => switch (ty.containerLayout(mod)) {
1332 .Auto, .Extern => {1332 .Auto, .Extern => {
1333 const field_vals = val.castTag(.aggregate).?.data;1333 const field_vals = val.castTag(.aggregate).?.data;
13341334
...@@ -1341,8 +1341,8 @@ pub const DeclGen = struct {...@@ -1341,8 +1341,8 @@ pub const DeclGen = struct {
1341 try writer.writeByte('{');1341 try writer.writeByte('{');
1342 var empty = true;1342 var empty = true;
1343 for (field_vals, 0..) |field_val, field_i| {1343 for (field_vals, 0..) |field_val, field_i| {
1344 if (ty.structFieldIsComptime(field_i)) continue;1344 if (ty.structFieldIsComptime(field_i, mod)) continue;
1345 const field_ty = ty.structFieldType(field_i);1345 const field_ty = ty.structFieldType(field_i, mod);
1346 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1346 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13471347
1348 if (!empty) try writer.writeByte(',');1348 if (!empty) try writer.writeByte(',');
...@@ -1363,8 +1363,8 @@ pub const DeclGen = struct {...@@ -1363,8 +1363,8 @@ pub const DeclGen = struct {
13631363
1364 var eff_num_fields: usize = 0;1364 var eff_num_fields: usize = 0;
1365 for (0..field_vals.len) |field_i| {1365 for (0..field_vals.len) |field_i| {
1366 if (ty.structFieldIsComptime(field_i)) continue;1366 if (ty.structFieldIsComptime(field_i, mod)) continue;
1367 const field_ty = ty.structFieldType(field_i);1367 const field_ty = ty.structFieldType(field_i, mod);
1368 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1368 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13691369
1370 eff_num_fields += 1;1370 eff_num_fields += 1;
...@@ -1386,8 +1386,8 @@ pub const DeclGen = struct {...@@ -1386,8 +1386,8 @@ pub const DeclGen = struct {
1386 var eff_index: usize = 0;1386 var eff_index: usize = 0;
1387 var needs_closing_paren = false;1387 var needs_closing_paren = false;
1388 for (field_vals, 0..) |field_val, field_i| {1388 for (field_vals, 0..) |field_val, field_i| {
1389 if (ty.structFieldIsComptime(field_i)) continue;1389 if (ty.structFieldIsComptime(field_i, mod)) continue;
1390 const field_ty = ty.structFieldType(field_i);1390 const field_ty = ty.structFieldType(field_i, mod);
1391 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1391 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13921392
1393 const cast_context = IntCastContext{ .value = .{ .value = field_val } };1393 const cast_context = IntCastContext{ .value = .{ .value = field_val } };
...@@ -1416,8 +1416,8 @@ pub const DeclGen = struct {...@@ -1416,8 +1416,8 @@ pub const DeclGen = struct {
1416 // a << a_off | b << b_off | c << c_off1416 // a << a_off | b << b_off | c << c_off
1417 var empty = true;1417 var empty = true;
1418 for (field_vals, 0..) |field_val, field_i| {1418 for (field_vals, 0..) |field_val, field_i| {
1419 if (ty.structFieldIsComptime(field_i)) continue;1419 if (ty.structFieldIsComptime(field_i, mod)) continue;
1420 const field_ty = ty.structFieldType(field_i);1420 const field_ty = ty.structFieldType(field_i, mod);
1421 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1421 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14221422
1423 if (!empty) try writer.writeAll(" | ");1423 if (!empty) try writer.writeAll(" | ");
...@@ -1453,7 +1453,7 @@ pub const DeclGen = struct {...@@ -1453,7 +1453,7 @@ pub const DeclGen = struct {
1453 const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?;1453 const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?;
1454 const field_ty = ty.unionFields().values()[field_i].ty;1454 const field_ty = ty.unionFields().values()[field_i].ty;
1455 const field_name = ty.unionFields().keys()[field_i];1455 const field_name = ty.unionFields().keys()[field_i];
1456 if (ty.containerLayout() == .Packed) {1456 if (ty.containerLayout(mod) == .Packed) {
1457 if (field_ty.hasRuntimeBits(mod)) {1457 if (field_ty.hasRuntimeBits(mod)) {
1458 if (field_ty.isPtrAtRuntime(mod)) {1458 if (field_ty.isPtrAtRuntime(mod)) {
1459 try writer.writeByte('(');1459 try writer.writeByte('(');
...@@ -5218,25 +5218,25 @@ fn fieldLocation(...@@ -5218,25 +5218,25 @@ fn fieldLocation(
5218 end: void,5218 end: void,
5219} {5219} {
5220 return switch (container_ty.zigTypeTag(mod)) {5220 return switch (container_ty.zigTypeTag(mod)) {
5221 .Struct => switch (container_ty.containerLayout()) {5221 .Struct => switch (container_ty.containerLayout(mod)) {
5222 .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| {5222 .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| {
5223 if (container_ty.structFieldIsComptime(next_field_index)) continue;5223 if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
5224 const field_ty = container_ty.structFieldType(next_field_index);5224 const field_ty = container_ty.structFieldType(next_field_index, mod);
5225 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;5225 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
52265226
5227 break .{ .field = if (container_ty.isSimpleTuple())5227 break .{ .field = if (container_ty.isSimpleTuple())
5228 .{ .field = next_field_index }5228 .{ .field = next_field_index }
5229 else5229 else
5230 .{ .identifier = container_ty.structFieldName(next_field_index) } };5230 .{ .identifier = container_ty.structFieldName(next_field_index, mod) } };
5231 } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,5231 } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,
5232 .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0)5232 .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0)
5233 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) }5233 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) }
5234 else5234 else
5235 .begin,5235 .begin,
5236 },5236 },
5237 .Union => switch (container_ty.containerLayout()) {5237 .Union => switch (container_ty.containerLayout(mod)) {
5238 .Auto, .Extern => {5238 .Auto, .Extern => {
5239 const field_ty = container_ty.structFieldType(field_index);5239 const field_ty = container_ty.structFieldType(field_index, mod);
5240 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))5240 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))
5241 return if (container_ty.unionTagTypeSafety() != null and5241 return if (container_ty.unionTagTypeSafety() != null and
5242 !container_ty.unionHasAllZeroBitFieldTypes(mod))5242 !container_ty.unionHasAllZeroBitFieldTypes(mod))
...@@ -5417,101 +5417,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5417,101 +5417,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5417 // Ensure complete type definition is visible before accessing fields.5417 // Ensure complete type definition is visible before accessing fields.
5418 _ = try f.typeToIndex(struct_ty, .complete);5418 _ = try f.typeToIndex(struct_ty, .complete);
54195419
5420 const field_name: CValue = switch (struct_ty.tag()) {5420 const field_name: CValue = switch (struct_ty.ip_index) {
5421 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {5421 .none => switch (struct_ty.tag()) {
5422 .Auto, .Extern => if (struct_ty.isSimpleTuple())5422 .tuple, .anon_struct => if (struct_ty.isSimpleTuple())
5423 .{ .field = extra.field_index }5423 .{ .field = extra.field_index }
5424 else5424 else
5425 .{ .identifier = struct_ty.structFieldName(extra.field_index) },5425 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
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);
54345426
5435 const field_int_signedness = if (inst_ty.isAbiInt(mod))5427 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout(mod) == .Packed) {
5436 inst_ty.intInfo(mod).signedness5428 const operand_lval = if (struct_byval == .constant) blk: {
5437 else5429 const operand_local = try f.allocLocal(inst, struct_ty);
5438 .unsigned;5430 try f.writeCValue(writer, operand_local, .Other);
5439 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));5431 try writer.writeAll(" = ");
54405432 try f.writeCValue(writer, struct_byval, .Initializer);
5441 const temp_local = try f.allocLocal(inst, field_int_ty);5433 try writer.writeAll(";\n");
5442 try f.writeCValue(writer, temp_local, .Other);5434 break :blk operand_local;
5443 try writer.writeAll(" = zig_wrap_");5435 } else struct_byval;
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;
54705436
5471 const local = try f.allocLocal(inst, inst_ty);5437 const local = try f.allocLocal(inst, inst_ty);
5472 try writer.writeAll("memcpy(");5438 try writer.writeAll("memcpy(&");
5473 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);5439 try f.writeCValue(writer, local, .Other);
5474 try writer.writeAll(", ");5440 try writer.writeAll(", &");
5475 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);5441 try f.writeCValue(writer, operand_lval, .Other);
5476 try writer.writeAll(", sizeof(");5442 try writer.writeAll(", sizeof(");
5477 try f.renderType(writer, inst_ty);5443 try f.renderType(writer, inst_ty);
5478 try writer.writeAll("));\n");5444 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
5480 return local;5450 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 };
5481 },5457 },
5458 else => unreachable,
5482 },5459 },
5483 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {5460 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
5484 const operand_lval = if (struct_byval == .constant) blk: {5461 .struct_type => switch (struct_ty.containerLayout(mod)) {
5485 const operand_local = try f.allocLocal(inst, struct_ty);5462 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5486 try f.writeCValue(writer, operand_local, .Other);5463 .{ .field = extra.field_index }
5487 try writer.writeAll(" = ");5464 else
5488 try f.writeCValue(writer, struct_byval, .Initializer);5465 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5489 try writer.writeAll(";\n");5466 .Packed => {
5490 break :blk operand_local;5467 const struct_obj = mod.typeToStruct(struct_ty).?;
5491 } else struct_byval;5468 const int_info = struct_ty.intInfo(mod);
54925469
5493 const local = try f.allocLocal(inst, inst_ty);5470 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
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");
55015471
5502 if (struct_byval == .constant) {5472 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);
5503 try freeLocal(f, inst, operand_lval.new_local, 0);5473 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
5504 }
55055474
5506 return local;5475 const field_int_signedness = if (inst_ty.isAbiInt(mod))
5507 } else field_name: {5476 inst_ty.intInfo(mod).signedness
5508 const name = struct_ty.unionFields().keys()[extra.field_index];5477 else
5509 break :field_name if (struct_ty.unionTagTypeSafety()) |_|5478 .unsigned;
5510 .{ .payload_identifier = name }5479 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
5511 else5480
5512 .{ .identifier = name };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,
5513 },5524 },
5514 else => unreachable,
5515 };5525 };
55165526
5517 const local = try f.allocLocal(inst, inst_ty);5527 const local = try f.allocLocal(inst, inst_ty);
...@@ -6805,17 +6815,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6805,17 +6815,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6805 try a.end(f, writer);6815 try a.end(f, writer);
6806 }6816 }
6807 },6817 },
6808 .Struct => switch (inst_ty.containerLayout()) {6818 .Struct => switch (inst_ty.containerLayout(mod)) {
6809 .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {6819 .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {
6810 if (inst_ty.structFieldIsComptime(field_i)) continue;6820 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6811 const field_ty = inst_ty.structFieldType(field_i);6821 const field_ty = inst_ty.structFieldType(field_i, mod);
6812 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;6822 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68136823
6814 const a = try Assignment.start(f, writer, field_ty);6824 const a = try Assignment.start(f, writer, field_ty);
6815 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())6825 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())
6816 .{ .field = field_i }6826 .{ .field = field_i }
6817 else6827 else
6818 .{ .identifier = inst_ty.structFieldName(field_i) });6828 .{ .identifier = inst_ty.structFieldName(field_i, mod) });
6819 try a.assign(f, writer);6829 try a.assign(f, writer);
6820 try f.writeCValue(writer, element, .Other);6830 try f.writeCValue(writer, element, .Other);
6821 try a.end(f, writer);6831 try a.end(f, writer);
...@@ -6831,8 +6841,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6831,8 +6841,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68316841
6832 var empty = true;6842 var empty = true;
6833 for (0..elements.len) |field_i| {6843 for (0..elements.len) |field_i| {
6834 if (inst_ty.structFieldIsComptime(field_i)) continue;6844 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6835 const field_ty = inst_ty.structFieldType(field_i);6845 const field_ty = inst_ty.structFieldType(field_i, mod);
6836 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;6846 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68376847
6838 if (!empty) {6848 if (!empty) {
...@@ -6844,8 +6854,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6844,8 +6854,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6844 }6854 }
6845 empty = true;6855 empty = true;
6846 for (resolved_elements, 0..) |element, field_i| {6856 for (resolved_elements, 0..) |element, field_i| {
6847 if (inst_ty.structFieldIsComptime(field_i)) continue;6857 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6848 const field_ty = inst_ty.structFieldType(field_i);6858 const field_ty = inst_ty.structFieldType(field_i, mod);
6849 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;6859 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68506860
6851 if (!empty) try writer.writeAll(", ");6861 if (!empty) try writer.writeAll(", ");
src/codegen/c/type.zig+25-25
...@@ -299,7 +299,7 @@ pub const CType = extern union {...@@ -299,7 +299,7 @@ pub const CType = extern union {
299 pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs {299 pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs {
300 return init(300 return init(
301 struct_ty.structFieldAlign(field_i, mod),301 struct_ty.structFieldAlign(field_i, mod),
302 struct_ty.structFieldType(field_i).abiAlignment(mod),302 struct_ty.structFieldType(field_i, mod).abiAlignment(mod),
303 );303 );
304 }304 }
305 pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs {305 pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs {
...@@ -1486,23 +1486,23 @@ pub const CType = extern union {...@@ -1486,23 +1486,23 @@ pub const CType = extern union {
1486 }1486 }
1487 },1487 },
14881488
1489 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout() == .Packed) {1489 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .Packed) {
1490 if (ty.castTag(.@"struct")) |struct_obj| {1490 if (mod.typeToStruct(ty)) |struct_obj| {
1491 try self.initType(struct_obj.data.backing_int_ty, kind, lookup);1491 try self.initType(struct_obj.backing_int_ty, kind, lookup);
1492 } else {1492 } else {
1493 const bits = @intCast(u16, ty.bitSize(mod));1493 const bits = @intCast(u16, ty.bitSize(mod));
1494 const int_ty = try mod.intType(.unsigned, bits);1494 const int_ty = try mod.intType(.unsigned, bits);
1495 try self.initType(int_ty, kind, lookup);1495 try self.initType(int_ty, kind, lookup);
1496 }1496 }
1497 } else if (ty.isTupleOrAnonStruct()) {1497 } else if (ty.isTupleOrAnonStruct(mod)) {
1498 if (lookup.isMutable()) {1498 if (lookup.isMutable()) {
1499 for (0..switch (zig_ty_tag) {1499 for (0..switch (zig_ty_tag) {
1500 .Struct => ty.structFieldCount(),1500 .Struct => ty.structFieldCount(mod),
1501 .Union => ty.unionFields().count(),1501 .Union => ty.unionFields().count(),
1502 else => unreachable,1502 else => unreachable,
1503 }) |field_i| {1503 }) |field_i| {
1504 const field_ty = ty.structFieldType(field_i);1504 const field_ty = ty.structFieldType(field_i, mod);
1505 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or1505 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1506 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1506 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1507 _ = try lookup.typeToIndex(field_ty, switch (kind) {1507 _ = try lookup.typeToIndex(field_ty, switch (kind) {
1508 .forward, .forward_parameter => .forward,1508 .forward, .forward_parameter => .forward,
...@@ -1579,11 +1579,11 @@ pub const CType = extern union {...@@ -1579,11 +1579,11 @@ pub const CType = extern union {
1579 } else {1579 } else {
1580 var is_packed = false;1580 var is_packed = false;
1581 for (0..switch (zig_ty_tag) {1581 for (0..switch (zig_ty_tag) {
1582 .Struct => ty.structFieldCount(),1582 .Struct => ty.structFieldCount(mod),
1583 .Union => ty.unionFields().count(),1583 .Union => ty.unionFields().count(),
1584 else => unreachable,1584 else => unreachable,
1585 }) |field_i| {1585 }) |field_i| {
1586 const field_ty = ty.structFieldType(field_i);1586 const field_ty = ty.structFieldType(field_i, mod);
1587 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1587 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
15881588
1589 const field_align = AlignAs.fieldAlign(ty, field_i, mod);1589 const field_align = AlignAs.fieldAlign(ty, field_i, mod);
...@@ -1929,15 +1929,15 @@ pub const CType = extern union {...@@ -1929,15 +1929,15 @@ pub const CType = extern union {
1929 => {1929 => {
1930 const zig_ty_tag = ty.zigTypeTag(mod);1930 const zig_ty_tag = ty.zigTypeTag(mod);
1931 const fields_len = switch (zig_ty_tag) {1931 const fields_len = switch (zig_ty_tag) {
1932 .Struct => ty.structFieldCount(),1932 .Struct => ty.structFieldCount(mod),
1933 .Union => ty.unionFields().count(),1933 .Union => ty.unionFields().count(),
1934 else => unreachable,1934 else => unreachable,
1935 };1935 };
19361936
1937 var c_fields_len: usize = 0;1937 var c_fields_len: usize = 0;
1938 for (0..fields_len) |field_i| {1938 for (0..fields_len) |field_i| {
1939 const field_ty = ty.structFieldType(field_i);1939 const field_ty = ty.structFieldType(field_i, mod);
1940 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or1940 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1941 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1941 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1942 c_fields_len += 1;1942 c_fields_len += 1;
1943 }1943 }
...@@ -1945,8 +1945,8 @@ pub const CType = extern union {...@@ -1945,8 +1945,8 @@ pub const CType = extern union {
1945 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);1945 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
1946 var c_field_i: usize = 0;1946 var c_field_i: usize = 0;
1947 for (0..fields_len) |field_i| {1947 for (0..fields_len) |field_i| {
1948 const field_ty = ty.structFieldType(field_i);1948 const field_ty = ty.structFieldType(field_i, mod);
1949 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or1949 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1950 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1950 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
19511951
1952 defer c_field_i += 1;1952 defer c_field_i += 1;
...@@ -1955,7 +1955,7 @@ pub const CType = extern union {...@@ -1955,7 +1955,7 @@ pub const CType = extern union {
1955 std.fmt.allocPrintZ(arena, "f{}", .{field_i})1955 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
1956 else1956 else
1957 arena.dupeZ(u8, switch (zig_ty_tag) {1957 arena.dupeZ(u8, switch (zig_ty_tag) {
1958 .Struct => ty.structFieldName(field_i),1958 .Struct => ty.structFieldName(field_i, mod),
1959 .Union => ty.unionFields().keys()[field_i],1959 .Union => ty.unionFields().keys()[field_i],
1960 else => unreachable,1960 else => unreachable,
1961 }),1961 }),
...@@ -2074,7 +2074,7 @@ pub const CType = extern union {...@@ -2074,7 +2074,7 @@ pub const CType = extern union {
2074 .fwd_anon_struct,2074 .fwd_anon_struct,
2075 .fwd_anon_union,2075 .fwd_anon_union,
2076 => {2076 => {
2077 if (!ty.isTupleOrAnonStruct()) return false;2077 if (!ty.isTupleOrAnonStruct(mod)) return false;
20782078
2079 var name_buf: [2079 var name_buf: [
2080 std.fmt.count("f{}", .{std.math.maxInt(usize)})2080 std.fmt.count("f{}", .{std.math.maxInt(usize)})
...@@ -2084,12 +2084,12 @@ pub const CType = extern union {...@@ -2084,12 +2084,12 @@ pub const CType = extern union {
2084 const zig_ty_tag = ty.zigTypeTag(mod);2084 const zig_ty_tag = ty.zigTypeTag(mod);
2085 var c_field_i: usize = 0;2085 var c_field_i: usize = 0;
2086 for (0..switch (zig_ty_tag) {2086 for (0..switch (zig_ty_tag) {
2087 .Struct => ty.structFieldCount(),2087 .Struct => ty.structFieldCount(mod),
2088 .Union => ty.unionFields().count(),2088 .Union => ty.unionFields().count(),
2089 else => unreachable,2089 else => unreachable,
2090 }) |field_i| {2090 }) |field_i| {
2091 const field_ty = ty.structFieldType(field_i);2091 const field_ty = ty.structFieldType(field_i, mod);
2092 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or2092 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
2093 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;2093 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
20942094
2095 defer c_field_i += 1;2095 defer c_field_i += 1;
...@@ -2105,7 +2105,7 @@ pub const CType = extern union {...@@ -2105,7 +2105,7 @@ pub const CType = extern union {
2105 if (ty.isSimpleTuple())2105 if (ty.isSimpleTuple())
2106 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable2106 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
2107 else switch (zig_ty_tag) {2107 else switch (zig_ty_tag) {
2108 .Struct => ty.structFieldName(field_i),2108 .Struct => ty.structFieldName(field_i, mod),
2109 .Union => ty.unionFields().keys()[field_i],2109 .Union => ty.unionFields().keys()[field_i],
2110 else => unreachable,2110 else => unreachable,
2111 },2111 },
...@@ -2210,12 +2210,12 @@ pub const CType = extern union {...@@ -2210,12 +2210,12 @@ pub const CType = extern union {
22102210
2211 const zig_ty_tag = ty.zigTypeTag(mod);2211 const zig_ty_tag = ty.zigTypeTag(mod);
2212 for (0..switch (ty.zigTypeTag(mod)) {2212 for (0..switch (ty.zigTypeTag(mod)) {
2213 .Struct => ty.structFieldCount(),2213 .Struct => ty.structFieldCount(mod),
2214 .Union => ty.unionFields().count(),2214 .Union => ty.unionFields().count(),
2215 else => unreachable,2215 else => unreachable,
2216 }) |field_i| {2216 }) |field_i| {
2217 const field_ty = ty.structFieldType(field_i);2217 const field_ty = ty.structFieldType(field_i, mod);
2218 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or2218 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
2219 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;2219 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22202220
2221 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {2221 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {
...@@ -2227,7 +2227,7 @@ pub const CType = extern union {...@@ -2227,7 +2227,7 @@ pub const CType = extern union {
2227 hasher.update(if (ty.isSimpleTuple())2227 hasher.update(if (ty.isSimpleTuple())
2228 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable2228 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
2229 else switch (zig_ty_tag) {2229 else switch (zig_ty_tag) {
2230 .Struct => ty.structFieldName(field_i),2230 .Struct => ty.structFieldName(field_i, mod),
2231 .Union => ty.unionFields().keys()[field_i],2231 .Union => ty.unionFields().keys()[field_i],
2232 else => unreachable,2232 else => unreachable,
2233 });2233 });
src/codegen/llvm.zig+26-28
...@@ -1986,8 +1986,7 @@ pub const Object = struct {...@@ -1986,8 +1986,7 @@ pub const Object = struct {
1986 const name = try ty.nameAlloc(gpa, o.module);1986 const name = try ty.nameAlloc(gpa, o.module);
1987 defer gpa.free(name);1987 defer gpa.free(name);
19881988
1989 if (ty.castTag(.@"struct")) |payload| {1989 if (mod.typeToStruct(ty)) |struct_obj| {
1990 const struct_obj = payload.data;
1991 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {1990 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
1992 assert(struct_obj.haveLayout());1991 assert(struct_obj.haveLayout());
1993 const info = struct_obj.backing_int_ty.intInfo(mod);1992 const info = struct_obj.backing_int_ty.intInfo(mod);
...@@ -2075,8 +2074,7 @@ pub const Object = struct {...@@ -2075,8 +2074,7 @@ pub const Object = struct {
2075 return full_di_ty;2074 return full_di_ty;
2076 }2075 }
20772076
2078 if (ty.castTag(.@"struct")) |payload| {2077 if (mod.typeToStruct(ty)) |struct_obj| {
2079 const struct_obj = payload.data;
2080 if (!struct_obj.haveFieldTypes()) {2078 if (!struct_obj.haveFieldTypes()) {
2081 // This can happen if a struct type makes it all the way to2079 // This can happen if a struct type makes it all the way to
2082 // flush() without ever being instantiated or referenced (even2080 // flush() without ever being instantiated or referenced (even
...@@ -2105,8 +2103,8 @@ pub const Object = struct {...@@ -2105,8 +2103,8 @@ pub const Object = struct {
2105 return struct_di_ty;2103 return struct_di_ty;
2106 }2104 }
21072105
2108 const fields = ty.structFields();2106 const fields = ty.structFields(mod);
2109 const layout = ty.containerLayout();2107 const layout = ty.containerLayout(mod);
21102108
2111 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2109 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2112 defer di_fields.deinit(gpa);2110 defer di_fields.deinit(gpa);
...@@ -2116,7 +2114,7 @@ pub const Object = struct {...@@ -2116,7 +2114,7 @@ pub const Object = struct {
2116 comptime assert(struct_layout_version == 2);2114 comptime assert(struct_layout_version == 2);
2117 var offset: u64 = 0;2115 var offset: u64 = 0;
21182116
2119 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod);2117 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
2120 while (it.next()) |field_and_index| {2118 while (it.next()) |field_and_index| {
2121 const field = field_and_index.field;2119 const field = field_and_index.field;
2122 const field_size = field.ty.abiSize(mod);2120 const field_size = field.ty.abiSize(mod);
...@@ -2990,7 +2988,7 @@ pub const DeclGen = struct {...@@ -2990,7 +2988,7 @@ pub const DeclGen = struct {
2990 return llvm_struct_ty;2988 return llvm_struct_ty;
2991 }2989 }
29922990
2993 const struct_obj = t.castTag(.@"struct").?.data;2991 const struct_obj = mod.typeToStruct(t).?;
29942992
2995 if (struct_obj.layout == .Packed) {2993 if (struct_obj.layout == .Packed) {
2996 assert(struct_obj.haveLayout());2994 assert(struct_obj.haveLayout());
...@@ -3696,7 +3694,7 @@ pub const DeclGen = struct {...@@ -3696,7 +3694,7 @@ pub const DeclGen = struct {
3696 }3694 }
3697 }3695 }
36983696
3699 const struct_obj = tv.ty.castTag(.@"struct").?.data;3697 const struct_obj = mod.typeToStruct(tv.ty).?;
37003698
3701 if (struct_obj.layout == .Packed) {3699 if (struct_obj.layout == .Packed) {
3702 assert(struct_obj.haveLayout());3700 assert(struct_obj.haveLayout());
...@@ -4043,7 +4041,7 @@ pub const DeclGen = struct {...@@ -4043,7 +4041,7 @@ pub const DeclGen = struct {
4043 const llvm_u32 = dg.context.intType(32);4041 const llvm_u32 = dg.context.intType(32);
4044 switch (parent_ty.zigTypeTag(mod)) {4042 switch (parent_ty.zigTypeTag(mod)) {
4045 .Union => {4043 .Union => {
4046 if (parent_ty.containerLayout() == .Packed) {4044 if (parent_ty.containerLayout(mod) == .Packed) {
4047 return parent_llvm_ptr;4045 return parent_llvm_ptr;
4048 }4046 }
40494047
...@@ -4065,14 +4063,14 @@ pub const DeclGen = struct {...@@ -4065,14 +4063,14 @@ pub const DeclGen = struct {
4065 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);4063 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4066 },4064 },
4067 .Struct => {4065 .Struct => {
4068 if (parent_ty.containerLayout() == .Packed) {4066 if (parent_ty.containerLayout(mod) == .Packed) {
4069 if (!byte_aligned) return parent_llvm_ptr;4067 if (!byte_aligned) return parent_llvm_ptr;
4070 const llvm_usize = dg.context.intType(target.ptrBitWidth());4068 const llvm_usize = dg.context.intType(target.ptrBitWidth());
4071 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);4069 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
4072 // count bits of fields before this one4070 // count bits of fields before this one
4073 const prev_bits = b: {4071 const prev_bits = b: {
4074 var b: usize = 0;4072 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| {
4076 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;4074 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
4077 b += @intCast(usize, field.ty.bitSize(mod));4075 b += @intCast(usize, field.ty.bitSize(mod));
4078 }4076 }
...@@ -5983,7 +5981,7 @@ pub const FuncGen = struct {...@@ -5983,7 +5981,7 @@ pub const FuncGen = struct {
5983 const struct_ty = self.typeOf(struct_field.struct_operand);5981 const struct_ty = self.typeOf(struct_field.struct_operand);
5984 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);5982 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
5985 const field_index = struct_field.field_index;5983 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);
5987 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {5985 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5988 return null;5986 return null;
5989 }5987 }
...@@ -5991,9 +5989,9 @@ pub const FuncGen = struct {...@@ -5991,9 +5989,9 @@ pub const FuncGen = struct {
5991 if (!isByRef(struct_ty, mod)) {5989 if (!isByRef(struct_ty, mod)) {
5992 assert(!isByRef(field_ty, mod));5990 assert(!isByRef(field_ty, mod));
5993 switch (struct_ty.zigTypeTag(mod)) {5991 switch (struct_ty.zigTypeTag(mod)) {
5994 .Struct => switch (struct_ty.containerLayout()) {5992 .Struct => switch (struct_ty.containerLayout(mod)) {
5995 .Packed => {5993 .Packed => {
5996 const struct_obj = struct_ty.castTag(.@"struct").?.data;5994 const struct_obj = mod.typeToStruct(struct_ty).?;
5997 const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index);5995 const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index);
5998 const containing_int = struct_llvm_val;5996 const containing_int = struct_llvm_val;
5999 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);5997 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);
...@@ -6019,7 +6017,7 @@ pub const FuncGen = struct {...@@ -6019,7 +6017,7 @@ pub const FuncGen = struct {
6019 },6017 },
6020 },6018 },
6021 .Union => {6019 .Union => {
6022 assert(struct_ty.containerLayout() == .Packed);6020 assert(struct_ty.containerLayout(mod) == .Packed);
6023 const containing_int = struct_llvm_val;6021 const containing_int = struct_llvm_val;
6024 const elem_llvm_ty = try self.dg.lowerType(field_ty);6022 const elem_llvm_ty = try self.dg.lowerType(field_ty);
6025 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {6023 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
...@@ -6041,7 +6039,7 @@ pub const FuncGen = struct {...@@ -6041,7 +6039,7 @@ pub const FuncGen = struct {
60416039
6042 switch (struct_ty.zigTypeTag(mod)) {6040 switch (struct_ty.zigTypeTag(mod)) {
6043 .Struct => {6041 .Struct => {
6044 assert(struct_ty.containerLayout() != .Packed);6042 assert(struct_ty.containerLayout(mod) != .Packed);
6045 var ptr_ty_buf: Type.Payload.Pointer = undefined;6043 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6046 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;6044 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
6047 const struct_llvm_ty = try self.dg.lowerType(struct_ty);6045 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
...@@ -9289,8 +9287,8 @@ pub const FuncGen = struct {...@@ -9289,8 +9287,8 @@ pub const FuncGen = struct {
9289 return vector;9287 return vector;
9290 },9288 },
9291 .Struct => {9289 .Struct => {
9292 if (result_ty.containerLayout() == .Packed) {9290 if (result_ty.containerLayout(mod) == .Packed) {
9293 const struct_obj = result_ty.castTag(.@"struct").?.data;9291 const struct_obj = mod.typeToStruct(result_ty).?;
9294 assert(struct_obj.haveLayout());9292 assert(struct_obj.haveLayout());
9295 const big_bits = struct_obj.backing_int_ty.bitSize(mod);9293 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
9296 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));9294 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));
...@@ -9795,7 +9793,7 @@ pub const FuncGen = struct {...@@ -9795,7 +9793,7 @@ pub const FuncGen = struct {
9795 const mod = self.dg.module;9793 const mod = self.dg.module;
9796 const struct_ty = struct_ptr_ty.childType(mod);9794 const struct_ty = struct_ptr_ty.childType(mod);
9797 switch (struct_ty.zigTypeTag(mod)) {9795 switch (struct_ty.zigTypeTag(mod)) {
9798 .Struct => switch (struct_ty.containerLayout()) {9796 .Struct => switch (struct_ty.containerLayout(mod)) {
9799 .Packed => {9797 .Packed => {
9800 const result_ty = self.typeOfIndex(inst);9798 const result_ty = self.typeOfIndex(inst);
9801 const result_ty_info = result_ty.ptrInfo(mod);9799 const result_ty_info = result_ty.ptrInfo(mod);
...@@ -9838,7 +9836,7 @@ pub const FuncGen = struct {...@@ -9838,7 +9836,7 @@ pub const FuncGen = struct {
9838 },9836 },
9839 .Union => {9837 .Union => {
9840 const layout = struct_ty.unionGetLayout(mod);9838 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;
9842 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);9840 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
9843 const union_llvm_ty = try self.dg.lowerType(struct_ty);9841 const union_llvm_ty = try self.dg.lowerType(struct_ty);
9844 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");9842 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");
...@@ -10530,11 +10528,11 @@ fn llvmFieldIndex(...@@ -10530,11 +10528,11 @@ fn llvmFieldIndex(
10530 }10528 }
10531 return null;10529 return null;
10532 }10530 }
10533 const layout = ty.containerLayout();10531 const layout = ty.containerLayout(mod);
10534 assert(layout != .Packed);10532 assert(layout != .Packed);
1053510533
10536 var llvm_field_index: c_uint = 0;10534 var llvm_field_index: c_uint = 0;
10537 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator(mod);10535 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
10538 while (it.next()) |field_and_index| {10536 while (it.next()) |field_and_index| {
10539 const field = field_and_index.field;10537 const field = field_and_index.field;
10540 const field_align = field.alignment(mod, layout);10538 const field_align = field.alignment(mod, layout);
...@@ -11113,7 +11111,7 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11113,7 +11111,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
11113 .Array, .Frame => return ty.hasRuntimeBits(mod),11111 .Array, .Frame => return ty.hasRuntimeBits(mod),
11114 .Struct => {11112 .Struct => {
11115 // Packed structs are represented to LLVM as integers.11113 // Packed structs are represented to LLVM as integers.
11116 if (ty.containerLayout() == .Packed) return false;11114 if (ty.containerLayout(mod) == .Packed) return false;
11117 if (ty.isSimpleTupleOrAnonStruct()) {11115 if (ty.isSimpleTupleOrAnonStruct()) {
11118 const tuple = ty.tupleFields();11116 const tuple = ty.tupleFields();
11119 var count: usize = 0;11117 var count: usize = 0;
...@@ -11127,7 +11125,7 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11127,7 +11125,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
11127 return false;11125 return false;
11128 }11126 }
11129 var count: usize = 0;11127 var count: usize = 0;
11130 const fields = ty.structFields();11128 const fields = ty.structFields(mod);
11131 for (fields.values()) |field| {11129 for (fields.values()) |field| {
11132 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;11130 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
1113311131
...@@ -11137,7 +11135,7 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11137,7 +11135,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
11137 }11135 }
11138 return false;11136 return false;
11139 },11137 },
11140 .Union => switch (ty.containerLayout()) {11138 .Union => switch (ty.containerLayout(mod)) {
11141 .Packed => return false,11139 .Packed => return false,
11142 else => return ty.hasRuntimeBits(mod),11140 else => return ty.hasRuntimeBits(mod),
11143 },11141 },
...@@ -11176,8 +11174,8 @@ fn isScalar(mod: *Module, ty: Type) bool {...@@ -11176,8 +11174,8 @@ fn isScalar(mod: *Module, ty: Type) bool {
11176 .Vector,11174 .Vector,
11177 => true,11175 => true,
1117811176
11179 .Struct => ty.containerLayout() == .Packed,11177 .Struct => ty.containerLayout(mod) == .Packed,
11180 .Union => ty.containerLayout() == .Packed,11178 .Union => ty.containerLayout(mod) == .Packed,
11181 else => false,11179 else => false,
11182 };11180 };
11183}11181}
src/codegen/spirv.zig+4-4
...@@ -685,7 +685,7 @@ pub const DeclGen = struct {...@@ -685,7 +685,7 @@ pub const DeclGen = struct {
685 if (ty.isSimpleTupleOrAnonStruct()) {685 if (ty.isSimpleTupleOrAnonStruct()) {
686 unreachable; // TODO686 unreachable; // TODO
687 } else {687 } else {
688 const struct_ty = ty.castTag(.@"struct").?.data;688 const struct_ty = mod.typeToStruct(ty).?;
689689
690 if (struct_ty.layout == .Packed) {690 if (struct_ty.layout == .Packed) {
691 return dg.todo("packed struct constants", .{});691 return dg.todo("packed struct constants", .{});
...@@ -1306,7 +1306,7 @@ pub const DeclGen = struct {...@@ -1306,7 +1306,7 @@ pub const DeclGen = struct {
1306 } });1306 } });
1307 }1307 }
13081308
1309 const struct_ty = ty.castTag(.@"struct").?.data;1309 const struct_ty = mod.typeToStruct(ty).?;
13101310
1311 if (struct_ty.layout == .Packed) {1311 if (struct_ty.layout == .Packed) {
1312 return try self.resolveType(struct_ty.backing_int_ty, .direct);1312 return try self.resolveType(struct_ty.backing_int_ty, .direct);
...@@ -2576,7 +2576,7 @@ pub const DeclGen = struct {...@@ -2576,7 +2576,7 @@ pub const DeclGen = struct {
2576 const struct_ty = self.typeOf(struct_field.struct_operand);2576 const struct_ty = self.typeOf(struct_field.struct_operand);
2577 const object_id = try self.resolve(struct_field.struct_operand);2577 const object_id = try self.resolve(struct_field.struct_operand);
2578 const field_index = struct_field.field_index;2578 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
2581 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;2581 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
25822582
...@@ -2595,7 +2595,7 @@ pub const DeclGen = struct {...@@ -2595,7 +2595,7 @@ pub const DeclGen = struct {
2595 const mod = self.module;2595 const mod = self.module;
2596 const object_ty = object_ptr_ty.childType(mod);2596 const object_ty = object_ptr_ty.childType(mod);
2597 switch (object_ty.zigTypeTag(mod)) {2597 switch (object_ty.zigTypeTag(mod)) {
2598 .Struct => switch (object_ty.containerLayout()) {2598 .Struct => switch (object_ty.containerLayout(mod)) {
2599 .Packed => unreachable, // TODO2599 .Packed => unreachable, // TODO
2600 else => {2600 else => {
2601 const field_index_ty_ref = try self.intType(.unsigned, 32);2601 const field_index_ty_ref = try self.intType(.unsigned, 32);
src/link/Dwarf.zig+2-2
...@@ -360,13 +360,13 @@ pub const DeclState = struct {...@@ -360,13 +360,13 @@ pub const DeclState = struct {
360 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);360 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
361 dbg_info_buffer.appendAssumeCapacity(0);361 dbg_info_buffer.appendAssumeCapacity(0);
362362
363 const struct_obj = ty.castTag(.@"struct").?.data;363 const struct_obj = mod.typeToStruct(ty).?;
364 if (struct_obj.layout == .Packed) {364 if (struct_obj.layout == .Packed) {
365 log.debug("TODO implement .debug_info for packed structs", .{});365 log.debug("TODO implement .debug_info for packed structs", .{});
366 break :blk;366 break :blk;
367 }367 }
368368
369 const fields = ty.structFields();369 const fields = ty.structFields(mod);
370 for (fields.keys(), 0..) |field_name, field_index| {370 for (fields.keys(), 0..) |field_name, field_index| {
371 const field = fields.get(field_name).?;371 const field = fields.get(field_name).?;
372 if (!field.ty.hasRuntimeBits(mod)) continue;372 if (!field.ty.hasRuntimeBits(mod)) continue;
src/type.zig+601-582
...@@ -59,8 +59,6 @@ pub const Type = struct {...@@ -59,8 +59,6 @@ pub const Type = struct {
5959
60 .anyframe_T => return .AnyFrame,60 .anyframe_T => return .AnyFrame,
6161
62 .empty_struct,
63 .@"struct",
64 .tuple,62 .tuple,
65 .anon_struct,63 .anon_struct,
66 => return .Struct,64 => return .Struct,
...@@ -148,6 +146,7 @@ pub const Type = struct {...@@ -148,6 +146,7 @@ pub const Type = struct {
148 .opt => unreachable,146 .opt => unreachable,
149 .enum_tag => unreachable,147 .enum_tag => unreachable,
150 .simple_value => unreachable,148 .simple_value => unreachable,
149 .aggregate => unreachable,
151 },150 },
152 }151 }
153 }152 }
...@@ -501,16 +500,6 @@ pub const Type = struct {...@@ -501,16 +500,6 @@ pub const Type = struct {
501 return a.elemType2(mod).eql(b.elemType2(mod), mod);500 return a.elemType2(mod).eql(b.elemType2(mod), mod);
502 },501 },
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 },
514 .tuple => {503 .tuple => {
515 if (!b.isSimpleTuple()) return false;504 if (!b.isSimpleTuple()) return false;
516505
...@@ -720,15 +709,6 @@ pub const Type = struct {...@@ -720,15 +709,6 @@ pub const Type = struct {
720 hashWithHasher(ty.childType(mod), hasher, mod);709 hashWithHasher(ty.childType(mod), hasher, mod);
721 },710 },
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 },
732 .tuple => {712 .tuple => {
733 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);713 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
734714
...@@ -955,8 +935,6 @@ pub const Type = struct {...@@ -955,8 +935,6 @@ pub const Type = struct {
955 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),935 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
956 .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred),936 .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred),
957 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),937 .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),
960 .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union),938 .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union),
961 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),939 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),
962 .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered),940 .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered),
...@@ -1033,14 +1011,6 @@ pub const Type = struct {...@@ -1033,14 +1011,6 @@ pub const Type = struct {
1033 while (true) {1011 while (true) {
1034 const t = ty.tag();1012 const t = ty.tag();
1035 switch (t) {1013 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 },
1044 .@"union", .union_safety_tagged, .union_tagged => {1014 .@"union", .union_safety_tagged, .union_tagged => {
1045 const union_obj = ty.cast(Payload.Union).?.data;1015 const union_obj = ty.cast(Payload.Union).?.data;
1046 return writer.print("({s} decl={d})", .{1016 return writer.print("({s} decl={d})", .{
...@@ -1247,22 +1217,10 @@ pub const Type = struct {...@@ -1247,22 +1217,10 @@ pub const Type = struct {
1247 /// Prints a name suitable for `@typeName`.1217 /// Prints a name suitable for `@typeName`.
1248 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {1218 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
1249 switch (ty.ip_index) {1219 switch (ty.ip_index) {
1250 .empty_struct_type => try writer.writeAll("@TypeOf(.{})"),
1251
1252 .none => switch (ty.tag()) {1220 .none => switch (ty.tag()) {
1253 .inferred_alloc_const => unreachable,1221 .inferred_alloc_const => unreachable,
1254 .inferred_alloc_mut => unreachable,1222 .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 },
1266 .@"union", .union_safety_tagged, .union_tagged => {1224 .@"union", .union_safety_tagged, .union_tagged => {
1267 const union_obj = ty.cast(Payload.Union).?.data;1225 const union_obj = ty.cast(Payload.Union).?.data;
1268 const decl = mod.declPtr(union_obj.owner_decl);1226 const decl = mod.declPtr(union_obj.owner_decl);
...@@ -1548,7 +1506,18 @@ pub const Type = struct {...@@ -1548,7 +1506,18 @@ pub const Type = struct {
1548 return;1506 return;
1549 },1507 },
1550 .simple_type => |s| return writer.writeAll(@tagName(s)),1508 .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
1552 .union_type => @panic("TODO"),1521 .union_type => @panic("TODO"),
1553 .opaque_type => |opaque_type| {1522 .opaque_type => |opaque_type| {
1554 const decl = mod.declPtr(opaque_type.decl);1523 const decl = mod.declPtr(opaque_type.decl);
...@@ -1562,6 +1531,7 @@ pub const Type = struct {...@@ -1562,6 +1531,7 @@ pub const Type = struct {
1562 .ptr => unreachable,1531 .ptr => unreachable,
1563 .opt => unreachable,1532 .opt => unreachable,
1564 .enum_tag => unreachable,1533 .enum_tag => unreachable,
1534 .aggregate => unreachable,
1565 },1535 },
1566 }1536 }
1567 }1537 }
...@@ -1624,12 +1594,10 @@ pub const Type = struct {...@@ -1624,12 +1594,10 @@ pub const Type = struct {
1624 },1594 },
16251595
1626 // These are false because they are comptime-only types.1596 // These are false because they are comptime-only types.
1627 .empty_struct,
1628 // These are function *bodies*, not pointers.1597 // These are function *bodies*, not pointers.
1629 // Special exceptions have to be made when emitting functions due to1598 // Special exceptions have to be made when emitting functions due to
1630 // this returning false.1599 // this returning false.
1631 .function,1600 .function => return false,
1632 => return false,
16331601
1634 .optional => {1602 .optional => {
1635 const child_ty = ty.optionalChild(mod);1603 const child_ty = ty.optionalChild(mod);
...@@ -1646,28 +1614,6 @@ pub const Type = struct {...@@ -1646,28 +1614,6 @@ pub const Type = struct {
1646 }1614 }
1647 },1615 },
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
1671 .enum_full => {1617 .enum_full => {
1672 const enum_full = ty.castTag(.enum_full).?.data;1618 const enum_full = ty.castTag(.enum_full).?.data;
1673 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);1619 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
...@@ -1824,7 +1770,31 @@ pub const Type = struct {...@@ -1824,7 +1770,31 @@ pub const Type = struct {
1824 .generic_poison => unreachable,1770 .generic_poison => unreachable,
1825 .var_args_param => unreachable,1771 .var_args_param => unreachable,
1826 },1772 },
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
1828 .union_type => @panic("TODO"),1798 .union_type => @panic("TODO"),
1829 .opaque_type => true,1799 .opaque_type => true,
18301800
...@@ -1835,6 +1805,7 @@ pub const Type = struct {...@@ -1835,6 +1805,7 @@ pub const Type = struct {
1835 .ptr => unreachable,1805 .ptr => unreachable,
1836 .opt => unreachable,1806 .opt => unreachable,
1837 .enum_tag => unreachable,1807 .enum_tag => unreachable,
1808 .aggregate => unreachable,
1838 },1809 },
1839 }1810 }
1840 }1811 }
...@@ -1862,7 +1833,6 @@ pub const Type = struct {...@@ -1862,7 +1833,6 @@ pub const Type = struct {
1862 .anyframe_T,1833 .anyframe_T,
1863 .tuple,1834 .tuple,
1864 .anon_struct,1835 .anon_struct,
1865 .empty_struct,
1866 => false,1836 => false,
18671837
1868 .enum_full,1838 .enum_full,
...@@ -1877,7 +1847,6 @@ pub const Type = struct {...@@ -1877,7 +1847,6 @@ pub const Type = struct {
1877 => ty.childType(mod).hasWellDefinedLayout(mod),1847 => ty.childType(mod).hasWellDefinedLayout(mod),
18781848
1879 .optional => ty.isPtrLikeOptional(mod),1849 .optional => ty.isPtrLikeOptional(mod),
1880 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,
1881 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,1850 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,
1882 .union_tagged => false,1851 .union_tagged => false,
1883 },1852 },
...@@ -1936,7 +1905,13 @@ pub const Type = struct {...@@ -1936,7 +1905,13 @@ pub const Type = struct {
19361905
1937 .var_args_param => unreachable,1906 .var_args_param => unreachable,
1938 },1907 },
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 },
1940 .union_type => @panic("TODO"),1915 .union_type => @panic("TODO"),
1941 .opaque_type => false,1916 .opaque_type => false,
19421917
...@@ -1947,6 +1922,7 @@ pub const Type = struct {...@@ -1947,6 +1922,7 @@ pub const Type = struct {
1947 .ptr => unreachable,1922 .ptr => unreachable,
1948 .opt => unreachable,1923 .opt => unreachable,
1949 .enum_tag => unreachable,1924 .enum_tag => unreachable,
1925 .aggregate => unreachable,
1950 },1926 },
1951 };1927 };
1952 }1928 }
...@@ -2146,68 +2122,6 @@ pub const Type = struct {...@@ -2146,68 +2122,6 @@ pub const Type = struct {
2146 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),2122 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
2147 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),2123 .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
2211 .tuple, .anon_struct => {2125 .tuple, .anon_struct => {
2212 const tuple = ty.tupleFields();2126 const tuple = ty.tupleFields();
2213 var big_align: u32 = 0;2127 var big_align: u32 = 0;
...@@ -2241,8 +2155,6 @@ pub const Type = struct {...@@ -2241,8 +2155,6 @@ pub const Type = struct {
2241 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true);2155 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true);
2242 },2156 },
22432157
2244 .empty_struct => return AbiAlignmentAdvanced{ .scalar = 0 },
2245
2246 .inferred_alloc_const,2158 .inferred_alloc_const,
2247 .inferred_alloc_mut,2159 .inferred_alloc_mut,
2248 => unreachable,2160 => unreachable,
...@@ -2337,7 +2249,69 @@ pub const Type = struct {...@@ -2337,7 +2249,69 @@ pub const Type = struct {
2337 .generic_poison => unreachable,2249 .generic_poison => unreachable,
2338 .var_args_param => unreachable,2250 .var_args_param => unreachable,
2339 },2251 },
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 },
2341 .union_type => @panic("TODO"),2315 .union_type => @panic("TODO"),
2342 .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 },2316 .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 },
23432317
...@@ -2348,6 +2322,7 @@ pub const Type = struct {...@@ -2348,6 +2322,7 @@ pub const Type = struct {
2348 .ptr => unreachable,2322 .ptr => unreachable,
2349 .opt => unreachable,2323 .opt => unreachable,
2350 .enum_tag => unreachable,2324 .enum_tag => unreachable,
2325 .aggregate => unreachable,
2351 },2326 },
2352 }2327 }
2353 }2328 }
...@@ -2517,42 +2492,16 @@ pub const Type = struct {...@@ -2517,42 +2492,16 @@ pub const Type = struct {
2517 .inferred_alloc_const => unreachable,2492 .inferred_alloc_const => unreachable,
2518 .inferred_alloc_mut => unreachable,2493 .inferred_alloc_mut => unreachable,
25192494
2520 .empty_struct => return AbiSizeAdvanced{ .scalar = 0 },2495 .tuple, .anon_struct => {
25212496 switch (strat) {
2522 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {2497 .sema => |sema| try sema.resolveTypeLayout(ty),
2523 .Packed => {2498 .lazy, .eager => {},
2524 const struct_obj = ty.castTag(.@"struct").?.data;2499 }
2525 switch (strat) {2500 const field_count = ty.structFieldCount(mod);
2526 .sema => |sema| try sema.resolveTypeLayout(ty),2501 if (field_count == 0) {
2527 .lazy => |arena| {2502 return AbiSizeAdvanced{ .scalar = 0 };
2528 if (!struct_obj.haveLayout()) {2503 }
2529 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };2504 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
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 },
2556 },2505 },
25572506
2558 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {2507 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
...@@ -2752,7 +2701,42 @@ pub const Type = struct {...@@ -2752,7 +2701,42 @@ pub const Type = struct {
2752 .generic_poison => unreachable,2701 .generic_poison => unreachable,
2753 .var_args_param => unreachable,2702 .var_args_param => unreachable,
2754 },2703 },
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 },
2756 .union_type => @panic("TODO"),2740 .union_type => @panic("TODO"),
2757 .opaque_type => unreachable, // no size available2741 .opaque_type => unreachable, // no size available
27582742
...@@ -2763,6 +2747,7 @@ pub const Type = struct {...@@ -2763,6 +2747,7 @@ pub const Type = struct {
2763 .ptr => unreachable,2747 .ptr => unreachable,
2764 .opt => unreachable,2748 .opt => unreachable,
2765 .enum_tag => unreachable,2749 .enum_tag => unreachable,
2750 .aggregate => unreachable,
2766 },2751 },
2767 }2752 }
2768 }2753 }
...@@ -2850,189 +2835,189 @@ pub const Type = struct {...@@ -2850,189 +2835,189 @@ pub const Type = struct {
2850 ) Module.CompileError!u64 {2835 ) Module.CompileError!u64 {
2851 const target = mod.getTarget();2836 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
2940 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;2838 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
29412839
2942 switch (ty.tag()) {2840 switch (ty.ip_index) {
2943 .function => unreachable, // represents machine code; not a pointer2841 .none => switch (ty.tag()) {
2944 .empty_struct => unreachable,2842 .function => unreachable, // represents machine code; not a pointer
2945 .inferred_alloc_const => unreachable,2843 .inferred_alloc_const => unreachable,
2946 .inferred_alloc_mut => unreachable,2844 .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 },
29692845
2970 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {2846 .tuple, .anon_struct => {
2971 const int_tag_ty = try ty.intTagType(mod);2847 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2972 return try bitSizeAdvanced(int_tag_ty, mod, opt_sema);2848 if (ty.containerLayout(mod) != .Packed) {
2973 },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 => {2858 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
2976 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);2859 const int_tag_ty = try ty.intTagType(mod);
2977 if (ty.containerLayout() != .Packed) {2860 return try bitSizeAdvanced(int_tag_ty, mod, opt_sema);
2978 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;2861 },
2979 }
2980 const union_obj = ty.cast(Payload.Union).?.data;
2981 assert(union_obj.haveFieldTypes());
29822862
2983 var size: u64 = 0;2863 .@"union", .union_safety_tagged, .union_tagged => {
2984 for (union_obj.fields.values()) |field| {2864 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2985 size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema));2865 if (ty.containerLayout(mod) != .Packed) {
2986 }2866 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2987 return size;2867 }
2988 },2868 const union_obj = ty.cast(Payload.Union).?.data;
2869 assert(union_obj.haveFieldTypes());
29892870
2990 .array => {2871 var size: u64 = 0;
2991 const payload = ty.castTag(.array).?.data;2872 for (union_obj.fields.values()) |field| {
2992 const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod));2873 size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema));
2993 if (elem_size == 0 or payload.len == 0)2874 }
2994 return @as(u64, 0);2875 return size;
2995 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);2876 },
2996 return (payload.len - 1) * 8 * elem_size + elem_bit_size;2877
2997 },2878 .array => {
2998 .array_sentinel => {2879 const payload = ty.castTag(.array).?.data;
2999 const payload = ty.castTag(.array_sentinel).?.data;2880 const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod));
3000 const elem_size = std.math.max(2881 if (elem_size == 0 or payload.len == 0)
3001 payload.elem_type.abiAlignment(mod),2882 return @as(u64, 0);
3002 payload.elem_type.abiSize(mod),2883 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);
3003 );2884 return (payload.len - 1) * 8 * elem_size + elem_bit_size;
3004 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, mod, opt_sema);2885 },
3005 return payload.len * 8 * elem_size + elem_bit_size;2886 .array_sentinel => {
3006 },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) {2898 .pointer => switch (ty.castTag(.pointer).?.data.size) {
3011 .Slice => return target.ptrBitWidth() * 2,2899 .Slice => return target.ptrBitWidth() * 2,
3012 else => return target.ptrBitWidth(),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 },
3013 },2914 },
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,2944 .usize,
3016 .error_set_single,2945 .isize,
3017 .error_set_inferred,2946 .@"anyframe",
3018 .error_set_merged,2947 => return target.ptrBitWidth(),
3019 => return 16, // TODO revisit this when we have the concept of the error tag type2948
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 => {3002 // values, not types
3022 // Optionals and error unions are not packed so their bitsize3003 .simple_value => unreachable,
3023 // includes padding bits.3004 .extern_func => unreachable,
3024 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;3005 .int => unreachable,
3006 .ptr => unreachable,
3007 .opt => unreachable,
3008 .enum_tag => unreachable,
3009 .aggregate => unreachable,
3025 },3010 },
3026 }3011 }
3027 }3012 }
30283013
3029 /// Returns true if the type's layout is already resolved and it is safe3014 /// Returns true if the type's layout is already resolved and it is safe
3030 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.3015 /// 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 {
3032 switch (ty.zigTypeTag(mod)) {3017 switch (ty.zigTypeTag(mod)) {
3033 .Struct => {3018 .Struct => {
3034 if (ty.castTag(.@"struct")) |struct_ty| {3019 if (mod.typeToStruct(ty)) |struct_obj| {
3035 return struct_ty.data.haveLayout();3020 return struct_obj.haveLayout();
3036 }3021 }
3037 return true;3022 return true;
3038 },3023 },
...@@ -3500,18 +3485,23 @@ pub const Type = struct {...@@ -3500,18 +3485,23 @@ pub const Type = struct {
3500 }3485 }
3501 }3486 }
35023487
3503 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {3488 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
3504 return switch (ty.ip_index) {3489 return switch (ty.ip_index) {
3505 .empty_struct_type => .Auto,3490 .empty_struct_type => .Auto,
3506 .none => switch (ty.tag()) {3491 .none => switch (ty.tag()) {
3507 .tuple, .anon_struct => .Auto,3492 .tuple, .anon_struct => .Auto,
3508 .@"struct" => ty.castTag(.@"struct").?.data.layout,
3509 .@"union" => ty.castTag(.@"union").?.data.layout,3493 .@"union" => ty.castTag(.@"union").?.data.layout,
3510 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,3494 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,
3511 .union_tagged => ty.castTag(.union_tagged).?.data.layout,3495 .union_tagged => ty.castTag(.union_tagged).?.data.layout,
3512 else => unreachable,3496 else => unreachable,
3513 },3497 },
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 },
3515 };3505 };
3516 }3506 }
35173507
...@@ -3631,14 +3621,16 @@ pub const Type = struct {...@@ -3631,14 +3621,16 @@ pub const Type = struct {
3631 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,3621 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,
3632 .tuple => ty.castTag(.tuple).?.data.types.len,3622 .tuple => ty.castTag(.tuple).?.data.types.len,
3633 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,3623 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
3634 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
3635 .empty_struct => 0,
36363624
3637 else => unreachable,3625 else => unreachable,
3638 },3626 },
3639 else => switch (ip.indexToKey(ty.ip_index)) {3627 else => switch (ip.indexToKey(ty.ip_index)) {
3640 .vector_type => |vector_type| vector_type.len,3628 .vector_type => |vector_type| vector_type.len,
3641 .array_type => |array_type| array_type.len,3629 .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 },
3642 else => unreachable,3634 else => unreachable,
3643 },3635 },
3644 };3636 };
...@@ -3665,11 +3657,9 @@ pub const Type = struct {...@@ -3665,11 +3657,9 @@ pub const Type = struct {
3665 /// Asserts the type is an array, pointer or vector.3657 /// Asserts the type is an array, pointer or vector.
3666 pub fn sentinel(ty: Type, mod: *const Module) ?Value {3658 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
3667 return switch (ty.ip_index) {3659 return switch (ty.ip_index) {
3668 .empty_struct_type => null,
3669 .none => switch (ty.tag()) {3660 .none => switch (ty.tag()) {
3670 .array,3661 .array,
3671 .tuple,3662 .tuple,
3672 .@"struct",
3673 => null,3663 => null,
36743664
3675 .pointer => ty.castTag(.pointer).?.data.sentinel,3665 .pointer => ty.castTag(.pointer).?.data.sentinel,
...@@ -3721,16 +3711,16 @@ pub const Type = struct {...@@ -3721,16 +3711,16 @@ pub const Type = struct {
37213711
3722 /// Returns true for integers, enums, error sets, and packed structs.3712 /// Returns true for integers, enums, error sets, and packed structs.
3723 /// If this function returns true, then intInfo() can be called on the type.3713 /// 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 {
3725 return switch (ty.zigTypeTag(mod)) {3715 return switch (ty.zigTypeTag(mod)) {
3726 .Int, .Enum, .ErrorSet => true,3716 .Int, .Enum, .ErrorSet => true,
3727 .Struct => ty.containerLayout() == .Packed,3717 .Struct => ty.containerLayout(mod) == .Packed,
3728 else => false,3718 else => false,
3729 };3719 };
3730 }3720 }
37313721
3732 /// Asserts the type is an integer, enum, error set, or vector of one of them.3722 /// 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 {
3734 const target = mod.getTarget();3724 const target = mod.getTarget();
3735 var ty = starting_ty;3725 var ty = starting_ty;
37363726
...@@ -3750,12 +3740,6 @@ pub const Type = struct {...@@ -3750,12 +3740,6 @@ pub const Type = struct {
3750 return .{ .signedness = .unsigned, .bits = 16 };3740 return .{ .signedness = .unsigned, .bits = 16 };
3751 },3741 },
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
3759 else => unreachable,3743 else => unreachable,
3760 },3744 },
3761 .anyerror_type => {3745 .anyerror_type => {
...@@ -3775,6 +3759,12 @@ pub const Type = struct {...@@ -3775,6 +3759,12 @@ pub const Type = struct {
3775 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },3759 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
3776 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {3760 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3777 .int_type => |int_type| return int_type,3761 .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
3778 .ptr_type => unreachable,3768 .ptr_type => unreachable,
3779 .array_type => unreachable,3769 .array_type => unreachable,
3780 .vector_type => |vector_type| ty = vector_type.child.toType(),3770 .vector_type => |vector_type| ty = vector_type.child.toType(),
...@@ -3782,7 +3772,7 @@ pub const Type = struct {...@@ -3782,7 +3772,7 @@ pub const Type = struct {
3782 .opt_type => unreachable,3772 .opt_type => unreachable,
3783 .error_union_type => unreachable,3773 .error_union_type => unreachable,
3784 .simple_type => unreachable, // handled via Index enum tag above3774 .simple_type => unreachable, // handled via Index enum tag above
3785 .struct_type => @panic("TODO"),3775
3786 .union_type => unreachable,3776 .union_type => unreachable,
3787 .opaque_type => unreachable,3777 .opaque_type => unreachable,
37883778
...@@ -3793,6 +3783,7 @@ pub const Type = struct {...@@ -3793,6 +3783,7 @@ pub const Type = struct {
3793 .ptr => unreachable,3783 .ptr => unreachable,
3794 .opt => unreachable,3784 .opt => unreachable,
3795 .enum_tag => unreachable,3785 .enum_tag => unreachable,
3786 .aggregate => unreachable,
3796 },3787 },
3797 };3788 };
3798 }3789 }
...@@ -3996,17 +3987,6 @@ pub const Type = struct {...@@ -3996,17 +3987,6 @@ pub const Type = struct {
3996 }3987 }
3997 },3988 },
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
4010 .tuple, .anon_struct => {3990 .tuple, .anon_struct => {
4011 const tuple = ty.tupleFields();3991 const tuple = ty.tupleFields();
4012 for (tuple.values, 0..) |val, i| {3992 for (tuple.values, 0..) |val, i| {
...@@ -4069,8 +4049,6 @@ pub const Type = struct {...@@ -4069,8 +4049,6 @@ pub const Type = struct {
4069 return Value.empty_struct;4049 return Value.empty_struct;
4070 },4050 },
40714051
4072 .empty_struct => return Value.empty_struct,
4073
4074 .array => {4052 .array => {
4075 if (ty.arrayLen(mod) == 0)4053 if (ty.arrayLen(mod) == 0)
4076 return Value.initTag(.empty_array);4054 return Value.initTag(.empty_array);
...@@ -4158,7 +4136,23 @@ pub const Type = struct {...@@ -4158,7 +4136,23 @@ pub const Type = struct {
4158 .generic_poison => unreachable,4136 .generic_poison => unreachable,
4159 .var_args_param => unreachable,4137 .var_args_param => unreachable,
4160 },4138 },
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
4162 .union_type => @panic("TODO"),4156 .union_type => @panic("TODO"),
4163 .opaque_type => return null,4157 .opaque_type => return null,
41644158
...@@ -4169,6 +4163,7 @@ pub const Type = struct {...@@ -4169,6 +4163,7 @@ pub const Type = struct {
4169 .ptr => unreachable,4163 .ptr => unreachable,
4170 .opt => unreachable,4164 .opt => unreachable,
4171 .enum_tag => unreachable,4165 .enum_tag => unreachable,
4166 .aggregate => unreachable,
4172 },4167 },
4173 };4168 };
4174 }4169 }
...@@ -4177,12 +4172,11 @@ pub const Type = struct {...@@ -4177,12 +4172,11 @@ pub const Type = struct {
4177 /// resolves field types rather than asserting they are already resolved.4172 /// resolves field types rather than asserting they are already resolved.
4178 /// TODO merge these implementations together with the "advanced" pattern seen4173 /// TODO merge these implementations together with the "advanced" pattern seen
4179 /// elsewhere in this file.4174 /// elsewhere in this file.
4180 pub fn comptimeOnly(ty: Type, mod: *const Module) bool {4175 pub fn comptimeOnly(ty: Type, mod: *Module) bool {
4181 return switch (ty.ip_index) {4176 return switch (ty.ip_index) {
4182 .empty_struct_type => false,4177 .empty_struct_type => false,
41834178
4184 .none => switch (ty.tag()) {4179 .none => switch (ty.tag()) {
4185 .empty_struct,
4186 .error_set,4180 .error_set,
4187 .error_set_single,4181 .error_set_single,
4188 .error_set_inferred,4182 .error_set_inferred,
...@@ -4222,20 +4216,6 @@ pub const Type = struct {...@@ -4222,20 +4216,6 @@ pub const Type = struct {
4222 return false;4216 return false;
4223 },4217 },
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
4239 .@"union", .union_safety_tagged, .union_tagged => {4219 .@"union", .union_safety_tagged, .union_tagged => {
4240 const union_obj = ty.cast(Type.Payload.Union).?.data;4220 const union_obj = ty.cast(Type.Payload.Union).?.data;
4241 switch (union_obj.requires_comptime) {4221 switch (union_obj.requires_comptime) {
...@@ -4326,7 +4306,21 @@ pub const Type = struct {...@@ -4326,7 +4306,21 @@ pub const Type = struct {
43264306
4327 .var_args_param => unreachable,4307 .var_args_param => unreachable,
4328 },4308 },
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
4330 .union_type => @panic("TODO"),4324 .union_type => @panic("TODO"),
4331 .opaque_type => false,4325 .opaque_type => false,
43324326
...@@ -4337,6 +4331,7 @@ pub const Type = struct {...@@ -4337,6 +4331,7 @@ pub const Type = struct {
4337 .ptr => unreachable,4331 .ptr => unreachable,
4338 .opt => unreachable,4332 .opt => unreachable,
4339 .enum_tag => unreachable,4333 .enum_tag => unreachable,
4334 .aggregate => unreachable,
4340 },4335 },
4341 };4336 };
4342 }4337 }
...@@ -4352,19 +4347,19 @@ pub const Type = struct {...@@ -4352,19 +4347,19 @@ pub const Type = struct {
4352 };4347 };
4353 }4348 }
43544349
4355 pub fn isIndexable(ty: Type, mod: *const Module) bool {4350 pub fn isIndexable(ty: Type, mod: *Module) bool {
4356 return switch (ty.zigTypeTag(mod)) {4351 return switch (ty.zigTypeTag(mod)) {
4357 .Array, .Vector => true,4352 .Array, .Vector => true,
4358 .Pointer => switch (ty.ptrSize(mod)) {4353 .Pointer => switch (ty.ptrSize(mod)) {
4359 .Slice, .Many, .C => true,4354 .Slice, .Many, .C => true,
4360 .One => ty.childType(mod).zigTypeTag(mod) == .Array,4355 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
4361 },4356 },
4362 .Struct => ty.isTuple(),4357 .Struct => ty.isTuple(mod),
4363 else => false,4358 else => false,
4364 };4359 };
4365 }4360 }
43664361
4367 pub fn indexableHasLen(ty: Type, mod: *const Module) bool {4362 pub fn indexableHasLen(ty: Type, mod: *Module) bool {
4368 return switch (ty.zigTypeTag(mod)) {4363 return switch (ty.zigTypeTag(mod)) {
4369 .Array, .Vector => true,4364 .Array, .Vector => true,
4370 .Pointer => switch (ty.ptrSize(mod)) {4365 .Pointer => switch (ty.ptrSize(mod)) {
...@@ -4372,7 +4367,7 @@ pub const Type = struct {...@@ -4372,7 +4367,7 @@ pub const Type = struct {
4372 .Slice => true,4367 .Slice => true,
4373 .One => ty.childType(mod).zigTypeTag(mod) == .Array,4368 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
4374 },4369 },
4375 .Struct => ty.isTuple(),4370 .Struct => ty.isTuple(mod),
4376 else => false,4371 else => false,
4377 };4372 };
4378 }4373 }
...@@ -4381,10 +4376,8 @@ pub const Type = struct {...@@ -4381,10 +4376,8 @@ pub const Type = struct {
4381 pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex {4376 pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex {
4382 return switch (ty.ip_index) {4377 return switch (ty.ip_index) {
4383 .none => switch (ty.tag()) {4378 .none => switch (ty.tag()) {
4384 .@"struct" => ty.castTag(.@"struct").?.data.namespace.toOptional(),
4385 .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(),4379 .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(),
4386 .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(),4380 .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(),
4387 .empty_struct => @panic("TODO"),
4388 .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(),4381 .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(),
4389 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(),4382 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(),
4390 .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(),4383 .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(),
...@@ -4393,6 +4386,7 @@ pub const Type = struct {...@@ -4393,6 +4386,7 @@ pub const Type = struct {
4393 },4386 },
4394 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {4387 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4395 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),4388 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
4389 .struct_type => |struct_type| struct_type.namespace,
4396 else => .none,4390 else => .none,
4397 },4391 },
4398 };4392 };
...@@ -4618,161 +4612,188 @@ pub const Type = struct {...@@ -4618,161 +4612,188 @@ pub const Type = struct {
4618 }4612 }
4619 }4613 }
46204614
4621 pub fn structFields(ty: Type) Module.Struct.Fields {4615 pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields {
4622 return switch (ty.ip_index) {4616 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4623 .empty_struct_type => .{},4617 .struct_type => |struct_type| {
4624 .none => switch (ty.tag()) {4618 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .{};
4625 .empty_struct => .{},4619 assert(struct_obj.haveFieldTypes());
4626 .@"struct" => {4620 return struct_obj.fields;
4627 const struct_obj = ty.castTag(.@"struct").?.data;
4628 assert(struct_obj.haveFieldTypes());
4629 return struct_obj.fields;
4630 },
4631 else => unreachable,
4632 },4621 },
4633 else => unreachable,4622 else => unreachable,
4634 };4623 }
4635 }4624 }
46364625
4637 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {4626 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 {
4638 switch (ty.tag()) {4627 switch (ty.ip_index) {
4639 .@"struct" => {4628 .none => switch (ty.tag()) {
4640 const struct_obj = ty.castTag(.@"struct").?.data;4629 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],
4641 assert(struct_obj.haveFieldTypes());4630 else => unreachable,
4642 return struct_obj.fields.keys()[field_index];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,
4643 },4639 },
4644 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],
4645 else => unreachable,
4646 }4640 }
4647 }4641 }
46484642
4649 pub fn structFieldCount(ty: Type) usize {4643 pub fn structFieldCount(ty: Type, mod: *Module) usize {
4650 return switch (ty.ip_index) {4644 return switch (ty.ip_index) {
4651 .empty_struct_type => 0,4645 .empty_struct_type => 0,
4652 .none => switch (ty.tag()) {4646 .none => switch (ty.tag()) {
4653 .@"struct" => {4647 .tuple => ty.castTag(.tuple).?.data.types.len,
4654 const struct_obj = ty.castTag(.@"struct").?.data;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;
4655 assert(struct_obj.haveFieldTypes());4654 assert(struct_obj.haveFieldTypes());
4656 return struct_obj.fields.count();4655 return struct_obj.fields.count();
4657 },4656 },
4658 .empty_struct => 0,
4659 .tuple => ty.castTag(.tuple).?.data.types.len,
4660 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
4661 else => unreachable,4657 else => unreachable,
4662 },4658 },
4663 else => unreachable,
4664 };4659 };
4665 }4660 }
46664661
4667 /// Supports structs and unions.4662 /// Supports structs and unions.
4668 pub fn structFieldType(ty: Type, index: usize) Type {4663 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
4669 switch (ty.tag()) {4664 return switch (ty.ip_index) {
4670 .@"struct" => {4665 .none => switch (ty.tag()) {
4671 const struct_obj = ty.castTag(.@"struct").?.data;4666 .@"union", .union_safety_tagged, .union_tagged => {
4672 return struct_obj.fields.values()[index].ty;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,
4673 },4673 },
4674 .@"union", .union_safety_tagged, .union_tagged => {4674 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4675 const union_obj = ty.cast(Payload.Union).?.data;4675 .struct_type => |struct_type| {
4676 return union_obj.fields.values()[index].ty;4676 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4677 return struct_obj.fields.values()[index].ty;
4678 },
4679 else => unreachable,
4677 },4680 },
4678 .tuple => return ty.castTag(.tuple).?.data.types[index],4681 };
4679 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
4680 else => unreachable,
4681 }
4682 }4682 }
46834683
4684 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {4684 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {
4685 switch (ty.tag()) {4685 switch (ty.ip_index) {
4686 .@"struct" => {4686 .none => switch (ty.tag()) {
4687 const struct_obj = ty.castTag(.@"struct").?.data;4687 .@"union", .union_safety_tagged, .union_tagged => {
4688 assert(struct_obj.layout != .Packed);4688 const union_obj = ty.cast(Payload.Union).?.data;
4689 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);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,
4690 },4694 },
4691 .@"union", .union_safety_tagged, .union_tagged => {4695 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4692 const union_obj = ty.cast(Payload.Union).?.data;4696 .struct_type => |struct_type| {
4693 return union_obj.fields.values()[index].normalAlignment(mod);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,
4694 },4702 },
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,
4698 }4703 }
4699 }4704 }
47004705
4701 pub fn structFieldDefaultValue(ty: Type, index: usize) Value {4706 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
4702 switch (ty.tag()) {4707 switch (ty.ip_index) {
4703 .@"struct" => {4708 .none => switch (ty.tag()) {
4704 const struct_obj = ty.castTag(.@"struct").?.data;4709 .tuple => {
4705 return struct_obj.fields.values()[index].default_val;4710 const tuple = ty.castTag(.tuple).?.data;
4706 },4711 return tuple.values[index];
4707 .tuple => {4712 },
4708 const tuple = ty.castTag(.tuple).?.data;4713 .anon_struct => {
4709 return tuple.values[index];4714 const struct_obj = ty.castTag(.anon_struct).?.data;
4715 return struct_obj.values[index];
4716 },
4717 else => unreachable,
4710 },4718 },
4711 .anon_struct => {4719 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4712 const struct_obj = ty.castTag(.anon_struct).?.data;4720 .struct_type => |struct_type| {
4713 return struct_obj.values[index];4721 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4722 return struct_obj.fields.values()[index].default_val;
4723 },
4724 else => unreachable,
4714 },4725 },
4715 else => unreachable,
4716 }4726 }
4717 }4727 }
47184728
4719 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {4729 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
4720 switch (ty.tag()) {4730 switch (ty.ip_index) {
4721 .@"struct" => {4731 .none => switch (ty.tag()) {
4722 const struct_obj = ty.castTag(.@"struct").?.data;4732 .tuple => {
4723 const field = struct_obj.fields.values()[index];4733 const tuple = ty.castTag(.tuple).?.data;
4724 if (field.is_comptime) {4734 const val = tuple.values[index];
4725 return field.default_val;4735 if (val.ip_index == .unreachable_value) {
4726 } else {4736 return tuple.types[index].onePossibleValue(mod);
4727 return field.ty.onePossibleValue(mod);4737 } else {
4728 }4738 return val;
4729 },4739 }
4730 .tuple => {4740 },
4731 const tuple = ty.castTag(.tuple).?.data;4741 .anon_struct => {
4732 const val = tuple.values[index];4742 const anon_struct = ty.castTag(.anon_struct).?.data;
4733 if (val.ip_index == .unreachable_value) {4743 const val = anon_struct.values[index];
4734 return tuple.types[index].onePossibleValue(mod);4744 if (val.ip_index == .unreachable_value) {
4735 } else {4745 return anon_struct.types[index].onePossibleValue(mod);
4736 return val;4746 } else {
4737 }4747 return val;
4748 }
4749 },
4750 else => unreachable,
4738 },4751 },
4739 .anon_struct => {4752 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4740 const anon_struct = ty.castTag(.anon_struct).?.data;4753 .struct_type => |struct_type| {
4741 const val = anon_struct.values[index];4754 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4742 if (val.ip_index == .unreachable_value) {4755 const field = struct_obj.fields.values()[index];
4743 return anon_struct.types[index].onePossibleValue(mod);4756 if (field.is_comptime) {
4744 } else {4757 return field.default_val;
4745 return val;4758 } else {
4746 }4759 return field.ty.onePossibleValue(mod);
4760 }
4761 },
4762 else => unreachable,
4747 },4763 },
4748 else => unreachable,
4749 }4764 }
4750 }4765 }
47514766
4752 pub fn structFieldIsComptime(ty: Type, index: usize) bool {4767 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
4753 switch (ty.tag()) {4768 switch (ty.ip_index) {
4754 .@"struct" => {4769 .none => switch (ty.tag()) {
4755 const struct_obj = ty.castTag(.@"struct").?.data;4770 .tuple => {
4756 if (struct_obj.layout == .Packed) return false;4771 const tuple = ty.castTag(.tuple).?.data;
4757 const field = struct_obj.fields.values()[index];4772 const val = tuple.values[index];
4758 return field.is_comptime;4773 return val.ip_index != .unreachable_value;
4759 },4774 },
4760 .tuple => {4775 .anon_struct => {
4761 const tuple = ty.castTag(.tuple).?.data;4776 const anon_struct = ty.castTag(.anon_struct).?.data;
4762 const val = tuple.values[index];4777 const val = anon_struct.values[index];
4763 return val.ip_index != .unreachable_value;4778 return val.ip_index != .unreachable_value;
4779 },
4780 else => unreachable,
4764 },4781 },
4765 .anon_struct => {4782 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4766 const anon_struct = ty.castTag(.anon_struct).?.data;4783 .struct_type => |struct_type| {
4767 const val = anon_struct.values[index];4784 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4768 return val.ip_index != .unreachable_value;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,
4769 },4790 },
4770 else => unreachable,
4771 }4791 }
4772 }4792 }
47734793
4774 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {4794 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).?;
4776 assert(struct_obj.layout == .Packed);4797 assert(struct_obj.layout == .Packed);
4777 comptime assert(Type.packed_struct_layout_version == 2);4798 comptime assert(Type.packed_struct_layout_version == 2);
47784799
...@@ -4833,7 +4854,8 @@ pub const Type = struct {...@@ -4833,7 +4854,8 @@ pub const Type = struct {
4833 /// Get an iterator that iterates over all the struct field, returning the field and4854 /// Get an iterator that iterates over all the struct field, returning the field and
4834 /// offset of that field. Asserts that the type is a non-packed struct.4855 /// offset of that field. Asserts that the type is a non-packed struct.
4835 pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator {4856 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).?;
4837 assert(struct_obj.haveLayout());4859 assert(struct_obj.haveLayout());
4838 assert(struct_obj.layout != .Packed);4860 assert(struct_obj.layout != .Packed);
4839 return .{ .struct_obj = struct_obj, .module = mod };4861 return .{ .struct_obj = struct_obj, .module = mod };
...@@ -4841,57 +4863,62 @@ pub const Type = struct {...@@ -4841,57 +4863,62 @@ pub const Type = struct {
48414863
4842 /// Supports structs and unions.4864 /// Supports structs and unions.
4843 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {4865 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
4844 switch (ty.tag()) {4866 switch (ty.ip_index) {
4845 .@"struct" => {4867 .none => switch (ty.tag()) {
4846 const struct_obj = ty.castTag(.@"struct").?.data;4868 .tuple, .anon_struct => {
4847 assert(struct_obj.haveLayout());4869 const tuple = ty.tupleFields();
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 },
48574870
4858 .tuple, .anon_struct => {4871 var offset: u64 = 0;
4859 const tuple = ty.tupleFields();4872 var big_align: u32 = 0;
48604873
4861 var offset: u64 = 0;4874 for (tuple.types, 0..) |field_ty, i| {
4862 var big_align: u32 = 0;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| {4882 const field_align = field_ty.abiAlignment(mod);
4865 const field_val = tuple.values[i];4883 big_align = @max(big_align, field_align);
4866 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) {4884 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
4867 // comptime field
4868 if (i == index) return offset;4885 if (i == index) return offset;
4869 continue;4886 offset += field_ty.abiSize(mod);
4870 }4887 }
4888 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
4889 return offset;
4890 },
48714891
4872 const field_align = field_ty.abiAlignment(mod);4892 .@"union" => return 0,
4873 big_align = @max(big_align, field_align);4893 .union_safety_tagged, .union_tagged => {
4874 offset = std.mem.alignForwardGeneric(u64, offset, field_align);4894 const union_obj = ty.cast(Payload.Union).?.data;
4875 if (i == index) return offset;4895 const layout = union_obj.getLayout(mod, true);
4876 offset += field_ty.abiSize(mod);4896 if (layout.tag_align >= layout.payload_align) {
4877 }4897 // {Tag, Payload}
4878 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));4898 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
4879 return offset;4899 } else {
4900 // {Payload, Tag}
4901 return 0;
4902 }
4903 },
4904 else => unreachable,
4880 },4905 },
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,4917 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4883 .union_safety_tagged, .union_tagged => {4918 },
4884 const union_obj = ty.cast(Payload.Union).?.data;4919
4885 const layout = union_obj.getLayout(mod, true);4920 else => unreachable,
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 }
4893 },4921 },
4894 else => unreachable,
4895 }4922 }
4896 }4923 }
48974924
...@@ -4901,6 +4928,7 @@ pub const Type = struct {...@@ -4901,6 +4928,7 @@ pub const Type = struct {
49014928
4902 pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {4929 pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {
4903 switch (ty.ip_index) {4930 switch (ty.ip_index) {
4931 .empty_struct_type => return null,
4904 .none => switch (ty.tag()) {4932 .none => switch (ty.tag()) {
4905 .enum_full, .enum_nonexhaustive => {4933 .enum_full, .enum_nonexhaustive => {
4906 const enum_full = ty.cast(Payload.EnumFull).?.data;4934 const enum_full = ty.cast(Payload.EnumFull).?.data;
...@@ -4914,10 +4942,6 @@ pub const Type = struct {...@@ -4914,10 +4942,6 @@ pub const Type = struct {
4914 const enum_simple = ty.castTag(.enum_simple).?.data;4942 const enum_simple = ty.castTag(.enum_simple).?.data;
4915 return enum_simple.srcLoc(mod);4943 return enum_simple.srcLoc(mod);
4916 },4944 },
4917 .@"struct" => {
4918 const struct_obj = ty.castTag(.@"struct").?.data;
4919 return struct_obj.srcLoc(mod);
4920 },
4921 .error_set => {4945 .error_set => {
4922 const error_set = ty.castTag(.error_set).?.data;4946 const error_set = ty.castTag(.error_set).?.data;
4923 return error_set.srcLoc(mod);4947 return error_set.srcLoc(mod);
...@@ -4930,7 +4954,10 @@ pub const Type = struct {...@@ -4930,7 +4954,10 @@ pub const Type = struct {
4930 else => return null,4954 else => return null,
4931 },4955 },
4932 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {4956 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 },
4934 .union_type => @panic("TODO"),4961 .union_type => @panic("TODO"),
4935 .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type),4962 .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type),
4936 else => null,4963 else => null,
...@@ -4954,10 +4981,6 @@ pub const Type = struct {...@@ -4954,10 +4981,6 @@ pub const Type = struct {
4954 const enum_simple = ty.castTag(.enum_simple).?.data;4981 const enum_simple = ty.castTag(.enum_simple).?.data;
4955 return enum_simple.owner_decl;4982 return enum_simple.owner_decl;
4956 },4983 },
4957 .@"struct" => {
4958 const struct_obj = ty.castTag(.@"struct").?.data;
4959 return struct_obj.owner_decl;
4960 },
4961 .error_set => {4984 .error_set => {
4962 const error_set = ty.castTag(.error_set).?.data;4985 const error_set = ty.castTag(.error_set).?.data;
4963 return error_set.owner_decl;4986 return error_set.owner_decl;
...@@ -4970,7 +4993,10 @@ pub const Type = struct {...@@ -4970,7 +4993,10 @@ pub const Type = struct {
4970 else => return null,4993 else => return null,
4971 },4994 },
4972 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {4995 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 },
4974 .union_type => @panic("TODO"),5000 .union_type => @panic("TODO"),
4975 .opaque_type => |opaque_type| opaque_type.decl,5001 .opaque_type => |opaque_type| opaque_type.decl,
4976 else => null,5002 else => null,
...@@ -5013,8 +5039,6 @@ pub const Type = struct {...@@ -5013,8 +5039,6 @@ pub const Type = struct {
5013 /// The type is the inferred error set of a specific function.5039 /// The type is the inferred error set of a specific function.
5014 error_set_inferred,5040 error_set_inferred,
5015 error_set_merged,5041 error_set_merged,
5016 empty_struct,
5017 @"struct",
5018 @"union",5042 @"union",
5019 union_safety_tagged,5043 union_safety_tagged,
5020 union_tagged,5044 union_tagged,
...@@ -5046,12 +5070,10 @@ pub const Type = struct {...@@ -5046,12 +5070,10 @@ pub const Type = struct {
5046 .function => Payload.Function,5070 .function => Payload.Function,
5047 .error_union => Payload.ErrorUnion,5071 .error_union => Payload.ErrorUnion,
5048 .error_set_single => Payload.Name,5072 .error_set_single => Payload.Name,
5049 .@"struct" => Payload.Struct,
5050 .@"union", .union_safety_tagged, .union_tagged => Payload.Union,5073 .@"union", .union_safety_tagged, .union_tagged => Payload.Union,
5051 .enum_full, .enum_nonexhaustive => Payload.EnumFull,5074 .enum_full, .enum_nonexhaustive => Payload.EnumFull,
5052 .enum_simple => Payload.EnumSimple,5075 .enum_simple => Payload.EnumSimple,
5053 .enum_numbered => Payload.EnumNumbered,5076 .enum_numbered => Payload.EnumNumbered,
5054 .empty_struct => Payload.ContainerScope,
5055 .tuple => Payload.Tuple,5077 .tuple => Payload.Tuple,
5056 .anon_struct => Payload.AnonStruct,5078 .anon_struct => Payload.AnonStruct,
5057 };5079 };
...@@ -5082,15 +5104,19 @@ pub const Type = struct {...@@ -5082,15 +5104,19 @@ pub const Type = struct {
5082 }5104 }
5083 };5105 };
50845106
5085 pub fn isTuple(ty: Type) bool {5107 pub fn isTuple(ty: Type, mod: *Module) bool {
5086 return switch (ty.ip_index) {5108 return switch (ty.ip_index) {
5087 .empty_struct_type => true,
5088 .none => switch (ty.tag()) {5109 .none => switch (ty.tag()) {
5089 .tuple => true,5110 .tuple => true,
5090 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
5091 else => false,5111 else => false,
5092 },5112 },
5093 else => false, // TODO struct5113 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 },
5094 };5120 };
5095 }5121 }
50965122
...@@ -5101,36 +5127,41 @@ pub const Type = struct {...@@ -5101,36 +5127,41 @@ pub const Type = struct {
5101 .anon_struct => true,5127 .anon_struct => true,
5102 else => false,5128 else => false,
5103 },5129 },
5104 else => false, // TODO struct5130 else => false,
5105 };5131 };
5106 }5132 }
51075133
5108 pub fn isTupleOrAnonStruct(ty: Type) bool {5134 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
5109 return switch (ty.ip_index) {5135 return switch (ty.ip_index) {
5110 .empty_struct_type => true,5136 .empty_struct_type => true,
5111 .none => switch (ty.tag()) {5137 .none => switch (ty.tag()) {
5112 .tuple, .anon_struct => true,5138 .tuple, .anon_struct => true,
5113 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
5114 else => false,5139 else => false,
5115 },5140 },
5116 else => false, // TODO struct5141 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 },
5117 };5148 };
5118 }5149 }
51195150
5120 pub fn isSimpleTuple(ty: Type) bool {5151 pub fn isSimpleTuple(ty: Type) bool {
5121 return switch (ty.ip_index) {5152 return switch (ty.ip_index) {
5122 .empty_struct => true,5153 .empty_struct_type => true,
5123 .none => switch (ty.tag()) {5154 .none => switch (ty.tag()) {
5124 .tuple => true,5155 .tuple => true,
5125 else => false,5156 else => false,
5126 },5157 },
5127 else => false, // TODO5158 else => false,
5128 };5159 };
5129 }5160 }
51305161
5131 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {5162 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {
5132 return switch (ty.ip_index) {5163 return switch (ty.ip_index) {
5133 .empty_struct => true,5164 .empty_struct_type => true,
5134 .none => switch (ty.tag()) {5165 .none => switch (ty.tag()) {
5135 .tuple, .anon_struct => true,5166 .tuple, .anon_struct => true,
5136 else => false,5167 else => false,
...@@ -5142,7 +5173,7 @@ pub const Type = struct {...@@ -5142,7 +5173,7 @@ pub const Type = struct {
5142 // Only allowed for simple tuple types5173 // Only allowed for simple tuple types
5143 pub fn tupleFields(ty: Type) Payload.Tuple.Data {5174 pub fn tupleFields(ty: Type) Payload.Tuple.Data {
5144 return switch (ty.ip_index) {5175 return switch (ty.ip_index) {
5145 .empty_struct => .{ .types = &.{}, .values = &.{} },5176 .empty_struct_type => .{ .types = &.{}, .values = &.{} },
5146 .none => switch (ty.tag()) {5177 .none => switch (ty.tag()) {
5147 .tuple => ty.castTag(.tuple).?.data,5178 .tuple => ty.castTag(.tuple).?.data,
5148 .anon_struct => .{5179 .anon_struct => .{
...@@ -5319,18 +5350,6 @@ pub const Type = struct {...@@ -5319,18 +5350,6 @@ pub const Type = struct {
5319 data: []const u8,5350 data: []const u8,
5320 };5351 };
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
5334 pub const Tuple = struct {5353 pub const Tuple = struct {
5335 base: Payload = .{ .tag = .tuple },5354 base: Payload = .{ .tag = .tuple },
5336 data: Data,5355 data: Data,
src/value.zig+19-26
...@@ -996,10 +996,10 @@ pub const Value = struct {...@@ -996,10 +996,10 @@ pub const Value = struct {
996 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;996 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
997 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);997 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
998 },998 },
999 .Struct => switch (ty.containerLayout()) {999 .Struct => switch (ty.containerLayout(mod)) {
1000 .Auto => return error.IllDefinedMemoryLayout,1000 .Auto => return error.IllDefinedMemoryLayout,
1001 .Extern => {1001 .Extern => {
1002 const fields = ty.structFields().values();1002 const fields = ty.structFields(mod).values();
1003 const field_vals = val.castTag(.aggregate).?.data;1003 const field_vals = val.castTag(.aggregate).?.data;
1004 for (fields, 0..) |field, i| {1004 for (fields, 0..) |field, i| {
1005 const off = @intCast(usize, ty.structFieldOffset(i, mod));1005 const off = @intCast(usize, ty.structFieldOffset(i, mod));
...@@ -1017,7 +1017,7 @@ pub const Value = struct {...@@ -1017,7 +1017,7 @@ pub const Value = struct {
1017 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;1017 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
1018 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);1018 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
1019 },1019 },
1020 .Union => switch (ty.containerLayout()) {1020 .Union => switch (ty.containerLayout(mod)) {
1021 .Auto => return error.IllDefinedMemoryLayout,1021 .Auto => return error.IllDefinedMemoryLayout,
1022 .Extern => return error.Unimplemented,1022 .Extern => return error.Unimplemented,
1023 .Packed => {1023 .Packed => {
...@@ -1119,12 +1119,12 @@ pub const Value = struct {...@@ -1119,12 +1119,12 @@ pub const Value = struct {
1119 bits += elem_bit_size;1119 bits += elem_bit_size;
1120 }1120 }
1121 },1121 },
1122 .Struct => switch (ty.containerLayout()) {1122 .Struct => switch (ty.containerLayout(mod)) {
1123 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1123 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1124 .Extern => unreachable, // Handled in non-packed writeToMemory1124 .Extern => unreachable, // Handled in non-packed writeToMemory
1125 .Packed => {1125 .Packed => {
1126 var bits: u16 = 0;1126 var bits: u16 = 0;
1127 const fields = ty.structFields().values();1127 const fields = ty.structFields(mod).values();
1128 const field_vals = val.castTag(.aggregate).?.data;1128 const field_vals = val.castTag(.aggregate).?.data;
1129 for (fields, 0..) |field, i| {1129 for (fields, 0..) |field, i| {
1130 const field_bits = @intCast(u16, field.ty.bitSize(mod));1130 const field_bits = @intCast(u16, field.ty.bitSize(mod));
...@@ -1133,7 +1133,7 @@ pub const Value = struct {...@@ -1133,7 +1133,7 @@ pub const Value = struct {
1133 }1133 }
1134 },1134 },
1135 },1135 },
1136 .Union => switch (ty.containerLayout()) {1136 .Union => switch (ty.containerLayout(mod)) {
1137 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1137 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1138 .Extern => unreachable, // Handled in non-packed writeToMemory1138 .Extern => unreachable, // Handled in non-packed writeToMemory
1139 .Packed => {1139 .Packed => {
...@@ -1236,14 +1236,14 @@ pub const Value = struct {...@@ -1236,14 +1236,14 @@ pub const Value = struct {
1236 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;1236 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1237 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);1237 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);
1238 },1238 },
1239 .Struct => switch (ty.containerLayout()) {1239 .Struct => switch (ty.containerLayout(mod)) {
1240 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1240 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1241 .Extern => {1241 .Extern => {
1242 const fields = ty.structFields().values();1242 const fields = ty.structFields(mod).values();
1243 const field_vals = try arena.alloc(Value, fields.len);1243 const field_vals = try arena.alloc(Value, fields.len);
1244 for (fields, 0..) |field, i| {1244 for (fields, 0..) |field, i| {
1245 const off = @intCast(usize, ty.structFieldOffset(i, mod));1245 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));
1247 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena);1247 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena);
1248 }1248 }
1249 return Tag.aggregate.create(arena, field_vals);1249 return Tag.aggregate.create(arena, field_vals);
...@@ -1346,12 +1346,12 @@ pub const Value = struct {...@@ -1346,12 +1346,12 @@ pub const Value = struct {
1346 }1346 }
1347 return Tag.aggregate.create(arena, elems);1347 return Tag.aggregate.create(arena, elems);
1348 },1348 },
1349 .Struct => switch (ty.containerLayout()) {1349 .Struct => switch (ty.containerLayout(mod)) {
1350 .Auto => unreachable, // Sema is supposed to have emitted a compile error already1350 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1351 .Extern => unreachable, // Handled by non-packed readFromMemory1351 .Extern => unreachable, // Handled by non-packed readFromMemory
1352 .Packed => {1352 .Packed => {
1353 var bits: u16 = 0;1353 var bits: u16 = 0;
1354 const fields = ty.structFields().values();1354 const fields = ty.structFields(mod).values();
1355 const field_vals = try arena.alloc(Value, fields.len);1355 const field_vals = try arena.alloc(Value, fields.len);
1356 for (fields, 0..) |field, i| {1356 for (fields, 0..) |field, i| {
1357 const field_bits = @intCast(u16, field.ty.bitSize(mod));1357 const field_bits = @intCast(u16, field.ty.bitSize(mod));
...@@ -1996,7 +1996,7 @@ pub const Value = struct {...@@ -1996,7 +1996,7 @@ pub const Value = struct {
1996 }1996 }
19971997
1998 if (ty.zigTypeTag(mod) == .Struct) {1998 if (ty.zigTypeTag(mod) == .Struct) {
1999 const fields = ty.structFields().values();1999 const fields = ty.structFields(mod).values();
2000 assert(fields.len == a_field_vals.len);2000 assert(fields.len == a_field_vals.len);
2001 for (fields, 0..) |field, i| {2001 for (fields, 0..) |field, i| {
2002 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {2002 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 {...@@ -2019,7 +2019,7 @@ pub const Value = struct {
2019 .@"union" => {2019 .@"union" => {
2020 const a_union = a.castTag(.@"union").?.data;2020 const a_union = a.castTag(.@"union").?.data;
2021 const b_union = b.castTag(.@"union").?.data;2021 const b_union = b.castTag(.@"union").?.data;
2022 switch (ty.containerLayout()) {2022 switch (ty.containerLayout(mod)) {
2023 .Packed, .Extern => {2023 .Packed, .Extern => {
2024 const tag_ty = ty.unionTagTypeHypothetical();2024 const tag_ty = ty.unionTagTypeHypothetical();
2025 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {2025 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {
...@@ -2252,7 +2252,7 @@ pub const Value = struct {...@@ -2252,7 +2252,7 @@ pub const Value = struct {
2252 .aggregate => {2252 .aggregate => {
2253 const field_values = val.castTag(.aggregate).?.data;2253 const field_values = val.castTag(.aggregate).?.data;
2254 for (field_values, 0..) |field_val, i| {2254 for (field_values, 0..) |field_val, i| {
2255 const field_ty = ty.structFieldType(i);2255 const field_ty = ty.structFieldType(i, mod);
2256 field_val.hash(field_ty, hasher, mod);2256 field_val.hash(field_ty, hasher, mod);
2257 }2257 }
2258 },2258 },
...@@ -2623,7 +2623,7 @@ pub const Value = struct {...@@ -2623,7 +2623,7 @@ pub const Value = struct {
2623 const data = val.castTag(.field_ptr).?.data;2623 const data = val.castTag(.field_ptr).?.data;
2624 if (data.container_ptr.pointerDecl()) |decl_index| {2624 if (data.container_ptr.pointerDecl()) |decl_index| {
2625 const container_decl = mod.declPtr(decl_index);2625 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);
2627 const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index);2627 const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index);
2628 return field_val.elemValue(mod, index);2628 return field_val.elemValue(mod, index);
2629 } else unreachable;2629 } else unreachable;
...@@ -2758,16 +2758,6 @@ pub const Value = struct {...@@ -2758,16 +2758,6 @@ pub const Value = struct {
2758 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {2758 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
2759 switch (val.ip_index) {2759 switch (val.ip_index) {
2760 .undef => return Value.undef,2760 .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
2772 .none => switch (val.tag()) {2762 .none => switch (val.tag()) {
2773 .aggregate => {2763 .aggregate => {
...@@ -2784,7 +2774,10 @@ pub const Value = struct {...@@ -2784,7 +2774,10 @@ pub const Value = struct {
27842774
2785 else => unreachable,2775 else => unreachable,
2786 },2776 },
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 },
2788 }2781 }
2789 }2782 }
27902783