authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-17 14:25:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-17 18:16:03-07:00
log7ef1eb1c27754cb0349fdc10db1f02ff2dddd99b
tree6a76839d8be347648741e17f50d6c70d8313adc3
parent8c1329b222ab620d7388d766e9e558baa502ce93

InternPool: safer enum API

The key changes in this commit are: ```diff - names: []const NullTerminatedString, + names: NullTerminatedString.Slice, - values: []const Index, + values: Index.Slice, ``` Which eliminates the slices from `InternPool.Key.EnumType` and replaces them with structs that contain `start` and `len` indexes. This makes the lifetime of `EnumType` change from expiring with updates to InternPool, to expiring when the InternPool is garbage-collected, which is currently never. This is gearing up for a larger change I started working on locally which moves union types into InternPool. As a bonus, I fixed some unnecessary instances of `@as`.

8 files changed, 176 insertions(+), 142 deletions(-)

src/InternPool.zig+137-110
......@@ -105,7 +105,7 @@ pub const OptionalMapIndex = enum(u32) {
105105
106106 pub fn unwrap(oi: OptionalMapIndex) ?MapIndex {
107107 if (oi == .none) return null;
108 return @as(MapIndex, @enumFromInt(@intFromEnum(oi)));
108 return @enumFromInt(@intFromEnum(oi));
109109 }
110110};
111111
......@@ -114,7 +114,7 @@ pub const MapIndex = enum(u32) {
114114 _,
115115
116116 pub fn toOptional(i: MapIndex) OptionalMapIndex {
117 return @as(OptionalMapIndex, @enumFromInt(@intFromEnum(i)));
117 return @enumFromInt(@intFromEnum(i));
118118 }
119119};
120120
......@@ -218,7 +218,7 @@ pub const OptionalNullTerminatedString = enum(u32) {
218218
219219 pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString {
220220 if (oi == .none) return null;
221 return @as(NullTerminatedString, @enumFromInt(@intFromEnum(oi)));
221 return @enumFromInt(@intFromEnum(oi));
222222 }
223223};
224224
......@@ -415,11 +415,11 @@ pub const Key = union(enum) {
415415 /// explicitly provided tag type or auto-numbered.
416416 tag_ty: Index,
417417 /// Set of field names in declaration order.
418 names: []const NullTerminatedString,
418 names: NullTerminatedString.Slice,
419419 /// Maps integer tag value to field index.
420420 /// Entries are in declaration order, same as `fields`.
421421 /// If this is empty, it means the enum tags are auto-numbered.
422 values: []const Index,
422 values: Index.Slice,
423423 tag_mode: TagMode,
424424 /// This is ignored by `get` but will always be provided by `indexToKey`.
425425 names_map: OptionalMapIndex = .none,
......@@ -441,9 +441,9 @@ pub const Key = union(enum) {
441441 /// Look up field index based on field name.
442442 pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
443443 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];
444 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names };
444 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
445445 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
446 return @as(u32, @intCast(field_index));
446 return @intCast(field_index);
447447 }
448448
449449 /// Look up field index based on tag value.
......@@ -461,9 +461,9 @@ pub const Key = union(enum) {
461461 };
462462 if (self.values_map.unwrap()) |values_map| {
463463 const map = &ip.maps.items[@intFromEnum(values_map)];
464 const adapter: Index.Adapter = .{ .indexes = self.values };
464 const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };
465465 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
466 return @as(u32, @intCast(field_index));
466 return @intCast(field_index);
467467 }
468468 // Auto-numbered enum. Convert `int_tag_val` to field index.
469469 const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {
......@@ -497,8 +497,8 @@ pub const Key = union(enum) {
497497 .namespace = self.namespace,
498498 .tag_ty = self.tag_ty,
499499 .tag_mode = self.tag_mode,
500 .names = &.{},
501 .values = &.{},
500 .names = .{ .start = 0, .len = 0 },
501 .values = .{ .start = 0, .len = 0 },
502502 };
503503 }
504504
......@@ -2570,7 +2570,7 @@ pub const Alignment = enum(u6) {
25702570 pub fn fromByteUnits(n: u64) Alignment {
25712571 if (n == 0) return .none;
25722572 assert(std.math.isPowerOfTwo(n));
2573 return @as(Alignment, @enumFromInt(@ctz(n)));
2573 return @enumFromInt(@ctz(n));
25742574 }
25752575
25762576 pub fn fromNonzeroByteUnits(n: u64) Alignment {
......@@ -2647,11 +2647,11 @@ pub const PackedU64 = packed struct(u64) {
26472647 b: u32,
26482648
26492649 pub fn get(x: PackedU64) u64 {
2650 return @as(u64, @bitCast(x));
2650 return @bitCast(x);
26512651 }
26522652
26532653 pub fn init(x: u64) PackedU64 {
2654 return @as(PackedU64, @bitCast(x));
2654 return @bitCast(x);
26552655 }
26562656};
26572657
......@@ -2714,7 +2714,7 @@ pub const Float64 = struct {
27142714
27152715 pub fn get(self: Float64) f64 {
27162716 const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32);
2717 return @as(f64, @bitCast(int_bits));
2717 return @bitCast(int_bits);
27182718 }
27192719
27202720 fn pack(val: f64) Float64 {
......@@ -2736,7 +2736,7 @@ pub const Float80 = struct {
27362736 const int_bits = @as(u80, self.piece0) |
27372737 (@as(u80, self.piece1) << 32) |
27382738 (@as(u80, self.piece2) << 64);
2739 return @as(f80, @bitCast(int_bits));
2739 return @bitCast(int_bits);
27402740 }
27412741
27422742 fn pack(val: f80) Float80 {
......@@ -2761,7 +2761,7 @@ pub const Float128 = struct {
27612761 (@as(u128, self.piece1) << 32) |
27622762 (@as(u128, self.piece2) << 64) |
27632763 (@as(u128, self.piece3) << 96);
2764 return @as(f128, @bitCast(int_bits));
2764 return @bitCast(int_bits);
27652765 }
27662766
27672767 fn pack(val: f128) Float128 {
......@@ -2968,16 +2968,18 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
29682968
29692969 .type_enum_auto => {
29702970 const enum_auto = ip.extraDataTrail(EnumAuto, data);
2971 const names = @as(
2972 []const NullTerminatedString,
2973 @ptrCast(ip.extra.items[enum_auto.end..][0..enum_auto.data.fields_len]),
2974 );
29752971 return .{ .enum_type = .{
29762972 .decl = enum_auto.data.decl,
29772973 .namespace = enum_auto.data.namespace,
29782974 .tag_ty = enum_auto.data.int_tag_type,
2979 .names = names,
2980 .values = &.{},
2975 .names = .{
2976 .start = @intCast(enum_auto.end),
2977 .len = enum_auto.data.fields_len,
2978 },
2979 .values = .{
2980 .start = 0,
2981 .len = 0,
2982 },
29812983 .tag_mode = .auto,
29822984 .names_map = enum_auto.data.names_map.toOptional(),
29832985 .values_map = .none,
......@@ -3443,21 +3445,19 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
34433445
34443446fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
34453447 const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
3446 const names = @as(
3447 []const NullTerminatedString,
3448 @ptrCast(ip.extra.items[enum_explicit.end..][0..enum_explicit.data.fields_len]),
3449 );
3450 const values = if (enum_explicit.data.values_map != .none) @as(
3451 []const Index,
3452 @ptrCast(ip.extra.items[enum_explicit.end + names.len ..][0..enum_explicit.data.fields_len]),
3453 ) else &[0]Index{};
3454
3448 const fields_len = enum_explicit.data.fields_len;
34553449 return .{ .enum_type = .{
34563450 .decl = enum_explicit.data.decl,
34573451 .namespace = enum_explicit.data.namespace,
34583452 .tag_ty = enum_explicit.data.int_tag_type,
3459 .names = names,
3460 .values = values,
3453 .names = .{
3454 .start = @intCast(enum_explicit.end),
3455 .len = fields_len,
3456 },
3457 .values = .{
3458 .start = @intCast(enum_explicit.end + fields_len),
3459 .len = if (enum_explicit.data.values_map != .none) fields_len else 0,
3460 },
34613461 .tag_mode = tag_mode,
34623462 .names_map = enum_explicit.data.names_map.toOptional(),
34633463 .values_map = enum_explicit.data.values_map,
......@@ -3506,7 +3506,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
35063506 .tag = .type_slice,
35073507 .data = @intFromEnum(ptr_type_index),
35083508 });
3509 return @as(Index, @enumFromInt(ip.items.len - 1));
3509 return @enumFromInt(ip.items.len - 1);
35103510 }
35113511
35123512 var ptr_type_adjusted = ptr_type;
......@@ -3530,7 +3530,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
35303530 .child = array_type.child,
35313531 }),
35323532 });
3533 return @as(Index, @enumFromInt(ip.items.len - 1));
3533 return @enumFromInt(ip.items.len - 1);
35343534 }
35353535 }
35363536
......@@ -3643,7 +3643,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
36433643 assert(anon_struct_type.types.len == anon_struct_type.values.len);
36443644 for (anon_struct_type.types) |elem| assert(elem != .none);
36453645
3646 const fields_len = @as(u32, @intCast(anon_struct_type.types.len));
3646 const fields_len: u32 = @intCast(anon_struct_type.types.len);
36473647 if (anon_struct_type.names.len == 0) {
36483648 try ip.extra.ensureUnusedCapacity(
36493649 gpa,
......@@ -3655,9 +3655,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
36553655 .fields_len = fields_len,
36563656 }),
36573657 });
3658 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.types)));
3659 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.values)));
3660 return @as(Index, @enumFromInt(ip.items.len - 1));
3658 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
3659 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
3660 return @enumFromInt(ip.items.len - 1);
36613661 }
36623662
36633663 assert(anon_struct_type.names.len == anon_struct_type.types.len);
......@@ -3672,10 +3672,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
36723672 .fields_len = fields_len,
36733673 }),
36743674 });
3675 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.types)));
3676 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.values)));
3677 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.names)));
3678 return @as(Index, @enumFromInt(ip.items.len - 1));
3675 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
3676 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
3677 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.names));
3678 return @enumFromInt(ip.items.len - 1);
36793679 },
36803680
36813681 .union_type => |union_type| {
......@@ -3696,38 +3696,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
36963696 });
36973697 },
36983698
3699 .enum_type => |enum_type| {
3700 assert(enum_type.tag_ty == .noreturn_type or ip.isIntegerType(enum_type.tag_ty));
3701 for (enum_type.values) |value| assert(ip.typeOf(value) == enum_type.tag_ty);
3702 assert(enum_type.names_map == .none);
3703 assert(enum_type.values_map == .none);
3704
3705 switch (enum_type.tag_mode) {
3706 .auto => {
3707 const names_map = try ip.addMap(gpa);
3708 try addStringsToMap(ip, gpa, names_map, enum_type.names);
3709
3710 const fields_len = @as(u32, @intCast(enum_type.names.len));
3711 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
3712 fields_len);
3713 ip.items.appendAssumeCapacity(.{
3714 .tag = .type_enum_auto,
3715 .data = ip.addExtraAssumeCapacity(EnumAuto{
3716 .decl = enum_type.decl,
3717 .namespace = enum_type.namespace,
3718 .int_tag_type = enum_type.tag_ty,
3719 .names_map = names_map,
3720 .fields_len = fields_len,
3721 }),
3722 });
3723 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.names)));
3724 return @as(Index, @enumFromInt(ip.items.len - 1));
3725 },
3726 .explicit => return finishGetEnum(ip, gpa, enum_type, .type_enum_explicit),
3727 .nonexhaustive => return finishGetEnum(ip, gpa, enum_type, .type_enum_nonexhaustive),
3728 }
3729 },
3730
3699 .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead
37313700 .func_type => unreachable, // use getFuncType() instead
37323701 .extern_func => unreachable, // use getExternFunc() instead
37333702 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
......@@ -3915,7 +3884,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
39153884 .lazy_ty = lazy_ty,
39163885 }),
39173886 });
3918 return @as(Index, @enumFromInt(ip.items.len - 1));
3887 return @enumFromInt(ip.items.len - 1);
39193888 },
39203889 }
39213890 switch (int.ty) {
......@@ -4056,7 +4025,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
40564025 .value = casted,
40574026 }),
40584027 });
4059 return @as(Index, @enumFromInt(ip.items.len - 1));
4028 return @enumFromInt(ip.items.len - 1);
40604029 } else |_| {}
40614030
40624031 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
......@@ -4071,7 +4040,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
40714040 .value = casted,
40724041 }),
40734042 });
4074 return @as(Index, @enumFromInt(ip.items.len - 1));
4043 return @enumFromInt(ip.items.len - 1);
40754044 }
40764045
40774046 var buf: [2]Limb = undefined;
......@@ -4234,7 +4203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
42344203 .tag = .only_possible_value,
42354204 .data = @intFromEnum(aggregate.ty),
42364205 });
4237 return @as(Index, @enumFromInt(ip.items.len - 1));
4206 return @enumFromInt(ip.items.len - 1);
42384207 }
42394208
42404209 switch (ty_key) {
......@@ -4262,7 +4231,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
42624231 .tag = .only_possible_value,
42634232 .data = @intFromEnum(aggregate.ty),
42644233 });
4265 return @as(Index, @enumFromInt(ip.items.len - 1));
4234 return @enumFromInt(ip.items.len - 1);
42664235 },
42674236 else => {},
42684237 }
......@@ -4301,7 +4270,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
43014270 .elem_val = elem,
43024271 }),
43034272 });
4304 return @as(Index, @enumFromInt(ip.items.len - 1));
4273 return @enumFromInt(ip.items.len - 1);
43054274 }
43064275
43074276 if (child == .u8_type) bytes: {
......@@ -4345,7 +4314,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
43454314 .bytes = string,
43464315 }),
43474316 });
4348 return @as(Index, @enumFromInt(ip.items.len - 1));
4317 return @enumFromInt(ip.items.len - 1);
43494318 }
43504319
43514320 try ip.extra.ensureUnusedCapacity(
......@@ -4358,7 +4327,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
43584327 .ty = aggregate.ty,
43594328 }),
43604329 });
4361 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(aggregate.storage.elems)));
4330 ip.extra.appendSliceAssumeCapacity(@ptrCast(aggregate.storage.elems));
43624331 if (sentinel != .none) ip.extra.appendAssumeCapacity(@intFromEnum(sentinel));
43634332 },
43644333
......@@ -4384,7 +4353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
43844353 .result = memoized_call.result,
43854354 }),
43864355 });
4387 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values)));
4356 ip.extra.appendSliceAssumeCapacity(@ptrCast(memoized_call.arg_values));
43884357 },
43894358 }
43904359 return @enumFromInt(ip.items.len - 1);
......@@ -5017,7 +4986,7 @@ pub const IncompleteEnumType = struct {
50174986 .strings = @as([]const NullTerminatedString, @ptrCast(strings)),
50184987 };
50194988 const gop = try map.getOrPutAdapted(gpa, name, adapter);
5020 if (gop.found_existing) return @as(u32, @intCast(gop.index));
4989 if (gop.found_existing) return @intCast(gop.index);
50214990 ip.extra.items[self.names_start + field_index] = @intFromEnum(name);
50224991 return null;
50234992 }
......@@ -5038,7 +5007,7 @@ pub const IncompleteEnumType = struct {
50385007 .indexes = @as([]const Index, @ptrCast(indexes)),
50395008 };
50405009 const gop = try map.getOrPutAdapted(gpa, value, adapter);
5041 if (gop.found_existing) return @as(u32, @intCast(gop.index));
5010 if (gop.found_existing) return @intCast(gop.index);
50425011 ip.extra.items[self.values_start + field_index] = @intFromEnum(value);
50435012 return null;
50445013 }
......@@ -5158,36 +5127,94 @@ fn getIncompleteEnumExplicit(
51585127 };
51595128}
51605129
5130pub const GetEnumInit = struct {
5131 decl: Module.Decl.Index,
5132 namespace: Module.Namespace.OptionalIndex,
5133 tag_ty: Index,
5134 names: []const NullTerminatedString,
5135 values: []const Index,
5136 tag_mode: Key.EnumType.TagMode,
5137};
5138
5139pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {
5140 const adapter: KeyAdapter = .{ .intern_pool = ip };
5141 const gop = try ip.map.getOrPutAdapted(gpa, Key{
5142 .enum_type = .{
5143 // Only the decl is used for hashing and equality.
5144 .decl = ini.decl,
5145
5146 .namespace = undefined,
5147 .tag_ty = undefined,
5148 .names = undefined,
5149 .values = undefined,
5150 .tag_mode = undefined,
5151 .names_map = undefined,
5152 .values_map = undefined,
5153 },
5154 }, adapter);
5155 if (gop.found_existing) return @enumFromInt(gop.index);
5156 errdefer _ = ip.map.pop();
5157 try ip.items.ensureUnusedCapacity(gpa, 1);
5158
5159 assert(ini.tag_ty == .noreturn_type or ip.isIntegerType(ini.tag_ty));
5160 for (ini.values) |value| assert(ip.typeOf(value) == ini.tag_ty);
5161
5162 switch (ini.tag_mode) {
5163 .auto => {
5164 const names_map = try ip.addMap(gpa);
5165 try addStringsToMap(ip, gpa, names_map, ini.names);
5166
5167 const fields_len: u32 = @intCast(ini.names.len);
5168 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
5169 fields_len);
5170 ip.items.appendAssumeCapacity(.{
5171 .tag = .type_enum_auto,
5172 .data = ip.addExtraAssumeCapacity(EnumAuto{
5173 .decl = ini.decl,
5174 .namespace = ini.namespace,
5175 .int_tag_type = ini.tag_ty,
5176 .names_map = names_map,
5177 .fields_len = fields_len,
5178 }),
5179 });
5180 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
5181 return @enumFromInt(ip.items.len - 1);
5182 },
5183 .explicit => return finishGetEnum(ip, gpa, ini, .type_enum_explicit),
5184 .nonexhaustive => return finishGetEnum(ip, gpa, ini, .type_enum_nonexhaustive),
5185 }
5186}
5187
51615188pub fn finishGetEnum(
51625189 ip: *InternPool,
51635190 gpa: Allocator,
5164 enum_type: Key.EnumType,
5191 ini: GetEnumInit,
51655192 tag: Tag,
51665193) Allocator.Error!Index {
51675194 const names_map = try ip.addMap(gpa);
5168 try addStringsToMap(ip, gpa, names_map, enum_type.names);
5195 try addStringsToMap(ip, gpa, names_map, ini.names);
51695196
5170 const values_map: OptionalMapIndex = if (enum_type.values.len == 0) .none else m: {
5197 const values_map: OptionalMapIndex = if (ini.values.len == 0) .none else m: {
51715198 const values_map = try ip.addMap(gpa);
5172 try addIndexesToMap(ip, gpa, values_map, enum_type.values);
5199 try addIndexesToMap(ip, gpa, values_map, ini.values);
51735200 break :m values_map.toOptional();
51745201 };
5175 const fields_len = @as(u32, @intCast(enum_type.names.len));
5202 const fields_len: u32 = @intCast(ini.names.len);
51765203 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +
51775204 fields_len);
51785205 ip.items.appendAssumeCapacity(.{
51795206 .tag = tag,
51805207 .data = ip.addExtraAssumeCapacity(EnumExplicit{
5181 .decl = enum_type.decl,
5182 .namespace = enum_type.namespace,
5183 .int_tag_type = enum_type.tag_ty,
5208 .decl = ini.decl,
5209 .namespace = ini.namespace,
5210 .int_tag_type = ini.tag_ty,
51845211 .fields_len = fields_len,
51855212 .names_map = names_map,
51865213 .values_map = values_map,
51875214 }),
51885215 });
5189 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names));
5190 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values));
5216 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
5217 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values));
51915218 return @enumFromInt(ip.items.len - 1);
51925219}
51935220
......@@ -5486,7 +5513,7 @@ pub fn slicePtrType(ip: *const InternPool, i: Index) Index {
54865513 }
54875514 const item = ip.items.get(@intFromEnum(i));
54885515 switch (item.tag) {
5489 .type_slice => return @as(Index, @enumFromInt(item.data)),
5516 .type_slice => return @enumFromInt(item.data),
54905517 else => unreachable, // not a slice type
54915518 }
54925519}
......@@ -5618,7 +5645,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
56185645 return ip.get(gpa, .{ .enum_tag = .{
56195646 .ty = new_ty,
56205647 .int = if (enum_type.values.len != 0)
5621 enum_type.values[index]
5648 enum_type.values.get(ip)[index]
56225649 else
56235650 try ip.get(gpa, .{ .int = .{
56245651 .ty = enum_type.tag_ty,
......@@ -6362,7 +6389,7 @@ pub fn createStruct(
63626389 }
63636390 const ptr = try ip.allocated_structs.addOne(gpa);
63646391 ptr.* = initialization;
6365 return @as(Module.Struct.Index, @enumFromInt(ip.allocated_structs.len - 1));
6392 return @enumFromInt(ip.allocated_structs.len - 1);
63666393}
63676394
63686395pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void {
......@@ -6384,7 +6411,7 @@ pub fn createUnion(
63846411 }
63856412 const ptr = try ip.allocated_unions.addOne(gpa);
63866413 ptr.* = initialization;
6387 return @as(Module.Union.Index, @enumFromInt(ip.allocated_unions.len - 1));
6414 return @enumFromInt(ip.allocated_unions.len - 1);
63886415}
63896416
63906417pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) void {
......@@ -6406,7 +6433,7 @@ pub fn createDecl(
64066433 }
64076434 const ptr = try ip.allocated_decls.addOne(gpa);
64086435 ptr.* = initialization;
6409 return @as(Module.Decl.Index, @enumFromInt(ip.allocated_decls.len - 1));
6436 return @enumFromInt(ip.allocated_decls.len - 1);
64106437}
64116438
64126439pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void {
......@@ -6428,7 +6455,7 @@ pub fn createNamespace(
64286455 }
64296456 const ptr = try ip.allocated_namespaces.addOne(gpa);
64306457 ptr.* = initialization;
6431 return @as(Module.Namespace.Index, @enumFromInt(ip.allocated_namespaces.len - 1));
6458 return @enumFromInt(ip.allocated_namespaces.len - 1);
64326459}
64336460
64346461pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void {
......@@ -6495,11 +6522,11 @@ pub fn getOrPutTrailingString(
64956522 });
64966523 if (gop.found_existing) {
64976524 string_bytes.shrinkRetainingCapacity(str_index);
6498 return @as(NullTerminatedString, @enumFromInt(gop.key_ptr.*));
6525 return @enumFromInt(gop.key_ptr.*);
64996526 } else {
65006527 gop.key_ptr.* = str_index;
65016528 string_bytes.appendAssumeCapacity(0);
6502 return @as(NullTerminatedString, @enumFromInt(str_index));
6529 return @enumFromInt(str_index);
65036530 }
65046531}
65056532
......@@ -6725,7 +6752,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
67256752/// Assumes that the enum's field indexes equal its value tags.
67266753pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
67276754 const int = ip.indexToKey(i).enum_tag.int;
6728 return @as(E, @enumFromInt(ip.indexToKey(int).int.storage.u64));
6755 return @enumFromInt(ip.indexToKey(int).int.storage.u64);
67296756}
67306757
67316758pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
......@@ -6758,9 +6785,9 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
67586785 else => unreachable,
67596786 };
67606787 assert(child_item.tag == .type_function);
6761 return @as(Index, @enumFromInt(ip.extra.items[
6788 return @enumFromInt(ip.extra.items[
67626789 child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
6763 ]));
6790 ]);
67646791}
67656792
67666793pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
......@@ -6791,9 +6818,9 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd
67916818 switch (ip.items.items(.tag)[base]) {
67926819 inline .ptr_decl,
67936820 .ptr_mut_decl,
6794 => |tag| return @as(Module.Decl.OptionalIndex, @enumFromInt(ip.extra.items[
6821 => |tag| return @enumFromInt(ip.extra.items[
67956822 ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "decl").?
6796 ])),
6823 ]),
67976824 inline .ptr_eu_payload,
67986825 .ptr_opt_payload,
67996826 .ptr_elem,
src/Module.zig+1-1
......@@ -6655,7 +6655,7 @@ pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.E
66556655
66566656 return (try ip.get(gpa, .{ .enum_tag = .{
66576657 .ty = ty.toIntern(),
6658 .int = enum_type.values[field_index],
6658 .int = enum_type.values.get(ip)[field_index],
66596659 } })).toValue();
66606660}
66616661
src/Sema.zig+17-14
......@@ -17170,14 +17170,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1717017170 for (enum_field_vals, 0..) |*field_val, i| {
1717117171 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
1717217172 const value_val = if (enum_type.values.len > 0)
17173 try mod.intern_pool.getCoerced(gpa, enum_type.values[i], .comptime_int_type)
17173 try mod.intern_pool.getCoerced(gpa, enum_type.values.get(ip)[i], .comptime_int_type)
1717417174 else
1717517175 try mod.intern(.{ .int = .{
1717617176 .ty = .comptime_int_type,
1717717177 .storage = .{ .u64 = @as(u64, @intCast(i)) },
1717817178 } });
1717917179 // TODO: write something like getCoercedInts to avoid needing to dupe
17180 const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names[i]));
17180 const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names.get(ip)[i]));
1718117181 const name_val = v: {
1718217182 var anon_decl = try block.startAnonDecl();
1718317183 defer anon_decl.deinit();
......@@ -20601,7 +20601,7 @@ fn zirReify(
2060120601 errdefer msg.destroy(gpa);
2060220602
2060320603 const enum_ty = union_obj.tag_ty;
20604 for (tag_info.names, 0..) |field_name, field_index| {
20604 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
2060520605 if (explicit_tags_seen[field_index]) continue;
2060620606 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
2060720607 field_name.fmt(ip),
......@@ -35420,7 +35420,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3542035420 errdefer msg.destroy(sema.gpa);
3542135421
3542235422 const enum_ty = union_obj.tag_ty;
35423 for (tag_info.names, 0..) |field_name, field_index| {
35423 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
3542435424 if (explicit_tags_seen[field_index]) continue;
3542535425 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
3542635426 field_name.fmt(ip),
......@@ -35452,12 +35452,13 @@ fn generateUnionTagTypeNumbered(
3545235452) !Type {
3545335453 const mod = sema.mod;
3545435454 const gpa = sema.gpa;
35455 const ip = &mod.intern_pool;
3545535456
3545635457 const src_decl = mod.declPtr(block.src_decl);
3545735458 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
3545835459 errdefer mod.destroyDecl(new_decl_index);
3545935460 const fqn = try union_obj.getFullyQualifiedName(mod);
35460 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
35461 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
3546135462 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
3546235463 .ty = Type.noreturn,
3546335464 .val = Value.@"unreachable",
......@@ -35469,17 +35470,17 @@ fn generateUnionTagTypeNumbered(
3546935470 new_decl.owns_tv = true;
3547035471 new_decl.name_fully_qualified = true;
3547135472
35472 const enum_ty = try mod.intern(.{ .enum_type = .{
35473 const enum_ty = try ip.getEnum(gpa, .{
3547335474 .decl = new_decl_index,
3547435475 .namespace = .none,
3547535476 .tag_ty = if (enum_field_vals.len == 0)
3547635477 (try mod.intType(.unsigned, 0)).toIntern()
3547735478 else
35478 mod.intern_pool.typeOf(enum_field_vals[0]),
35479 ip.typeOf(enum_field_vals[0]),
3547935480 .names = enum_field_names,
3548035481 .values = enum_field_vals,
3548135482 .tag_mode = .explicit,
35482 } });
35483 });
3548335484
3548435485 new_decl.ty = Type.type;
3548535486 new_decl.val = enum_ty.toValue();
......@@ -35495,6 +35496,7 @@ fn generateUnionTagTypeSimple(
3549535496 maybe_union_obj: ?*Module.Union,
3549635497) !Type {
3549735498 const mod = sema.mod;
35499 const ip = &mod.intern_pool;
3549835500 const gpa = sema.gpa;
3549935501
3550035502 const new_decl_index = new_decl_index: {
......@@ -35508,7 +35510,7 @@ fn generateUnionTagTypeSimple(
3550835510 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
3550935511 errdefer mod.destroyDecl(new_decl_index);
3551035512 const fqn = try union_obj.getFullyQualifiedName(mod);
35511 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
35513 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
3551235514 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
3551335515 .ty = Type.noreturn,
3551435516 .val = Value.@"unreachable",
......@@ -35518,7 +35520,7 @@ fn generateUnionTagTypeSimple(
3551835520 };
3551935521 errdefer mod.abortAnonDecl(new_decl_index);
3552035522
35521 const enum_ty = try mod.intern(.{ .enum_type = .{
35523 const enum_ty = try ip.getEnum(gpa, .{
3552235524 .decl = new_decl_index,
3552335525 .namespace = .none,
3552435526 .tag_ty = if (enum_field_names.len == 0)
......@@ -35528,7 +35530,7 @@ fn generateUnionTagTypeSimple(
3552835530 .names = enum_field_names,
3552935531 .values = &.{},
3553035532 .tag_mode = .auto,
35531 } });
35533 });
3553235534
3553335535 const new_decl = mod.declPtr(new_decl_index);
3553435536 new_decl.owns_tv = true;
......@@ -35625,6 +35627,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
3562535627/// TODO assert the return value matches `ty.onePossibleValue`
3562635628pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3562735629 const mod = sema.mod;
35630 const ip = &mod.intern_pool;
3562835631 return switch (ty.toIntern()) {
3562935632 .u0_type,
3563035633 .i0_type,
......@@ -35718,7 +35721,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3571835721 .none,
3571935722 => unreachable,
3572035723
35721 _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
35724 _ => switch (ip.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
3572235725 .type_int_signed, // i0 handled above
3572335726 .type_int_unsigned, // u0 handled above
3572435727 .type_pointer,
......@@ -35801,7 +35804,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3580135804 .type_union_tagged,
3580235805 .type_union_untagged,
3580335806 .type_union_safety,
35804 => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
35807 => switch (ip.indexToKey(ty.toIntern())) {
3580535808 inline .array_type, .vector_type => |seq_type, seq_tag| {
3580635809 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
3580735810 if (seq_type.len + @intFromBool(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
......@@ -35930,7 +35933,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3593035933 .storage = .{ .u64 = 0 },
3593135934 } })
3593235935 else
35933 enum_type.values[0]).toValue(), ty),
35936 enum_type.values.get(ip)[0]).toValue(), ty),
3593435937 else => return null,
3593535938 }
3593635939 },
src/TypedValue.zig+1-1
......@@ -238,7 +238,7 @@ pub fn print(
238238 }
239239 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
240240 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
241 try writer.print(".{i}", .{enum_type.names[tag_index].fmt(ip)});
241 try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
242242 return;
243243 }
244244 try writer.writeAll("@enumFromInt(");
src/codegen/llvm.zig+7-6
......@@ -1909,12 +1909,12 @@ pub const Object = struct {
19091909 const int_info = ty.intInfo(mod);
19101910 assert(int_info.bits != 0);
19111911
1912 for (enum_type.names, 0..) |field_name_ip, i| {
1912 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
19131913 const field_name_z = ip.stringToSlice(field_name_ip);
19141914
19151915 var bigint_space: Value.BigIntSpace = undefined;
19161916 const bigint = if (enum_type.values.len != 0)
1917 enum_type.values[i].toValue().toBigInt(&bigint_space, mod)
1917 enum_type.values.get(ip)[i].toValue().toBigInt(&bigint_space, mod)
19181918 else
19191919 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
19201920
......@@ -9206,7 +9206,8 @@ pub const FuncGen = struct {
92069206 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
92079207 const o = self.dg.object;
92089208 const mod = o.module;
9209 const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
9209 const ip = &mod.intern_pool;
9210 const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
92109211
92119212 // TODO: detect when the type changes and re-emit this function.
92129213 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
......@@ -9218,7 +9219,7 @@ pub const FuncGen = struct {
92189219 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
92199220 const function_index = try o.builder.addFunction(
92209221 try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),
9221 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}),
9222 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
92229223 toLlvmAddressSpace(.generic, mod.getTarget()),
92239224 );
92249225
......@@ -9241,8 +9242,8 @@ pub const FuncGen = struct {
92419242 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
92429243 defer wip_switch.finish(&wip);
92439244
9244 for (enum_type.names, 0..) |name, field_index| {
9245 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
9245 for (enum_type.names.get(ip), 0..) |name, field_index| {
9246 const name_string = try o.builder.string(ip.stringToSlice(name));
92469247 const name_init = try o.builder.stringNullConst(name_string);
92479248 const name_variable_index =
92489249 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
src/link/Dwarf.zig+5-4
......@@ -388,9 +388,10 @@ pub const DeclState = struct {
388388 try ty.print(dbg_info_buffer.writer(), mod);
389389 try dbg_info_buffer.append(0);
390390
391 const enum_type = mod.intern_pool.indexToKey(ty.ip_index).enum_type;
392 for (enum_type.names, 0..) |field_name_index, field_i| {
393 const field_name = mod.intern_pool.stringToSlice(field_name_index);
391 const ip = &mod.intern_pool;
392 const enum_type = ip.indexToKey(ty.ip_index).enum_type;
393 for (enum_type.names.get(ip), 0..) |field_name_index, field_i| {
394 const field_name = ip.stringToSlice(field_name_index);
394395 // DW.AT.enumerator
395396 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
396397 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));
......@@ -400,7 +401,7 @@ pub const DeclState = struct {
400401 // DW.AT.const_value, DW.FORM.data8
401402 const value: u64 = value: {
402403 if (enum_type.values.len == 0) break :value field_i; // auto-numbered
403 const value = enum_type.values[field_i];
404 const value = enum_type.values.get(ip)[field_i];
404405 // TODO do not assume a 64bit enum value - could be bigger.
405406 // See https://github.com/ziglang/zig/issues/645
406407 const field_int_val = try value.toValue().intFromEnum(ty, mod);
src/type.zig+7-5
......@@ -2434,11 +2434,11 @@ pub const Type = struct {
24342434 /// resolves field types rather than asserting they are already resolved.
24352435 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
24362436 var ty = starting_type;
2437
2437 const ip = &mod.intern_pool;
24382438 while (true) switch (ty.toIntern()) {
24392439 .empty_struct_type => return Value.empty_struct,
24402440
2441 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2441 else => switch (ip.indexToKey(ty.toIntern())) {
24422442 .int_type => |int_type| {
24432443 if (int_type.bits == 0) {
24442444 return try mod.intValue(ty, 0);
......@@ -2619,7 +2619,7 @@ pub const Type = struct {
26192619 } });
26202620 return only.toValue();
26212621 } else {
2622 return enum_type.values[0].toValue();
2622 return enum_type.values.get(ip)[0].toValue();
26232623 }
26242624 },
26252625 else => return null,
......@@ -2967,7 +2967,8 @@ pub const Type = struct {
29672967 }
29682968
29692969 pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2970 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
2970 const ip = &mod.intern_pool;
2971 return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip);
29712972 }
29722973
29732974 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
......@@ -2975,7 +2976,8 @@ pub const Type = struct {
29752976 }
29762977
29772978 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
2978 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names[field_index];
2979 const ip = &mod.intern_pool;
2980 return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip)[field_index];
29792981 }
29802982
29812983 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
src/value.zig+1-1
......@@ -426,7 +426,7 @@ pub const Value = struct {
426426 // Assume it is already an integer and return it directly.
427427 .simple_type, .int_type => val,
428428 .enum_type => |enum_type| if (enum_type.values.len != 0)
429 enum_type.values[field_index].toValue()
429 enum_type.values.get(ip)[field_index].toValue()
430430 else // Field index and integer values are the same.
431431 mod.intValue(enum_type.tag_ty.toType(), field_index),
432432 else => unreachable,