authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-12 13:32:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-12 20:08:56-04:00
logcb6201715a7bcae2b278811186afc17a697b25f7
tree30db7b0844d0769b87664e83164f734fae1a9627
parent7e2b6b0f1bc5877f11c50a217dd88c11481bbad4

InternPool: prevent anon struct UAF bugs with type safety

Instead of using actual slices for InternPool.Key.AnonStructType, this commit changes to use Slice types instead, which store a long-lived index rather than a pointer. This is a follow-up to 7ef1eb1c27754cb0349fdc10db1f02ff2dddd99b.

10 files changed, 248 insertions(+), 178 deletions(-)

src/InternPool.zig+116-80
...@@ -373,11 +373,11 @@ pub const Key = union(enum) {...@@ -373,11 +373,11 @@ pub const Key = union(enum) {
373 };373 };
374374
375 pub const AnonStructType = struct {375 pub const AnonStructType = struct {
376 types: []const Index,376 types: Index.Slice,
377 /// This may be empty, indicating this is a tuple.377 /// This may be empty, indicating this is a tuple.
378 names: []const NullTerminatedString,378 names: NullTerminatedString.Slice,
379 /// These elements may be `none`, indicating runtime-known.379 /// These elements may be `none`, indicating runtime-known.
380 values: []const Index,380 values: Index.Slice,
381381
382 pub fn isTuple(self: AnonStructType) bool {382 pub fn isTuple(self: AnonStructType) bool {
383 return self.names.len == 0;383 return self.names.len == 0;
...@@ -1020,9 +1020,9 @@ pub const Key = union(enum) {...@@ -1020,9 +1020,9 @@ pub const Key = union(enum) {
10201020
1021 .anon_struct_type => |anon_struct_type| {1021 .anon_struct_type => |anon_struct_type| {
1022 var hasher = Hash.init(seed);1022 var hasher = Hash.init(seed);
1023 for (anon_struct_type.types) |elem| std.hash.autoHash(&hasher, elem);1023 for (anon_struct_type.types.get(ip)) |elem| std.hash.autoHash(&hasher, elem);
1024 for (anon_struct_type.values) |elem| std.hash.autoHash(&hasher, elem);1024 for (anon_struct_type.values.get(ip)) |elem| std.hash.autoHash(&hasher, elem);
1025 for (anon_struct_type.names) |elem| std.hash.autoHash(&hasher, elem);1025 for (anon_struct_type.names.get(ip)) |elem| std.hash.autoHash(&hasher, elem);
1026 return hasher.final();1026 return hasher.final();
1027 },1027 },
10281028
...@@ -1352,9 +1352,9 @@ pub const Key = union(enum) {...@@ -1352,9 +1352,9 @@ pub const Key = union(enum) {
1352 },1352 },
1353 .anon_struct_type => |a_info| {1353 .anon_struct_type => |a_info| {
1354 const b_info = b.anon_struct_type;1354 const b_info = b.anon_struct_type;
1355 return std.mem.eql(Index, a_info.types, b_info.types) and1355 return std.mem.eql(Index, a_info.types.get(ip), b_info.types.get(ip)) and
1356 std.mem.eql(Index, a_info.values, b_info.values) and1356 std.mem.eql(Index, a_info.values.get(ip), b_info.values.get(ip)) and
1357 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);1357 std.mem.eql(NullTerminatedString, a_info.names.get(ip), b_info.names.get(ip));
1358 },1358 },
1359 .error_set_type => |a_info| {1359 .error_set_type => |a_info| {
1360 const b_info = b.error_set_type;1360 const b_info = b.error_set_type;
...@@ -2113,9 +2113,9 @@ pub const static_keys = [_]Key{...@@ -2113,9 +2113,9 @@ pub const static_keys = [_]Key{
21132113
2114 // empty_struct_type2114 // empty_struct_type
2115 .{ .anon_struct_type = .{2115 .{ .anon_struct_type = .{
2116 .types = &.{},2116 .types = .{ .start = 0, .len = 0 },
2117 .names = &.{},2117 .names = .{ .start = 0, .len = 0 },
2118 .values = &.{},2118 .values = .{ .start = 0, .len = 0 },
2119 } },2119 } },
21202120
2121 .{ .simple_value = .undefined },2121 .{ .simple_value = .undefined },
...@@ -3025,7 +3025,17 @@ pub fn init(ip: *InternPool, gpa: Allocator) !void {...@@ -3025,7 +3025,17 @@ pub fn init(ip: *InternPool, gpa: Allocator) !void {
30253025
3026 // This inserts all the statically-known values into the intern pool in the3026 // This inserts all the statically-known values into the intern pool in the
3027 // order expected.3027 // order expected.
3028 for (static_keys) |key| _ = ip.get(gpa, key) catch unreachable;3028 for (static_keys[0..@intFromEnum(Index.empty_struct_type)]) |key| {
3029 _ = ip.get(gpa, key) catch unreachable;
3030 }
3031 _ = ip.getAnonStructType(gpa, .{
3032 .types = &.{},
3033 .names = &.{},
3034 .values = &.{},
3035 }) catch unreachable;
3036 for (static_keys[@intFromEnum(Index.empty_struct_type) + 1 ..]) |key| {
3037 _ = ip.get(gpa, key) catch unreachable;
3038 }
30293039
3030 if (std.debug.runtime_safety) {3040 if (std.debug.runtime_safety) {
3031 // Sanity check.3041 // Sanity check.
...@@ -3155,30 +3165,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -3155,30 +3165,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3155 .namespace = @as(Module.Namespace.Index, @enumFromInt(data)).toOptional(),3165 .namespace = @as(Module.Namespace.Index, @enumFromInt(data)).toOptional(),
3156 } },3166 } },
31573167
3158 .type_struct_anon => {3168 .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(ip, data) },
3159 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);3169 .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(ip, data) },
3160 const fields_len = type_struct_anon.data.fields_len;
3161 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
3162 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
3163 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
3164 return .{ .anon_struct_type = .{
3165 .types = @ptrCast(types),
3166 .values = @ptrCast(values),
3167 .names = @ptrCast(names),
3168 } };
3169 },
3170 .type_tuple_anon => {
3171 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
3172 const fields_len = type_struct_anon.data.fields_len;
3173 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
3174 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
3175 return .{ .anon_struct_type = .{
3176 .types = @ptrCast(types),
3177 .values = @ptrCast(values),
3178 .names = &.{},
3179 } };
3180 },
3181
3182 .type_union => .{ .union_type = extraUnionType(ip, data) },3170 .type_union => .{ .union_type = extraUnionType(ip, data) },
31833171
3184 .type_enum_auto => {3172 .type_enum_auto => {
...@@ -3577,6 +3565,44 @@ fn extraUnionType(ip: *const InternPool, extra_index: u32) Key.UnionType {...@@ -3577,6 +3565,44 @@ fn extraUnionType(ip: *const InternPool, extra_index: u32) Key.UnionType {
3577 };3565 };
3578}3566}
35793567
3568fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType {
3569 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index);
3570 const fields_len = type_struct_anon.data.fields_len;
3571 return .{
3572 .types = .{
3573 .start = type_struct_anon.end,
3574 .len = fields_len,
3575 },
3576 .values = .{
3577 .start = type_struct_anon.end + fields_len,
3578 .len = fields_len,
3579 },
3580 .names = .{
3581 .start = type_struct_anon.end + fields_len + fields_len,
3582 .len = fields_len,
3583 },
3584 };
3585}
3586
3587fn extraTypeTupleAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType {
3588 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index);
3589 const fields_len = type_struct_anon.data.fields_len;
3590 return .{
3591 .types = .{
3592 .start = type_struct_anon.end,
3593 .len = fields_len,
3594 },
3595 .values = .{
3596 .start = type_struct_anon.end + fields_len,
3597 .len = fields_len,
3598 },
3599 .names = .{
3600 .start = 0,
3601 .len = 0,
3602 },
3603 };
3604}
3605
3580fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {3606fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
3581 const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index);3607 const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index);
3582 var index: usize = type_function.end;3608 var index: usize = type_function.end;
...@@ -3864,44 +3890,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3864,44 +3890,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3864 });3890 });
3865 },3891 },
38663892
3867 .anon_struct_type => |anon_struct_type| {3893 .anon_struct_type => unreachable, // use getAnonStructType() instead
3868 assert(anon_struct_type.types.len == anon_struct_type.values.len);
3869 for (anon_struct_type.types) |elem| assert(elem != .none);
3870
3871 const fields_len: u32 = @intCast(anon_struct_type.types.len);
3872 if (anon_struct_type.names.len == 0) {
3873 try ip.extra.ensureUnusedCapacity(
3874 gpa,
3875 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 2),
3876 );
3877 ip.items.appendAssumeCapacity(.{
3878 .tag = .type_tuple_anon,
3879 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
3880 .fields_len = fields_len,
3881 }),
3882 });
3883 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
3884 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
3885 return @enumFromInt(ip.items.len - 1);
3886 }
3887
3888 assert(anon_struct_type.names.len == anon_struct_type.types.len);
3889
3890 try ip.extra.ensureUnusedCapacity(
3891 gpa,
3892 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 3),
3893 );
3894 ip.items.appendAssumeCapacity(.{
3895 .tag = .type_struct_anon,
3896 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
3897 .fields_len = fields_len,
3898 }),
3899 });
3900 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
3901 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
3902 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.names));
3903 return @enumFromInt(ip.items.len - 1);
3904 },
39053894
3906 .union_type => unreachable, // use getUnionType() instead3895 .union_type => unreachable, // use getUnionType() instead
39073896
...@@ -4408,7 +4397,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4408,7 +4397,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4408 }4397 }
4409 },4398 },
4410 .anon_struct_type => |anon_struct_type| {4399 .anon_struct_type => |anon_struct_type| {
4411 for (aggregate.storage.values(), anon_struct_type.types) |elem, ty| {4400 for (aggregate.storage.values(), anon_struct_type.types.get(ip)) |elem, ty| {
4412 assert(ip.typeOf(elem) == ty);4401 assert(ip.typeOf(elem) == ty);
4413 }4402 }
4414 },4403 },
...@@ -4426,7 +4415,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4426,7 +4415,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4426 switch (ty_key) {4415 switch (ty_key) {
4427 .anon_struct_type => |anon_struct_type| opv: {4416 .anon_struct_type => |anon_struct_type| opv: {
4428 switch (aggregate.storage) {4417 switch (aggregate.storage) {
4429 .bytes => |bytes| for (anon_struct_type.values, bytes) |value, byte| {4418 .bytes => |bytes| for (anon_struct_type.values.get(ip), bytes) |value, byte| {
4430 if (value != ip.getIfExists(.{ .int = .{4419 if (value != ip.getIfExists(.{ .int = .{
4431 .ty = .u8_type,4420 .ty = .u8_type,
4432 .storage = .{ .u64 = byte },4421 .storage = .{ .u64 = byte },
...@@ -4434,10 +4423,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4434,10 +4423,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4434 },4423 },
4435 .elems => |elems| if (!std.mem.eql(4424 .elems => |elems| if (!std.mem.eql(
4436 Index,4425 Index,
4437 anon_struct_type.values,4426 anon_struct_type.values.get(ip),
4438 elems,4427 elems,
4439 )) break :opv,4428 )) break :opv,
4440 .repeated_elem => |elem| for (anon_struct_type.values) |value| {4429 .repeated_elem => |elem| for (anon_struct_type.values.get(ip)) |value| {
4441 if (value != elem) break :opv;4430 if (value != elem) break :opv;
4442 },4431 },
4443 }4432 }
...@@ -4646,6 +4635,53 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat...@@ -4646,6 +4635,53 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
4646 return @enumFromInt(ip.items.len - 1);4635 return @enumFromInt(ip.items.len - 1);
4647}4636}
46484637
4638pub const AnonStructTypeInit = struct {
4639 types: []const Index,
4640 /// This may be empty, indicating this is a tuple.
4641 names: []const NullTerminatedString,
4642 /// These elements may be `none`, indicating runtime-known.
4643 values: []const Index,
4644};
4645
4646pub fn getAnonStructType(ip: *InternPool, gpa: Allocator, ini: AnonStructTypeInit) Allocator.Error!Index {
4647 assert(ini.types.len == ini.values.len);
4648 for (ini.types) |elem| assert(elem != .none);
4649
4650 const prev_extra_len = ip.extra.items.len;
4651 const fields_len: u32 = @intCast(ini.types.len);
4652
4653 try ip.extra.ensureUnusedCapacity(
4654 gpa,
4655 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 3),
4656 );
4657 try ip.items.ensureUnusedCapacity(gpa, 1);
4658
4659 const extra_index = ip.addExtraAssumeCapacity(TypeStructAnon{
4660 .fields_len = fields_len,
4661 });
4662 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.types));
4663 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values));
4664
4665 const adapter: KeyAdapter = .{ .intern_pool = ip };
4666 const key: Key = .{
4667 .anon_struct_type = if (ini.names.len == 0) extraTypeTupleAnon(ip, extra_index) else k: {
4668 assert(ini.names.len == ini.types.len);
4669 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
4670 break :k extraTypeStructAnon(ip, extra_index);
4671 },
4672 };
4673 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
4674 if (gop.found_existing) {
4675 ip.extra.items.len = prev_extra_len;
4676 return @enumFromInt(gop.index);
4677 }
4678 ip.items.appendAssumeCapacity(.{
4679 .tag = if (ini.names.len == 0) .type_tuple_anon else .type_struct_anon,
4680 .data = extra_index,
4681 });
4682 return @enumFromInt(ip.items.len - 1);
4683}
4684
4649/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.4685/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.
4650pub const GetFuncTypeKey = struct {4686pub const GetFuncTypeKey = struct {
4651 param_types: []Index,4687 param_types: []Index,
...@@ -6056,7 +6092,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -6056,7 +6092,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
6056 for (agg_elems, 0..) |*elem, i| {6092 for (agg_elems, 0..) |*elem, i| {
6057 const new_elem_ty = switch (ip.indexToKey(new_ty)) {6093 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
6058 inline .array_type, .vector_type => |seq_type| seq_type.child,6094 inline .array_type, .vector_type => |seq_type| seq_type.child,
6059 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],6095 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[i],
6060 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)6096 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)
6061 .fields.values()[i].ty.toIntern(),6097 .fields.values()[i].ty.toIntern(),
6062 else => unreachable,6098 else => unreachable,
src/Sema.zig+60-51
...@@ -8052,11 +8052,12 @@ fn instantiateGenericCall(...@@ -8052,11 +8052,12 @@ fn instantiateGenericCall(
80528052
8053fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {8053fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
8054 const mod = sema.mod;8054 const mod = sema.mod;
8055 const tuple = switch (mod.intern_pool.indexToKey(ty.toIntern())) {8055 const ip = &mod.intern_pool;
8056 const tuple = switch (ip.indexToKey(ty.toIntern())) {
8056 .anon_struct_type => |tuple| tuple,8057 .anon_struct_type => |tuple| tuple,
8057 else => return,8058 else => return,
8058 };8059 };
8059 for (tuple.types, tuple.values) |field_ty, field_val| {8060 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {
8060 try sema.resolveTupleLazyValues(block, src, field_ty.toType());8061 try sema.resolveTupleLazyValues(block, src, field_ty.toType());
8061 if (field_val == .none) continue;8062 if (field_val == .none) continue;
8062 // TODO: mutate in intern pool8063 // TODO: mutate in intern pool
...@@ -12929,7 +12930,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12929,7 +12930,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12929 },12930 },
12930 .anon_struct_type => |anon_struct| {12931 .anon_struct_type => |anon_struct| {
12931 if (anon_struct.names.len != 0) {12932 if (anon_struct.names.len != 0) {
12932 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names, field_name) != null;12933 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names.get(ip), field_name) != null;
12933 } else {12934 } else {
12934 const field_index = field_name.toUnsigned(ip) orelse break :hf false;12935 const field_index = field_name.toUnsigned(ip) orelse break :hf false;
12935 break :hf field_index < ty.structFieldCount(mod);12936 break :hf field_index < ty.structFieldCount(mod);
...@@ -13558,11 +13559,11 @@ fn analyzeTupleCat(...@@ -13558,11 +13559,11 @@ fn analyzeTupleCat(
13558 break :rs runtime_src;13559 break :rs runtime_src;
13559 };13560 };
1356013561
13561 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{13562 const tuple_ty = try mod.intern_pool.getAnonStructType(mod.gpa, .{
13562 .types = types,13563 .types = types,
13563 .values = values,13564 .values = values,
13564 .names = &.{},13565 .names = &.{},
13565 } });13566 });
1356613567
13567 const runtime_src = opt_runtime_src orelse {13568 const runtime_src = opt_runtime_src orelse {
13568 const tuple_val = try mod.intern(.{ .aggregate = .{13569 const tuple_val = try mod.intern(.{ .aggregate = .{
...@@ -13889,11 +13890,11 @@ fn analyzeTupleMul(...@@ -13889,11 +13890,11 @@ fn analyzeTupleMul(
13889 break :rs runtime_src;13890 break :rs runtime_src;
13890 };13891 };
1389113892
13892 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{13893 const tuple_ty = try mod.intern_pool.getAnonStructType(mod.gpa, .{
13893 .types = types,13894 .types = types,
13894 .values = values,13895 .values = values,
13895 .names = &.{},13896 .names = &.{},
13896 } });13897 });
1389713898
13898 const runtime_src = opt_runtime_src orelse {13899 const runtime_src = opt_runtime_src orelse {
13899 const tuple_val = try mod.intern(.{ .aggregate = .{13900 const tuple_val = try mod.intern(.{ .aggregate = .{
...@@ -15217,6 +15218,7 @@ fn zirOverflowArithmetic(...@@ -15217,6 +15218,7 @@ fn zirOverflowArithmetic(
15217 const lhs_ty = sema.typeOf(uncasted_lhs);15218 const lhs_ty = sema.typeOf(uncasted_lhs);
15218 const rhs_ty = sema.typeOf(uncasted_rhs);15219 const rhs_ty = sema.typeOf(uncasted_rhs);
15219 const mod = sema.mod;15220 const mod = sema.mod;
15221 const ip = &mod.intern_pool;
1522015222
15221 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);15223 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1522215224
...@@ -15244,7 +15246,7 @@ fn zirOverflowArithmetic(...@@ -15244,7 +15246,7 @@ fn zirOverflowArithmetic(
15244 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);15246 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);
1524515247
15246 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);15248 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
15247 const overflow_ty = mod.intern_pool.indexToKey(tuple_ty.toIntern()).anon_struct_type.types[1].toType();15249 const overflow_ty = ip.indexToKey(tuple_ty.toIntern()).anon_struct_type.types.get(ip)[1].toType();
1524815250
15249 var result: struct {15251 var result: struct {
15250 inst: Air.Inst.Ref = .none,15252 inst: Air.Inst.Ref = .none,
...@@ -15418,6 +15420,7 @@ fn splat(sema: *Sema, ty: Type, val: Value) !Value {...@@ -15418,6 +15420,7 @@ fn splat(sema: *Sema, ty: Type, val: Value) !Value {
1541815420
15419fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {15421fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
15420 const mod = sema.mod;15422 const mod = sema.mod;
15423 const ip = &mod.intern_pool;
15421 const ov_ty = if (ty.zigTypeTag(mod) == .Vector) try mod.vectorType(.{15424 const ov_ty = if (ty.zigTypeTag(mod) == .Vector) try mod.vectorType(.{
15422 .len = ty.vectorLen(mod),15425 .len = ty.vectorLen(mod),
15423 .child = .u1_type,15426 .child = .u1_type,
...@@ -15425,11 +15428,11 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {...@@ -15425,11 +15428,11 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
1542515428
15426 const types = [2]InternPool.Index{ ty.toIntern(), ov_ty.toIntern() };15429 const types = [2]InternPool.Index{ ty.toIntern(), ov_ty.toIntern() };
15427 const values = [2]InternPool.Index{ .none, .none };15430 const values = [2]InternPool.Index{ .none, .none };
15428 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{15431 const tuple_ty = try ip.getAnonStructType(mod.gpa, .{
15429 .types = &types,15432 .types = &types,
15430 .values = &values,15433 .values = &values,
15431 .names = &.{},15434 .names = &.{},
15432 } });15435 });
15433 return tuple_ty.toType();15436 return tuple_ty.toType();
15434}15437}
1543515438
...@@ -17578,15 +17581,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17578,15 +17581,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17578 struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len);17581 struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len);
17579 for (struct_field_vals, 0..) |*struct_field_val, i| {17582 for (struct_field_vals, 0..) |*struct_field_val, i| {
17580 const anon_struct_type = ip.indexToKey(ty.toIntern()).anon_struct_type;17583 const anon_struct_type = ip.indexToKey(ty.toIntern()).anon_struct_type;
17581 const field_ty = anon_struct_type.types[i];17584 const field_ty = anon_struct_type.types.get(ip)[i];
17582 const field_val = anon_struct_type.values[i];17585 const field_val = anon_struct_type.values.get(ip)[i];
17583 const name_val = v: {17586 const name_val = v: {
17584 var anon_decl = try block.startAnonDecl();17587 var anon_decl = try block.startAnonDecl();
17585 defer anon_decl.deinit();17588 defer anon_decl.deinit();
17586 // TODO: write something like getCoercedInts to avoid needing to dupe17589 // TODO: write something like getCoercedInts to avoid needing to dupe
17587 const bytes = if (tuple.names.len != 0)17590 const bytes = if (tuple.names.len != 0)
17588 // https://github.com/ziglang/zig/issues/1570917591 // https://github.com/ziglang/zig/issues/15709
17589 try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).anon_struct_type.names[i]))17592 try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).anon_struct_type.names.get(ip)[i]))
17590 else17593 else
17591 try std.fmt.allocPrint(sema.arena, "{d}", .{i});17594 try std.fmt.allocPrint(sema.arena, "{d}", .{i});
17592 const new_decl_ty = try mod.arrayType(.{17595 const new_decl_ty = try mod.arrayType(.{
...@@ -19254,7 +19257,7 @@ fn finishStructInit(...@@ -19254,7 +19257,7 @@ fn finishStructInit(
1925419257
19255 switch (ip.indexToKey(struct_ty.toIntern())) {19258 switch (ip.indexToKey(struct_ty.toIntern())) {
19256 .anon_struct_type => |anon_struct| {19259 .anon_struct_type => |anon_struct| {
19257 for (anon_struct.values, 0..) |default_val, i| {19260 for (anon_struct.values.get(ip), 0..) |default_val, i| {
19258 if (field_inits[i] != .none) continue;19261 if (field_inits[i] != .none) continue;
1925919262
19260 if (default_val == .none) {19263 if (default_val == .none) {
...@@ -19266,7 +19269,7 @@ fn finishStructInit(...@@ -19266,7 +19269,7 @@ fn finishStructInit(
19266 root_msg = try sema.errMsg(block, init_src, template, .{i});19269 root_msg = try sema.errMsg(block, init_src, template, .{i});
19267 }19270 }
19268 } else {19271 } else {
19269 const field_name = anon_struct.names[i];19272 const field_name = anon_struct.names.get(ip)[i];
19270 const template = "missing struct field: {}";19273 const template = "missing struct field: {}";
19271 const args = .{field_name.fmt(ip)};19274 const args = .{field_name.fmt(ip)};
19272 if (root_msg) |msg| {19275 if (root_msg) |msg| {
...@@ -19395,6 +19398,7 @@ fn structInitAnon(...@@ -19395,6 +19398,7 @@ fn structInitAnon(
19395) CompileError!Air.Inst.Ref {19398) CompileError!Air.Inst.Ref {
19396 const mod = sema.mod;19399 const mod = sema.mod;
19397 const gpa = sema.gpa;19400 const gpa = sema.gpa;
19401 const ip = &mod.intern_pool;
19398 const zir_datas = sema.code.instructions.items(.data);19402 const zir_datas = sema.code.instructions.items(.data);
1939919403
19400 const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len);19404 const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len);
...@@ -19465,11 +19469,11 @@ fn structInitAnon(...@@ -19465,11 +19469,11 @@ fn structInitAnon(
19465 break :rs runtime_index;19469 break :rs runtime_index;
19466 };19470 };
1946719471
19468 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{19472 const tuple_ty = try ip.getAnonStructType(gpa, .{
19469 .names = fields.keys(),19473 .names = fields.keys(),
19470 .types = types,19474 .types = types,
19471 .values = values,19475 .values = values,
19472 } });19476 });
1947319477
19474 const runtime_index = opt_runtime_index orelse {19478 const runtime_index = opt_runtime_index orelse {
19475 const tuple_val = try mod.intern(.{ .aggregate = .{19479 const tuple_val = try mod.intern(.{ .aggregate = .{
...@@ -19688,6 +19692,8 @@ fn arrayInitAnon(...@@ -19688,6 +19692,8 @@ fn arrayInitAnon(
19688 is_ref: bool,19692 is_ref: bool,
19689) CompileError!Air.Inst.Ref {19693) CompileError!Air.Inst.Ref {
19690 const mod = sema.mod;19694 const mod = sema.mod;
19695 const gpa = sema.gpa;
19696 const ip = &mod.intern_pool;
1969119697
19692 const types = try sema.arena.alloc(InternPool.Index, operands.len);19698 const types = try sema.arena.alloc(InternPool.Index, operands.len);
19693 const values = try sema.arena.alloc(InternPool.Index, operands.len);19699 const values = try sema.arena.alloc(InternPool.Index, operands.len);
...@@ -19701,7 +19707,7 @@ fn arrayInitAnon(...@@ -19701,7 +19707,7 @@ fn arrayInitAnon(
19701 if (types[i].toType().zigTypeTag(mod) == .Opaque) {19707 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
19702 const msg = msg: {19708 const msg = msg: {
19703 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});19709 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
19704 errdefer msg.destroy(sema.gpa);19710 errdefer msg.destroy(gpa);
1970519711
19706 try sema.addDeclaredHereNote(msg, types[i].toType());19712 try sema.addDeclaredHereNote(msg, types[i].toType());
19707 break :msg msg;19713 break :msg msg;
...@@ -19718,11 +19724,11 @@ fn arrayInitAnon(...@@ -19718,11 +19724,11 @@ fn arrayInitAnon(
19718 break :rs runtime_src;19724 break :rs runtime_src;
19719 };19725 };
1972019726
19721 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{19727 const tuple_ty = try ip.getAnonStructType(gpa, .{
19722 .types = types,19728 .types = types,
19723 .values = values,19729 .values = values,
19724 .names = &.{},19730 .names = &.{},
19725 } });19731 });
1972619732
19727 const runtime_src = opt_runtime_src orelse {19733 const runtime_src = opt_runtime_src orelse {
19728 const tuple_val = try mod.intern(.{ .aggregate = .{19734 const tuple_val = try mod.intern(.{ .aggregate = .{
...@@ -19832,7 +19838,7 @@ fn fieldType(...@@ -19832,7 +19838,7 @@ fn fieldType(
19832 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {19838 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {
19833 .anon_struct_type => |anon_struct| {19839 .anon_struct_type => |anon_struct| {
19834 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);19840 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
19835 return Air.internedToRef(anon_struct.types[field_index]);19841 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);
19836 },19842 },
19837 .struct_type => |struct_type| {19843 .struct_type => |struct_type| {
19838 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;19844 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
...@@ -30574,13 +30580,14 @@ fn coerceAnonStructToUnion(...@@ -30574,13 +30580,14 @@ fn coerceAnonStructToUnion(
30574 inst_src: LazySrcLoc,30580 inst_src: LazySrcLoc,
30575) !Air.Inst.Ref {30581) !Air.Inst.Ref {
30576 const mod = sema.mod;30582 const mod = sema.mod;
30583 const ip = &mod.intern_pool;
30577 const inst_ty = sema.typeOf(inst);30584 const inst_ty = sema.typeOf(inst);
30578 const field_info: union(enum) {30585 const field_info: union(enum) {
30579 name: InternPool.NullTerminatedString,30586 name: InternPool.NullTerminatedString,
30580 count: usize,30587 count: usize,
30581 } = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {30588 } = switch (ip.indexToKey(inst_ty.toIntern())) {
30582 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)30589 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
30583 .{ .name = anon_struct_type.names[0] }30590 .{ .name = anon_struct_type.names.get(ip)[0] }
30584 else30591 else
30585 .{ .count = anon_struct_type.names.len },30592 .{ .count = anon_struct_type.names.len },
30586 .struct_type => |struct_type| name: {30593 .struct_type => |struct_type| name: {
...@@ -30876,7 +30883,7 @@ fn coerceTupleToStruct(...@@ -30876,7 +30883,7 @@ fn coerceTupleToStruct(
30876 // https://github.com/ziglang/zig/issues/1570930883 // https://github.com/ziglang/zig/issues/15709
30877 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {30884 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
30878 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)30885 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
30879 anon_struct_type.names[field_i]30886 anon_struct_type.names.get(ip)[field_i]
30880 else30887 else
30881 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),30888 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
30882 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],30889 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
...@@ -30994,7 +31001,7 @@ fn coerceTupleToTuple(...@@ -30994,7 +31001,7 @@ fn coerceTupleToTuple(
30994 // https://github.com/ziglang/zig/issues/1570931001 // https://github.com/ziglang/zig/issues/15709
30995 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {31002 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
30996 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)31003 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
30997 anon_struct_type.names[field_i]31004 anon_struct_type.names.get(ip)[field_i]
30998 else31005 else
30999 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),31006 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
31000 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],31007 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
...@@ -31005,12 +31012,12 @@ fn coerceTupleToTuple(...@@ -31005,12 +31012,12 @@ fn coerceTupleToTuple(
31005 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});31012 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
3100631013
31007 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {31014 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
31008 .anon_struct_type => |anon_struct_type| anon_struct_type.types[field_index_usize].toType(),31015 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[field_index_usize].toType(),
31009 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].ty,31016 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].ty,
31010 else => unreachable,31017 else => unreachable,
31011 };31018 };
31012 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {31019 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
31013 .anon_struct_type => |anon_struct_type| anon_struct_type.values[field_index_usize],31020 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize],
31014 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].default_val,31021 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].default_val,
31015 else => unreachable,31022 else => unreachable,
31016 };31023 };
...@@ -31048,7 +31055,7 @@ fn coerceTupleToTuple(...@@ -31048,7 +31055,7 @@ fn coerceTupleToTuple(
31048 if (field_ref.* != .none) continue;31055 if (field_ref.* != .none) continue;
3104931056
31050 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {31057 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
31051 .anon_struct_type => |anon_struct_type| anon_struct_type.values[i],31058 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i],
31052 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].default_val,31059 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].default_val,
31053 else => unreachable,31060 else => unreachable,
31054 };31061 };
...@@ -32855,6 +32862,7 @@ fn resolvePeerTypesInner(...@@ -32855,6 +32862,7 @@ fn resolvePeerTypesInner(
32855 peer_vals: []?Value,32862 peer_vals: []?Value,
32856) !PeerResolveResult {32863) !PeerResolveResult {
32857 const mod = sema.mod;32864 const mod = sema.mod;
32865 const ip = &mod.intern_pool;
3285832866
32859 var strat_reason: usize = 0;32867 var strat_reason: usize = 0;
32860 var s: PeerResolveStrategy = .unknown;32868 var s: PeerResolveStrategy = .unknown;
...@@ -32912,7 +32920,7 @@ fn resolvePeerTypesInner(...@@ -32912,7 +32920,7 @@ fn resolvePeerTypesInner(
32912 .ErrorUnion => blk: {32920 .ErrorUnion => blk: {
32913 const set_ty = ty.errorUnionSet(mod);32921 const set_ty = ty.errorUnionSet(mod);
32914 ty_ptr.* = ty.errorUnionPayload(mod);32922 ty_ptr.* = ty.errorUnionPayload(mod);
32915 if (val_ptr.*) |eu_val| switch (mod.intern_pool.indexToKey(eu_val.toIntern())) {32923 if (val_ptr.*) |eu_val| switch (ip.indexToKey(eu_val.toIntern())) {
32916 .error_union => |eu| switch (eu.val) {32924 .error_union => |eu| switch (eu.val) {
32917 .payload => |payload_ip| val_ptr.* = payload_ip.toValue(),32925 .payload => |payload_ip| val_ptr.* = payload_ip.toValue(),
32918 .err_name => val_ptr.* = null,32926 .err_name => val_ptr.* = null,
...@@ -33166,8 +33174,8 @@ fn resolvePeerTypesInner(...@@ -33166,8 +33174,8 @@ fn resolvePeerTypesInner(
33166 }).toIntern();33174 }).toIntern();
3316733175
33168 if (ptr_info.sentinel != .none and peer_info.sentinel != .none) {33176 if (ptr_info.sentinel != .none and peer_info.sentinel != .none) {
33169 const peer_sent = try mod.intern_pool.getCoerced(sema.gpa, ptr_info.sentinel, ptr_info.child);33177 const peer_sent = try ip.getCoerced(sema.gpa, ptr_info.sentinel, ptr_info.child);
33170 const ptr_sent = try mod.intern_pool.getCoerced(sema.gpa, peer_info.sentinel, ptr_info.child);33178 const ptr_sent = try ip.getCoerced(sema.gpa, peer_info.sentinel, ptr_info.child);
33171 if (ptr_sent == peer_sent) {33179 if (ptr_sent == peer_sent) {
33172 ptr_info.sentinel = ptr_sent;33180 ptr_info.sentinel = ptr_sent;
33173 } else {33181 } else {
...@@ -33278,7 +33286,7 @@ fn resolvePeerTypesInner(...@@ -33278,7 +33286,7 @@ fn resolvePeerTypesInner(
33278 ptr_info.flags.is_volatile = ptr_info.flags.is_volatile or peer_info.flags.is_volatile;33286 ptr_info.flags.is_volatile = ptr_info.flags.is_volatile or peer_info.flags.is_volatile;
3327933287
33280 const peer_sentinel: InternPool.Index = switch (peer_info.flags.size) {33288 const peer_sentinel: InternPool.Index = switch (peer_info.flags.size) {
33281 .One => switch (mod.intern_pool.indexToKey(peer_info.child)) {33289 .One => switch (ip.indexToKey(peer_info.child)) {
33282 .array_type => |array_type| array_type.sentinel,33290 .array_type => |array_type| array_type.sentinel,
33283 else => .none,33291 else => .none,
33284 },33292 },
...@@ -33287,7 +33295,7 @@ fn resolvePeerTypesInner(...@@ -33287,7 +33295,7 @@ fn resolvePeerTypesInner(
33287 };33295 };
3328833296
33289 const cur_sentinel: InternPool.Index = switch (ptr_info.flags.size) {33297 const cur_sentinel: InternPool.Index = switch (ptr_info.flags.size) {
33290 .One => switch (mod.intern_pool.indexToKey(ptr_info.child)) {33298 .One => switch (ip.indexToKey(ptr_info.child)) {
33291 .array_type => |array_type| array_type.sentinel,33299 .array_type => |array_type| array_type.sentinel,
33292 else => .none,33300 else => .none,
33293 },33301 },
...@@ -33449,7 +33457,7 @@ fn resolvePeerTypesInner(...@@ -33449,7 +33457,7 @@ fn resolvePeerTypesInner(
33449 }33457 }
3345033458
33451 const sentinel_ty = switch (ptr_info.flags.size) {33459 const sentinel_ty = switch (ptr_info.flags.size) {
33452 .One => switch (mod.intern_pool.indexToKey(ptr_info.child)) {33460 .One => switch (ip.indexToKey(ptr_info.child)) {
33453 .array_type => |array_type| array_type.child,33461 .array_type => |array_type| array_type.child,
33454 else => ptr_info.child,33462 else => ptr_info.child,
33455 },33463 },
...@@ -33460,11 +33468,11 @@ fn resolvePeerTypesInner(...@@ -33460,11 +33468,11 @@ fn resolvePeerTypesInner(
33460 no_sentinel: {33468 no_sentinel: {
33461 if (peer_sentinel == .none) break :no_sentinel;33469 if (peer_sentinel == .none) break :no_sentinel;
33462 if (cur_sentinel == .none) break :no_sentinel;33470 if (cur_sentinel == .none) break :no_sentinel;
33463 const peer_sent_coerced = try mod.intern_pool.getCoerced(sema.gpa, peer_sentinel, sentinel_ty);33471 const peer_sent_coerced = try ip.getCoerced(sema.gpa, peer_sentinel, sentinel_ty);
33464 const cur_sent_coerced = try mod.intern_pool.getCoerced(sema.gpa, cur_sentinel, sentinel_ty);33472 const cur_sent_coerced = try ip.getCoerced(sema.gpa, cur_sentinel, sentinel_ty);
33465 if (peer_sent_coerced != cur_sent_coerced) break :no_sentinel;33473 if (peer_sent_coerced != cur_sent_coerced) break :no_sentinel;
33466 // Sentinels match33474 // Sentinels match
33467 if (ptr_info.flags.size == .One) switch (mod.intern_pool.indexToKey(ptr_info.child)) {33475 if (ptr_info.flags.size == .One) switch (ip.indexToKey(ptr_info.child)) {
33468 .array_type => |array_type| ptr_info.child = (try mod.arrayType(.{33476 .array_type => |array_type| ptr_info.child = (try mod.arrayType(.{
33469 .len = array_type.len,33477 .len = array_type.len,
33470 .child = array_type.child,33478 .child = array_type.child,
...@@ -33478,7 +33486,7 @@ fn resolvePeerTypesInner(...@@ -33478,7 +33486,7 @@ fn resolvePeerTypesInner(
33478 }33486 }
33479 // Clear existing sentinel33487 // Clear existing sentinel
33480 ptr_info.sentinel = .none;33488 ptr_info.sentinel = .none;
33481 switch (mod.intern_pool.indexToKey(ptr_info.child)) {33489 switch (ip.indexToKey(ptr_info.child)) {
33482 .array_type => |array_type| ptr_info.child = (try mod.arrayType(.{33490 .array_type => |array_type| ptr_info.child = (try mod.arrayType(.{
33483 .len = array_type.len,33491 .len = array_type.len,
33484 .child = array_type.child,33492 .child = array_type.child,
...@@ -33501,7 +33509,7 @@ fn resolvePeerTypesInner(...@@ -33501,7 +33509,7 @@ fn resolvePeerTypesInner(
33501 .peer_idx_a = first_idx,33509 .peer_idx_a = first_idx,
33502 .peer_idx_b = other_idx,33510 .peer_idx_b = other_idx,
33503 } },33511 } },
33504 else => switch (mod.intern_pool.indexToKey(pointee)) {33512 else => switch (ip.indexToKey(pointee)) {
33505 .array_type => |array_type| if (array_type.child == .noreturn_type) return .{ .conflict = .{33513 .array_type => |array_type| if (array_type.child == .noreturn_type) return .{ .conflict = .{
33506 .peer_idx_a = first_idx,33514 .peer_idx_a = first_idx,
33507 .peer_idx_b = other_idx,33515 .peer_idx_b = other_idx,
...@@ -33785,7 +33793,7 @@ fn resolvePeerTypesInner(...@@ -33785,7 +33793,7 @@ fn resolvePeerTypesInner(
33785 is_tuple = ty.isTuple(mod);33793 is_tuple = ty.isTuple(mod);
33786 field_count = ty.structFieldCount(mod);33794 field_count = ty.structFieldCount(mod);
33787 if (!is_tuple) {33795 if (!is_tuple) {
33788 const names = mod.intern_pool.indexToKey(ty.toIntern()).anon_struct_type.names;33796 const names = ip.indexToKey(ty.toIntern()).anon_struct_type.names.get(ip);
33789 field_names = try sema.arena.dupe(InternPool.NullTerminatedString, names);33797 field_names = try sema.arena.dupe(InternPool.NullTerminatedString, names);
33790 }33798 }
33791 continue;33799 continue;
...@@ -33839,7 +33847,7 @@ fn resolvePeerTypesInner(...@@ -33839,7 +33847,7 @@ fn resolvePeerTypesInner(
33839 result_buf.* = result;33847 result_buf.* = result;
33840 const field_name = if (is_tuple) name: {33848 const field_name = if (is_tuple) name: {
33841 break :name try std.fmt.allocPrint(sema.arena, "{d}", .{field_idx});33849 break :name try std.fmt.allocPrint(sema.arena, "{d}", .{field_idx});
33842 } else try sema.arena.dupe(u8, mod.intern_pool.stringToSlice(field_names[field_idx]));33850 } else try sema.arena.dupe(u8, ip.stringToSlice(field_names[field_idx]));
3384333851
33844 // The error info needs the field types, but we can't reuse sub_peer_tys33852 // The error info needs the field types, but we can't reuse sub_peer_tys
33845 // since the recursive call may have clobbered it.33853 // since the recursive call may have clobbered it.
...@@ -33892,11 +33900,11 @@ fn resolvePeerTypesInner(...@@ -33892,11 +33900,11 @@ fn resolvePeerTypesInner(
33892 field_val.* = if (comptime_val) |v| v.toIntern() else .none;33900 field_val.* = if (comptime_val) |v| v.toIntern() else .none;
33893 }33901 }
3389433902
33895 const final_ty = try mod.intern(.{ .anon_struct_type = .{33903 const final_ty = try ip.getAnonStructType(mod.gpa, .{
33896 .types = field_types,33904 .types = field_types,
33897 .names = if (is_tuple) &.{} else field_names,33905 .names = if (is_tuple) &.{} else field_names,
33898 .values = field_vals,33906 .values = field_vals,
33899 } });33907 });
3390033908
33901 return .{ .success = final_ty.toType() };33909 return .{ .success = final_ty.toType() };
33902 },33910 },
...@@ -34491,6 +34499,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -34491,6 +34499,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
34491/// be resolved.34499/// be resolved.
34492pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {34500pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
34493 const mod = sema.mod;34501 const mod = sema.mod;
34502 const ip = &mod.intern_pool;
34494 switch (ty.zigTypeTag(mod)) {34503 switch (ty.zigTypeTag(mod)) {
34495 .Pointer => {34504 .Pointer => {
34496 return sema.resolveTypeFully(ty.childType(mod));34505 return sema.resolveTypeFully(ty.childType(mod));
...@@ -34498,7 +34507,7 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -34498,7 +34507,7 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
34498 .Struct => switch (mod.intern_pool.indexToKey(ty.toIntern())) {34507 .Struct => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
34499 .struct_type => return sema.resolveStructFully(ty),34508 .struct_type => return sema.resolveStructFully(ty),
34500 .anon_struct_type => |tuple| {34509 .anon_struct_type => |tuple| {
34501 for (tuple.types) |field_ty| {34510 for (tuple.types.get(ip)) |field_ty| {
34502 try sema.resolveTypeFully(field_ty.toType());34511 try sema.resolveTypeFully(field_ty.toType());
34503 }34512 }
34504 },34513 },
...@@ -34518,7 +34527,6 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -34518,7 +34527,6 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
34518 // the function is instantiated.34527 // the function is instantiated.
34519 return;34528 return;
34520 }34529 }
34521 const ip = &mod.intern_pool;
34522 for (0..info.param_types.len) |i| {34530 for (0..info.param_types.len) |i| {
34523 const param_ty = info.param_types.get(ip)[i];34531 const param_ty = info.param_types.get(ip)[i];
34524 try sema.resolveTypeFully(param_ty.toType());34532 try sema.resolveTypeFully(param_ty.toType());
...@@ -36133,7 +36141,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36133,7 +36141,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36133 },36141 },
3613436142
36135 .anon_struct_type => |tuple| {36143 .anon_struct_type => |tuple| {
36136 for (tuple.values) |val| {36144 for (tuple.values.get(ip)) |val| {
36137 if (val == .none) return null;36145 if (val == .none) return null;
36138 }36146 }
36139 // In this case the struct has all comptime-known fields and36147 // In this case the struct has all comptime-known fields and
...@@ -36141,7 +36149,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36141,7 +36149,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36141 // TODO: write something like getCoercedInts to avoid needing to dupe36149 // TODO: write something like getCoercedInts to avoid needing to dupe
36142 return (try mod.intern(.{ .aggregate = .{36150 return (try mod.intern(.{ .aggregate = .{
36143 .ty = ty.toIntern(),36151 .ty = ty.toIntern(),
36144 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },36152 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values.get(ip)) },
36145 } })).toValue();36153 } })).toValue();
36146 },36154 },
3614736155
...@@ -36611,7 +36619,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -36611,7 +36619,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
36611 }36619 }
36612 },36620 },
36613 .anon_struct_type => |tuple| {36621 .anon_struct_type => |tuple| {
36614 for (tuple.types, tuple.values) |field_ty, val| {36622 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
36615 const have_comptime_val = val != .none;36623 const have_comptime_val = val != .none;
36616 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty.toType())) {36624 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty.toType())) {
36617 return true;36625 return true;
...@@ -36784,8 +36792,9 @@ fn anonStructFieldIndex(...@@ -36784,8 +36792,9 @@ fn anonStructFieldIndex(
36784 field_src: LazySrcLoc,36792 field_src: LazySrcLoc,
36785) !u32 {36793) !u32 {
36786 const mod = sema.mod;36794 const mod = sema.mod;
36787 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {36795 const ip = &mod.intern_pool;
36788 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names, 0..) |name, i| {36796 switch (ip.indexToKey(struct_ty.toIntern())) {
36797 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| {
36789 if (name == field_name) return @intCast(i);36798 if (name == field_name) return @intCast(i);
36790 },36799 },
36791 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {36800 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
...@@ -36798,7 +36807,7 @@ fn anonStructFieldIndex(...@@ -36798,7 +36807,7 @@ fn anonStructFieldIndex(
36798 else => unreachable,36807 else => unreachable,
36799 }36808 }
36800 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{36809 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{
36801 field_name.fmt(&mod.intern_pool), struct_ty.fmt(sema.mod),36810 field_name.fmt(ip), struct_ty.fmt(sema.mod),
36802 });36811 });
36803}36812}
3680436813
src/TypedValue.zig+4-3
...@@ -423,6 +423,7 @@ fn printAggregate(...@@ -423,6 +423,7 @@ fn printAggregate(
423 if (level == 0) {423 if (level == 0) {
424 return writer.writeAll(".{ ... }");424 return writer.writeAll(".{ ... }");
425 }425 }
426 const ip = &mod.intern_pool;
426 if (ty.zigTypeTag(mod) == .Struct) {427 if (ty.zigTypeTag(mod) == .Struct) {
427 try writer.writeAll(".{");428 try writer.writeAll(".{");
428 const max_len = @min(ty.structFieldCount(mod), max_aggregate_items);429 const max_len = @min(ty.structFieldCount(mod), max_aggregate_items);
...@@ -430,13 +431,13 @@ fn printAggregate(...@@ -430,13 +431,13 @@ fn printAggregate(
430 for (0..max_len) |i| {431 for (0..max_len) |i| {
431 if (i != 0) try writer.writeAll(", ");432 if (i != 0) try writer.writeAll(", ");
432433
433 const field_name = switch (mod.intern_pool.indexToKey(ty.toIntern())) {434 const field_name = switch (ip.indexToKey(ty.toIntern())) {
434 .struct_type => |x| mod.structPtrUnwrap(x.index).?.fields.keys()[i].toOptional(),435 .struct_type => |x| mod.structPtrUnwrap(x.index).?.fields.keys()[i].toOptional(),
435 .anon_struct_type => |x| if (x.isTuple()) .none else x.names[i].toOptional(),436 .anon_struct_type => |x| if (x.isTuple()) .none else x.names.get(ip)[i].toOptional(),
436 else => unreachable,437 else => unreachable,
437 };438 };
438439
439 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(&mod.intern_pool)});440 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)});
440 try print(.{441 try print(.{
441 .ty = ty.structFieldType(i, mod),442 .ty = ty.structFieldType(i, mod),
442 .val = try val.fieldValue(mod, i),443 .val = try val.fieldValue(mod, i),
src/codegen.zig+5-1
...@@ -438,7 +438,11 @@ pub fn generateSymbol(...@@ -438,7 +438,11 @@ pub fn generateSymbol(
438 },438 },
439 .anon_struct_type => |tuple| {439 .anon_struct_type => |tuple| {
440 const struct_begin = code.items.len;440 const struct_begin = code.items.len;
441 for (tuple.types, tuple.values, 0..) |field_ty, comptime_val, index| {441 for (
442 tuple.types.get(ip),
443 tuple.values.get(ip),
444 0..,
445 ) |field_ty, comptime_val, index| {
442 if (comptime_val != .none) continue;446 if (comptime_val != .none) continue;
443 if (!field_ty.toType().hasRuntimeBits(mod)) continue;447 if (!field_ty.toType().hasRuntimeBits(mod)) continue;
444448
src/codegen/c.zig+10-4
...@@ -1275,7 +1275,11 @@ pub const DeclGen = struct {...@@ -1275,7 +1275,11 @@ pub const DeclGen = struct {
12751275
1276 try writer.writeByte('{');1276 try writer.writeByte('{');
1277 var empty = true;1277 var empty = true;
1278 for (tuple.types, tuple.values, 0..) |field_ty, comptime_ty, field_i| {1278 for (
1279 tuple.types.get(ip),
1280 tuple.values.get(ip),
1281 0..,
1282 ) |field_ty, comptime_ty, field_i| {
1279 if (comptime_ty != .none) continue;1283 if (comptime_ty != .none) continue;
1280 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;1284 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
12811285
...@@ -7745,16 +7749,18 @@ fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {...@@ -7745,16 +7749,18 @@ fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
7745 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;7749 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
77467750
7747 if (lowersToArray(ret_ty, mod)) {7751 if (lowersToArray(ret_ty, mod)) {
7752 const gpa = mod.gpa;
7753 const ip = &mod.intern_pool;
7748 const names = [1]InternPool.NullTerminatedString{7754 const names = [1]InternPool.NullTerminatedString{
7749 try mod.intern_pool.getOrPutString(mod.gpa, "array"),7755 try ip.getOrPutString(gpa, "array"),
7750 };7756 };
7751 const types = [1]InternPool.Index{ret_ty.ip_index};7757 const types = [1]InternPool.Index{ret_ty.ip_index};
7752 const values = [1]InternPool.Index{.none};7758 const values = [1]InternPool.Index{.none};
7753 const interned = try mod.intern(.{ .anon_struct_type = .{7759 const interned = try ip.getAnonStructType(gpa, .{
7754 .names = &names,7760 .names = &names,
7755 .types = &types,7761 .types = &types,
7756 .values = &values,7762 .values = &values,
7757 } });7763 });
7758 return interned.toType();7764 return interned.toType();
7759 }7765 }
77607766
src/codegen/llvm.zig+17-8
...@@ -2392,7 +2392,7 @@ pub const Object = struct {...@@ -2392,7 +2392,7 @@ pub const Object = struct {
2392 comptime assert(struct_layout_version == 2);2392 comptime assert(struct_layout_version == 2);
2393 var offset: u64 = 0;2393 var offset: u64 = 0;
23942394
2395 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {2395 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
2396 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;2396 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
23972397
2398 const field_size = field_ty.toType().abiSize(mod);2398 const field_size = field_ty.toType().abiSize(mod);
...@@ -2401,7 +2401,7 @@ pub const Object = struct {...@@ -2401,7 +2401,7 @@ pub const Object = struct {
2401 offset = field_offset + field_size;2401 offset = field_offset + field_size;
24022402
2403 const field_name = if (tuple.names.len != 0)2403 const field_name = if (tuple.names.len != 0)
2404 ip.stringToSlice(tuple.names[i])2404 ip.stringToSlice(tuple.names.get(ip)[i])
2405 else2405 else
2406 try std.fmt.allocPrintZ(gpa, "{d}", .{i});2406 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2407 defer if (tuple.names.len == 0) gpa.free(field_name);2407 defer if (tuple.names.len == 0) gpa.free(field_name);
...@@ -3325,7 +3325,10 @@ pub const Object = struct {...@@ -3325,7 +3325,10 @@ pub const Object = struct {
3325 var offset: u64 = 0;3325 var offset: u64 = 0;
3326 var big_align: u32 = 0;3326 var big_align: u32 = 0;
33273327
3328 for (anon_struct_type.types, anon_struct_type.values) |field_ty, field_val| {3328 for (
3329 anon_struct_type.types.get(ip),
3330 anon_struct_type.values.get(ip),
3331 ) |field_ty, field_val| {
3329 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;3332 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
33303333
3331 const field_align = field_ty.toType().abiAlignment(mod);3334 const field_align = field_ty.toType().abiAlignment(mod);
...@@ -3874,7 +3877,11 @@ pub const Object = struct {...@@ -3874,7 +3877,11 @@ pub const Object = struct {
3874 var offset: u64 = 0;3877 var offset: u64 = 0;
3875 var big_align: u32 = 0;3878 var big_align: u32 = 0;
3876 var need_unnamed = false;3879 var need_unnamed = false;
3877 for (tuple.types, tuple.values, 0..) |field_ty, field_val, field_index| {3880 for (
3881 tuple.types.get(ip),
3882 tuple.values.get(ip),
3883 0..,
3884 ) |field_ty, field_val, field_index| {
3878 if (field_val != .none) continue;3885 if (field_val != .none) continue;
3879 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;3886 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
38803887
...@@ -10537,10 +10544,11 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {...@@ -10537,10 +10544,11 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
10537 var offset: u64 = 0;10544 var offset: u64 = 0;
10538 var big_align: u32 = 0;10545 var big_align: u32 = 0;
1053910546
10540 const struct_type = switch (mod.intern_pool.indexToKey(ty.toIntern())) {10547 const ip = &mod.intern_pool;
10548 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
10541 .anon_struct_type => |tuple| {10549 .anon_struct_type => |tuple| {
10542 var llvm_field_index: c_uint = 0;10550 var llvm_field_index: c_uint = 0;
10543 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {10551 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
10544 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;10552 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1054510553
10546 const field_align = field_ty.toType().abiAlignment(mod);10554 const field_align = field_ty.toType().abiAlignment(mod);
...@@ -11118,6 +11126,7 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11118,6 +11126,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
11118 // For tuples and structs, if there are more than this many non-void11126 // For tuples and structs, if there are more than this many non-void
11119 // fields, then we make it byref, otherwise byval.11127 // fields, then we make it byref, otherwise byval.
11120 const max_fields_byval = 0;11128 const max_fields_byval = 0;
11129 const ip = &mod.intern_pool;
1112111130
11122 switch (ty.zigTypeTag(mod)) {11131 switch (ty.zigTypeTag(mod)) {
11123 .Type,11132 .Type,
...@@ -11146,10 +11155,10 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11146,10 +11155,10 @@ fn isByRef(ty: Type, mod: *Module) bool {
11146 .Struct => {11155 .Struct => {
11147 // Packed structs are represented to LLVM as integers.11156 // Packed structs are represented to LLVM as integers.
11148 if (ty.containerLayout(mod) == .Packed) return false;11157 if (ty.containerLayout(mod) == .Packed) return false;
11149 const struct_type = switch (mod.intern_pool.indexToKey(ty.toIntern())) {11158 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
11150 .anon_struct_type => |tuple| {11159 .anon_struct_type => |tuple| {
11151 var count: usize = 0;11160 var count: usize = 0;
11152 for (tuple.types, tuple.values) |field_ty, field_val| {11161 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {
11153 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;11162 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1115411163
11155 count += 1;11164 count += 1;
src/codegen/spirv.zig+5-5
...@@ -1227,6 +1227,7 @@ pub const DeclGen = struct {...@@ -1227,6 +1227,7 @@ pub const DeclGen = struct {
1227 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.1227 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
1228 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {1228 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {
1229 const mod = self.module;1229 const mod = self.module;
1230 const ip = &mod.intern_pool;
1230 log.debug("resolveType: ty = {}", .{ty.fmt(self.module)});1231 log.debug("resolveType: ty = {}", .{ty.fmt(self.module)});
1231 const target = self.getTarget();1232 const target = self.getTarget();
1232 switch (ty.zigTypeTag(mod)) {1233 switch (ty.zigTypeTag(mod)) {
...@@ -1271,7 +1272,6 @@ pub const DeclGen = struct {...@@ -1271,7 +1272,6 @@ pub const DeclGen = struct {
1271 },1272 },
1272 .Fn => switch (repr) {1273 .Fn => switch (repr) {
1273 .direct => {1274 .direct => {
1274 const ip = &mod.intern_pool;
1275 const fn_info = mod.typeToFunc(ty).?;1275 const fn_info = mod.typeToFunc(ty).?;
1276 // TODO: Put this somewhere in Sema.zig1276 // TODO: Put this somewhere in Sema.zig
1277 if (fn_info.is_var_args)1277 if (fn_info.is_var_args)
...@@ -1333,13 +1333,13 @@ pub const DeclGen = struct {...@@ -1333,13 +1333,13 @@ pub const DeclGen = struct {
1333 } });1333 } });
1334 },1334 },
1335 .Struct => {1335 .Struct => {
1336 const struct_ty = switch (mod.intern_pool.indexToKey(ty.toIntern())) {1336 const struct_ty = switch (ip.indexToKey(ty.toIntern())) {
1337 .anon_struct_type => |tuple| {1337 .anon_struct_type => |tuple| {
1338 const member_types = try self.gpa.alloc(CacheRef, tuple.values.len);1338 const member_types = try self.gpa.alloc(CacheRef, tuple.values.len);
1339 defer self.gpa.free(member_types);1339 defer self.gpa.free(member_types);
13401340
1341 var member_index: usize = 0;1341 var member_index: usize = 0;
1342 for (tuple.types, tuple.values) |field_ty, field_val| {1342 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {
1343 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;1343 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
13441344
1345 member_types[member_index] = try self.resolveType(field_ty.toType(), .indirect);1345 member_types[member_index] = try self.resolveType(field_ty.toType(), .indirect);
...@@ -1369,12 +1369,12 @@ pub const DeclGen = struct {...@@ -1369,12 +1369,12 @@ pub const DeclGen = struct {
1369 while (it.next()) |field_and_index| {1369 while (it.next()) |field_and_index| {
1370 const field = field_and_index.field;1370 const field = field_and_index.field;
1371 const index = field_and_index.index;1371 const index = field_and_index.index;
1372 const field_name = mod.intern_pool.stringToSlice(struct_obj.fields.keys()[index]);1372 const field_name = ip.stringToSlice(struct_obj.fields.keys()[index]);
1373 try member_types.append(try self.resolveType(field.ty, .indirect));1373 try member_types.append(try self.resolveType(field.ty, .indirect));
1374 try member_names.append(try self.spv.resolveString(field_name));1374 try member_names.append(try self.spv.resolveString(field_name));
1375 }1375 }
13761376
1377 const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(self.module));1377 const name = ip.stringToSlice(try struct_obj.getFullyQualifiedName(self.module));
13781378
1379 return try self.spv.resolve(.{ .struct_type = .{1379 return try self.spv.resolve(.{ .struct_type = .{
1380 .name = try self.spv.resolveString(name),1380 .name = try self.spv.resolveString(name),
src/link/Dwarf.zig+1-1
...@@ -327,7 +327,7 @@ pub const DeclState = struct {...@@ -327,7 +327,7 @@ pub const DeclState = struct {
327 // DW.AT.name, DW.FORM.string327 // DW.AT.name, DW.FORM.string
328 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});328 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
329329
330 for (fields.types, 0..) |field_ty, field_index| {330 for (fields.types.get(ip), 0..) |field_ty, field_index| {
331 // DW.AT.member331 // DW.AT.member
332 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member));332 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member));
333 // DW.AT.name, DW.FORM.string333 // DW.AT.name, DW.FORM.string
src/type.zig+26-22
...@@ -170,7 +170,8 @@ pub const Type = struct {...@@ -170,7 +170,8 @@ pub const Type = struct {
170170
171 /// Prints a name suitable for `@typeName`.171 /// Prints a name suitable for `@typeName`.
172 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {172 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
173 switch (mod.intern_pool.indexToKey(ty.toIntern())) {173 const ip = &mod.intern_pool;
174 switch (ip.indexToKey(ty.toIntern())) {
174 .int_type => |int_type| {175 .int_type => |int_type| {
175 const sign_char: u8 = switch (int_type.signedness) {176 const sign_char: u8 = switch (int_type.signedness) {
176 .signed => 'i',177 .signed => 'i',
...@@ -257,7 +258,6 @@ pub const Type = struct {...@@ -257,7 +258,6 @@ pub const Type = struct {
257 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");258 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
258 },259 },
259 .error_set_type => |error_set_type| {260 .error_set_type => |error_set_type| {
260 const ip = &mod.intern_pool;
261 const names = error_set_type.names;261 const names = error_set_type.names;
262 try writer.writeAll("error{");262 try writer.writeAll("error{");
263 for (names.get(ip), 0..) |name, i| {263 for (names.get(ip), 0..) |name, i| {
...@@ -330,13 +330,13 @@ pub const Type = struct {...@@ -330,13 +330,13 @@ pub const Type = struct {
330 return writer.writeAll("@TypeOf(.{})");330 return writer.writeAll("@TypeOf(.{})");
331 }331 }
332 try writer.writeAll("struct{");332 try writer.writeAll("struct{");
333 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {333 for (anon_struct.types.get(ip), anon_struct.values.get(ip), 0..) |field_ty, val, i| {
334 if (i != 0) try writer.writeAll(", ");334 if (i != 0) try writer.writeAll(", ");
335 if (val != .none) {335 if (val != .none) {
336 try writer.writeAll("comptime ");336 try writer.writeAll("comptime ");
337 }337 }
338 if (anon_struct.names.len != 0) {338 if (anon_struct.names.len != 0) {
339 try writer.print("{}: ", .{anon_struct.names[i].fmt(&mod.intern_pool)});339 try writer.print("{}: ", .{anon_struct.names.get(ip)[i].fmt(&mod.intern_pool)});
340 }340 }
341341
342 try print(field_ty.toType(), writer, mod);342 try print(field_ty.toType(), writer, mod);
...@@ -587,7 +587,7 @@ pub const Type = struct {...@@ -587,7 +587,7 @@ pub const Type = struct {
587 }587 }
588 },588 },
589 .anon_struct_type => |tuple| {589 .anon_struct_type => |tuple| {
590 for (tuple.types, tuple.values) |field_ty, val| {590 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
591 if (val != .none) continue; // comptime field591 if (val != .none) continue; // comptime field
592 if (try field_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;592 if (try field_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
593 }593 }
...@@ -1055,7 +1055,7 @@ pub const Type = struct {...@@ -1055,7 +1055,7 @@ pub const Type = struct {
1055 },1055 },
1056 .anon_struct_type => |tuple| {1056 .anon_struct_type => |tuple| {
1057 var big_align: u32 = 0;1057 var big_align: u32 = 0;
1058 for (tuple.types, tuple.values) |field_ty, val| {1058 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
1059 if (val != .none) continue; // comptime field1059 if (val != .none) continue; // comptime field
1060 if (!(field_ty.toType().hasRuntimeBits(mod))) continue;1060 if (!(field_ty.toType().hasRuntimeBits(mod))) continue;
10611061
...@@ -2155,7 +2155,7 @@ pub const Type = struct {...@@ -2155,7 +2155,7 @@ pub const Type = struct {
2155 pub fn vectorLen(ty: Type, mod: *const Module) u32 {2155 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
2156 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {2156 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2157 .vector_type => |vector_type| vector_type.len,2157 .vector_type => |vector_type| vector_type.len,
2158 .anon_struct_type => |tuple| @as(u32, @intCast(tuple.types.len)),2158 .anon_struct_type => |tuple| @intCast(tuple.types.len),
2159 else => unreachable,2159 else => unreachable,
2160 };2160 };
2161 }2161 }
...@@ -2536,13 +2536,13 @@ pub const Type = struct {...@@ -2536,13 +2536,13 @@ pub const Type = struct {
2536 },2536 },
25372537
2538 .anon_struct_type => |tuple| {2538 .anon_struct_type => |tuple| {
2539 for (tuple.values) |val| {2539 for (tuple.values.get(ip)) |val| {
2540 if (val == .none) return null;2540 if (val == .none) return null;
2541 }2541 }
2542 // In this case the struct has all comptime-known fields and2542 // In this case the struct has all comptime-known fields and
2543 // therefore has one possible value.2543 // therefore has one possible value.
2544 // TODO: write something like getCoercedInts to avoid needing to dupe2544 // TODO: write something like getCoercedInts to avoid needing to dupe
2545 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values);2545 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values.get(ip));
2546 defer mod.gpa.free(duped_values);2546 defer mod.gpa.free(duped_values);
2547 return (try mod.intern(.{ .aggregate = .{2547 return (try mod.intern(.{ .aggregate = .{
2548 .ty = ty.toIntern(),2548 .ty = ty.toIntern(),
...@@ -2732,7 +2732,7 @@ pub const Type = struct {...@@ -2732,7 +2732,7 @@ pub const Type = struct {
2732 },2732 },
27332733
2734 .anon_struct_type => |tuple| {2734 .anon_struct_type => |tuple| {
2735 for (tuple.types, tuple.values) |field_ty, val| {2735 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
2736 const have_comptime_val = val != .none;2736 const have_comptime_val = val != .none;
2737 if (!have_comptime_val and field_ty.toType().comptimeOnly(mod)) return true;2737 if (!have_comptime_val and field_ty.toType().comptimeOnly(mod)) return true;
2738 }2738 }
...@@ -2996,13 +2996,14 @@ pub const Type = struct {...@@ -2996,13 +2996,14 @@ pub const Type = struct {
2996 }2996 }
29972997
2998 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {2998 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
2999 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {2999 const ip = &mod.intern_pool;
3000 return switch (ip.indexToKey(ty.toIntern())) {
3000 .struct_type => |struct_type| {3001 .struct_type => |struct_type| {
3001 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;3002 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3002 assert(struct_obj.haveFieldTypes());3003 assert(struct_obj.haveFieldTypes());
3003 return struct_obj.fields.keys()[field_index];3004 return struct_obj.fields.keys()[field_index];
3004 },3005 },
3005 .anon_struct_type => |anon_struct| anon_struct.names[field_index],3006 .anon_struct_type => |anon_struct| anon_struct.names.get(ip)[field_index],
3006 else => unreachable,3007 else => unreachable,
3007 };3008 };
3008 }3009 }
...@@ -3032,7 +3033,7 @@ pub const Type = struct {...@@ -3032,7 +3033,7 @@ pub const Type = struct {
3032 const union_obj = ip.loadUnionType(union_type);3033 const union_obj = ip.loadUnionType(union_type);
3033 return union_obj.field_types.get(ip)[index].toType();3034 return union_obj.field_types.get(ip)[index].toType();
3034 },3035 },
3035 .anon_struct_type => |anon_struct| anon_struct.types[index].toType(),3036 .anon_struct_type => |anon_struct| anon_struct.types.get(ip)[index].toType(),
3036 else => unreachable,3037 else => unreachable,
3037 };3038 };
3038 }3039 }
...@@ -3046,7 +3047,7 @@ pub const Type = struct {...@@ -3046,7 +3047,7 @@ pub const Type = struct {
3046 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);3047 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
3047 },3048 },
3048 .anon_struct_type => |anon_struct| {3049 .anon_struct_type => |anon_struct| {
3049 return anon_struct.types[index].toType().abiAlignment(mod);3050 return anon_struct.types.get(ip)[index].toType().abiAlignment(mod);
3050 },3051 },
3051 .union_type => |union_type| {3052 .union_type => |union_type| {
3052 const union_obj = ip.loadUnionType(union_type);3053 const union_obj = ip.loadUnionType(union_type);
...@@ -3057,7 +3058,8 @@ pub const Type = struct {...@@ -3057,7 +3058,8 @@ pub const Type = struct {
3057 }3058 }
30583059
3059 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {3060 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
3060 switch (mod.intern_pool.indexToKey(ty.toIntern())) {3061 const ip = &mod.intern_pool;
3062 switch (ip.indexToKey(ty.toIntern())) {
3061 .struct_type => |struct_type| {3063 .struct_type => |struct_type| {
3062 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;3064 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3063 const val = struct_obj.fields.values()[index].default_val;3065 const val = struct_obj.fields.values()[index].default_val;
...@@ -3066,7 +3068,7 @@ pub const Type = struct {...@@ -3066,7 +3068,7 @@ pub const Type = struct {
3066 return val.toValue();3068 return val.toValue();
3067 },3069 },
3068 .anon_struct_type => |anon_struct| {3070 .anon_struct_type => |anon_struct| {
3069 const val = anon_struct.values[index];3071 const val = anon_struct.values.get(ip)[index];
3070 // TODO: avoid using `unreachable` to indicate this.3072 // TODO: avoid using `unreachable` to indicate this.
3071 if (val == .none) return Value.@"unreachable";3073 if (val == .none) return Value.@"unreachable";
3072 return val.toValue();3074 return val.toValue();
...@@ -3076,7 +3078,8 @@ pub const Type = struct {...@@ -3076,7 +3078,8 @@ pub const Type = struct {
3076 }3078 }
30773079
3078 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {3080 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
3079 switch (mod.intern_pool.indexToKey(ty.toIntern())) {3081 const ip = &mod.intern_pool;
3082 switch (ip.indexToKey(ty.toIntern())) {
3080 .struct_type => |struct_type| {3083 .struct_type => |struct_type| {
3081 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;3084 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3082 const field = struct_obj.fields.values()[index];3085 const field = struct_obj.fields.values()[index];
...@@ -3087,9 +3090,9 @@ pub const Type = struct {...@@ -3087,9 +3090,9 @@ pub const Type = struct {
3087 }3090 }
3088 },3091 },
3089 .anon_struct_type => |tuple| {3092 .anon_struct_type => |tuple| {
3090 const val = tuple.values[index];3093 const val = tuple.values.get(ip)[index];
3091 if (val == .none) {3094 if (val == .none) {
3092 return tuple.types[index].toType().onePossibleValue(mod);3095 return tuple.types.get(ip)[index].toType().onePossibleValue(mod);
3093 } else {3096 } else {
3094 return val.toValue();3097 return val.toValue();
3095 }3098 }
...@@ -3099,14 +3102,15 @@ pub const Type = struct {...@@ -3099,14 +3102,15 @@ pub const Type = struct {
3099 }3102 }
31003103
3101 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {3104 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
3102 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {3105 const ip = &mod.intern_pool;
3106 return switch (ip.indexToKey(ty.toIntern())) {
3103 .struct_type => |struct_type| {3107 .struct_type => |struct_type| {
3104 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;3108 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3105 if (struct_obj.layout == .Packed) return false;3109 if (struct_obj.layout == .Packed) return false;
3106 const field = struct_obj.fields.values()[index];3110 const field = struct_obj.fields.values()[index];
3107 return field.is_comptime;3111 return field.is_comptime;
3108 },3112 },
3109 .anon_struct_type => |anon_struct| anon_struct.values[index] != .none,3113 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,
3110 else => unreachable,3114 else => unreachable,
3111 };3115 };
3112 }3116 }
...@@ -3202,7 +3206,7 @@ pub const Type = struct {...@@ -3202,7 +3206,7 @@ pub const Type = struct {
3202 var offset: u64 = 0;3206 var offset: u64 = 0;
3203 var big_align: u32 = 0;3207 var big_align: u32 = 0;
32043208
3205 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {3209 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
3206 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {3210 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {
3207 // comptime field3211 // comptime field
3208 if (i == index) return offset;3212 if (i == index) return offset;
src/value.zig+4-3
...@@ -268,6 +268,7 @@ pub const Value = struct {...@@ -268,6 +268,7 @@ pub const Value = struct {
268268
269 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {269 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
270 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();270 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
271 const ip = &mod.intern_pool;
271 switch (val.tag()) {272 switch (val.tag()) {
272 .eu_payload => {273 .eu_payload => {
273 const pl = val.castTag(.eu_payload).?.data;274 const pl = val.castTag(.eu_payload).?.data;
...@@ -286,7 +287,7 @@ pub const Value = struct {...@@ -286,7 +287,7 @@ pub const Value = struct {
286 .slice => {287 .slice => {
287 const pl = val.castTag(.slice).?.data;288 const pl = val.castTag(.slice).?.data;
288 const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);289 const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
289 var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;290 var ptr_key = ip.indexToKey(ptr).ptr;
290 assert(ptr_key.len == .none);291 assert(ptr_key.len == .none);
291 ptr_key.ty = ty.toIntern();292 ptr_key.ty = ty.toIntern();
292 ptr_key.len = try pl.len.intern(Type.usize, mod);293 ptr_key.len = try pl.len.intern(Type.usize, mod);
...@@ -311,11 +312,11 @@ pub const Value = struct {...@@ -311,11 +312,11 @@ pub const Value = struct {
311 const old_elems = val.castTag(.aggregate).?.data[0..len];312 const old_elems = val.castTag(.aggregate).?.data[0..len];
312 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);313 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
313 defer mod.gpa.free(new_elems);314 defer mod.gpa.free(new_elems);
314 const ty_key = mod.intern_pool.indexToKey(ty.toIntern());315 const ty_key = ip.indexToKey(ty.toIntern());
315 for (new_elems, old_elems, 0..) |*new_elem, old_elem, field_i|316 for (new_elems, old_elems, 0..) |*new_elem, old_elem, field_i|
316 new_elem.* = try old_elem.intern(switch (ty_key) {317 new_elem.* = try old_elem.intern(switch (ty_key) {
317 .struct_type => ty.structFieldType(field_i, mod),318 .struct_type => ty.structFieldType(field_i, mod),
318 .anon_struct_type => |info| info.types[field_i].toType(),319 .anon_struct_type => |info| info.types.get(ip)[field_i].toType(),
319 inline .array_type, .vector_type => |info| info.child.toType(),320 inline .array_type, .vector_type => |info| info.child.toType(),
320 else => unreachable,321 else => unreachable,
321 }, mod);322 }, mod);