authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-14 19:23:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:52-07:00
logd18881de1be811c1dff52590223b92c916c4b773
treec4c2f82134654737d0921efc360f900e428d5d92
parent88dbd62bcbac24c09791a7838d2f08c2f540967a

stage2: move anon tuples and anon structs to InternPool


11 files changed, 1147 insertions(+), 1264 deletions(-)

src/InternPool.zig+185-18
...@@ -137,9 +137,14 @@ pub const Key = union(enum) {...@@ -137,9 +137,14 @@ pub const Key = union(enum) {
137 payload_type: Index,137 payload_type: Index,
138 },138 },
139 simple_type: SimpleType,139 simple_type: SimpleType,
140 /// If `empty_struct_type` is handled separately, then this value may be140 /// This represents a struct that has been explicitly declared in source code,
141 /// safely assumed to never be `none`.141 /// or was created with `@Type`. It is unique and based on a declaration.
142 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
142 struct_type: StructType,143 struct_type: StructType,
144 /// This is an anonymous struct or tuple type which has no corresponding
145 /// declaration. It is used for types that have no `struct` keyword in the
146 /// source code, and were not created via `@Type`.
147 anon_struct_type: AnonStructType,
143 union_type: UnionType,148 union_type: UnionType,
144 opaque_type: OpaqueType,149 opaque_type: OpaqueType,
145 enum_type: EnumType,150 enum_type: EnumType,
...@@ -168,7 +173,7 @@ pub const Key = union(enum) {...@@ -168,7 +173,7 @@ pub const Key = union(enum) {
168 /// Each element/field stored as an `Index`.173 /// Each element/field stored as an `Index`.
169 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,174 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
170 /// so the slice length will be one more than the type's array length.175 /// so the slice length will be one more than the type's array length.
171 aggregate: Aggregate,176 aggregate: Key.Aggregate,
172 /// An instance of a union.177 /// An instance of a union.
173 un: Union,178 un: Union,
174179
...@@ -222,22 +227,25 @@ pub const Key = union(enum) {...@@ -222,22 +227,25 @@ pub const Key = union(enum) {
222 namespace: Module.Namespace.Index,227 namespace: Module.Namespace.Index,
223 };228 };
224229
225 /// There are three possibilities here:
226 /// * `@TypeOf(.{})` (untyped empty struct literal)
227 /// - namespace == .none, index == .none
228 /// * A struct which has a namepace, but no fields.
229 /// - index == .none
230 /// * A struct which has fields as well as a namepace.
231 pub const StructType = struct {230 pub const StructType = struct {
232 /// The `none` tag is used to represent two cases:231 /// The `none` tag is used to represent a struct with no fields.
233 /// * `@TypeOf(.{})`, in which case `namespace` will also be `none`.
234 /// * A struct with no fields, in which case `namespace` will be populated.
235 index: Module.Struct.OptionalIndex,232 index: Module.Struct.OptionalIndex,
236 /// This will be `none` only in the case of `@TypeOf(.{})`233 /// May be `none` if the struct has no declarations.
237 /// (`Index.empty_struct_type`).
238 namespace: Module.Namespace.OptionalIndex,234 namespace: Module.Namespace.OptionalIndex,
239 };235 };
240236
237 pub const AnonStructType = struct {
238 types: []const Index,
239 /// This may be empty, indicating this is a tuple.
240 names: []const NullTerminatedString,
241 /// These elements may be `none`, indicating runtime-known.
242 values: []const Index,
243
244 pub fn isTuple(self: AnonStructType) bool {
245 return self.names.len == 0;
246 }
247 };
248
241 pub const UnionType = struct {249 pub const UnionType = struct {
242 index: Module.Union.Index,250 index: Module.Union.Index,
243 runtime_tag: RuntimeTag,251 runtime_tag: RuntimeTag,
...@@ -498,6 +506,12 @@ pub const Key = union(enum) {...@@ -498,6 +506,12 @@ pub const Key = union(enum) {
498 std.hash.autoHash(hasher, aggregate.ty);506 std.hash.autoHash(hasher, aggregate.ty);
499 for (aggregate.fields) |field| std.hash.autoHash(hasher, field);507 for (aggregate.fields) |field| std.hash.autoHash(hasher, field);
500 },508 },
509
510 .anon_struct_type => |anon_struct_type| {
511 for (anon_struct_type.types) |elem| std.hash.autoHash(hasher, elem);
512 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);
513 for (anon_struct_type.names) |elem| std.hash.autoHash(hasher, elem);
514 },
501 }515 }
502 }516 }
503517
...@@ -650,6 +664,12 @@ pub const Key = union(enum) {...@@ -650,6 +664,12 @@ pub const Key = union(enum) {
650 if (a_info.ty != b_info.ty) return false;664 if (a_info.ty != b_info.ty) return false;
651 return std.mem.eql(Index, a_info.fields, b_info.fields);665 return std.mem.eql(Index, a_info.fields, b_info.fields);
652 },666 },
667 .anon_struct_type => |a_info| {
668 const b_info = b.anon_struct_type;
669 return std.mem.eql(Index, a_info.types, b_info.types) and
670 std.mem.eql(Index, a_info.values, b_info.values) and
671 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
672 },
653 }673 }
654 }674 }
655675
...@@ -666,6 +686,7 @@ pub const Key = union(enum) {...@@ -666,6 +686,7 @@ pub const Key = union(enum) {
666 .union_type,686 .union_type,
667 .opaque_type,687 .opaque_type,
668 .enum_type,688 .enum_type,
689 .anon_struct_type,
669 => .type_type,690 => .type_type,
670691
671 inline .ptr,692 inline .ptr,
...@@ -1020,9 +1041,10 @@ pub const static_keys = [_]Key{...@@ -1020,9 +1041,10 @@ pub const static_keys = [_]Key{
1020 .{ .simple_type = .var_args_param },1041 .{ .simple_type = .var_args_param },
10211042
1022 // empty_struct_type1043 // empty_struct_type
1023 .{ .struct_type = .{1044 .{ .anon_struct_type = .{
1024 .namespace = .none,1045 .types = &.{},
1025 .index = .none,1046 .names = &.{},
1047 .values = &.{},
1026 } },1048 } },
10271049
1028 .{ .simple_value = .undefined },1050 .{ .simple_value = .undefined },
...@@ -1144,6 +1166,12 @@ pub const Tag = enum(u8) {...@@ -1144,6 +1166,12 @@ pub const Tag = enum(u8) {
1144 /// Module.Struct object allocated for it.1166 /// Module.Struct object allocated for it.
1145 /// data is Module.Namespace.Index.1167 /// data is Module.Namespace.Index.
1146 type_struct_ns,1168 type_struct_ns,
1169 /// An AnonStructType which stores types, names, and values for each field.
1170 /// data is extra index of `TypeStructAnon`.
1171 type_struct_anon,
1172 /// An AnonStructType which has only types and values for each field.
1173 /// data is extra index of `TypeStructAnon`.
1174 type_tuple_anon,
1147 /// A tagged union type.1175 /// A tagged union type.
1148 /// `data` is `Module.Union.Index`.1176 /// `data` is `Module.Union.Index`.
1149 type_union_tagged,1177 type_union_tagged,
...@@ -1249,6 +1277,26 @@ pub const Tag = enum(u8) {...@@ -1249,6 +1277,26 @@ pub const Tag = enum(u8) {
1249 only_possible_value,1277 only_possible_value,
1250 /// data is extra index to Key.Union.1278 /// data is extra index to Key.Union.
1251 union_value,1279 union_value,
1280 /// An instance of a struct, array, or vector.
1281 /// data is extra index to `Aggregate`.
1282 aggregate,
1283};
1284
1285/// Trailing:
1286/// 0. element: Index for each len
1287/// len is determined by the aggregate type.
1288pub const Aggregate = struct {
1289 /// The type of the aggregate.
1290 ty: Index,
1291};
1292
1293/// Trailing:
1294/// 0. type: Index for each fields_len
1295/// 1. value: Index for each fields_len
1296/// 2. name: NullTerminatedString for each fields_len
1297/// The set of field names is omitted when the `Tag` is `type_tuple_anon`.
1298pub const TypeStructAnon = struct {
1299 fields_len: u32,
1252};1300};
12531301
1254/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to1302/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to
...@@ -1572,6 +1620,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -1572,6 +1620,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
1572}1620}
15731621
1574pub fn indexToKey(ip: InternPool, index: Index) Key {1622pub fn indexToKey(ip: InternPool, index: Index) Key {
1623 assert(index != .none);
1575 const item = ip.items.get(@enumToInt(index));1624 const item = ip.items.get(@enumToInt(index));
1576 const data = item.data;1625 const data = item.data;
1577 return switch (item.tag) {1626 return switch (item.tag) {
...@@ -1659,6 +1708,30 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1659,6 +1708,30 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1659 .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(),1708 .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(),
1660 } },1709 } },
16611710
1711 .type_struct_anon => {
1712 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
1713 const fields_len = type_struct_anon.data.fields_len;
1714 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
1715 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
1716 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
1717 return .{ .anon_struct_type = .{
1718 .types = @ptrCast([]const Index, types),
1719 .values = @ptrCast([]const Index, values),
1720 .names = @ptrCast([]const NullTerminatedString, names),
1721 } };
1722 },
1723 .type_tuple_anon => {
1724 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
1725 const fields_len = type_struct_anon.data.fields_len;
1726 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
1727 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
1728 return .{ .anon_struct_type = .{
1729 .types = @ptrCast([]const Index, types),
1730 .values = @ptrCast([]const Index, values),
1731 .names = &.{},
1732 } };
1733 },
1734
1662 .type_union_untagged => .{ .union_type = .{1735 .type_union_untagged => .{ .union_type = .{
1663 .index = @intToEnum(Module.Union.Index, data),1736 .index = @intToEnum(Module.Union.Index, data),
1664 .runtime_tag = .none,1737 .runtime_tag = .none,
...@@ -1797,6 +1870,15 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1797,6 +1870,15 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1797 else => unreachable,1870 else => unreachable,
1798 };1871 };
1799 },1872 },
1873 .aggregate => {
1874 const extra = ip.extraDataTrail(Aggregate, data);
1875 const len = @intCast(u32, ip.aggregateTypeLen(extra.data.ty));
1876 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);
1877 return .{ .aggregate = .{
1878 .ty = extra.data.ty,
1879 .fields = fields,
1880 } };
1881 },
1800 .union_value => .{ .un = ip.extraData(Key.Union, data) },1882 .union_value => .{ .un = ip.extraData(Key.Union, data) },
1801 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },1883 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },
1802 };1884 };
...@@ -1982,6 +2064,45 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1982,6 +2064,45 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1982 });2064 });
1983 },2065 },
19842066
2067 .anon_struct_type => |anon_struct_type| {
2068 assert(anon_struct_type.types.len == anon_struct_type.values.len);
2069 for (anon_struct_type.types) |elem| assert(elem != .none);
2070
2071 const fields_len = @intCast(u32, anon_struct_type.types.len);
2072 if (anon_struct_type.names.len == 0) {
2073 try ip.extra.ensureUnusedCapacity(
2074 gpa,
2075 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 2),
2076 );
2077 ip.items.appendAssumeCapacity(.{
2078 .tag = .type_tuple_anon,
2079 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
2080 .fields_len = fields_len,
2081 }),
2082 });
2083 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.types));
2084 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.values));
2085 return @intToEnum(Index, ip.items.len - 1);
2086 }
2087
2088 assert(anon_struct_type.names.len == anon_struct_type.types.len);
2089
2090 try ip.extra.ensureUnusedCapacity(
2091 gpa,
2092 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 3),
2093 );
2094 ip.items.appendAssumeCapacity(.{
2095 .tag = .type_struct_anon,
2096 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
2097 .fields_len = fields_len,
2098 }),
2099 });
2100 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.types));
2101 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.values));
2102 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.names));
2103 return @intToEnum(Index, ip.items.len - 1);
2104 },
2105
1985 .union_type => |union_type| {2106 .union_type => |union_type| {
1986 ip.items.appendAssumeCapacity(.{2107 ip.items.appendAssumeCapacity(.{
1987 .tag = switch (union_type.runtime_tag) {2108 .tag = switch (union_type.runtime_tag) {
...@@ -2269,6 +2390,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2269,6 +2390,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2269 },2390 },
22702391
2271 .aggregate => |aggregate| {2392 .aggregate => |aggregate| {
2393 assert(aggregate.ty != .none);
2394 for (aggregate.fields) |elem| assert(elem != .none);
2395 if (aggregate.fields.len != ip.aggregateTypeLen(aggregate.ty)) {
2396 std.debug.print("aggregate fields len = {d}, type len = {d}\n", .{
2397 aggregate.fields.len,
2398 ip.aggregateTypeLen(aggregate.ty),
2399 });
2400 }
2401 assert(aggregate.fields.len == ip.aggregateTypeLen(aggregate.ty));
2402
2272 if (aggregate.fields.len == 0) {2403 if (aggregate.fields.len == 0) {
2273 ip.items.appendAssumeCapacity(.{2404 ip.items.appendAssumeCapacity(.{
2274 .tag = .only_possible_value,2405 .tag = .only_possible_value,
...@@ -2276,7 +2407,19 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2276,7 +2407,19 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2276 });2407 });
2277 return @intToEnum(Index, ip.items.len - 1);2408 return @intToEnum(Index, ip.items.len - 1);
2278 }2409 }
2279 @panic("TODO");2410
2411 try ip.extra.ensureUnusedCapacity(
2412 gpa,
2413 @typeInfo(Aggregate).Struct.fields.len + aggregate.fields.len,
2414 );
2415
2416 ip.items.appendAssumeCapacity(.{
2417 .tag = .aggregate,
2418 .data = ip.addExtraAssumeCapacity(Aggregate{
2419 .ty = aggregate.ty,
2420 }),
2421 });
2422 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.fields));
2280 },2423 },
22812424
2282 .un => |un| {2425 .un => |un| {
...@@ -2913,6 +3056,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -2913,6 +3056,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
2913 .type_opaque => @sizeOf(Key.OpaqueType),3056 .type_opaque => @sizeOf(Key.OpaqueType),
2914 .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),3057 .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
2915 .type_struct_ns => @sizeOf(Module.Namespace),3058 .type_struct_ns => @sizeOf(Module.Namespace),
3059 .type_struct_anon => b: {
3060 const info = ip.extraData(TypeStructAnon, data);
3061 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
3062 },
3063 .type_tuple_anon => b: {
3064 const info = ip.extraData(TypeStructAnon, data);
3065 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 2 * info.fields_len);
3066 },
29163067
2917 .type_union_tagged,3068 .type_union_tagged,
2918 .type_union_untagged,3069 .type_union_untagged,
...@@ -2942,6 +3093,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -2942,6 +3093,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
2942 },3093 },
2943 .enum_tag => @sizeOf(Key.EnumTag),3094 .enum_tag => @sizeOf(Key.EnumTag),
29443095
3096 .aggregate => b: {
3097 const info = ip.extraData(Aggregate, data);
3098 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));
3099 break :b @sizeOf(Aggregate) + (@sizeOf(u32) * fields_len);
3100 },
3101
2945 .float_f16 => 0,3102 .float_f16 => 0,
2946 .float_f32 => 0,3103 .float_f32 => 0,
2947 .float_f64 => @sizeOf(Float64),3104 .float_f64 => @sizeOf(Float64),
...@@ -3079,3 +3236,13 @@ pub fn toEnum(ip: InternPool, comptime E: type, i: Index) E {...@@ -3079,3 +3236,13 @@ pub fn toEnum(ip: InternPool, comptime E: type, i: Index) E {
3079 const int = ip.indexToKey(i).enum_tag.int;3236 const int = ip.indexToKey(i).enum_tag.int;
3080 return @intToEnum(E, ip.indexToKey(int).int.storage.u64);3237 return @intToEnum(E, ip.indexToKey(int).int.storage.u64);
3081}3238}
3239
3240pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
3241 return switch (ip.indexToKey(ty)) {
3242 .struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
3243 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
3244 .array_type => |array_type| array_type.len,
3245 .vector_type => |vector_type| vector_type.len,
3246 else => unreachable,
3247 };
3248}
src/Sema.zig+384-331
...@@ -7896,12 +7896,15 @@ fn resolveGenericInstantiationType(...@@ -7896,12 +7896,15 @@ fn resolveGenericInstantiationType(
7896}7896}
78977897
7898fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {7898fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
7899 if (!ty.isSimpleTupleOrAnonStruct()) return;7899 const mod = sema.mod;
7900 const tuple = ty.tupleFields();7900 const tuple = switch (mod.intern_pool.indexToKey(ty.ip_index)) {
7901 for (tuple.values, 0..) |field_val, i| {7901 .anon_struct_type => |tuple| tuple,
7902 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);7902 else => return,
7903 if (field_val.ip_index == .unreachable_value) continue;7903 };
7904 try sema.resolveLazyValue(field_val);7904 for (tuple.types, tuple.values) |field_ty, field_val| {
7905 try sema.resolveTupleLazyValues(block, src, field_ty.toType());
7906 if (field_val == .none) continue;
7907 try sema.resolveLazyValue(field_val.toValue());
7905 }7908 }
7906}7909}
79077910
...@@ -12038,31 +12041,49 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12038,31 +12041,49 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12038 const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);12041 const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);
12039 const field_name = try sema.resolveConstString(block, name_src, extra.rhs, "field name must be comptime-known");12042 const field_name = try sema.resolveConstString(block, name_src, extra.rhs, "field name must be comptime-known");
12040 const ty = try sema.resolveTypeFields(unresolved_ty);12043 const ty = try sema.resolveTypeFields(unresolved_ty);
12044 const ip = &mod.intern_pool;
1204112045
12042 const has_field = hf: {12046 const has_field = hf: {
12043 if (ty.isSlice(mod)) {12047 switch (ip.indexToKey(ty.ip_index)) {
12044 if (mem.eql(u8, field_name, "ptr")) break :hf true;12048 .ptr_type => |ptr_type| switch (ptr_type.size) {
12045 if (mem.eql(u8, field_name, "len")) break :hf true;12049 .Slice => {
12046 break :hf false;12050 if (mem.eql(u8, field_name, "ptr")) break :hf true;
12047 }12051 if (mem.eql(u8, field_name, "len")) break :hf true;
12048 if (ty.castTag(.anon_struct)) |pl| {12052 break :hf false;
12049 break :hf for (pl.data.names) |name| {12053 },
12050 if (mem.eql(u8, name, field_name)) break true;12054 else => {},
12051 } else false;12055 },
12052 }12056 .anon_struct_type => |anon_struct| {
12053 if (ty.isTuple(mod)) {12057 if (anon_struct.names.len != 0) {
12054 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;12058 // If the string is not interned, then the field certainly is not present.
12055 break :hf field_index < ty.structFieldCount(mod);12059 const name_interned = ip.getString(field_name).unwrap() orelse break :hf false;
12056 }12060 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names, name_interned) != null;
12057 break :hf switch (ty.zigTypeTag(mod)) {12061 } else {
12058 .Struct => ty.structFields(mod).contains(field_name),12062 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;
12059 .Union => ty.unionFields(mod).contains(field_name),12063 break :hf field_index < ty.structFieldCount(mod);
12060 .Enum => ty.enumFieldIndex(field_name, mod) != null,12064 }
12061 .Array => mem.eql(u8, field_name, "len"),12065 },
12062 else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{12066 .struct_type => |struct_type| {
12063 ty.fmt(sema.mod),12067 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :hf false;
12064 }),12068 assert(struct_obj.haveFieldTypes());
12065 };12069 break :hf struct_obj.fields.contains(field_name);
12070 },
12071 .union_type => |union_type| {
12072 const union_obj = mod.unionPtr(union_type.index);
12073 assert(union_obj.haveFieldTypes());
12074 break :hf union_obj.fields.contains(field_name);
12075 },
12076 .enum_type => |enum_type| {
12077 // If the string is not interned, then the field certainly is not present.
12078 const name_interned = ip.getString(field_name).unwrap() orelse break :hf false;
12079 break :hf enum_type.nameIndex(ip, name_interned) != null;
12080 },
12081 .array_type => break :hf mem.eql(u8, field_name, "len"),
12082 else => {},
12083 }
12084 return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
12085 ty.fmt(sema.mod),
12086 });
12066 };12087 };
12067 if (has_field) {12088 if (has_field) {
12068 return Air.Inst.Ref.bool_true;12089 return Air.Inst.Ref.bool_true;
...@@ -12632,42 +12653,48 @@ fn analyzeTupleCat(...@@ -12632,42 +12653,48 @@ fn analyzeTupleCat(
12632 }12653 }
12633 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);12654 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
1263412655
12635 const types = try sema.arena.alloc(Type, final_len);12656 const types = try sema.arena.alloc(InternPool.Index, final_len);
12636 const values = try sema.arena.alloc(Value, final_len);12657 const values = try sema.arena.alloc(InternPool.Index, final_len);
1263712658
12638 const opt_runtime_src = rs: {12659 const opt_runtime_src = rs: {
12639 var runtime_src: ?LazySrcLoc = null;12660 var runtime_src: ?LazySrcLoc = null;
12640 var i: u32 = 0;12661 var i: u32 = 0;
12641 while (i < lhs_len) : (i += 1) {12662 while (i < lhs_len) : (i += 1) {
12642 types[i] = lhs_ty.structFieldType(i, mod);12663 types[i] = lhs_ty.structFieldType(i, mod).ip_index;
12643 const default_val = lhs_ty.structFieldDefaultValue(i, mod);12664 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
12644 values[i] = default_val;12665 values[i] = default_val.ip_index;
12645 const operand_src = lhs_src; // TODO better source location12666 const operand_src = lhs_src; // TODO better source location
12646 if (default_val.ip_index == .unreachable_value) {12667 if (default_val.ip_index == .unreachable_value) {
12647 runtime_src = operand_src;12668 runtime_src = operand_src;
12669 values[i] = .none;
12648 }12670 }
12649 }12671 }
12650 i = 0;12672 i = 0;
12651 while (i < rhs_len) : (i += 1) {12673 while (i < rhs_len) : (i += 1) {
12652 types[i + lhs_len] = rhs_ty.structFieldType(i, mod);12674 types[i + lhs_len] = rhs_ty.structFieldType(i, mod).ip_index;
12653 const default_val = rhs_ty.structFieldDefaultValue(i, mod);12675 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
12654 values[i + lhs_len] = default_val;12676 values[i + lhs_len] = default_val.ip_index;
12655 const operand_src = rhs_src; // TODO better source location12677 const operand_src = rhs_src; // TODO better source location
12656 if (default_val.ip_index == .unreachable_value) {12678 if (default_val.ip_index == .unreachable_value) {
12657 runtime_src = operand_src;12679 runtime_src = operand_src;
12680 values[i + lhs_len] = .none;
12658 }12681 }
12659 }12682 }
12660 break :rs runtime_src;12683 break :rs runtime_src;
12661 };12684 };
1266212685
12663 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{12686 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
12664 .types = types,12687 .types = types,
12665 .values = values,12688 .values = values,
12666 });12689 .names = &.{},
12690 } });
1266712691
12668 const runtime_src = opt_runtime_src orelse {12692 const runtime_src = opt_runtime_src orelse {
12669 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);12693 const tuple_val = try mod.intern(.{ .aggregate = .{
12670 return sema.addConstant(tuple_ty, tuple_val);12694 .ty = tuple_ty,
12695 .fields = values,
12696 } });
12697 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
12671 };12698 };
1267212699
12673 try sema.requireRuntimeBlock(block, src, runtime_src);12700 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -12685,7 +12712,7 @@ fn analyzeTupleCat(...@@ -12685,7 +12712,7 @@ fn analyzeTupleCat(
12685 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);12712 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);
12686 }12713 }
1268712714
12688 return block.addAggregateInit(tuple_ty, element_refs);12715 return block.addAggregateInit(tuple_ty.toType(), element_refs);
12689}12716}
1269012717
12691fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {12718fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -12938,7 +12965,7 @@ fn analyzeTupleMul(...@@ -12938,7 +12965,7 @@ fn analyzeTupleMul(
12938 block: *Block,12965 block: *Block,
12939 src_node: i32,12966 src_node: i32,
12940 operand: Air.Inst.Ref,12967 operand: Air.Inst.Ref,
12941 factor: u64,12968 factor: usize,
12942) CompileError!Air.Inst.Ref {12969) CompileError!Air.Inst.Ref {
12943 const mod = sema.mod;12970 const mod = sema.mod;
12944 const operand_ty = sema.typeOf(operand);12971 const operand_ty = sema.typeOf(operand);
...@@ -12947,44 +12974,45 @@ fn analyzeTupleMul(...@@ -12947,44 +12974,45 @@ fn analyzeTupleMul(
12947 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };12974 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1294812975
12949 const tuple_len = operand_ty.structFieldCount(mod);12976 const tuple_len = operand_ty.structFieldCount(mod);
12950 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch12977 const final_len = std.math.mul(usize, tuple_len, factor) catch
12951 return sema.fail(block, rhs_src, "operation results in overflow", .{});12978 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1295212979
12953 if (final_len_u64 == 0) {12980 if (final_len == 0) {
12954 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);12981 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
12955 }12982 }
12956 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);12983 const types = try sema.arena.alloc(InternPool.Index, final_len);
1295712984 const values = try sema.arena.alloc(InternPool.Index, final_len);
12958 const types = try sema.arena.alloc(Type, final_len);
12959 const values = try sema.arena.alloc(Value, final_len);
1296012985
12961 const opt_runtime_src = rs: {12986 const opt_runtime_src = rs: {
12962 var runtime_src: ?LazySrcLoc = null;12987 var runtime_src: ?LazySrcLoc = null;
12963 var i: u32 = 0;12988 for (0..tuple_len) |i| {
12964 while (i < tuple_len) : (i += 1) {12989 types[i] = operand_ty.structFieldType(i, mod).ip_index;
12965 types[i] = operand_ty.structFieldType(i, mod);12990 values[i] = operand_ty.structFieldDefaultValue(i, mod).ip_index;
12966 values[i] = operand_ty.structFieldDefaultValue(i, mod);
12967 const operand_src = lhs_src; // TODO better source location12991 const operand_src = lhs_src; // TODO better source location
12968 if (values[i].ip_index == .unreachable_value) {12992 if (values[i] == .unreachable_value) {
12969 runtime_src = operand_src;12993 runtime_src = operand_src;
12994 values[i] = .none; // TODO don't treat unreachable_value as special
12970 }12995 }
12971 }12996 }
12972 i = 0;12997 for (0..factor) |i| {
12973 while (i < factor) : (i += 1) {12998 mem.copyForwards(InternPool.Index, types[tuple_len * i ..], types[0..tuple_len]);
12974 mem.copyForwards(Type, types[tuple_len * i ..], types[0..tuple_len]);12999 mem.copyForwards(InternPool.Index, values[tuple_len * i ..], values[0..tuple_len]);
12975 mem.copyForwards(Value, values[tuple_len * i ..], values[0..tuple_len]);
12976 }13000 }
12977 break :rs runtime_src;13001 break :rs runtime_src;
12978 };13002 };
1297913003
12980 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{13004 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
12981 .types = types,13005 .types = types,
12982 .values = values,13006 .values = values,
12983 });13007 .names = &.{},
13008 } });
1298413009
12985 const runtime_src = opt_runtime_src orelse {13010 const runtime_src = opt_runtime_src orelse {
12986 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);13011 const tuple_val = try mod.intern(.{ .aggregate = .{
12987 return sema.addConstant(tuple_ty, tuple_val);13012 .ty = tuple_ty,
13013 .fields = values,
13014 } });
13015 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
12988 };13016 };
1298913017
12990 try sema.requireRuntimeBlock(block, src, runtime_src);13018 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -13000,7 +13028,7 @@ fn analyzeTupleMul(...@@ -13000,7 +13028,7 @@ fn analyzeTupleMul(
13000 @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]);13028 @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]);
13001 }13029 }
1300213030
13003 return block.addAggregateInit(tuple_ty, element_refs);13031 return block.addAggregateInit(tuple_ty.toType(), element_refs);
13004}13032}
1300513033
13006fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {13034fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -13020,7 +13048,8 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13020,7 +13048,8 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13020 if (lhs_ty.isTuple(mod)) {13048 if (lhs_ty.isTuple(mod)) {
13021 // In `**` rhs must be comptime-known, but lhs can be runtime-known13049 // In `**` rhs must be comptime-known, but lhs can be runtime-known
13022 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");13050 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
13023 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);13051 const factor_casted = try sema.usizeCast(block, rhs_src, factor);
13052 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor_casted);
13024 }13053 }
1302513054
13026 // Analyze the lhs first, to catch the case that someone tried to do exponentiation13055 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
...@@ -14533,19 +14562,14 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {...@@ -14533,19 +14562,14 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
14533 .child = .u1_type,14562 .child = .u1_type,
14534 }) else Type.u1;14563 }) else Type.u1;
1453514564
14536 const types = try sema.arena.alloc(Type, 2);14565 const types = [2]InternPool.Index{ ty.ip_index, ov_ty.ip_index };
14537 const values = try sema.arena.alloc(Value, 2);14566 const values = [2]InternPool.Index{ .none, .none };
14538 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{14567 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
14539 .types = types,14568 .types = &types,
14540 .values = values,14569 .values = &values,
14541 });14570 .names = &.{},
1454214571 } });
14543 types[0] = ty;14572 return tuple_ty.toType();
14544 types[1] = ov_ty;
14545 values[0] = Value.@"unreachable";
14546 values[1] = Value.@"unreachable";
14547
14548 return tuple_ty;
14549}14573}
1455014574
14551fn analyzeArithmetic(14575fn analyzeArithmetic(
...@@ -16506,57 +16530,66 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16506,57 +16530,66 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16506 const layout = struct_ty.containerLayout(mod);16530 const layout = struct_ty.containerLayout(mod);
1650716531
16508 const struct_field_vals = fv: {16532 const struct_field_vals = fv: {
16509 if (struct_ty.isSimpleTupleOrAnonStruct()) {16533 const struct_type = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
16510 const tuple = struct_ty.tupleFields();16534 .anon_struct_type => |tuple| {
16511 const field_types = tuple.types;16535 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, tuple.types.len);
16512 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);16536 for (
16513 for (struct_field_vals, 0..) |*struct_field_val, i| {16537 tuple.types,
16514 const field_ty = field_types[i];16538 tuple.values,
16515 const name_val = v: {16539 struct_field_vals,
16516 var anon_decl = try block.startAnonDecl();16540 0..,
16517 defer anon_decl.deinit();16541 ) |field_ty, field_val, *struct_field_val, i| {
16518 const bytes = if (struct_ty.castTag(.anon_struct)) |payload|16542 const name_val = v: {
16519 try anon_decl.arena().dupeZ(u8, payload.data.names[i])16543 var anon_decl = try block.startAnonDecl();
16520 else16544 defer anon_decl.deinit();
16521 try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});16545 const bytes = if (tuple.names.len != 0)
16522 const new_decl = try anon_decl.finish(16546 // https://github.com/ziglang/zig/issues/15709
16523 try Type.array(anon_decl.arena(), bytes.len, Value.zero_u8, Type.u8, mod),16547 @as([]const u8, mod.intern_pool.stringToSlice(tuple.names[i]))
16524 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),16548 else
16525 0, // default alignment16549 try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
16526 );16550 const new_decl = try anon_decl.finish(
16527 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{16551 try Type.array(anon_decl.arena(), bytes.len, Value.zero_u8, Type.u8, mod),
16528 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),16552 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16529 .len = try mod.intValue(Type.usize, bytes.len),16553 0, // default alignment
16530 });16554 );
16531 };16555 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
1653216556 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16533 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);16557 .len = try mod.intValue(Type.usize, bytes.len),
16534 const field_val = tuple.values[i];16558 });
16535 const is_comptime = field_val.ip_index != .unreachable_value;16559 };
16536 const opt_default_val = if (is_comptime) field_val else null;
16537 const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val);
16538 struct_field_fields.* = .{
16539 // name: []const u8,
16540 name_val,
16541 // type: type,
16542 try Value.Tag.ty.create(fields_anon_decl.arena(), field_ty),
16543 // default_value: ?*const anyopaque,
16544 try default_val_ptr.copy(fields_anon_decl.arena()),
16545 // is_comptime: bool,
16546 Value.makeBool(is_comptime),
16547 // alignment: comptime_int,
16548 try field_ty.lazyAbiAlignment(mod, fields_anon_decl.arena()),
16549 };
16550 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16551 }
16552 break :fv struct_field_vals;
16553 }
16554 const struct_fields = struct_ty.structFields(mod);
16555 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
1655616560
16557 for (struct_field_vals, 0..) |*field_val, i| {16561 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16558 const field = struct_fields.values()[i];16562 const is_comptime = field_val != .none;
16559 const name = struct_fields.keys()[i];16563 const opt_default_val = if (is_comptime) field_val.toValue() else null;
16564 const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
16565 struct_field_fields.* = .{
16566 // name: []const u8,
16567 name_val,
16568 // type: type,
16569 field_ty.toValue(),
16570 // default_value: ?*const anyopaque,
16571 try default_val_ptr.copy(fields_anon_decl.arena()),
16572 // is_comptime: bool,
16573 Value.makeBool(is_comptime),
16574 // alignment: comptime_int,
16575 try field_ty.toType().lazyAbiAlignment(mod, fields_anon_decl.arena()),
16576 };
16577 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16578 }
16579 break :fv struct_field_vals;
16580 },
16581 .struct_type => |s| s,
16582 else => unreachable,
16583 };
16584 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
16585 break :fv &[0]Value{};
16586 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_obj.fields.count());
16587
16588 for (
16589 struct_field_vals,
16590 struct_obj.fields.keys(),
16591 struct_obj.fields.values(),
16592 ) |*field_val, name, field| {
16560 const name_val = v: {16593 const name_val = v: {
16561 var anon_decl = try block.startAnonDecl();16594 var anon_decl = try block.startAnonDecl();
16562 defer anon_decl.deinit();16595 defer anon_decl.deinit();
...@@ -18013,7 +18046,7 @@ fn zirStructInit(...@@ -18013,7 +18046,7 @@ fn zirStructInit(
18013 try sema.requireRuntimeBlock(block, src, null);18046 try sema.requireRuntimeBlock(block, src, null);
18014 try sema.queueFullTypeResolution(resolved_ty);18047 try sema.queueFullTypeResolution(resolved_ty);
18015 return block.addUnionInit(resolved_ty, field_index, init_inst);18048 return block.addUnionInit(resolved_ty, field_index, init_inst);
18016 } else if (resolved_ty.isAnonStruct()) {18049 } else if (resolved_ty.isAnonStruct(mod)) {
18017 return sema.fail(block, src, "TODO anon struct init validation", .{});18050 return sema.fail(block, src, "TODO anon struct init validation", .{});
18018 }18051 }
18019 unreachable;18052 unreachable;
...@@ -18034,60 +18067,54 @@ fn finishStructInit(...@@ -18034,60 +18067,54 @@ fn finishStructInit(
18034 var root_msg: ?*Module.ErrorMsg = null;18067 var root_msg: ?*Module.ErrorMsg = null;
18035 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);18068 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
1803618069
18037 if (struct_ty.isAnonStruct()) {18070 switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
18038 const struct_obj = struct_ty.castTag(.anon_struct).?.data;18071 .anon_struct_type => |anon_struct| {
18039 for (struct_obj.values, 0..) |default_val, i| {18072 for (anon_struct.types, anon_struct.values, 0..) |field_ty, default_val, i| {
18040 if (field_inits[i] != .none) continue;18073 if (field_inits[i] != .none) continue;
18041
18042 if (default_val.ip_index == .unreachable_value) {
18043 const field_name = struct_obj.names[i];
18044 const template = "missing struct field: {s}";
18045 const args = .{field_name};
18046 if (root_msg) |msg| {
18047 try sema.errNote(block, init_src, msg, template, args);
18048 } else {
18049 root_msg = try sema.errMsg(block, init_src, template, args);
18050 }
18051 } else {
18052 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
18053 }
18054 }
18055 } else if (struct_ty.isTuple(mod)) {
18056 var i: u32 = 0;
18057 const len = struct_ty.structFieldCount(mod);
18058 while (i < len) : (i += 1) {
18059 if (field_inits[i] != .none) continue;
1806018074
18061 const default_val = struct_ty.structFieldDefaultValue(i, mod);18075 if (default_val == .none) {
18062 if (default_val.ip_index == .unreachable_value) {18076 if (anon_struct.names.len == 0) {
18063 const template = "missing tuple field with index {d}";18077 const template = "missing tuple field with index {d}";
18064 if (root_msg) |msg| {18078 if (root_msg) |msg| {
18065 try sema.errNote(block, init_src, msg, template, .{i});18079 try sema.errNote(block, init_src, msg, template, .{i});
18080 } else {
18081 root_msg = try sema.errMsg(block, init_src, template, .{i});
18082 }
18083 } else {
18084 const field_name = mod.intern_pool.stringToSlice(anon_struct.names[i]);
18085 const template = "missing struct field: {s}";
18086 const args = .{field_name};
18087 if (root_msg) |msg| {
18088 try sema.errNote(block, init_src, msg, template, args);
18089 } else {
18090 root_msg = try sema.errMsg(block, init_src, template, args);
18091 }
18092 }
18066 } else {18093 } else {
18067 root_msg = try sema.errMsg(block, init_src, template, .{i});18094 field_inits[i] = try sema.addConstant(field_ty.toType(), default_val.toValue());
18068 }18095 }
18069 } else {
18070 field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i, mod), default_val);
18071 }18096 }
18072 }18097 },
18073 } else {18098 .struct_type => |struct_type| {
18074 const struct_obj = mod.typeToStruct(struct_ty).?;18099 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18075 for (struct_obj.fields.values(), 0..) |field, i| {18100 for (struct_obj.fields.values(), 0..) |field, i| {
18076 if (field_inits[i] != .none) continue;18101 if (field_inits[i] != .none) continue;
1807718102
18078 if (field.default_val.ip_index == .unreachable_value) {18103 if (field.default_val.ip_index == .unreachable_value) {
18079 const field_name = struct_obj.fields.keys()[i];18104 const field_name = struct_obj.fields.keys()[i];
18080 const template = "missing struct field: {s}";18105 const template = "missing struct field: {s}";
18081 const args = .{field_name};18106 const args = .{field_name};
18082 if (root_msg) |msg| {18107 if (root_msg) |msg| {
18083 try sema.errNote(block, init_src, msg, template, args);18108 try sema.errNote(block, init_src, msg, template, args);
18109 } else {
18110 root_msg = try sema.errMsg(block, init_src, template, args);
18111 }
18084 } else {18112 } else {
18085 root_msg = try sema.errMsg(block, init_src, template, args);18113 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
18086 }18114 }
18087 } else {
18088 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
18089 }18115 }
18090 }18116 },
18117 else => unreachable,
18091 }18118 }
1809218119
18093 if (root_msg) |msg| {18120 if (root_msg) |msg| {
...@@ -18159,31 +18186,33 @@ fn zirStructInitAnon(...@@ -18159,31 +18186,33 @@ fn zirStructInitAnon(
18159 is_ref: bool,18186 is_ref: bool,
18160) CompileError!Air.Inst.Ref {18187) CompileError!Air.Inst.Ref {
18161 const mod = sema.mod;18188 const mod = sema.mod;
18189 const gpa = sema.gpa;
18162 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;18190 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
18163 const src = inst_data.src();18191 const src = inst_data.src();
18164 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);18192 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
18165 const types = try sema.arena.alloc(Type, extra.data.fields_len);18193 const types = try sema.arena.alloc(InternPool.Index, extra.data.fields_len);
18166 const values = try sema.arena.alloc(Value, types.len);18194 const values = try sema.arena.alloc(InternPool.Index, types.len);
18167 var fields = std.StringArrayHashMapUnmanaged(u32){};18195 var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena);
18168 defer fields.deinit(sema.gpa);18196 try fields.ensureUnusedCapacity(types.len);
18169 try fields.ensureUnusedCapacity(sema.gpa, types.len);
1817018197
18171 // Find which field forces the expression to be runtime, if any.18198 // Find which field forces the expression to be runtime, if any.
18172 const opt_runtime_index = rs: {18199 const opt_runtime_index = rs: {
18173 var runtime_index: ?usize = null;18200 var runtime_index: ?usize = null;
18174 var extra_index = extra.end;18201 var extra_index = extra.end;
18175 for (types, 0..) |*field_ty, i| {18202 for (types, 0..) |*field_ty, i_usize| {
18203 const i = @intCast(u32, i_usize);
18176 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);18204 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
18177 extra_index = item.end;18205 extra_index = item.end;
1817818206
18179 const name = sema.code.nullTerminatedString(item.data.field_name);18207 const name = sema.code.nullTerminatedString(item.data.field_name);
18180 const gop = fields.getOrPutAssumeCapacity(name);18208 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
18209 const gop = fields.getOrPutAssumeCapacity(name_ip);
18181 if (gop.found_existing) {18210 if (gop.found_existing) {
18182 const msg = msg: {18211 const msg = msg: {
18183 const decl = sema.mod.declPtr(block.src_decl);18212 const decl = sema.mod.declPtr(block.src_decl);
18184 const field_src = mod.initSrc(src.node_offset.x, decl, i);18213 const field_src = mod.initSrc(src.node_offset.x, decl, i);
18185 const msg = try sema.errMsg(block, field_src, "duplicate field", .{});18214 const msg = try sema.errMsg(block, field_src, "duplicate field", .{});
18186 errdefer msg.destroy(sema.gpa);18215 errdefer msg.destroy(gpa);
1818718216
18188 const prev_source = mod.initSrc(src.node_offset.x, decl, gop.value_ptr.*);18217 const prev_source = mod.initSrc(src.node_offset.x, decl, gop.value_ptr.*);
18189 try sema.errNote(block, prev_source, msg, "other field here", .{});18218 try sema.errNote(block, prev_source, msg, "other field here", .{});
...@@ -18191,41 +18220,44 @@ fn zirStructInitAnon(...@@ -18191,41 +18220,44 @@ fn zirStructInitAnon(
18191 };18220 };
18192 return sema.failWithOwnedErrorMsg(msg);18221 return sema.failWithOwnedErrorMsg(msg);
18193 }18222 }
18194 gop.value_ptr.* = @intCast(u32, i);18223 gop.value_ptr.* = i;
1819518224
18196 const init = try sema.resolveInst(item.data.init);18225 const init = try sema.resolveInst(item.data.init);
18197 field_ty.* = sema.typeOf(init);18226 field_ty.* = sema.typeOf(init).ip_index;
18198 if (types[i].zigTypeTag(mod) == .Opaque) {18227 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
18199 const msg = msg: {18228 const msg = msg: {
18200 const decl = sema.mod.declPtr(block.src_decl);18229 const decl = sema.mod.declPtr(block.src_decl);
18201 const field_src = mod.initSrc(src.node_offset.x, decl, i);18230 const field_src = mod.initSrc(src.node_offset.x, decl, i);
18202 const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});18231 const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
18203 errdefer msg.destroy(sema.gpa);18232 errdefer msg.destroy(sema.gpa);
1820418233
18205 try sema.addDeclaredHereNote(msg, types[i]);18234 try sema.addDeclaredHereNote(msg, types[i].toType());
18206 break :msg msg;18235 break :msg msg;
18207 };18236 };
18208 return sema.failWithOwnedErrorMsg(msg);18237 return sema.failWithOwnedErrorMsg(msg);
18209 }18238 }
18210 if (try sema.resolveMaybeUndefVal(init)) |init_val| {18239 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
18211 values[i] = init_val;18240 values[i] = init_val.ip_index;
18212 } else {18241 } else {
18213 values[i] = Value.@"unreachable";18242 values[i] = .none;
18214 runtime_index = i;18243 runtime_index = i;
18215 }18244 }
18216 }18245 }
18217 break :rs runtime_index;18246 break :rs runtime_index;
18218 };18247 };
1821918248
18220 const tuple_ty = try Type.Tag.anon_struct.create(sema.arena, .{18249 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
18221 .names = try sema.arena.dupe([]const u8, fields.keys()),18250 .names = fields.keys(),
18222 .types = types,18251 .types = types,
18223 .values = values,18252 .values = values,
18224 });18253 } });
1822518254
18226 const runtime_index = opt_runtime_index orelse {18255 const runtime_index = opt_runtime_index orelse {
18227 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);18256 const tuple_val = try mod.intern(.{ .aggregate = .{
18228 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);18257 .ty = tuple_ty,
18258 .fields = values,
18259 } });
18260 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
18229 };18261 };
1823018262
18231 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {18263 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
...@@ -18241,7 +18273,7 @@ fn zirStructInitAnon(...@@ -18241,7 +18273,7 @@ fn zirStructInitAnon(
18241 if (is_ref) {18273 if (is_ref) {
18242 const target = sema.mod.getTarget();18274 const target = sema.mod.getTarget();
18243 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{18275 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18244 .pointee_type = tuple_ty,18276 .pointee_type = tuple_ty.toType(),
18245 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18277 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18246 });18278 });
18247 const alloc = try block.addTy(.alloc, alloc_ty);18279 const alloc = try block.addTy(.alloc, alloc_ty);
...@@ -18254,9 +18286,9 @@ fn zirStructInitAnon(...@@ -18254,9 +18286,9 @@ fn zirStructInitAnon(
18254 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{18286 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18255 .mutable = true,18287 .mutable = true,
18256 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18288 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18257 .pointee_type = field_ty,18289 .pointee_type = field_ty.toType(),
18258 });18290 });
18259 if (values[i].ip_index == .unreachable_value) {18291 if (values[i] == .none) {
18260 const init = try sema.resolveInst(item.data.init);18292 const init = try sema.resolveInst(item.data.init);
18261 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);18293 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
18262 _ = try block.addBinOp(.store, field_ptr, init);18294 _ = try block.addBinOp(.store, field_ptr, init);
...@@ -18274,7 +18306,7 @@ fn zirStructInitAnon(...@@ -18274,7 +18306,7 @@ fn zirStructInitAnon(
18274 element_refs[i] = try sema.resolveInst(item.data.init);18306 element_refs[i] = try sema.resolveInst(item.data.init);
18275 }18307 }
1827618308
18277 return block.addAggregateInit(tuple_ty, element_refs);18309 return block.addAggregateInit(tuple_ty.toType(), element_refs);
18278}18310}
1827918311
18280fn zirArrayInit(18312fn zirArrayInit(
...@@ -18400,43 +18432,47 @@ fn zirArrayInitAnon(...@@ -18400,43 +18432,47 @@ fn zirArrayInitAnon(
18400 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);18432 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);
18401 const mod = sema.mod;18433 const mod = sema.mod;
1840218434
18403 const types = try sema.arena.alloc(Type, operands.len);18435 const types = try sema.arena.alloc(InternPool.Index, operands.len);
18404 const values = try sema.arena.alloc(Value, operands.len);18436 const values = try sema.arena.alloc(InternPool.Index, operands.len);
1840518437
18406 const opt_runtime_src = rs: {18438 const opt_runtime_src = rs: {
18407 var runtime_src: ?LazySrcLoc = null;18439 var runtime_src: ?LazySrcLoc = null;
18408 for (operands, 0..) |operand, i| {18440 for (operands, 0..) |operand, i| {
18409 const operand_src = src; // TODO better source location18441 const operand_src = src; // TODO better source location
18410 const elem = try sema.resolveInst(operand);18442 const elem = try sema.resolveInst(operand);
18411 types[i] = sema.typeOf(elem);18443 types[i] = sema.typeOf(elem).ip_index;
18412 if (types[i].zigTypeTag(mod) == .Opaque) {18444 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
18413 const msg = msg: {18445 const msg = msg: {
18414 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});18446 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
18415 errdefer msg.destroy(sema.gpa);18447 errdefer msg.destroy(sema.gpa);
1841618448
18417 try sema.addDeclaredHereNote(msg, types[i]);18449 try sema.addDeclaredHereNote(msg, types[i].toType());
18418 break :msg msg;18450 break :msg msg;
18419 };18451 };
18420 return sema.failWithOwnedErrorMsg(msg);18452 return sema.failWithOwnedErrorMsg(msg);
18421 }18453 }
18422 if (try sema.resolveMaybeUndefVal(elem)) |val| {18454 if (try sema.resolveMaybeUndefVal(elem)) |val| {
18423 values[i] = val;18455 values[i] = val.ip_index;
18424 } else {18456 } else {
18425 values[i] = Value.@"unreachable";18457 values[i] = .none;
18426 runtime_src = operand_src;18458 runtime_src = operand_src;
18427 }18459 }
18428 }18460 }
18429 break :rs runtime_src;18461 break :rs runtime_src;
18430 };18462 };
1843118463
18432 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{18464 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
18433 .types = types,18465 .types = types,
18434 .values = values,18466 .values = values,
18435 });18467 .names = &.{},
18468 } });
1843618469
18437 const runtime_src = opt_runtime_src orelse {18470 const runtime_src = opt_runtime_src orelse {
18438 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);18471 const tuple_val = try mod.intern(.{ .aggregate = .{
18439 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);18472 .ty = tuple_ty,
18473 .fields = values,
18474 } });
18475 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
18440 };18476 };
1844118477
18442 try sema.requireRuntimeBlock(block, src, runtime_src);18478 try sema.requireRuntimeBlock(block, src, runtime_src);
...@@ -18444,7 +18480,7 @@ fn zirArrayInitAnon(...@@ -18444,7 +18480,7 @@ fn zirArrayInitAnon(
18444 if (is_ref) {18480 if (is_ref) {
18445 const target = sema.mod.getTarget();18481 const target = sema.mod.getTarget();
18446 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{18482 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18447 .pointee_type = tuple_ty,18483 .pointee_type = tuple_ty.toType(),
18448 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18484 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18449 });18485 });
18450 const alloc = try block.addTy(.alloc, alloc_ty);18486 const alloc = try block.addTy(.alloc, alloc_ty);
...@@ -18453,9 +18489,9 @@ fn zirArrayInitAnon(...@@ -18453,9 +18489,9 @@ fn zirArrayInitAnon(
18453 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{18489 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18454 .mutable = true,18490 .mutable = true,
18455 .@"addrspace" = target_util.defaultAddressSpace(target, .local),18491 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18456 .pointee_type = types[i],18492 .pointee_type = types[i].toType(),
18457 });18493 });
18458 if (values[i].ip_index == .unreachable_value) {18494 if (values[i] == .none) {
18459 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);18495 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
18460 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));18496 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));
18461 }18497 }
...@@ -18469,7 +18505,7 @@ fn zirArrayInitAnon(...@@ -18469,7 +18505,7 @@ fn zirArrayInitAnon(
18469 element_refs[i] = try sema.resolveInst(operand);18505 element_refs[i] = try sema.resolveInst(operand);
18470 }18506 }
1847118507
18472 return block.addAggregateInit(tuple_ty, element_refs);18508 return block.addAggregateInit(tuple_ty.toType(), element_refs);
18473}18509}
1847418510
18475fn addConstantMaybeRef(18511fn addConstantMaybeRef(
...@@ -18532,15 +18568,18 @@ fn fieldType(...@@ -18532,15 +18568,18 @@ fn fieldType(
18532 const resolved_ty = try sema.resolveTypeFields(cur_ty);18568 const resolved_ty = try sema.resolveTypeFields(cur_ty);
18533 cur_ty = resolved_ty;18569 cur_ty = resolved_ty;
18534 switch (cur_ty.zigTypeTag(mod)) {18570 switch (cur_ty.zigTypeTag(mod)) {
18535 .Struct => {18571 .Struct => switch (mod.intern_pool.indexToKey(cur_ty.ip_index)) {
18536 if (cur_ty.isAnonStruct()) {18572 .anon_struct_type => |anon_struct| {
18537 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);18573 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
18538 return sema.addType(cur_ty.tupleFields().types[field_index]);18574 return sema.addType(anon_struct.types[field_index].toType());
18539 }18575 },
18540 const struct_obj = mod.typeToStruct(cur_ty).?;18576 .struct_type => |struct_type| {
18541 const field = struct_obj.fields.get(field_name) orelse18577 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18542 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);18578 const field = struct_obj.fields.get(field_name) orelse
18543 return sema.addType(field.ty);18579 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18580 return sema.addType(field.ty);
18581 },
18582 else => unreachable,
18544 },18583 },
18545 .Union => {18584 .Union => {
18546 const union_obj = mod.typeToUnion(cur_ty).?;18585 const union_obj = mod.typeToUnion(cur_ty).?;
...@@ -24697,7 +24736,7 @@ fn structFieldPtr(...@@ -24697,7 +24736,7 @@ fn structFieldPtr(
24697 }24736 }
24698 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);24737 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
24699 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);24738 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
24700 } else if (struct_ty.isAnonStruct()) {24739 } else if (struct_ty.isAnonStruct(mod)) {
24701 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);24740 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24702 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);24741 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
24703 }24742 }
...@@ -24721,11 +24760,11 @@ fn structFieldPtrByIndex(...@@ -24721,11 +24760,11 @@ fn structFieldPtrByIndex(
24721 struct_ty: Type,24760 struct_ty: Type,
24722 initializing: bool,24761 initializing: bool,
24723) CompileError!Air.Inst.Ref {24762) CompileError!Air.Inst.Ref {
24724 if (struct_ty.isAnonStruct()) {24763 const mod = sema.mod;
24764 if (struct_ty.isAnonStruct(mod)) {
24725 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);24765 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);
24726 }24766 }
2472724767
24728 const mod = sema.mod;
24729 const struct_obj = mod.typeToStruct(struct_ty).?;24768 const struct_obj = mod.typeToStruct(struct_ty).?;
24730 const field = struct_obj.fields.values()[field_index];24769 const field = struct_obj.fields.values()[field_index];
24731 const struct_ptr_ty = sema.typeOf(struct_ptr);24770 const struct_ptr_ty = sema.typeOf(struct_ptr);
...@@ -24830,45 +24869,42 @@ fn structFieldVal(...@@ -24830,45 +24869,42 @@ fn structFieldVal(
24830 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);24869 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
2483124870
24832 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);24871 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24833 switch (struct_ty.ip_index) {24872 switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
24834 .empty_struct_type => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),24873 .struct_type => |struct_type| {
24835 .none => switch (struct_ty.tag()) {24874 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
24836 .tuple => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),24875 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
24837 .anon_struct => {
24838 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24839 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24840 },
24841 else => unreachable,
24842 },
24843 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
24844 .struct_type => |struct_type| {
24845 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
24846 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2484724876
24848 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse24877 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24849 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);24878 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
24850 const field_index = @intCast(u32, field_index_usize);24879 const field_index = @intCast(u32, field_index_usize);
24851 const field = struct_obj.fields.values()[field_index];24880 const field = struct_obj.fields.values()[field_index];
24852
24853 if (field.is_comptime) {
24854 return sema.addConstant(field.ty, field.default_val);
24855 }
2485624881
24857 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {24882 if (field.is_comptime) {
24858 if (struct_val.isUndef(mod)) return sema.addConstUndef(field.ty);24883 return sema.addConstant(field.ty, field.default_val);
24859 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {24884 }
24860 return sema.addConstant(field.ty, opv);
24861 }
2486224885
24863 const field_values = struct_val.castTag(.aggregate).?.data;24886 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24864 return sema.addConstant(field.ty, field_values[field_index]);24887 if (struct_val.isUndef(mod)) return sema.addConstUndef(field.ty);
24888 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24889 return sema.addConstant(field.ty, opv);
24865 }24890 }
2486624891
24867 try sema.requireRuntimeBlock(block, src, null);24892 const field_values = struct_val.castTag(.aggregate).?.data;
24868 return block.addStructFieldVal(struct_byval, field_index, field.ty);24893 return sema.addConstant(field.ty, field_values[field_index]);
24869 },24894 }
24870 else => unreachable,24895
24896 try sema.requireRuntimeBlock(block, src, null);
24897 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24898 },
24899 .anon_struct_type => |anon_struct| {
24900 if (anon_struct.names.len == 0) {
24901 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
24902 } else {
24903 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24904 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24905 }
24871 },24906 },
24907 else => unreachable,
24872 }24908 }
24873}24909}
2487424910
...@@ -25931,7 +25967,7 @@ fn coerceExtra(...@@ -25931,7 +25967,7 @@ fn coerceExtra(
25931 .Union => {25967 .Union => {
25932 // pointer to anonymous struct to pointer to union25968 // pointer to anonymous struct to pointer to union
25933 if (inst_ty.isSinglePointer(mod) and25969 if (inst_ty.isSinglePointer(mod) and
25934 inst_ty.childType(mod).isAnonStruct() and25970 inst_ty.childType(mod).isAnonStruct(mod) and
25935 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))25971 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
25936 {25972 {
25937 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);25973 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
...@@ -25940,7 +25976,7 @@ fn coerceExtra(...@@ -25940,7 +25976,7 @@ fn coerceExtra(
25940 .Struct => {25976 .Struct => {
25941 // pointer to anonymous struct to pointer to struct25977 // pointer to anonymous struct to pointer to struct
25942 if (inst_ty.isSinglePointer(mod) and25978 if (inst_ty.isSinglePointer(mod) and
25943 inst_ty.childType(mod).isAnonStruct() and25979 inst_ty.childType(mod).isAnonStruct(mod) and
25944 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))25980 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
25945 {25981 {
25946 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {25982 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {
...@@ -26231,7 +26267,7 @@ fn coerceExtra(...@@ -26231,7 +26267,7 @@ fn coerceExtra(
26231 .Union => switch (inst_ty.zigTypeTag(mod)) {26267 .Union => switch (inst_ty.zigTypeTag(mod)) {
26232 .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),26268 .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),
26233 .Struct => {26269 .Struct => {
26234 if (inst_ty.isAnonStruct()) {26270 if (inst_ty.isAnonStruct(mod)) {
26235 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);26271 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);
26236 }26272 }
26237 },26273 },
...@@ -28771,8 +28807,8 @@ fn coerceAnonStructToUnion(...@@ -28771,8 +28807,8 @@ fn coerceAnonStructToUnion(
28771 return sema.failWithOwnedErrorMsg(msg);28807 return sema.failWithOwnedErrorMsg(msg);
28772 }28808 }
2877328809
28774 const anon_struct = inst_ty.castTag(.anon_struct).?.data;28810 const anon_struct = mod.intern_pool.indexToKey(inst_ty.ip_index).anon_struct_type;
28775 const field_name = anon_struct.names[0];28811 const field_name = mod.intern_pool.stringToSlice(anon_struct.names[0]);
28776 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);28812 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
28777 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);28813 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
28778}28814}
...@@ -29010,13 +29046,14 @@ fn coerceTupleToStruct(...@@ -29010,13 +29046,14 @@ fn coerceTupleToStruct(
29010 @memset(field_refs, .none);29046 @memset(field_refs, .none);
2901129047
29012 const inst_ty = sema.typeOf(inst);29048 const inst_ty = sema.typeOf(inst);
29049 const anon_struct = mod.intern_pool.indexToKey(inst_ty.ip_index).anon_struct_type;
29013 var runtime_src: ?LazySrcLoc = null;29050 var runtime_src: ?LazySrcLoc = null;
29014 const field_count = inst_ty.structFieldCount(mod);29051 for (0..anon_struct.types.len) |field_index_usize| {
29015 var field_i: u32 = 0;29052 const field_i = @intCast(u32, field_index_usize);
29016 while (field_i < field_count) : (field_i += 1) {
29017 const field_src = inst_src; // TODO better source location29053 const field_src = inst_src; // TODO better source location
29018 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|29054 const field_name = if (anon_struct.names.len != 0)
29019 payload.data.names[field_i]29055 // https://github.com/ziglang/zig/issues/15709
29056 @as([]const u8, mod.intern_pool.stringToSlice(anon_struct.names[field_i]))
29020 else29057 else
29021 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});29058 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
29022 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);29059 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
...@@ -29094,21 +29131,22 @@ fn coerceTupleToTuple(...@@ -29094,21 +29131,22 @@ fn coerceTupleToTuple(
29094 inst_src: LazySrcLoc,29131 inst_src: LazySrcLoc,
29095) !Air.Inst.Ref {29132) !Air.Inst.Ref {
29096 const mod = sema.mod;29133 const mod = sema.mod;
29097 const dest_field_count = tuple_ty.structFieldCount(mod);29134 const dest_tuple = mod.intern_pool.indexToKey(tuple_ty.ip_index).anon_struct_type;
29098 const field_vals = try sema.arena.alloc(Value, dest_field_count);29135 const field_vals = try sema.arena.alloc(InternPool.Index, dest_tuple.types.len);
29099 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);29136 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
29100 @memset(field_refs, .none);29137 @memset(field_refs, .none);
2910129138
29102 const inst_ty = sema.typeOf(inst);29139 const inst_ty = sema.typeOf(inst);
29103 const inst_field_count = inst_ty.structFieldCount(mod);29140 const src_tuple = mod.intern_pool.indexToKey(inst_ty.ip_index).anon_struct_type;
29104 if (inst_field_count > dest_field_count) return error.NotCoercible;29141 if (src_tuple.types.len > dest_tuple.types.len) return error.NotCoercible;
2910529142
29106 var runtime_src: ?LazySrcLoc = null;29143 var runtime_src: ?LazySrcLoc = null;
29107 var field_i: u32 = 0;29144 for (dest_tuple.types, dest_tuple.values, 0..) |field_ty, default_val, field_index_usize| {
29108 while (field_i < inst_field_count) : (field_i += 1) {29145 const field_i = @intCast(u32, field_index_usize);
29109 const field_src = inst_src; // TODO better source location29146 const field_src = inst_src; // TODO better source location
29110 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|29147 const field_name = if (src_tuple.names.len != 0)
29111 payload.data.names[field_i]29148 // https://github.com/ziglang/zig/issues/15709
29149 @as([]const u8, mod.intern_pool.stringToSlice(src_tuple.names[field_i]))
29112 else29150 else
29113 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});29151 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
2911429152
...@@ -29118,23 +29156,21 @@ fn coerceTupleToTuple(...@@ -29118,23 +29156,21 @@ fn coerceTupleToTuple(
2911829156
29119 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);29157 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2912029158
29121 const field_ty = tuple_ty.structFieldType(field_i, mod);
29122 const default_val = tuple_ty.structFieldDefaultValue(field_i, mod);
29123 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);29159 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
29124 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);29160 const coerced = try sema.coerce(block, field_ty.toType(), elem_ref, field_src);
29125 field_refs[field_index] = coerced;29161 field_refs[field_index] = coerced;
29126 if (default_val.ip_index != .unreachable_value) {29162 if (default_val != .none) {
29127 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {29163 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
29128 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");29164 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
29129 };29165 };
2913029166
29131 if (!init_val.eql(default_val, field_ty, sema.mod)) {29167 if (!init_val.eql(default_val.toValue(), field_ty.toType(), sema.mod)) {
29132 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);29168 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
29133 }29169 }
29134 }29170 }
29135 if (runtime_src == null) {29171 if (runtime_src == null) {
29136 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {29172 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {
29137 field_vals[field_index] = field_val;29173 field_vals[field_index] = field_val.ip_index;
29138 } else {29174 } else {
29139 runtime_src = field_src;29175 runtime_src = field_src;
29140 }29176 }
...@@ -29145,14 +29181,16 @@ fn coerceTupleToTuple(...@@ -29145,14 +29181,16 @@ fn coerceTupleToTuple(
29145 var root_msg: ?*Module.ErrorMsg = null;29181 var root_msg: ?*Module.ErrorMsg = null;
29146 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);29182 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
2914729183
29148 for (field_refs, 0..) |*field_ref, i| {29184 for (
29185 dest_tuple.types,
29186 dest_tuple.values,
29187 field_refs,
29188 0..,
29189 ) |field_ty, default_val, *field_ref, i| {
29149 if (field_ref.* != .none) continue;29190 if (field_ref.* != .none) continue;
2915029191
29151 const default_val = tuple_ty.structFieldDefaultValue(i, mod);
29152 const field_ty = tuple_ty.structFieldType(i, mod);
29153
29154 const field_src = inst_src; // TODO better source location29192 const field_src = inst_src; // TODO better source location
29155 if (default_val.ip_index == .unreachable_value) {29193 if (default_val == .none) {
29156 if (tuple_ty.isTuple(mod)) {29194 if (tuple_ty.isTuple(mod)) {
29157 const template = "missing tuple field: {d}";29195 const template = "missing tuple field: {d}";
29158 if (root_msg) |msg| {29196 if (root_msg) |msg| {
...@@ -29174,7 +29212,7 @@ fn coerceTupleToTuple(...@@ -29174,7 +29212,7 @@ fn coerceTupleToTuple(
29174 if (runtime_src == null) {29212 if (runtime_src == null) {
29175 field_vals[i] = default_val;29213 field_vals[i] = default_val;
29176 } else {29214 } else {
29177 field_ref.* = try sema.addConstant(field_ty, default_val);29215 field_ref.* = try sema.addConstant(field_ty.toType(), default_val.toValue());
29178 }29216 }
29179 }29217 }
2918029218
...@@ -29191,7 +29229,10 @@ fn coerceTupleToTuple(...@@ -29191,7 +29229,10 @@ fn coerceTupleToTuple(
2919129229
29192 return sema.addConstant(29230 return sema.addConstant(
29193 tuple_ty,29231 tuple_ty,
29194 try Value.Tag.aggregate.create(sema.arena, field_vals),29232 (try mod.intern(.{ .aggregate = .{
29233 .ty = tuple_ty.ip_index,
29234 .fields = field_vals,
29235 } })).toValue(),
29195 );29236 );
29196}29237}
2919729238
...@@ -31591,17 +31632,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31591,17 +31632,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31591 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));31632 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));
31592 },31633 },
3159331634
31594 .tuple, .anon_struct => {
31595 const tuple = ty.tupleFields();
31596 for (tuple.types, 0..) |field_ty, i| {
31597 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
31598 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
31599 return true;
31600 }
31601 }
31602 return false;
31603 },
31604
31605 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),31635 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
31606 .anyframe_T => {31636 .anyframe_T => {
31607 const child_ty = ty.castTag(.anyframe_T).?.data;31637 const child_ty = ty.castTag(.anyframe_T).?.data;
...@@ -31690,6 +31720,16 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31690,6 +31720,16 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31690 }31720 }
31691 },31721 },
3169231722
31723 .anon_struct_type => |tuple| {
31724 for (tuple.types, tuple.values) |field_ty, field_val| {
31725 const have_comptime_val = field_val != .none;
31726 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty.toType())) {
31727 return true;
31728 }
31729 }
31730 return false;
31731 },
31732
31693 .union_type => |union_type| {31733 .union_type => |union_type| {
31694 const union_obj = mod.unionPtr(union_type.index);31734 const union_obj = mod.unionPtr(union_type.index);
31695 switch (union_obj.requires_comptime) {31735 switch (union_obj.requires_comptime) {
...@@ -31740,20 +31780,16 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31740,20 +31780,16 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31740 return sema.resolveTypeFully(child_ty);31780 return sema.resolveTypeFully(child_ty);
31741 },31781 },
31742 .Struct => switch (ty.ip_index) {31782 .Struct => switch (ty.ip_index) {
31743 .none => switch (ty.tag()) {31783 .none => {}, // TODO make this unreachable when all types are migrated to InternPool
31744 .tuple, .anon_struct => {31784 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31745 const tuple = ty.tupleFields();31785 .struct_type => return sema.resolveStructFully(ty),
3174631786 .anon_struct_type => |tuple| {
31747 for (tuple.types) |field_ty| {31787 for (tuple.types) |field_ty| {
31748 try sema.resolveTypeFully(field_ty);31788 try sema.resolveTypeFully(field_ty.toType());
31749 }31789 }
31750 },31790 },
31751 else => {},31791 else => {},
31752 },31792 },
31753 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31754 .struct_type => return sema.resolveStructFully(ty),
31755 else => {},
31756 },
31757 },31793 },
31758 .Union => return sema.resolveUnionFully(ty),31794 .Union => return sema.resolveUnionFully(ty),
31759 .Array => return sema.resolveTypeFully(ty.childType(mod)),31795 .Array => return sema.resolveTypeFully(ty.childType(mod)),
...@@ -33038,17 +33074,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33038,17 +33074,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33038 }33074 }
33039 },33075 },
3304033076
33041 .tuple, .anon_struct => {
33042 const tuple = ty.tupleFields();
33043 for (tuple.values, 0..) |val, i| {
33044 const is_comptime = val.ip_index != .unreachable_value;
33045 if (is_comptime) continue;
33046 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
33047 return null;
33048 }
33049 return Value.empty_struct;
33050 },
33051
33052 .inferred_alloc_const => unreachable,33077 .inferred_alloc_const => unreachable,
33053 .inferred_alloc_mut => unreachable,33078 .inferred_alloc_mut => unreachable,
33054 },33079 },
...@@ -33150,7 +33175,36 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33150,7 +33175,36 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33150 }33175 }
33151 }33176 }
33152 }33177 }
33153 // In this case the struct has no fields and therefore has one possible value.33178 // In this case the struct has no runtime-known fields and
33179 // therefore has one possible value.
33180
33181 // TODO: this is incorrect for structs with comptime fields, I think
33182 // we should use a temporary allocator to construct an aggregate that
33183 // is populated with the comptime values and then intern that value here.
33184 // This TODO is repeated for anon_struct_type below, as well as
33185 // in the redundant implementation of one-possible-value in type.zig.
33186 const empty = try mod.intern(.{ .aggregate = .{
33187 .ty = ty.ip_index,
33188 .fields = &.{},
33189 } });
33190 return empty.toValue();
33191 },
33192
33193 .anon_struct_type => |tuple| {
33194 for (tuple.types, tuple.values) |field_ty, val| {
33195 const is_comptime = val != .none;
33196 if (is_comptime) continue;
33197 if ((try sema.typeHasOnePossibleValue(field_ty.toType())) != null) continue;
33198 return null;
33199 }
33200 // In this case the struct has no runtime-known fields and
33201 // therefore has one possible value.
33202
33203 // TODO: this is incorrect for structs with comptime fields, I think
33204 // we should use a temporary allocator to construct an aggregate that
33205 // is populated with the comptime values and then intern that value here.
33206 // This TODO is repeated for struct_type above, as well as
33207 // in the redundant implementation of one-possible-value in type.zig.
33154 const empty = try mod.intern(.{ .aggregate = .{33208 const empty = try mod.intern(.{ .aggregate = .{
33155 .ty = ty.ip_index,33209 .ty = ty.ip_index,
33156 .fields = &.{},33210 .fields = &.{},
...@@ -33647,17 +33701,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33647,17 +33701,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33647 return sema.typeRequiresComptime(ty.optionalChild(mod));33701 return sema.typeRequiresComptime(ty.optionalChild(mod));
33648 },33702 },
3364933703
33650 .tuple, .anon_struct => {
33651 const tuple = ty.tupleFields();
33652 for (tuple.types, 0..) |field_ty, i| {
33653 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
33654 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
33655 return true;
33656 }
33657 }
33658 return false;
33659 },
33660
33661 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),33704 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
33662 .anyframe_T => {33705 .anyframe_T => {
33663 const child_ty = ty.castTag(.anyframe_T).?.data;33706 const child_ty = ty.castTag(.anyframe_T).?.data;
...@@ -33752,6 +33795,15 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33752,6 +33795,15 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33752 },33795 },
33753 }33796 }
33754 },33797 },
33798 .anon_struct_type => |tuple| {
33799 for (tuple.types, tuple.values) |field_ty, val| {
33800 const have_comptime_val = val != .none;
33801 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty.toType())) {
33802 return true;
33803 }
33804 }
33805 return false;
33806 },
3375533807
33756 .union_type => |union_type| {33808 .union_type => |union_type| {
33757 const union_obj = mod.unionPtr(union_type.index);33809 const union_obj = mod.unionPtr(union_type.index);
...@@ -33865,7 +33917,7 @@ fn structFieldIndex(...@@ -33865,7 +33917,7 @@ fn structFieldIndex(
33865) !u32 {33917) !u32 {
33866 const mod = sema.mod;33918 const mod = sema.mod;
33867 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);33919 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
33868 if (struct_ty.isAnonStruct()) {33920 if (struct_ty.isAnonStruct(mod)) {
33869 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);33921 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
33870 } else {33922 } else {
33871 const struct_obj = mod.typeToStruct(struct_ty).?;33923 const struct_obj = mod.typeToStruct(struct_ty).?;
...@@ -33882,9 +33934,10 @@ fn anonStructFieldIndex(...@@ -33882,9 +33934,10 @@ fn anonStructFieldIndex(
33882 field_name: []const u8,33934 field_name: []const u8,
33883 field_src: LazySrcLoc,33935 field_src: LazySrcLoc,
33884) !u32 {33936) !u32 {
33885 const anon_struct = struct_ty.castTag(.anon_struct).?.data;33937 const mod = sema.mod;
33938 const anon_struct = mod.intern_pool.indexToKey(struct_ty.ip_index).anon_struct_type;
33886 for (anon_struct.names, 0..) |name, i| {33939 for (anon_struct.names, 0..) |name, i| {
33887 if (mem.eql(u8, name, field_name)) {33940 if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {
33888 return @intCast(u32, i);33941 return @intCast(u32, i);
33889 }33942 }
33890 }33943 }
src/TypedValue.zig+10-10
...@@ -177,13 +177,16 @@ pub fn print(...@@ -177,13 +177,16 @@ pub fn print(
177 }177 }
178178
179 if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) {179 if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) {
180 switch (field_ptr.container_ty.tag()) {180 switch (mod.intern_pool.indexToKey(field_ptr.container_ty.ip_index)) {
181 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),181 .anon_struct_type => |anon_struct| {
182 else => {182 if (anon_struct.names.len == 0) {
183 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod);183 return writer.print(".@\"{d}\"", .{field_ptr.field_index});
184 return writer.print(".{s}", .{field_name});184 }
185 },185 },
186 else => {},
186 }187 }
188 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod);
189 return writer.print(".{s}", .{field_name});
187 } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) {190 } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) {
188 const field_name = field_ptr.container_ty.unionFields(mod).keys()[field_ptr.field_index];191 const field_name = field_ptr.container_ty.unionFields(mod).keys()[field_ptr.field_index];
189 return writer.print(".{s}", .{field_name});192 return writer.print(".{s}", .{field_name});
...@@ -396,12 +399,9 @@ fn printAggregate(...@@ -396,12 +399,9 @@ fn printAggregate(
396 while (i < max_len) : (i += 1) {399 while (i < max_len) : (i += 1) {
397 if (i != 0) try writer.writeAll(", ");400 if (i != 0) try writer.writeAll(", ");
398 switch (ty.ip_index) {401 switch (ty.ip_index) {
399 .none => switch (ty.tag()) {402 .none => {}, // TODO make this unreachable after finishing InternPool migration
400 .anon_struct => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
401 else => {},
402 },
403 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {403 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
404 .struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),404 .struct_type, .anon_struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
405 else => {},405 else => {},
406 },406 },
407 }407 }
src/arch/x86_64/CodeGen.zig+1-1
...@@ -11411,7 +11411,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -11411,7 +11411,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
11411 const union_obj = mod.typeToUnion(union_ty).?;11411 const union_obj = mod.typeToUnion(union_ty).?;
11412 const field_name = union_obj.fields.keys()[extra.field_index];11412 const field_name = union_obj.fields.keys()[extra.field_index];
11413 const tag_ty = union_obj.tag_ty;11413 const tag_ty = union_obj.tag_ty;
11414 const field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);11414 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
11415 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);11415 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
11416 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);11416 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);
11417 const tag_int = tag_int_val.toUnsignedInt(mod);11417 const tag_int = tag_int_val.toUnsignedInt(mod);
src/codegen/c.zig+25-31
...@@ -3417,8 +3417,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3417,8 +3417,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3417 const op_inst = Air.refToIndex(un_op);3417 const op_inst = Air.refToIndex(un_op);
3418 const op_ty = f.typeOf(un_op);3418 const op_ty = f.typeOf(un_op);
3419 const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;3419 const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;
3420 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;3420 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
3421 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, mod);
34223421
3423 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {3422 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {
3424 try reap(f, inst, &.{un_op});3423 try reap(f, inst, &.{un_op});
...@@ -4115,8 +4114,7 @@ fn airCall(...@@ -4115,8 +4114,7 @@ fn airCall(
4115 }4114 }
4116 resolved_arg.* = try f.resolveInst(arg);4115 resolved_arg.* = try f.resolveInst(arg);
4117 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {4116 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {
4118 var lowered_arg_buf: LowerFnRetTyBuffer = undefined;4117 const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod);
4119 const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, mod);
41204118
4121 const array_local = try f.allocLocal(inst, lowered_arg_ty);4119 const array_local = try f.allocLocal(inst, lowered_arg_ty);
4122 try writer.writeAll("memcpy(");4120 try writer.writeAll("memcpy(");
...@@ -4146,8 +4144,7 @@ fn airCall(...@@ -4146,8 +4144,7 @@ fn airCall(
4146 };4144 };
41474145
4148 const ret_ty = fn_ty.fnReturnType();4146 const ret_ty = fn_ty.fnReturnType();
4149 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;4147 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
4150 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, mod);
41514148
4152 const result_local = result: {4149 const result_local = result: {
4153 if (modifier == .always_tail) {4150 if (modifier == .always_tail) {
...@@ -5200,7 +5197,7 @@ fn fieldLocation(...@@ -5200,7 +5197,7 @@ fn fieldLocation(
5200 const field_ty = container_ty.structFieldType(next_field_index, mod);5197 const field_ty = container_ty.structFieldType(next_field_index, mod);
5201 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;5198 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
52025199
5203 break .{ .field = if (container_ty.isSimpleTuple())5200 break .{ .field = if (container_ty.isSimpleTuple(mod))
5204 .{ .field = next_field_index }5201 .{ .field = next_field_index }
5205 else5202 else
5206 .{ .identifier = container_ty.structFieldName(next_field_index, mod) } };5203 .{ .identifier = container_ty.structFieldName(next_field_index, mod) } };
...@@ -5395,16 +5392,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5395,16 +5392,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
53955392
5396 const field_name: CValue = switch (struct_ty.ip_index) {5393 const field_name: CValue = switch (struct_ty.ip_index) {
5397 .none => switch (struct_ty.tag()) {5394 .none => switch (struct_ty.tag()) {
5398 .tuple, .anon_struct => if (struct_ty.isSimpleTuple())
5399 .{ .field = extra.field_index }
5400 else
5401 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5402
5403 else => unreachable,5395 else => unreachable,
5404 },5396 },
5405 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {5397 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
5406 .struct_type => switch (struct_ty.containerLayout(mod)) {5398 .struct_type => switch (struct_ty.containerLayout(mod)) {
5407 .Auto, .Extern => if (struct_ty.isSimpleTuple())5399 .Auto, .Extern => if (struct_ty.isSimpleTuple(mod))
5408 .{ .field = extra.field_index }5400 .{ .field = extra.field_index }
5409 else5401 else
5410 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },5402 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
...@@ -5465,6 +5457,12 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5465,6 +5457,12 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5465 return local;5457 return local;
5466 },5458 },
5467 },5459 },
5460
5461 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
5462 .{ .field = extra.field_index }
5463 else
5464 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5465
5468 .union_type => |union_type| field_name: {5466 .union_type => |union_type| field_name: {
5469 const union_obj = mod.unionPtr(union_type.index);5467 const union_obj = mod.unionPtr(union_type.index);
5470 if (union_obj.layout == .Packed) {5468 if (union_obj.layout == .Packed) {
...@@ -6791,7 +6789,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6791,7 +6789,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6791 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;6789 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
67926790
6793 const a = try Assignment.start(f, writer, field_ty);6791 const a = try Assignment.start(f, writer, field_ty);
6794 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())6792 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod))
6795 .{ .field = field_i }6793 .{ .field = field_i }
6796 else6794 else
6797 .{ .identifier = inst_ty.structFieldName(field_i, mod) });6795 .{ .identifier = inst_ty.structFieldName(field_i, mod) });
...@@ -7704,25 +7702,21 @@ const Vectorize = struct {...@@ -7704,25 +7702,21 @@ const Vectorize = struct {
7704 }7702 }
7705};7703};
77067704
7707const LowerFnRetTyBuffer = struct {7705fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
7708 names: [1][]const u8,7706 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
7709 types: [1]Type,
7710 values: [1]Value,
7711 payload: Type.Payload.AnonStruct,
7712};
7713fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *Module) Type {
7714 if (ret_ty.zigTypeTag(mod) == .NoReturn) return Type.noreturn;
77157707
7716 if (lowersToArray(ret_ty, mod)) {7708 if (lowersToArray(ret_ty, mod)) {
7717 buffer.names = [1][]const u8{"array"};7709 const names = [1]InternPool.NullTerminatedString{
7718 buffer.types = [1]Type{ret_ty};7710 try mod.intern_pool.getOrPutString(mod.gpa, "array"),
7719 buffer.values = [1]Value{Value.@"unreachable"};7711 };
7720 buffer.payload = .{ .data = .{7712 const types = [1]InternPool.Index{ret_ty.ip_index};
7721 .names = &buffer.names,7713 const values = [1]InternPool.Index{.none};
7722 .types = &buffer.types,7714 const interned = try mod.intern(.{ .anon_struct_type = .{
7723 .values = &buffer.values,7715 .names = &names,
7724 } };7716 .types = &types,
7725 return Type.initPayload(&buffer.payload.base);7717 .values = &values,
7718 } });
7719 return interned.toType();
7726 }7720 }
77277721
7728 return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void;7722 return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void;
src/codegen/c/type.zig+3-3
...@@ -1951,7 +1951,7 @@ pub const CType = extern union {...@@ -1951,7 +1951,7 @@ pub const CType = extern union {
19511951
1952 defer c_field_i += 1;1952 defer c_field_i += 1;
1953 fields_pl[c_field_i] = .{1953 fields_pl[c_field_i] = .{
1954 .name = try if (ty.isSimpleTuple())1954 .name = try if (ty.isSimpleTuple(mod))
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) {
...@@ -2102,7 +2102,7 @@ pub const CType = extern union {...@@ -2102,7 +2102,7 @@ pub const CType = extern union {
2102 .payload => unreachable,2102 .payload => unreachable,
2103 }) or !mem.eql(2103 }) or !mem.eql(
2104 u8,2104 u8,
2105 if (ty.isSimpleTuple())2105 if (ty.isSimpleTuple(mod))
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, mod),2108 .Struct => ty.structFieldName(field_i, mod),
...@@ -2224,7 +2224,7 @@ pub const CType = extern union {...@@ -2224,7 +2224,7 @@ pub const CType = extern union {
2224 .global => .global,2224 .global => .global,
2225 .payload => unreachable,2225 .payload => unreachable,
2226 });2226 });
2227 hasher.update(if (ty.isSimpleTuple())2227 hasher.update(if (ty.isSimpleTuple(mod))
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, mod),2230 .Struct => ty.structFieldName(field_i, mod),
src/codegen/llvm.zig+263-255
...@@ -2009,83 +2009,84 @@ pub const Object = struct {...@@ -2009,83 +2009,84 @@ pub const Object = struct {
2009 break :blk fwd_decl;2009 break :blk fwd_decl;
2010 };2010 };
20112011
2012 if (ty.isSimpleTupleOrAnonStruct()) {2012 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2013 const tuple = ty.tupleFields();2013 .anon_struct_type => |tuple| {
20142014 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2015 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2015 defer di_fields.deinit(gpa);
2016 defer di_fields.deinit(gpa);2016
20172017 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2018 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);2018
20192019 comptime assert(struct_layout_version == 2);
2020 comptime assert(struct_layout_version == 2);2020 var offset: u64 = 0;
2021 var offset: u64 = 0;2021
20222022 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
2023 for (tuple.types, 0..) |field_ty, i| {2023 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
2024 const field_val = tuple.values[i];2024
2025 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;2025 const field_size = field_ty.toType().abiSize(mod);
20262026 const field_align = field_ty.toType().abiAlignment(mod);
2027 const field_size = field_ty.abiSize(mod);2027 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2028 const field_align = field_ty.abiAlignment(mod);2028 offset = field_offset + field_size;
2029 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);2029
2030 offset = field_offset + field_size;2030 const field_name = if (tuple.names.len != 0)
20312031 mod.intern_pool.stringToSlice(tuple.names[i])
2032 const field_name = if (ty.castTag(.anon_struct)) |payload|2032 else
2033 try gpa.dupeZ(u8, payload.data.names[i])2033 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2034 else2034 defer gpa.free(field_name);
2035 try std.fmt.allocPrintZ(gpa, "{d}", .{i});2035
2036 defer gpa.free(field_name);2036 try di_fields.append(gpa, dib.createMemberType(
2037 fwd_decl.toScope(),
2038 field_name,
2039 null, // file
2040 0, // line
2041 field_size * 8, // size in bits
2042 field_align * 8, // align in bits
2043 field_offset * 8, // offset in bits
2044 0, // flags
2045 try o.lowerDebugType(field_ty.toType(), .full),
2046 ));
2047 }
20372048
2038 try di_fields.append(gpa, dib.createMemberType(2049 const full_di_ty = dib.createStructType(
2039 fwd_decl.toScope(),2050 compile_unit_scope,
2040 field_name,2051 name.ptr,
2041 null, // file2052 null, // file
2042 0, // line2053 0, // line
2043 field_size * 8, // size in bits2054 ty.abiSize(mod) * 8, // size in bits
2044 field_align * 8, // align in bits2055 ty.abiAlignment(mod) * 8, // align in bits
2045 field_offset * 8, // offset in bits
2046 0, // flags2056 0, // flags
2047 try o.lowerDebugType(field_ty, .full),2057 null, // derived from
2048 ));2058 di_fields.items.ptr,
2049 }2059 @intCast(c_int, di_fields.items.len),
20502060 0, // run time lang
2051 const full_di_ty = dib.createStructType(2061 null, // vtable holder
2052 compile_unit_scope,2062 "", // unique id
2053 name.ptr,2063 );
2054 null, // file2064 dib.replaceTemporary(fwd_decl, full_di_ty);
2055 0, // line2065 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2056 ty.abiSize(mod) * 8, // size in bits2066 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2057 ty.abiAlignment(mod) * 8, // align in bits2067 return full_di_ty;
2058 0, // flags2068 },
2059 null, // derived from2069 .struct_type => |struct_type| s: {
2060 di_fields.items.ptr,2070 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
2061 @intCast(c_int, di_fields.items.len),2071
2062 0, // run time lang2072 if (!struct_obj.haveFieldTypes()) {
2063 null, // vtable holder2073 // This can happen if a struct type makes it all the way to
2064 "", // unique id2074 // flush() without ever being instantiated or referenced (even
2065 );2075 // via pointer). The only reason we are hearing about it now is
2066 dib.replaceTemporary(fwd_decl, full_di_ty);2076 // that it is being used as a namespace to put other debug types
2067 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2077 // into. Therefore we can satisfy this by making an empty namespace,
2068 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });2078 // rather than changing the frontend to unnecessarily resolve the
2069 return full_di_ty;2079 // struct field types.
2070 }2080 const owner_decl_index = ty.getOwnerDecl(mod);
20712081 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2072 if (mod.typeToStruct(ty)) |struct_obj| {2082 dib.replaceTemporary(fwd_decl, struct_di_ty);
2073 if (!struct_obj.haveFieldTypes()) {2083 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2074 // This can happen if a struct type makes it all the way to2084 // means we can't use `gop` anymore.
2075 // flush() without ever being instantiated or referenced (even2085 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
2076 // via pointer). The only reason we are hearing about it now is2086 return struct_di_ty;
2077 // that it is being used as a namespace to put other debug types2087 }
2078 // into. Therefore we can satisfy this by making an empty namespace,2088 },
2079 // rather than changing the frontend to unnecessarily resolve the2089 else => {},
2080 // struct field types.
2081 const owner_decl_index = ty.getOwnerDecl(mod);
2082 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2083 dib.replaceTemporary(fwd_decl, struct_di_ty);
2084 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2085 // means we can't use `gop` anymore.
2086 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
2087 return struct_di_ty;
2088 }
2089 }2090 }
20902091
2091 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {2092 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
...@@ -2931,59 +2932,61 @@ pub const DeclGen = struct {...@@ -2931,59 +2932,61 @@ pub const DeclGen = struct {
2931 // reference, we need to copy it here.2932 // reference, we need to copy it here.
2932 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());2933 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
29332934
2934 if (t.isSimpleTupleOrAnonStruct()) {2935 const struct_type = switch (mod.intern_pool.indexToKey(t.ip_index)) {
2935 const tuple = t.tupleFields();2936 .anon_struct_type => |tuple| {
2936 const llvm_struct_ty = dg.context.structCreateNamed("");2937 const llvm_struct_ty = dg.context.structCreateNamed("");
2937 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls2938 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
29382939
2939 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};2940 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
2940 defer llvm_field_types.deinit(gpa);2941 defer llvm_field_types.deinit(gpa);
29412942
2942 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);2943 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
29432944
2944 comptime assert(struct_layout_version == 2);2945 comptime assert(struct_layout_version == 2);
2945 var offset: u64 = 0;2946 var offset: u64 = 0;
2946 var big_align: u32 = 0;2947 var big_align: u32 = 0;
29472948
2948 for (tuple.types, 0..) |field_ty, i| {2949 for (tuple.types, tuple.values) |field_ty, field_val| {
2949 const field_val = tuple.values[i];2950 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
2950 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;
29512951
2952 const field_align = field_ty.abiAlignment(mod);2952 const field_align = field_ty.toType().abiAlignment(mod);
2953 big_align = @max(big_align, field_align);2953 big_align = @max(big_align, field_align);
2954 const prev_offset = offset;2954 const prev_offset = offset;
2955 offset = std.mem.alignForwardGeneric(u64, offset, field_align);2955 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
29562956
2957 const padding_len = offset - prev_offset;2957 const padding_len = offset - prev_offset;
2958 if (padding_len > 0) {2958 if (padding_len > 0) {
2959 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));2959 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2960 try llvm_field_types.append(gpa, llvm_array_ty);2960 try llvm_field_types.append(gpa, llvm_array_ty);
2961 }2961 }
2962 const field_llvm_ty = try dg.lowerType(field_ty);2962 const field_llvm_ty = try dg.lowerType(field_ty.toType());
2963 try llvm_field_types.append(gpa, field_llvm_ty);2963 try llvm_field_types.append(gpa, field_llvm_ty);
29642964
2965 offset += field_ty.abiSize(mod);2965 offset += field_ty.toType().abiSize(mod);
2966 }2966 }
2967 {2967 {
2968 const prev_offset = offset;2968 const prev_offset = offset;
2969 offset = std.mem.alignForwardGeneric(u64, offset, big_align);2969 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2970 const padding_len = offset - prev_offset;2970 const padding_len = offset - prev_offset;
2971 if (padding_len > 0) {2971 if (padding_len > 0) {
2972 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));2972 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2973 try llvm_field_types.append(gpa, llvm_array_ty);2973 try llvm_field_types.append(gpa, llvm_array_ty);
2974 }
2974 }2975 }
2975 }
29762976
2977 llvm_struct_ty.structSetBody(2977 llvm_struct_ty.structSetBody(
2978 llvm_field_types.items.ptr,2978 llvm_field_types.items.ptr,
2979 @intCast(c_uint, llvm_field_types.items.len),2979 @intCast(c_uint, llvm_field_types.items.len),
2980 .False,2980 .False,
2981 );2981 );
29822982
2983 return llvm_struct_ty;2983 return llvm_struct_ty;
2984 }2984 },
2985 .struct_type => |struct_type| struct_type,
2986 else => unreachable,
2987 };
29852988
2986 const struct_obj = mod.typeToStruct(t).?;2989 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
29872990
2988 if (struct_obj.layout == .Packed) {2991 if (struct_obj.layout == .Packed) {
2989 assert(struct_obj.haveLayout());2992 assert(struct_obj.haveLayout());
...@@ -3625,71 +3628,74 @@ pub const DeclGen = struct {...@@ -3625,71 +3628,74 @@ pub const DeclGen = struct {
3625 const field_vals = tv.val.castTag(.aggregate).?.data;3628 const field_vals = tv.val.castTag(.aggregate).?.data;
3626 const gpa = dg.gpa;3629 const gpa = dg.gpa;
36273630
3628 if (tv.ty.isSimpleTupleOrAnonStruct()) {3631 const struct_type = switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {
3629 const tuple = tv.ty.tupleFields();3632 .anon_struct_type => |tuple| {
3630 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};3633 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3631 defer llvm_fields.deinit(gpa);3634 defer llvm_fields.deinit(gpa);
36323635
3633 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);3636 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
36343637
3635 comptime assert(struct_layout_version == 2);3638 comptime assert(struct_layout_version == 2);
3636 var offset: u64 = 0;3639 var offset: u64 = 0;
3637 var big_align: u32 = 0;3640 var big_align: u32 = 0;
3638 var need_unnamed = false;3641 var need_unnamed = false;
36393642
3640 for (tuple.types, 0..) |field_ty, i| {3643 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3641 if (tuple.values[i].ip_index != .unreachable_value) continue;3644 if (field_val != .none) continue;
3642 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;3645 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
3643
3644 const field_align = field_ty.abiAlignment(mod);
3645 big_align = @max(big_align, field_align);
3646 const prev_offset = offset;
3647 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3648
3649 const padding_len = offset - prev_offset;
3650 if (padding_len > 0) {
3651 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3652 // TODO make this and all other padding elsewhere in debug
3653 // builds be 0xaa not undef.
3654 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3655 }
36563646
3657 const field_llvm_val = try dg.lowerValue(.{3647 const field_align = field_ty.toType().abiAlignment(mod);
3658 .ty = field_ty,3648 big_align = @max(big_align, field_align);
3659 .val = field_vals[i],3649 const prev_offset = offset;
3660 });3650 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
36613651
3662 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);3652 const padding_len = offset - prev_offset;
3653 if (padding_len > 0) {
3654 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3655 // TODO make this and all other padding elsewhere in debug
3656 // builds be 0xaa not undef.
3657 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3658 }
36633659
3664 llvm_fields.appendAssumeCapacity(field_llvm_val);3660 const field_llvm_val = try dg.lowerValue(.{
3661 .ty = field_ty.toType(),
3662 .val = field_vals[i],
3663 });
36653664
3666 offset += field_ty.abiSize(mod);3665 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
3667 }3666
3668 {3667 llvm_fields.appendAssumeCapacity(field_llvm_val);
3669 const prev_offset = offset;3668
3670 offset = std.mem.alignForwardGeneric(u64, offset, big_align);3669 offset += field_ty.toType().abiSize(mod);
3671 const padding_len = offset - prev_offset;3670 }
3672 if (padding_len > 0) {3671 {
3673 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));3672 const prev_offset = offset;
3674 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());3673 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3674 const padding_len = offset - prev_offset;
3675 if (padding_len > 0) {
3676 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3677 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3678 }
3675 }3679 }
3676 }
36773680
3678 if (need_unnamed) {3681 if (need_unnamed) {
3679 return dg.context.constStruct(3682 return dg.context.constStruct(
3680 llvm_fields.items.ptr,3683 llvm_fields.items.ptr,
3681 @intCast(c_uint, llvm_fields.items.len),3684 @intCast(c_uint, llvm_fields.items.len),
3682 .False,3685 .False,
3683 );3686 );
3684 } else {3687 } else {
3685 return llvm_struct_ty.constNamedStruct(3688 return llvm_struct_ty.constNamedStruct(
3686 llvm_fields.items.ptr,3689 llvm_fields.items.ptr,
3687 @intCast(c_uint, llvm_fields.items.len),3690 @intCast(c_uint, llvm_fields.items.len),
3688 );3691 );
3689 }3692 }
3690 }3693 },
3694 .struct_type => |struct_type| struct_type,
3695 else => unreachable,
3696 };
36913697
3692 const struct_obj = mod.typeToStruct(tv.ty).?;3698 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
36933699
3694 if (struct_obj.layout == .Packed) {3700 if (struct_obj.layout == .Packed) {
3695 assert(struct_obj.haveLayout());3701 assert(struct_obj.haveLayout());
...@@ -4077,13 +4083,11 @@ pub const DeclGen = struct {...@@ -4077,13 +4083,11 @@ pub const DeclGen = struct {
4077 return field_addr.constIntToPtr(final_llvm_ty);4083 return field_addr.constIntToPtr(final_llvm_ty);
4078 }4084 }
40794085
4080 var ty_buf: Type.Payload.Pointer = undefined;
4081
4082 const parent_llvm_ty = try dg.lowerType(parent_ty);4086 const parent_llvm_ty = try dg.lowerType(parent_ty);
4083 if (llvmFieldIndex(parent_ty, field_index, mod, &ty_buf)) |llvm_field_index| {4087 if (llvmField(parent_ty, field_index, mod)) |llvm_field| {
4084 const indices: [2]*llvm.Value = .{4088 const indices: [2]*llvm.Value = .{
4085 llvm_u32.constInt(0, .False),4089 llvm_u32.constInt(0, .False),
4086 llvm_u32.constInt(llvm_field_index, .False),4090 llvm_u32.constInt(llvm_field.index, .False),
4087 };4091 };
4088 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);4092 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4089 } else {4093 } else {
...@@ -6006,8 +6010,7 @@ pub const FuncGen = struct {...@@ -6006,8 +6010,7 @@ pub const FuncGen = struct {
6006 return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");6010 return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
6007 },6011 },
6008 else => {6012 else => {
6009 var ptr_ty_buf: Type.Payload.Pointer = undefined;6013 const llvm_field_index = llvmField(struct_ty, field_index, mod).?.index;
6010 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
6011 return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, "");6014 return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, "");
6012 },6015 },
6013 },6016 },
...@@ -6035,16 +6038,22 @@ pub const FuncGen = struct {...@@ -6035,16 +6038,22 @@ pub const FuncGen = struct {
6035 switch (struct_ty.zigTypeTag(mod)) {6038 switch (struct_ty.zigTypeTag(mod)) {
6036 .Struct => {6039 .Struct => {
6037 assert(struct_ty.containerLayout(mod) != .Packed);6040 assert(struct_ty.containerLayout(mod) != .Packed);
6038 var ptr_ty_buf: Type.Payload.Pointer = undefined;6041 const llvm_field = llvmField(struct_ty, field_index, mod).?;
6039 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
6040 const struct_llvm_ty = try self.dg.lowerType(struct_ty);6042 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6041 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, "");6043 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");
6042 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);6044 const field_ptr_ty = try mod.ptrType(.{
6045 .elem_type = llvm_field.ty.ip_index,
6046 .alignment = llvm_field.alignment,
6047 });
6043 if (isByRef(field_ty, mod)) {6048 if (isByRef(field_ty, mod)) {
6044 if (canElideLoad(self, body_tail))6049 if (canElideLoad(self, body_tail))
6045 return field_ptr;6050 return field_ptr;
60466051
6047 return self.loadByRef(field_ptr, field_ty, ptr_ty_buf.data.alignment(mod), false);6052 const field_alignment = if (llvm_field.alignment != 0)
6053 llvm_field.alignment
6054 else
6055 llvm_field.ty.abiAlignment(mod);
6056 return self.loadByRef(field_ptr, field_ty, field_alignment, false);
6048 } else {6057 } else {
6049 return self.load(field_ptr, field_ptr_ty);6058 return self.load(field_ptr, field_ptr_ty);
6050 }6059 }
...@@ -6912,12 +6921,14 @@ pub const FuncGen = struct {...@@ -6912,12 +6921,14 @@ pub const FuncGen = struct {
6912 const struct_ty = self.air.getRefType(ty_pl.ty);6921 const struct_ty = self.air.getRefType(ty_pl.ty);
6913 const field_index = ty_pl.payload;6922 const field_index = ty_pl.payload;
69146923
6915 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6916 const mod = self.dg.module;6924 const mod = self.dg.module;
6917 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;6925 const llvm_field = llvmField(struct_ty, field_index, mod).?;
6918 const struct_llvm_ty = try self.dg.lowerType(struct_ty);6926 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6919 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, "");6927 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");
6920 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);6928 const field_ptr_ty = try mod.ptrType(.{
6929 .elem_type = llvm_field.ty.ip_index,
6930 .alignment = llvm_field.alignment,
6931 });
6921 return self.load(field_ptr, field_ptr_ty);6932 return self.load(field_ptr, field_ptr_ty);
6922 }6933 }
69236934
...@@ -7430,9 +7441,8 @@ pub const FuncGen = struct {...@@ -7430,9 +7441,8 @@ pub const FuncGen = struct {
7430 const result = self.builder.buildExtractValue(result_struct, 0, "");7441 const result = self.builder.buildExtractValue(result_struct, 0, "");
7431 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");7442 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");
74327443
7433 var ty_buf: Type.Payload.Pointer = undefined;7444 const result_index = llvmField(dest_ty, 0, mod).?.index;
7434 const result_index = llvmFieldIndex(dest_ty, 0, mod, &ty_buf).?;7445 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
7435 const overflow_index = llvmFieldIndex(dest_ty, 1, mod, &ty_buf).?;
74367446
7437 if (isByRef(dest_ty, mod)) {7447 if (isByRef(dest_ty, mod)) {
7438 const result_alignment = dest_ty.abiAlignment(mod);7448 const result_alignment = dest_ty.abiAlignment(mod);
...@@ -7736,9 +7746,8 @@ pub const FuncGen = struct {...@@ -7736,9 +7746,8 @@ pub const FuncGen = struct {
77367746
7737 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");7747 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");
77387748
7739 var ty_buf: Type.Payload.Pointer = undefined;7749 const result_index = llvmField(dest_ty, 0, mod).?.index;
7740 const result_index = llvmFieldIndex(dest_ty, 0, mod, &ty_buf).?;7750 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
7741 const overflow_index = llvmFieldIndex(dest_ty, 1, mod, &ty_buf).?;
77427751
7743 if (isByRef(dest_ty, mod)) {7752 if (isByRef(dest_ty, mod)) {
7744 const result_alignment = dest_ty.abiAlignment(mod);7753 const result_alignment = dest_ty.abiAlignment(mod);
...@@ -9300,8 +9309,6 @@ pub const FuncGen = struct {...@@ -9300,8 +9309,6 @@ pub const FuncGen = struct {
9300 return running_int;9309 return running_int;
9301 }9310 }
93029311
9303 var ptr_ty_buf: Type.Payload.Pointer = undefined;
9304
9305 if (isByRef(result_ty, mod)) {9312 if (isByRef(result_ty, mod)) {
9306 const llvm_u32 = self.context.intType(32);9313 const llvm_u32 = self.context.intType(32);
9307 // TODO in debug builds init to undef so that the padding will be 0xaa9314 // TODO in debug builds init to undef so that the padding will be 0xaa
...@@ -9313,7 +9320,7 @@ pub const FuncGen = struct {...@@ -9313,7 +9320,7 @@ pub const FuncGen = struct {
9313 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;9320 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93149321
9315 const llvm_elem = try self.resolveInst(elem);9322 const llvm_elem = try self.resolveInst(elem);
9316 const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;9323 const llvm_i = llvmField(result_ty, i, mod).?.index;
9317 indices[1] = llvm_u32.constInt(llvm_i, .False);9324 indices[1] = llvm_u32.constInt(llvm_i, .False);
9318 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");9325 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
9319 var field_ptr_payload: Type.Payload.Pointer = .{9326 var field_ptr_payload: Type.Payload.Pointer = .{
...@@ -9334,7 +9341,7 @@ pub const FuncGen = struct {...@@ -9334,7 +9341,7 @@ pub const FuncGen = struct {
9334 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;9341 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93359342
9336 const llvm_elem = try self.resolveInst(elem);9343 const llvm_elem = try self.resolveInst(elem);
9337 const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;9344 const llvm_i = llvmField(result_ty, i, mod).?.index;
9338 result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");9345 result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");
9339 }9346 }
9340 return result;9347 return result;
...@@ -9796,9 +9803,8 @@ pub const FuncGen = struct {...@@ -9796,9 +9803,8 @@ pub const FuncGen = struct {
9796 else => {9803 else => {
9797 const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty);9804 const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty);
97989805
9799 var ty_buf: Type.Payload.Pointer = undefined;9806 if (llvmField(struct_ty, field_index, mod)) |llvm_field| {
9800 if (llvmFieldIndex(struct_ty, field_index, mod, &ty_buf)) |llvm_field_index| {9807 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field.index, "");
9801 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, "");
9802 } else {9808 } else {
9803 // If we found no index then this means this is a zero sized field at the9809 // If we found no index then this means this is a zero sized field at the
9804 // end of the struct. Treat our struct pointer as an array of two and get9810 // end of the struct. Treat our struct pointer as an array of two and get
...@@ -10457,59 +10463,61 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ...@@ -10457,59 +10463,61 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ
10457 };10463 };
10458}10464}
1045910465
10466const LlvmField = struct {
10467 index: c_uint,
10468 ty: Type,
10469 alignment: u32,
10470};
10471
10460/// Take into account 0 bit fields and padding. Returns null if an llvm10472/// Take into account 0 bit fields and padding. Returns null if an llvm
10461/// field could not be found.10473/// field could not be found.
10462/// This only happens if you want the field index of a zero sized field at10474/// This only happens if you want the field index of a zero sized field at
10463/// the end of the struct.10475/// the end of the struct.
10464fn llvmFieldIndex(10476fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
10465 ty: Type,
10466 field_index: usize,
10467 mod: *Module,
10468 ptr_pl_buf: *Type.Payload.Pointer,
10469) ?c_uint {
10470 // Detects where we inserted extra padding fields so that we can skip10477 // Detects where we inserted extra padding fields so that we can skip
10471 // over them in this function.10478 // over them in this function.
10472 comptime assert(struct_layout_version == 2);10479 comptime assert(struct_layout_version == 2);
10473 var offset: u64 = 0;10480 var offset: u64 = 0;
10474 var big_align: u32 = 0;10481 var big_align: u32 = 0;
1047510482
10476 if (ty.isSimpleTupleOrAnonStruct()) {10483 const struct_type = switch (mod.intern_pool.indexToKey(ty.ip_index)) {
10477 const tuple = ty.tupleFields();10484 .anon_struct_type => |tuple| {
10478 var llvm_field_index: c_uint = 0;10485 var llvm_field_index: c_uint = 0;
10479 for (tuple.types, 0..) |field_ty, i| {10486 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
10480 if (tuple.values[i].ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;10487 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1048110488
10482 const field_align = field_ty.abiAlignment(mod);10489 const field_align = field_ty.toType().abiAlignment(mod);
10483 big_align = @max(big_align, field_align);10490 big_align = @max(big_align, field_align);
10484 const prev_offset = offset;10491 const prev_offset = offset;
10485 offset = std.mem.alignForwardGeneric(u64, offset, field_align);10492 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1048610493
10487 const padding_len = offset - prev_offset;10494 const padding_len = offset - prev_offset;
10488 if (padding_len > 0) {10495 if (padding_len > 0) {
10489 llvm_field_index += 1;10496 llvm_field_index += 1;
10490 }10497 }
1049110498
10492 if (field_index <= i) {10499 if (field_index <= i) {
10493 ptr_pl_buf.* = .{10500 return .{
10494 .data = .{10501 .index = llvm_field_index,
10495 .pointee_type = field_ty,10502 .ty = field_ty.toType(),
10496 .@"align" = field_align,10503 .alignment = field_align,
10497 .@"addrspace" = .generic,10504 };
10498 },10505 }
10499 };
10500 return llvm_field_index;
10501 }
1050210506
10503 llvm_field_index += 1;10507 llvm_field_index += 1;
10504 offset += field_ty.abiSize(mod);10508 offset += field_ty.toType().abiSize(mod);
10505 }10509 }
10506 return null;10510 return null;
10507 }10511 },
10508 const layout = ty.containerLayout(mod);10512 .struct_type => |s| s,
10513 else => unreachable,
10514 };
10515 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
10516 const layout = struct_obj.layout;
10509 assert(layout != .Packed);10517 assert(layout != .Packed);
1051010518
10511 var llvm_field_index: c_uint = 0;10519 var llvm_field_index: c_uint = 0;
10512 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);10520 var it = struct_obj.runtimeFieldIterator(mod);
10513 while (it.next()) |field_and_index| {10521 while (it.next()) |field_and_index| {
10514 const field = field_and_index.field;10522 const field = field_and_index.field;
10515 const field_align = field.alignment(mod, layout);10523 const field_align = field.alignment(mod, layout);
...@@ -10523,14 +10531,11 @@ fn llvmFieldIndex(...@@ -10523,14 +10531,11 @@ fn llvmFieldIndex(
10523 }10531 }
1052410532
10525 if (field_index == field_and_index.index) {10533 if (field_index == field_and_index.index) {
10526 ptr_pl_buf.* = .{10534 return .{
10527 .data = .{10535 .index = llvm_field_index,
10528 .pointee_type = field.ty,10536 .ty = field.ty,
10529 .@"align" = field_align,10537 .alignment = field_align,
10530 .@"addrspace" = .generic,
10531 },
10532 };10538 };
10533 return llvm_field_index;
10534 }10539 }
1053510540
10536 llvm_field_index += 1;10541 llvm_field_index += 1;
...@@ -11089,21 +11094,24 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11089,21 +11094,24 @@ fn isByRef(ty: Type, mod: *Module) bool {
11089 .Struct => {11094 .Struct => {
11090 // Packed structs are represented to LLVM as integers.11095 // Packed structs are represented to LLVM as integers.
11091 if (ty.containerLayout(mod) == .Packed) return false;11096 if (ty.containerLayout(mod) == .Packed) return false;
11092 if (ty.isSimpleTupleOrAnonStruct()) {11097 const struct_type = switch (mod.intern_pool.indexToKey(ty.ip_index)) {
11093 const tuple = ty.tupleFields();11098 .anon_struct_type => |tuple| {
11094 var count: usize = 0;11099 var count: usize = 0;
11095 for (tuple.values, 0..) |field_val, i| {11100 for (tuple.types, tuple.values) |field_ty, field_val| {
11096 if (field_val.ip_index != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue;11101 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1109711102
11098 count += 1;11103 count += 1;
11099 if (count > max_fields_byval) return true;11104 if (count > max_fields_byval) return true;
11100 if (isByRef(tuple.types[i], mod)) return true;11105 if (isByRef(field_ty.toType(), mod)) return true;
11101 }11106 }
11102 return false;11107 return false;
11103 }11108 },
11109 .struct_type => |s| s,
11110 else => unreachable,
11111 };
11112 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
11104 var count: usize = 0;11113 var count: usize = 0;
11105 const fields = ty.structFields(mod);11114 for (struct_obj.fields.values()) |field| {
11106 for (fields.values()) |field| {
11107 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;11115 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
1110811116
11109 count += 1;11117 count += 1;
src/codegen/spirv.zig+6-5
...@@ -682,7 +682,7 @@ pub const DeclGen = struct {...@@ -682,7 +682,7 @@ pub const DeclGen = struct {
682 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),682 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
683 },683 },
684 .Struct => {684 .Struct => {
685 if (ty.isSimpleTupleOrAnonStruct()) {685 if (ty.isSimpleTupleOrAnonStruct(mod)) {
686 unreachable; // TODO686 unreachable; // TODO
687 } else {687 } else {
688 const struct_ty = mod.typeToStruct(ty).?;688 const struct_ty = mod.typeToStruct(ty).?;
...@@ -1319,7 +1319,8 @@ pub const DeclGen = struct {...@@ -1319,7 +1319,8 @@ pub const DeclGen = struct {
1319 defer self.gpa.free(member_names);1319 defer self.gpa.free(member_names);
13201320
1321 var member_index: usize = 0;1321 var member_index: usize = 0;
1322 for (struct_ty.fields.values(), 0..) |field, i| {1322 const struct_obj = void; // TODO
1323 for (struct_obj.fields.values(), 0..) |field, i| {
1323 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;1324 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
13241325
1325 member_types[member_index] = try self.resolveType(field.ty, .indirect);1326 member_types[member_index] = try self.resolveType(field.ty, .indirect);
...@@ -1327,7 +1328,7 @@ pub const DeclGen = struct {...@@ -1327,7 +1328,7 @@ pub const DeclGen = struct {
1327 member_index += 1;1328 member_index += 1;
1328 }1329 }
13291330
1330 const name = try struct_ty.getFullyQualifiedName(self.module);1331 const name = try struct_obj.getFullyQualifiedName(self.module);
1331 defer self.module.gpa.free(name);1332 defer self.module.gpa.free(name);
13321333
1333 return try self.spv.resolve(.{ .struct_type = .{1334 return try self.spv.resolve(.{ .struct_type = .{
...@@ -2090,7 +2091,7 @@ pub const DeclGen = struct {...@@ -2090,7 +2091,7 @@ pub const DeclGen = struct {
20902091
2091 var i: usize = 0;2092 var i: usize = 0;
2092 while (i < mask_len) : (i += 1) {2093 while (i < mask_len) : (i += 1) {
2093 const elem = try mask.elemValue(self.module, i);2094 const elem = try mask.elemValue(mod, i);
2094 if (elem.isUndef(mod)) {2095 if (elem.isUndef(mod)) {
2095 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);2096 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
2096 } else {2097 } else {
...@@ -2805,7 +2806,7 @@ pub const DeclGen = struct {...@@ -2805,7 +2806,7 @@ pub const DeclGen = struct {
2805 const value = try self.resolve(bin_op.rhs);2806 const value = try self.resolve(bin_op.rhs);
2806 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);2807 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
28072808
2808 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;2809 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
2809 if (val_is_undef) {2810 if (val_is_undef) {
2810 const undef = try self.spv.constUndef(ptr_ty_ref);2811 const undef = try self.spv.constUndef(ptr_ty_ref);
2811 try self.store(ptr_ty, ptr, undef);2812 try self.store(ptr_ty, ptr, undef);
src/link/Dwarf.zig+12-10
...@@ -333,13 +333,12 @@ pub const DeclState = struct {...@@ -333,13 +333,12 @@ pub const DeclState = struct {
333 // DW.AT.byte_size, DW.FORM.udata333 // DW.AT.byte_size, DW.FORM.udata
334 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));334 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
335335
336 switch (ty.tag()) {336 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
337 .tuple, .anon_struct => {337 .anon_struct_type => |fields| {
338 // DW.AT.name, DW.FORM.string338 // DW.AT.name, DW.FORM.string
339 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});339 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
340340
341 const fields = ty.tupleFields();341 for (fields.types, 0..) |field_ty, field_index| {
342 for (fields.types, 0..) |field, field_index| {
343 // DW.AT.member342 // DW.AT.member
344 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));343 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
345 // DW.AT.name, DW.FORM.string344 // DW.AT.name, DW.FORM.string
...@@ -347,28 +346,30 @@ pub const DeclState = struct {...@@ -347,28 +346,30 @@ pub const DeclState = struct {
347 // DW.AT.type, DW.FORM.ref4346 // DW.AT.type, DW.FORM.ref4
348 var index = dbg_info_buffer.items.len;347 var index = dbg_info_buffer.items.len;
349 try dbg_info_buffer.resize(index + 4);348 try dbg_info_buffer.resize(index + 4);
350 try self.addTypeRelocGlobal(atom_index, field, @intCast(u32, index));349 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(u32, index));
351 // DW.AT.data_member_location, DW.FORM.udata350 // DW.AT.data_member_location, DW.FORM.udata
352 const field_off = ty.structFieldOffset(field_index, mod);351 const field_off = ty.structFieldOffset(field_index, mod);
353 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);352 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
354 }353 }
355 },354 },
356 else => {355 .struct_type => |struct_type| s: {
356 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
357 // DW.AT.name, DW.FORM.string357 // DW.AT.name, DW.FORM.string
358 const struct_name = try ty.nameAllocArena(arena, mod);358 const struct_name = try ty.nameAllocArena(arena, mod);
359 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);359 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
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 = mod.typeToStruct(ty).?;
364 if (struct_obj.layout == .Packed) {363 if (struct_obj.layout == .Packed) {
365 log.debug("TODO implement .debug_info for packed structs", .{});364 log.debug("TODO implement .debug_info for packed structs", .{});
366 break :blk;365 break :blk;
367 }366 }
368367
369 const fields = ty.structFields(mod);368 for (
370 for (fields.keys(), 0..) |field_name, field_index| {369 struct_obj.fields.keys(),
371 const field = fields.get(field_name).?;370 struct_obj.fields.values(),
371 0..,
372 ) |field_name, field, field_index| {
372 if (!field.ty.hasRuntimeBits(mod)) continue;373 if (!field.ty.hasRuntimeBits(mod)) continue;
373 // DW.AT.member374 // DW.AT.member
374 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);375 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
...@@ -385,6 +386,7 @@ pub const DeclState = struct {...@@ -385,6 +386,7 @@ pub const DeclState = struct {
385 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);386 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
386 }387 }
387 },388 },
389 else => unreachable,
388 }390 }
389391
390 // DW.AT.structure_type delimit children392 // DW.AT.structure_type delimit children
src/type.zig+238-568
...@@ -54,10 +54,6 @@ pub const Type = struct {...@@ -54,10 +54,6 @@ pub const Type = struct {
54 .error_union => return .ErrorUnion,54 .error_union => return .ErrorUnion,
5555
56 .anyframe_T => return .AnyFrame,56 .anyframe_T => return .AnyFrame,
57
58 .tuple,
59 .anon_struct,
60 => return .Struct,
61 },57 },
62 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {58 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
63 .int_type => return .Int,59 .int_type => return .Int,
...@@ -66,7 +62,7 @@ pub const Type = struct {...@@ -66,7 +62,7 @@ pub const Type = struct {
66 .vector_type => return .Vector,62 .vector_type => return .Vector,
67 .opt_type => return .Optional,63 .opt_type => return .Optional,
68 .error_union_type => return .ErrorUnion,64 .error_union_type => return .ErrorUnion,
69 .struct_type => return .Struct,65 .struct_type, .anon_struct_type => return .Struct,
70 .union_type => return .Union,66 .union_type => return .Union,
71 .opaque_type => return .Opaque,67 .opaque_type => return .Opaque,
72 .enum_type => return .Enum,68 .enum_type => return .Enum,
...@@ -465,76 +461,6 @@ pub const Type = struct {...@@ -465,76 +461,6 @@ pub const Type = struct {
465 if (b.zigTypeTag(mod) != .AnyFrame) return false;461 if (b.zigTypeTag(mod) != .AnyFrame) return false;
466 return a.elemType2(mod).eql(b.elemType2(mod), mod);462 return a.elemType2(mod).eql(b.elemType2(mod), mod);
467 },463 },
468
469 .tuple => {
470 if (!b.isSimpleTuple()) return false;
471
472 const a_tuple = a.tupleFields();
473 const b_tuple = b.tupleFields();
474
475 if (a_tuple.types.len != b_tuple.types.len) return false;
476
477 for (a_tuple.types, 0..) |a_ty, i| {
478 const b_ty = b_tuple.types[i];
479 if (!eql(a_ty, b_ty, mod)) return false;
480 }
481
482 for (a_tuple.values, 0..) |a_val, i| {
483 const ty = a_tuple.types[i];
484 const b_val = b_tuple.values[i];
485 if (a_val.ip_index == .unreachable_value) {
486 if (b_val.ip_index == .unreachable_value) {
487 continue;
488 } else {
489 return false;
490 }
491 } else {
492 if (b_val.ip_index == .unreachable_value) {
493 return false;
494 } else {
495 if (!Value.eql(a_val, b_val, ty, mod)) return false;
496 }
497 }
498 }
499
500 return true;
501 },
502 .anon_struct => {
503 const a_struct_obj = a.castTag(.anon_struct).?.data;
504 const b_struct_obj = (b.castTag(.anon_struct) orelse return false).data;
505
506 if (a_struct_obj.types.len != b_struct_obj.types.len) return false;
507
508 for (a_struct_obj.names, 0..) |a_name, i| {
509 const b_name = b_struct_obj.names[i];
510 if (!std.mem.eql(u8, a_name, b_name)) return false;
511 }
512
513 for (a_struct_obj.types, 0..) |a_ty, i| {
514 const b_ty = b_struct_obj.types[i];
515 if (!eql(a_ty, b_ty, mod)) return false;
516 }
517
518 for (a_struct_obj.values, 0..) |a_val, i| {
519 const ty = a_struct_obj.types[i];
520 const b_val = b_struct_obj.values[i];
521 if (a_val.ip_index == .unreachable_value) {
522 if (b_val.ip_index == .unreachable_value) {
523 continue;
524 } else {
525 return false;
526 }
527 } else {
528 if (b_val.ip_index == .unreachable_value) {
529 return false;
530 } else {
531 if (!Value.eql(a_val, b_val, ty, mod)) return false;
532 }
533 }
534 }
535
536 return true;
537 },
538 }464 }
539 }465 }
540466
...@@ -641,34 +567,6 @@ pub const Type = struct {...@@ -641,34 +567,6 @@ pub const Type = struct {
641 std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame);567 std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame);
642 hashWithHasher(ty.childType(mod), hasher, mod);568 hashWithHasher(ty.childType(mod), hasher, mod);
643 },569 },
644
645 .tuple => {
646 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
647
648 const tuple = ty.tupleFields();
649 std.hash.autoHash(hasher, tuple.types.len);
650
651 for (tuple.types, 0..) |field_ty, i| {
652 hashWithHasher(field_ty, hasher, mod);
653 const field_val = tuple.values[i];
654 if (field_val.ip_index == .unreachable_value) continue;
655 field_val.hash(field_ty, hasher, mod);
656 }
657 },
658 .anon_struct => {
659 const struct_obj = ty.castTag(.anon_struct).?.data;
660 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
661 std.hash.autoHash(hasher, struct_obj.types.len);
662
663 for (struct_obj.types, 0..) |field_ty, i| {
664 const field_name = struct_obj.names[i];
665 const field_val = struct_obj.values[i];
666 hasher.update(field_name);
667 hashWithHasher(field_ty, hasher, mod);
668 if (field_val.ip_index == .unreachable_value) continue;
669 field_val.hash(field_ty, hasher, mod);
670 }
671 },
672 }570 }
673 }571 }
674572
...@@ -733,41 +631,6 @@ pub const Type = struct {...@@ -733,41 +631,6 @@ pub const Type = struct {
733 };631 };
734 },632 },
735633
736 .tuple => {
737 const payload = self.castTag(.tuple).?.data;
738 const types = try allocator.alloc(Type, payload.types.len);
739 const values = try allocator.alloc(Value, payload.values.len);
740 for (payload.types, 0..) |ty, i| {
741 types[i] = try ty.copy(allocator);
742 }
743 for (payload.values, 0..) |val, i| {
744 values[i] = try val.copy(allocator);
745 }
746 return Tag.tuple.create(allocator, .{
747 .types = types,
748 .values = values,
749 });
750 },
751 .anon_struct => {
752 const payload = self.castTag(.anon_struct).?.data;
753 const names = try allocator.alloc([]const u8, payload.names.len);
754 const types = try allocator.alloc(Type, payload.types.len);
755 const values = try allocator.alloc(Value, payload.values.len);
756 for (payload.names, 0..) |name, i| {
757 names[i] = try allocator.dupe(u8, name);
758 }
759 for (payload.types, 0..) |ty, i| {
760 types[i] = try ty.copy(allocator);
761 }
762 for (payload.values, 0..) |val, i| {
763 values[i] = try val.copy(allocator);
764 }
765 return Tag.anon_struct.create(allocator, .{
766 .names = names,
767 .types = types,
768 .values = values,
769 });
770 },
771 .function => {634 .function => {
772 const payload = self.castTag(.function).?.data;635 const payload = self.castTag(.function).?.data;
773 const param_types = try allocator.alloc(Type, payload.param_types.len);636 const param_types = try allocator.alloc(Type, payload.param_types.len);
...@@ -935,42 +798,6 @@ pub const Type = struct {...@@ -935,42 +798,6 @@ pub const Type = struct {
935 ty = return_type;798 ty = return_type;
936 continue;799 continue;
937 },800 },
938 .tuple => {
939 const tuple = ty.castTag(.tuple).?.data;
940 try writer.writeAll("tuple{");
941 for (tuple.types, 0..) |field_ty, i| {
942 if (i != 0) try writer.writeAll(", ");
943 const val = tuple.values[i];
944 if (val.ip_index != .unreachable_value) {
945 try writer.writeAll("comptime ");
946 }
947 try field_ty.dump("", .{}, writer);
948 if (val.ip_index != .unreachable_value) {
949 try writer.print(" = {}", .{val.fmtDebug()});
950 }
951 }
952 try writer.writeAll("}");
953 return;
954 },
955 .anon_struct => {
956 const anon_struct = ty.castTag(.anon_struct).?.data;
957 try writer.writeAll("struct{");
958 for (anon_struct.types, 0..) |field_ty, i| {
959 if (i != 0) try writer.writeAll(", ");
960 const val = anon_struct.values[i];
961 if (val.ip_index != .unreachable_value) {
962 try writer.writeAll("comptime ");
963 }
964 try writer.writeAll(anon_struct.names[i]);
965 try writer.writeAll(": ");
966 try field_ty.dump("", .{}, writer);
967 if (val.ip_index != .unreachable_value) {
968 try writer.print(" = {}", .{val.fmtDebug()});
969 }
970 }
971 try writer.writeAll("}");
972 return;
973 },
974 .optional => {801 .optional => {
975 const child_type = ty.castTag(.optional).?.data;802 const child_type = ty.castTag(.optional).?.data;
976 try writer.writeByte('?');803 try writer.writeByte('?');
...@@ -1131,45 +958,6 @@ pub const Type = struct {...@@ -1131,45 +958,6 @@ pub const Type = struct {
1131 try print(error_union.payload, writer, mod);958 try print(error_union.payload, writer, mod);
1132 },959 },
1133960
1134 .tuple => {
1135 const tuple = ty.castTag(.tuple).?.data;
1136
1137 try writer.writeAll("tuple{");
1138 for (tuple.types, 0..) |field_ty, i| {
1139 if (i != 0) try writer.writeAll(", ");
1140 const val = tuple.values[i];
1141 if (val.ip_index != .unreachable_value) {
1142 try writer.writeAll("comptime ");
1143 }
1144 try print(field_ty, writer, mod);
1145 if (val.ip_index != .unreachable_value) {
1146 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1147 }
1148 }
1149 try writer.writeAll("}");
1150 },
1151 .anon_struct => {
1152 const anon_struct = ty.castTag(.anon_struct).?.data;
1153
1154 try writer.writeAll("struct{");
1155 for (anon_struct.types, 0..) |field_ty, i| {
1156 if (i != 0) try writer.writeAll(", ");
1157 const val = anon_struct.values[i];
1158 if (val.ip_index != .unreachable_value) {
1159 try writer.writeAll("comptime ");
1160 }
1161 try writer.writeAll(anon_struct.names[i]);
1162 try writer.writeAll(": ");
1163
1164 try print(field_ty, writer, mod);
1165
1166 if (val.ip_index != .unreachable_value) {
1167 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1168 }
1169 }
1170 try writer.writeAll("}");
1171 },
1172
1173 .pointer => {961 .pointer => {
1174 const info = ty.ptrInfo(mod);962 const info = ty.ptrInfo(mod);
1175963
...@@ -1335,6 +1123,27 @@ pub const Type = struct {...@@ -1335,6 +1123,27 @@ pub const Type = struct {
1335 try writer.writeAll("@TypeOf(.{})");1123 try writer.writeAll("@TypeOf(.{})");
1336 }1124 }
1337 },1125 },
1126 .anon_struct_type => |anon_struct| {
1127 try writer.writeAll("struct{");
1128 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
1129 if (i != 0) try writer.writeAll(", ");
1130 if (val != .none) {
1131 try writer.writeAll("comptime ");
1132 }
1133 if (anon_struct.names.len != 0) {
1134 const name = mod.intern_pool.stringToSlice(anon_struct.names[i]);
1135 try writer.writeAll(name);
1136 try writer.writeAll(": ");
1137 }
1138
1139 try print(field_ty.toType(), writer, mod);
1140
1141 if (val != .none) {
1142 try writer.print(" = {}", .{val.toValue().fmtValue(field_ty.toType(), mod)});
1143 }
1144 }
1145 try writer.writeAll("}");
1146 },
13381147
1339 .union_type => |union_type| {1148 .union_type => |union_type| {
1340 const union_obj = mod.unionPtr(union_type.index);1149 const union_obj = mod.unionPtr(union_type.index);
...@@ -1443,16 +1252,6 @@ pub const Type = struct {...@@ -1443,16 +1252,6 @@ pub const Type = struct {
1443 }1252 }
1444 },1253 },
14451254
1446 .tuple, .anon_struct => {
1447 const tuple = ty.tupleFields();
1448 for (tuple.types, 0..) |field_ty, i| {
1449 const val = tuple.values[i];
1450 if (val.ip_index != .unreachable_value) continue; // comptime field
1451 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1452 }
1453 return false;
1454 },
1455
1456 .inferred_alloc_const => unreachable,1255 .inferred_alloc_const => unreachable,
1457 .inferred_alloc_mut => unreachable,1256 .inferred_alloc_mut => unreachable,
1458 },1257 },
...@@ -1567,6 +1366,13 @@ pub const Type = struct {...@@ -1567,6 +1366,13 @@ pub const Type = struct {
1567 return false;1366 return false;
1568 }1367 }
1569 },1368 },
1369 .anon_struct_type => |tuple| {
1370 for (tuple.types, tuple.values) |field_ty, val| {
1371 if (val != .none) continue; // comptime field
1372 if (try field_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1373 }
1374 return false;
1375 },
15701376
1571 .union_type => |union_type| {1377 .union_type => |union_type| {
1572 const union_obj = mod.unionPtr(union_type.index);1378 const union_obj = mod.unionPtr(union_type.index);
...@@ -1634,8 +1440,6 @@ pub const Type = struct {...@@ -1634,8 +1440,6 @@ pub const Type = struct {
1634 .function,1440 .function,
1635 .error_union,1441 .error_union,
1636 .anyframe_T,1442 .anyframe_T,
1637 .tuple,
1638 .anon_struct,
1639 => false,1443 => false,
16401444
1641 .inferred_alloc_mut => unreachable,1445 .inferred_alloc_mut => unreachable,
...@@ -1705,6 +1509,7 @@ pub const Type = struct {...@@ -1705,6 +1509,7 @@ pub const Type = struct {
1705 };1509 };
1706 return struct_obj.layout != .Auto;1510 return struct_obj.layout != .Auto;
1707 },1511 },
1512 .anon_struct_type => false,
1708 .union_type => |union_type| switch (union_type.runtime_tag) {1513 .union_type => |union_type| switch (union_type.runtime_tag) {
1709 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,1514 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,
1710 .tagged => false,1515 .tagged => false,
...@@ -1923,26 +1728,6 @@ pub const Type = struct {...@@ -1923,26 +1728,6 @@ pub const Type = struct {
1923 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),1728 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
1924 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),1729 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
19251730
1926 .tuple, .anon_struct => {
1927 const tuple = ty.tupleFields();
1928 var big_align: u32 = 0;
1929 for (tuple.types, 0..) |field_ty, i| {
1930 const val = tuple.values[i];
1931 if (val.ip_index != .unreachable_value) continue; // comptime field
1932 if (!(field_ty.hasRuntimeBits(mod))) continue;
1933
1934 switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
1935 .scalar => |field_align| big_align = @max(big_align, field_align),
1936 .val => switch (strat) {
1937 .eager => unreachable, // field type alignment not resolved
1938 .sema => unreachable, // passed to abiAlignmentAdvanced above
1939 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1940 },
1941 }
1942 }
1943 return AbiAlignmentAdvanced{ .scalar = big_align };
1944 },
1945
1946 .inferred_alloc_const,1731 .inferred_alloc_const,
1947 .inferred_alloc_mut,1732 .inferred_alloc_mut,
1948 => unreachable,1733 => unreachable,
...@@ -2100,6 +1885,24 @@ pub const Type = struct {...@@ -2100,6 +1885,24 @@ pub const Type = struct {
2100 }1885 }
2101 return AbiAlignmentAdvanced{ .scalar = big_align };1886 return AbiAlignmentAdvanced{ .scalar = big_align };
2102 },1887 },
1888 .anon_struct_type => |tuple| {
1889 var big_align: u32 = 0;
1890 for (tuple.types, tuple.values) |field_ty, val| {
1891 if (val != .none) continue; // comptime field
1892 if (!(field_ty.toType().hasRuntimeBits(mod))) continue;
1893
1894 switch (try field_ty.toType().abiAlignmentAdvanced(mod, strat)) {
1895 .scalar => |field_align| big_align = @max(big_align, field_align),
1896 .val => switch (strat) {
1897 .eager => unreachable, // field type alignment not resolved
1898 .sema => unreachable, // passed to abiAlignmentAdvanced above
1899 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1900 },
1901 }
1902 }
1903 return AbiAlignmentAdvanced{ .scalar = big_align };
1904 },
1905
2103 .union_type => |union_type| {1906 .union_type => |union_type| {
2104 const union_obj = mod.unionPtr(union_type.index);1907 const union_obj = mod.unionPtr(union_type.index);
2105 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());1908 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
...@@ -2287,18 +2090,6 @@ pub const Type = struct {...@@ -2287,18 +2090,6 @@ pub const Type = struct {
2287 .inferred_alloc_const => unreachable,2090 .inferred_alloc_const => unreachable,
2288 .inferred_alloc_mut => unreachable,2091 .inferred_alloc_mut => unreachable,
22892092
2290 .tuple, .anon_struct => {
2291 switch (strat) {
2292 .sema => |sema| try sema.resolveTypeLayout(ty),
2293 .lazy, .eager => {},
2294 }
2295 const field_count = ty.structFieldCount(mod);
2296 if (field_count == 0) {
2297 return AbiSizeAdvanced{ .scalar = 0 };
2298 }
2299 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2300 },
2301
2302 .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },2093 .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
23032094
2304 .pointer => switch (ty.castTag(.pointer).?.data.size) {2095 .pointer => switch (ty.castTag(.pointer).?.data.size) {
...@@ -2496,6 +2287,18 @@ pub const Type = struct {...@@ -2496,6 +2287,18 @@ pub const Type = struct {
2496 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };2287 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2497 },2288 },
2498 },2289 },
2290 .anon_struct_type => |tuple| {
2291 switch (strat) {
2292 .sema => |sema| try sema.resolveTypeLayout(ty),
2293 .lazy, .eager => {},
2294 }
2295 const field_count = tuple.types.len;
2296 if (field_count == 0) {
2297 return AbiSizeAdvanced{ .scalar = 0 };
2298 }
2299 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2300 },
2301
2499 .union_type => |union_type| {2302 .union_type => |union_type| {
2500 const union_obj = mod.unionPtr(union_type.index);2303 const union_obj = mod.unionPtr(union_type.index);
2501 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());2304 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
...@@ -2609,18 +2412,6 @@ pub const Type = struct {...@@ -2609,18 +2412,6 @@ pub const Type = struct {
2609 .inferred_alloc_const => unreachable,2412 .inferred_alloc_const => unreachable,
2610 .inferred_alloc_mut => unreachable,2413 .inferred_alloc_mut => unreachable,
26112414
2612 .tuple, .anon_struct => {
2613 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2614 if (ty.containerLayout(mod) != .Packed) {
2615 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2616 }
2617 var total: u64 = 0;
2618 for (ty.tupleFields().types) |field_ty| {
2619 total += try bitSizeAdvanced(field_ty, mod, opt_sema);
2620 }
2621 return total;
2622 },
2623
2624 .anyframe_T => return target.ptrBitWidth(),2415 .anyframe_T => return target.ptrBitWidth(),
26252416
2626 .pointer => switch (ty.castTag(.pointer).?.data.size) {2417 .pointer => switch (ty.castTag(.pointer).?.data.size) {
...@@ -2724,6 +2515,11 @@ pub const Type = struct {...@@ -2724,6 +2515,11 @@ pub const Type = struct {
2724 return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema);2515 return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema);
2725 },2516 },
27262517
2518 .anon_struct_type => {
2519 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2520 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2521 },
2522
2727 .union_type => |union_type| {2523 .union_type => |union_type| {
2728 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);2524 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2729 if (ty.containerLayout(mod) != .Packed) {2525 if (ty.containerLayout(mod) != .Packed) {
...@@ -3220,23 +3016,17 @@ pub const Type = struct {...@@ -3220,23 +3016,17 @@ pub const Type = struct {
3220 }3016 }
32213017
3222 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {3018 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
3223 return switch (ty.ip_index) {3019 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3224 .empty_struct_type => .Auto,3020 .struct_type => |struct_type| {
3225 .none => switch (ty.tag()) {3021 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;
3226 .tuple, .anon_struct => .Auto,3022 return struct_obj.layout;
3227 else => unreachable,
3228 },3023 },
3229 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {3024 .anon_struct_type => .Auto,
3230 .struct_type => |struct_type| {3025 .union_type => |union_type| {
3231 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;3026 const union_obj = mod.unionPtr(union_type.index);
3232 return struct_obj.layout;3027 return union_obj.layout;
3233 },
3234 .union_type => |union_type| {
3235 const union_obj = mod.unionPtr(union_type.index);
3236 return union_obj.layout;
3237 },
3238 else => unreachable,
3239 },3028 },
3029 else => unreachable,
3240 };3030 };
3241 }3031 }
32423032
...@@ -3349,23 +3139,16 @@ pub const Type = struct {...@@ -3349,23 +3139,16 @@ pub const Type = struct {
3349 }3139 }
33503140
3351 pub fn arrayLenIp(ty: Type, ip: InternPool) u64 {3141 pub fn arrayLenIp(ty: Type, ip: InternPool) u64 {
3352 return switch (ty.ip_index) {3142 return switch (ip.indexToKey(ty.ip_index)) {
3353 .empty_struct_type => 0,3143 .vector_type => |vector_type| vector_type.len,
3354 .none => switch (ty.tag()) {3144 .array_type => |array_type| array_type.len,
3355 .tuple => ty.castTag(.tuple).?.data.types.len,3145 .struct_type => |struct_type| {
3356 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,3146 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
33573147 return struct_obj.fields.count();
3358 else => unreachable,
3359 },
3360 else => switch (ip.indexToKey(ty.ip_index)) {
3361 .vector_type => |vector_type| vector_type.len,
3362 .array_type => |array_type| array_type.len,
3363 .struct_type => |struct_type| {
3364 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
3365 return struct_obj.fields.count();
3366 },
3367 else => unreachable,
3368 },3148 },
3149 .anon_struct_type => |tuple| tuple.types.len,
3150
3151 else => unreachable,
3369 };3152 };
3370 }3153 }
33713154
...@@ -3374,16 +3157,10 @@ pub const Type = struct {...@@ -3374,16 +3157,10 @@ pub const Type = struct {
3374 }3157 }
33753158
3376 pub fn vectorLen(ty: Type, mod: *const Module) u32 {3159 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
3377 return switch (ty.ip_index) {3160 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3378 .none => switch (ty.tag()) {3161 .vector_type => |vector_type| vector_type.len,
3379 .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),3162 .anon_struct_type => |tuple| @intCast(u32, tuple.types.len),
3380 .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len),3163 else => unreachable,
3381 else => unreachable,
3382 },
3383 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3384 .vector_type => |vector_type| vector_type.len,
3385 else => unreachable,
3386 },
3387 };3164 };
3388 }3165 }
33893166
...@@ -3391,8 +3168,6 @@ pub const Type = struct {...@@ -3391,8 +3168,6 @@ pub const Type = struct {
3391 pub fn sentinel(ty: Type, mod: *const Module) ?Value {3168 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
3392 return switch (ty.ip_index) {3169 return switch (ty.ip_index) {
3393 .none => switch (ty.tag()) {3170 .none => switch (ty.tag()) {
3394 .tuple => null,
3395
3396 .pointer => ty.castTag(.pointer).?.data.sentinel,3171 .pointer => ty.castTag(.pointer).?.data.sentinel,
33973172
3398 else => unreachable,3173 else => unreachable,
...@@ -3400,6 +3175,7 @@ pub const Type = struct {...@@ -3400,6 +3175,7 @@ pub const Type = struct {
3400 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {3175 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3401 .vector_type,3176 .vector_type,
3402 .struct_type,3177 .struct_type,
3178 .anon_struct_type,
3403 => null,3179 => null,
34043180
3405 .array_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,3181 .array_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,
...@@ -3486,10 +3262,12 @@ pub const Type = struct {...@@ -3486,10 +3262,12 @@ pub const Type = struct {
3486 ty = struct_obj.backing_int_ty;3262 ty = struct_obj.backing_int_ty;
3487 },3263 },
3488 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),3264 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
3265 .vector_type => |vector_type| ty = vector_type.child.toType(),
3266
3267 .anon_struct_type => unreachable,
34893268
3490 .ptr_type => unreachable,3269 .ptr_type => unreachable,
3491 .array_type => unreachable,3270 .array_type => unreachable,
3492 .vector_type => |vector_type| ty = vector_type.child.toType(),
34933271
3494 .opt_type => unreachable,3272 .opt_type => unreachable,
3495 .error_union_type => unreachable,3273 .error_union_type => unreachable,
...@@ -3711,17 +3489,6 @@ pub const Type = struct {...@@ -3711,17 +3489,6 @@ pub const Type = struct {
3711 }3489 }
3712 },3490 },
37133491
3714 .tuple, .anon_struct => {
3715 const tuple = ty.tupleFields();
3716 for (tuple.values, 0..) |val, i| {
3717 const is_comptime = val.ip_index != .unreachable_value;
3718 if (is_comptime) continue;
3719 if ((try tuple.types[i].onePossibleValue(mod)) != null) continue;
3720 return null;
3721 }
3722 return Value.empty_struct;
3723 },
3724
3725 .inferred_alloc_const => unreachable,3492 .inferred_alloc_const => unreachable,
3726 .inferred_alloc_mut => unreachable,3493 .inferred_alloc_mut => unreachable,
3727 },3494 },
...@@ -3810,7 +3577,33 @@ pub const Type = struct {...@@ -3810,7 +3577,33 @@ pub const Type = struct {
3810 return null;3577 return null;
3811 }3578 }
3812 }3579 }
3813 // In this case the struct has no fields and therefore has one possible value.3580 // In this case the struct has no runtime-known fields and
3581 // therefore has one possible value.
3582
3583 // TODO: this is incorrect for structs with comptime fields, I think
3584 // we should use a temporary allocator to construct an aggregate that
3585 // is populated with the comptime values and then intern that value here.
3586 // This TODO is repeated for anon_struct_type below, as well as in
3587 // the redundant implementation of one-possible-value logic in Sema.zig.
3588 const empty = try mod.intern(.{ .aggregate = .{
3589 .ty = ty.ip_index,
3590 .fields = &.{},
3591 } });
3592 return empty.toValue();
3593 },
3594
3595 .anon_struct_type => |tuple| {
3596 for (tuple.types, tuple.values) |field_ty, val| {
3597 if (val != .none) continue; // comptime field
3598 if ((try field_ty.toType().onePossibleValue(mod)) != null) continue;
3599 return null;
3600 }
3601
3602 // TODO: this is incorrect for structs with comptime fields, I think
3603 // we should use a temporary allocator to construct an aggregate that
3604 // is populated with the comptime values and then intern that value here.
3605 // This TODO is repeated for struct_type above, as well as in
3606 // the redundant implementation of one-possible-value logic in Sema.zig.
3814 const empty = try mod.intern(.{ .aggregate = .{3607 const empty = try mod.intern(.{ .aggregate = .{
3815 .ty = ty.ip_index,3608 .ty = ty.ip_index,
3816 .fields = &.{},3609 .fields = &.{},
...@@ -3915,15 +3708,6 @@ pub const Type = struct {...@@ -3915,15 +3708,6 @@ pub const Type = struct {
3915 return ty.optionalChild(mod).comptimeOnly(mod);3708 return ty.optionalChild(mod).comptimeOnly(mod);
3916 },3709 },
39173710
3918 .tuple, .anon_struct => {
3919 const tuple = ty.tupleFields();
3920 for (tuple.types, 0..) |field_ty, i| {
3921 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
3922 if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true;
3923 }
3924 return false;
3925 },
3926
3927 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),3711 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),
3928 .anyframe_T => {3712 .anyframe_T => {
3929 const child_ty = ty.castTag(.anyframe_T).?.data;3713 const child_ty = ty.castTag(.anyframe_T).?.data;
...@@ -4007,6 +3791,14 @@ pub const Type = struct {...@@ -4007,6 +3791,14 @@ pub const Type = struct {
4007 }3791 }
4008 },3792 },
40093793
3794 .anon_struct_type => |tuple| {
3795 for (tuple.types, tuple.values) |field_ty, val| {
3796 const have_comptime_val = val != .none;
3797 if (!have_comptime_val and field_ty.toType().comptimeOnly(mod)) return true;
3798 }
3799 return false;
3800 },
3801
4010 .union_type => |union_type| {3802 .union_type => |union_type| {
4011 const union_obj = mod.unionPtr(union_type.index);3803 const union_obj = mod.unionPtr(union_type.index);
4012 switch (union_obj.requires_comptime) {3804 switch (union_obj.requires_comptime) {
...@@ -4275,171 +4067,116 @@ pub const Type = struct {...@@ -4275,171 +4067,116 @@ pub const Type = struct {
4275 }4067 }
42764068
4277 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 {4069 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 {
4278 switch (ty.ip_index) {4070 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4279 .none => switch (ty.tag()) {4071 .struct_type => |struct_type| {
4280 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],4072 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4281 else => unreachable,4073 assert(struct_obj.haveFieldTypes());
4074 return struct_obj.fields.keys()[field_index];
4282 },4075 },
4283 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {4076 .anon_struct_type => |anon_struct| {
4284 .struct_type => |struct_type| {4077 const name = anon_struct.names[field_index];
4285 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;4078 return mod.intern_pool.stringToSlice(name);
4286 assert(struct_obj.haveFieldTypes());
4287 return struct_obj.fields.keys()[field_index];
4288 },
4289 else => unreachable,
4290 },4079 },
4080 else => unreachable,
4291 }4081 }
4292 }4082 }
42934083
4294 pub fn structFieldCount(ty: Type, mod: *Module) usize {4084 pub fn structFieldCount(ty: Type, mod: *Module) usize {
4295 return switch (ty.ip_index) {4085 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4296 .empty_struct_type => 0,4086 .struct_type => |struct_type| {
4297 .none => switch (ty.tag()) {4087 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
4298 .tuple => ty.castTag(.tuple).?.data.types.len,4088 assert(struct_obj.haveFieldTypes());
4299 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,4089 return struct_obj.fields.count();
4300 else => unreachable,
4301 },
4302 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4303 .struct_type => |struct_type| {
4304 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
4305 assert(struct_obj.haveFieldTypes());
4306 return struct_obj.fields.count();
4307 },
4308 else => unreachable,
4309 },4090 },
4091 .anon_struct_type => |anon_struct| anon_struct.types.len,
4092 else => unreachable,
4310 };4093 };
4311 }4094 }
43124095
4313 /// Supports structs and unions.4096 /// Supports structs and unions.
4314 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {4097 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
4315 return switch (ty.ip_index) {4098 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4316 .none => switch (ty.tag()) {4099 .struct_type => |struct_type| {
4317 .tuple => return ty.castTag(.tuple).?.data.types[index],4100 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4318 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],4101 return struct_obj.fields.values()[index].ty;
4319 else => unreachable,
4320 },4102 },
4321 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {4103 .union_type => |union_type| {
4322 .struct_type => |struct_type| {4104 const union_obj = mod.unionPtr(union_type.index);
4323 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;4105 return union_obj.fields.values()[index].ty;
4324 return struct_obj.fields.values()[index].ty;
4325 },
4326 .union_type => |union_type| {
4327 const union_obj = mod.unionPtr(union_type.index);
4328 return union_obj.fields.values()[index].ty;
4329 },
4330 else => unreachable,
4331 },4106 },
4107 .anon_struct_type => |anon_struct| anon_struct.types[index].toType(),
4108 else => unreachable,
4332 };4109 };
4333 }4110 }
43344111
4335 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {4112 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {
4336 switch (ty.ip_index) {4113 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4337 .none => switch (ty.tag()) {4114 .struct_type => |struct_type| {
4338 .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod),4115 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4339 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod),4116 assert(struct_obj.layout != .Packed);
4340 else => unreachable,4117 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
4341 },4118 },
4342 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {4119 .anon_struct_type => |anon_struct| {
4343 .struct_type => |struct_type| {4120 return anon_struct.types[index].toType().abiAlignment(mod);
4344 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4345 assert(struct_obj.layout != .Packed);
4346 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
4347 },
4348 .union_type => |union_type| {
4349 const union_obj = mod.unionPtr(union_type.index);
4350 return union_obj.fields.values()[index].normalAlignment(mod);
4351 },
4352 else => unreachable,
4353 },4121 },
4122 .union_type => |union_type| {
4123 const union_obj = mod.unionPtr(union_type.index);
4124 return union_obj.fields.values()[index].normalAlignment(mod);
4125 },
4126 else => unreachable,
4354 }4127 }
4355 }4128 }
43564129
4357 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {4130 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
4358 switch (ty.ip_index) {4131 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4359 .none => switch (ty.tag()) {4132 .struct_type => |struct_type| {
4360 .tuple => {4133 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4361 const tuple = ty.castTag(.tuple).?.data;4134 return struct_obj.fields.values()[index].default_val;
4362 return tuple.values[index];
4363 },
4364 .anon_struct => {
4365 const struct_obj = ty.castTag(.anon_struct).?.data;
4366 return struct_obj.values[index];
4367 },
4368 else => unreachable,
4369 },4135 },
4370 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {4136 .anon_struct_type => |anon_struct| {
4371 .struct_type => |struct_type| {4137 const val = anon_struct.values[index];
4372 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;4138 // TODO: avoid using `unreachable` to indicate this.
4373 return struct_obj.fields.values()[index].default_val;4139 if (val == .none) return Value.@"unreachable";
4374 },4140 return val.toValue();
4375 else => unreachable,
4376 },4141 },
4142 else => unreachable,
4377 }4143 }
4378 }4144 }
43794145
4380 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {4146 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
4381 switch (ty.ip_index) {4147 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4382 .none => switch (ty.tag()) {4148 .struct_type => |struct_type| {
4383 .tuple => {4149 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4384 const tuple = ty.castTag(.tuple).?.data;4150 const field = struct_obj.fields.values()[index];
4385 const val = tuple.values[index];4151 if (field.is_comptime) {
4386 if (val.ip_index == .unreachable_value) {4152 return field.default_val;
4387 return tuple.types[index].onePossibleValue(mod);4153 } else {
4388 } else {4154 return field.ty.onePossibleValue(mod);
4389 return val;4155 }
4390 }
4391 },
4392 .anon_struct => {
4393 const anon_struct = ty.castTag(.anon_struct).?.data;
4394 const val = anon_struct.values[index];
4395 if (val.ip_index == .unreachable_value) {
4396 return anon_struct.types[index].onePossibleValue(mod);
4397 } else {
4398 return val;
4399 }
4400 },
4401 else => unreachable,
4402 },4156 },
4403 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {4157 .anon_struct_type => |tuple| {
4404 .struct_type => |struct_type| {4158 const val = tuple.values[index];
4405 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;4159 if (val == .none) {
4406 const field = struct_obj.fields.values()[index];4160 return tuple.types[index].toType().onePossibleValue(mod);
4407 if (field.is_comptime) {4161 } else {
4408 return field.default_val;4162 return val.toValue();
4409 } else {4163 }
4410 return field.ty.onePossibleValue(mod);
4411 }
4412 },
4413 else => unreachable,
4414 },4164 },
4165 else => unreachable,
4415 }4166 }
4416 }4167 }
44174168
4418 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {4169 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
4419 switch (ty.ip_index) {4170 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4420 .none => switch (ty.tag()) {4171 .struct_type => |struct_type| {
4421 .tuple => {4172 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4422 const tuple = ty.castTag(.tuple).?.data;4173 if (struct_obj.layout == .Packed) return false;
4423 const val = tuple.values[index];4174 const field = struct_obj.fields.values()[index];
4424 return val.ip_index != .unreachable_value;4175 return field.is_comptime;
4425 },
4426 .anon_struct => {
4427 const anon_struct = ty.castTag(.anon_struct).?.data;
4428 const val = anon_struct.values[index];
4429 return val.ip_index != .unreachable_value;
4430 },
4431 else => unreachable,
4432 },
4433 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4434 .struct_type => |struct_type| {
4435 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4436 if (struct_obj.layout == .Packed) return false;
4437 const field = struct_obj.fields.values()[index];
4438 return field.is_comptime;
4439 },
4440 else => unreachable,
4441 },4176 },
4442 }4177 .anon_struct_type => |anon_struct| anon_struct.values[index] != .none,
4178 else => unreachable,
4179 };
4443 }4180 }
44444181
4445 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {4182 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
...@@ -4516,46 +4253,43 @@ pub const Type = struct {...@@ -4516,46 +4253,43 @@ pub const Type = struct {
4516 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {4253 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
4517 switch (ty.ip_index) {4254 switch (ty.ip_index) {
4518 .none => switch (ty.tag()) {4255 .none => switch (ty.tag()) {
4519 .tuple, .anon_struct => {4256 else => unreachable,
4520 const tuple = ty.tupleFields();4257 },
4258 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4259 .struct_type => |struct_type| {
4260 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4261 assert(struct_obj.haveLayout());
4262 assert(struct_obj.layout != .Packed);
4263 var it = ty.iterateStructOffsets(mod);
4264 while (it.next()) |field_offset| {
4265 if (index == field_offset.field)
4266 return field_offset.offset;
4267 }
45214268
4269 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4270 },
4271
4272 .anon_struct_type => |tuple| {
4522 var offset: u64 = 0;4273 var offset: u64 = 0;
4523 var big_align: u32 = 0;4274 var big_align: u32 = 0;
45244275
4525 for (tuple.types, 0..) |field_ty, i| {4276 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
4526 const field_val = tuple.values[i];4277 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {
4527 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) {
4528 // comptime field4278 // comptime field
4529 if (i == index) return offset;4279 if (i == index) return offset;
4530 continue;4280 continue;
4531 }4281 }
45324282
4533 const field_align = field_ty.abiAlignment(mod);4283 const field_align = field_ty.toType().abiAlignment(mod);
4534 big_align = @max(big_align, field_align);4284 big_align = @max(big_align, field_align);
4535 offset = std.mem.alignForwardGeneric(u64, offset, field_align);4285 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
4536 if (i == index) return offset;4286 if (i == index) return offset;
4537 offset += field_ty.abiSize(mod);4287 offset += field_ty.toType().abiSize(mod);
4538 }4288 }
4539 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));4289 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
4540 return offset;4290 return offset;
4541 },4291 },
45424292
4543 else => unreachable,
4544 },
4545 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4546 .struct_type => |struct_type| {
4547 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4548 assert(struct_obj.haveLayout());
4549 assert(struct_obj.layout != .Packed);
4550 var it = ty.iterateStructOffsets(mod);
4551 while (it.next()) |field_offset| {
4552 if (index == field_offset.field)
4553 return field_offset.offset;
4554 }
4555
4556 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4557 },
4558
4559 .union_type => |union_type| {4293 .union_type => |union_type| {
4560 if (!union_type.hasTag())4294 if (!union_type.hasTag())
4561 return 0;4295 return 0;
...@@ -4655,10 +4389,6 @@ pub const Type = struct {...@@ -4655,10 +4389,6 @@ pub const Type = struct {
4655 inferred_alloc_const, // See last_no_payload_tag below.4389 inferred_alloc_const, // See last_no_payload_tag below.
4656 // After this, the tag requires a payload.4390 // After this, the tag requires a payload.
46574391
4658 /// Possible Value tags for this: @"struct"
4659 tuple,
4660 /// Possible Value tags for this: @"struct"
4661 anon_struct,
4662 pointer,4392 pointer,
4663 function,4393 function,
4664 optional,4394 optional,
...@@ -4691,8 +4421,6 @@ pub const Type = struct {...@@ -4691,8 +4421,6 @@ pub const Type = struct {
4691 .function => Payload.Function,4421 .function => Payload.Function,
4692 .error_union => Payload.ErrorUnion,4422 .error_union => Payload.ErrorUnion,
4693 .error_set_single => Payload.Name,4423 .error_set_single => Payload.Name,
4694 .tuple => Payload.Tuple,
4695 .anon_struct => Payload.AnonStruct,
4696 };4424 };
4697 }4425 }
46984426
...@@ -4723,83 +4451,48 @@ pub const Type = struct {...@@ -4723,83 +4451,48 @@ pub const Type = struct {
47234451
4724 pub fn isTuple(ty: Type, mod: *Module) bool {4452 pub fn isTuple(ty: Type, mod: *Module) bool {
4725 return switch (ty.ip_index) {4453 return switch (ty.ip_index) {
4726 .none => switch (ty.tag()) {4454 .none => false,
4727 .tuple => true,4455 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4728 else => false,
4729 },
4730 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4731 .struct_type => |struct_type| {4456 .struct_type => |struct_type| {
4732 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;4457 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
4733 return struct_obj.is_tuple;4458 return struct_obj.is_tuple;
4734 },4459 },
4460 .anon_struct_type => |anon_struct| anon_struct.names.len == 0,
4735 else => false,4461 else => false,
4736 },4462 },
4737 };4463 };
4738 }4464 }
47394465
4740 pub fn isAnonStruct(ty: Type) bool {4466 pub fn isAnonStruct(ty: Type, mod: *Module) bool {
4741 return switch (ty.ip_index) {4467 if (ty.ip_index == .empty_struct_type) return true;
4742 .empty_struct_type => true,4468 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4743 .none => switch (ty.tag()) {4469 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
4744 .anon_struct => true,
4745 else => false,
4746 },
4747 else => false,4470 else => false,
4748 };4471 };
4749 }4472 }
47504473
4751 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {4474 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
4752 return switch (ty.ip_index) {4475 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4753 .empty_struct_type => true,4476 .struct_type => |struct_type| {
4754 .none => switch (ty.tag()) {4477 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
4755 .tuple, .anon_struct => true,4478 return struct_obj.is_tuple;
4756 else => false,
4757 },
4758 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4759 .struct_type => |struct_type| {
4760 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
4761 return struct_obj.is_tuple;
4762 },
4763 else => false,
4764 },
4765 };
4766 }
4767
4768 pub fn isSimpleTuple(ty: Type) bool {
4769 return switch (ty.ip_index) {
4770 .empty_struct_type => true,
4771 .none => switch (ty.tag()) {
4772 .tuple => true,
4773 else => false,
4774 },4479 },
4480 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
4775 else => false,4481 else => false,
4776 };4482 };
4777 }4483 }
47784484
4779 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {4485 pub fn isSimpleTuple(ty: Type, mod: *Module) bool {
4780 return switch (ty.ip_index) {4486 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4781 .empty_struct_type => true,4487 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
4782 .none => switch (ty.tag()) {
4783 .tuple, .anon_struct => true,
4784 else => false,
4785 },
4786 else => false,4488 else => false,
4787 };4489 };
4788 }4490 }
47894491
4790 // Only allowed for simple tuple types4492 pub fn isSimpleTupleOrAnonStruct(ty: Type, mod: *Module) bool {
4791 pub fn tupleFields(ty: Type) Payload.Tuple.Data {4493 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4792 return switch (ty.ip_index) {4494 .anon_struct_type => true,
4793 .empty_struct_type => .{ .types = &.{}, .values = &.{} },4495 else => false,
4794 .none => switch (ty.tag()) {
4795 .tuple => ty.castTag(.tuple).?.data,
4796 .anon_struct => .{
4797 .types = ty.castTag(.anon_struct).?.data.types,
4798 .values = ty.castTag(.anon_struct).?.data.values,
4799 },
4800 else => unreachable,
4801 },
4802 else => unreachable,
4803 };4496 };
4804 }4497 }
48054498
...@@ -4947,29 +4640,6 @@ pub const Type = struct {...@@ -4947,29 +4640,6 @@ pub const Type = struct {
4947 /// memory is owned by `Module`4640 /// memory is owned by `Module`
4948 data: []const u8,4641 data: []const u8,
4949 };4642 };
4950
4951 pub const Tuple = struct {
4952 base: Payload = .{ .tag = .tuple },
4953 data: Data,
4954
4955 pub const Data = struct {
4956 types: []Type,
4957 /// unreachable_value elements are used to indicate runtime-known.
4958 values: []Value,
4959 };
4960 };
4961
4962 pub const AnonStruct = struct {
4963 base: Payload = .{ .tag = .anon_struct },
4964 data: Data,
4965
4966 pub const Data = struct {
4967 names: []const []const u8,
4968 types: []Type,
4969 /// unreachable_value elements are used to indicate runtime-known.
4970 values: []Value,
4971 };
4972 };
4973 };4643 };
49744644
4975 pub const @"u1": Type = .{ .ip_index = .u1_type, .legacy = undefined };4645 pub const @"u1": Type = .{ .ip_index = .u1_type, .legacy = undefined };
src/value.zig+20-32
...@@ -1889,26 +1889,28 @@ pub const Value = struct {...@@ -1889,26 +1889,28 @@ pub const Value = struct {
1889 const b_field_vals = b.castTag(.aggregate).?.data;1889 const b_field_vals = b.castTag(.aggregate).?.data;
1890 assert(a_field_vals.len == b_field_vals.len);1890 assert(a_field_vals.len == b_field_vals.len);
18911891
1892 if (ty.isSimpleTupleOrAnonStruct()) {1892 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1893 const types = ty.tupleFields().types;1893 .anon_struct_type => |anon_struct| {
1894 assert(types.len == a_field_vals.len);1894 assert(anon_struct.types.len == a_field_vals.len);
1895 for (types, 0..) |field_ty, i| {1895 for (anon_struct.types, 0..) |field_ty, i| {
1896 if (!(try eqlAdvanced(a_field_vals[i], field_ty, b_field_vals[i], field_ty, mod, opt_sema))) {1896 if (!(try eqlAdvanced(a_field_vals[i], field_ty.toType(), b_field_vals[i], field_ty.toType(), mod, opt_sema))) {
1897 return false;1897 return false;
1898 }
1898 }1899 }
1899 }1900 return true;
1900 return true;1901 },
1901 }1902 .struct_type => |struct_type| {
19021903 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1903 if (ty.zigTypeTag(mod) == .Struct) {1904 const fields = struct_obj.fields.values();
1904 const fields = ty.structFields(mod).values();1905 assert(fields.len == a_field_vals.len);
1905 assert(fields.len == a_field_vals.len);1906 for (fields, 0..) |field, i| {
1906 for (fields, 0..) |field, i| {1907 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
1907 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {1908 return false;
1908 return false;1909 }
1909 }1910 }
1910 }1911 return true;
1911 return true;1912 },
1913 else => {},
1912 }1914 }
19131915
1914 const elem_ty = ty.childType(mod);1916 const elem_ty = ty.childType(mod);
...@@ -2017,20 +2019,6 @@ pub const Value = struct {...@@ -2017,20 +2019,6 @@ pub const Value = struct {
2017 if ((try ty.onePossibleValue(mod)) != null) {2019 if ((try ty.onePossibleValue(mod)) != null) {
2018 return true;2020 return true;
2019 }2021 }
2020 if (a_ty.castTag(.anon_struct)) |payload| {
2021 const tuple = payload.data;
2022 if (tuple.values.len != 1) {
2023 return false;
2024 }
2025 const field_name = tuple.names[0];
2026 const union_obj = mod.typeToUnion(ty).?;
2027 const field_index = @intCast(u32, union_obj.fields.getIndex(field_name) orelse return false);
2028 const tag_and_val = b.castTag(.@"union").?.data;
2029 const field_tag = try mod.enumValueFieldIndex(union_obj.tag_ty, field_index);
2030 const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, mod);
2031 if (!tag_matches) return false;
2032 return eqlAdvanced(tag_and_val.val, union_obj.tag_ty, tuple.values[0], tuple.types[0], mod, opt_sema);
2033 }
2034 return false;2022 return false;
2035 },2023 },
2036 .Float => {2024 .Float => {