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) {...@@ -105,7 +105,7 @@ pub const OptionalMapIndex = enum(u32) {
105105
106 pub fn unwrap(oi: OptionalMapIndex) ?MapIndex {106 pub fn unwrap(oi: OptionalMapIndex) ?MapIndex {
107 if (oi == .none) return null;107 if (oi == .none) return null;
108 return @as(MapIndex, @enumFromInt(@intFromEnum(oi)));108 return @enumFromInt(@intFromEnum(oi));
109 }109 }
110};110};
111111
...@@ -114,7 +114,7 @@ pub const MapIndex = enum(u32) {...@@ -114,7 +114,7 @@ pub const MapIndex = enum(u32) {
114 _,114 _,
115115
116 pub fn toOptional(i: MapIndex) OptionalMapIndex {116 pub fn toOptional(i: MapIndex) OptionalMapIndex {
117 return @as(OptionalMapIndex, @enumFromInt(@intFromEnum(i)));117 return @enumFromInt(@intFromEnum(i));
118 }118 }
119};119};
120120
...@@ -218,7 +218,7 @@ pub const OptionalNullTerminatedString = enum(u32) {...@@ -218,7 +218,7 @@ pub const OptionalNullTerminatedString = enum(u32) {
218218
219 pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString {219 pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString {
220 if (oi == .none) return null;220 if (oi == .none) return null;
221 return @as(NullTerminatedString, @enumFromInt(@intFromEnum(oi)));221 return @enumFromInt(@intFromEnum(oi));
222 }222 }
223};223};
224224
...@@ -415,11 +415,11 @@ pub const Key = union(enum) {...@@ -415,11 +415,11 @@ pub const Key = union(enum) {
415 /// explicitly provided tag type or auto-numbered.415 /// explicitly provided tag type or auto-numbered.
416 tag_ty: Index,416 tag_ty: Index,
417 /// Set of field names in declaration order.417 /// Set of field names in declaration order.
418 names: []const NullTerminatedString,418 names: NullTerminatedString.Slice,
419 /// Maps integer tag value to field index.419 /// Maps integer tag value to field index.
420 /// Entries are in declaration order, same as `fields`.420 /// Entries are in declaration order, same as `fields`.
421 /// If this is empty, it means the enum tags are auto-numbered.421 /// If this is empty, it means the enum tags are auto-numbered.
422 values: []const Index,422 values: Index.Slice,
423 tag_mode: TagMode,423 tag_mode: TagMode,
424 /// This is ignored by `get` but will always be provided by `indexToKey`.424 /// This is ignored by `get` but will always be provided by `indexToKey`.
425 names_map: OptionalMapIndex = .none,425 names_map: OptionalMapIndex = .none,
...@@ -441,9 +441,9 @@ pub const Key = union(enum) {...@@ -441,9 +441,9 @@ pub const Key = union(enum) {
441 /// Look up field index based on field name.441 /// Look up field index based on field name.
442 pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {442 pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
443 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];443 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) };
445 const field_index = map.getIndexAdapted(name, adapter) orelse return null;445 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
446 return @as(u32, @intCast(field_index));446 return @intCast(field_index);
447 }447 }
448448
449 /// Look up field index based on tag value.449 /// Look up field index based on tag value.
...@@ -461,9 +461,9 @@ pub const Key = union(enum) {...@@ -461,9 +461,9 @@ pub const Key = union(enum) {
461 };461 };
462 if (self.values_map.unwrap()) |values_map| {462 if (self.values_map.unwrap()) |values_map| {
463 const map = &ip.maps.items[@intFromEnum(values_map)];463 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) };
465 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;465 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
466 return @as(u32, @intCast(field_index));466 return @intCast(field_index);
467 }467 }
468 // Auto-numbered enum. Convert `int_tag_val` to field index.468 // Auto-numbered enum. Convert `int_tag_val` to field index.
469 const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {469 const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {
...@@ -497,8 +497,8 @@ pub const Key = union(enum) {...@@ -497,8 +497,8 @@ pub const Key = union(enum) {
497 .namespace = self.namespace,497 .namespace = self.namespace,
498 .tag_ty = self.tag_ty,498 .tag_ty = self.tag_ty,
499 .tag_mode = self.tag_mode,499 .tag_mode = self.tag_mode,
500 .names = &.{},500 .names = .{ .start = 0, .len = 0 },
501 .values = &.{},501 .values = .{ .start = 0, .len = 0 },
502 };502 };
503 }503 }
504504
...@@ -2570,7 +2570,7 @@ pub const Alignment = enum(u6) {...@@ -2570,7 +2570,7 @@ pub const Alignment = enum(u6) {
2570 pub fn fromByteUnits(n: u64) Alignment {2570 pub fn fromByteUnits(n: u64) Alignment {
2571 if (n == 0) return .none;2571 if (n == 0) return .none;
2572 assert(std.math.isPowerOfTwo(n));2572 assert(std.math.isPowerOfTwo(n));
2573 return @as(Alignment, @enumFromInt(@ctz(n)));2573 return @enumFromInt(@ctz(n));
2574 }2574 }
25752575
2576 pub fn fromNonzeroByteUnits(n: u64) Alignment {2576 pub fn fromNonzeroByteUnits(n: u64) Alignment {
...@@ -2647,11 +2647,11 @@ pub const PackedU64 = packed struct(u64) {...@@ -2647,11 +2647,11 @@ pub const PackedU64 = packed struct(u64) {
2647 b: u32,2647 b: u32,
26482648
2649 pub fn get(x: PackedU64) u64 {2649 pub fn get(x: PackedU64) u64 {
2650 return @as(u64, @bitCast(x));2650 return @bitCast(x);
2651 }2651 }
26522652
2653 pub fn init(x: u64) PackedU64 {2653 pub fn init(x: u64) PackedU64 {
2654 return @as(PackedU64, @bitCast(x));2654 return @bitCast(x);
2655 }2655 }
2656};2656};
26572657
...@@ -2714,7 +2714,7 @@ pub const Float64 = struct {...@@ -2714,7 +2714,7 @@ pub const Float64 = struct {
27142714
2715 pub fn get(self: Float64) f64 {2715 pub fn get(self: Float64) f64 {
2716 const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32);2716 const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32);
2717 return @as(f64, @bitCast(int_bits));2717 return @bitCast(int_bits);
2718 }2718 }
27192719
2720 fn pack(val: f64) Float64 {2720 fn pack(val: f64) Float64 {
...@@ -2736,7 +2736,7 @@ pub const Float80 = struct {...@@ -2736,7 +2736,7 @@ pub const Float80 = struct {
2736 const int_bits = @as(u80, self.piece0) |2736 const int_bits = @as(u80, self.piece0) |
2737 (@as(u80, self.piece1) << 32) |2737 (@as(u80, self.piece1) << 32) |
2738 (@as(u80, self.piece2) << 64);2738 (@as(u80, self.piece2) << 64);
2739 return @as(f80, @bitCast(int_bits));2739 return @bitCast(int_bits);
2740 }2740 }
27412741
2742 fn pack(val: f80) Float80 {2742 fn pack(val: f80) Float80 {
...@@ -2761,7 +2761,7 @@ pub const Float128 = struct {...@@ -2761,7 +2761,7 @@ pub const Float128 = struct {
2761 (@as(u128, self.piece1) << 32) |2761 (@as(u128, self.piece1) << 32) |
2762 (@as(u128, self.piece2) << 64) |2762 (@as(u128, self.piece2) << 64) |
2763 (@as(u128, self.piece3) << 96);2763 (@as(u128, self.piece3) << 96);
2764 return @as(f128, @bitCast(int_bits));2764 return @bitCast(int_bits);
2765 }2765 }
27662766
2767 fn pack(val: f128) Float128 {2767 fn pack(val: f128) Float128 {
...@@ -2968,16 +2968,18 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2968,16 +2968,18 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
29682968
2969 .type_enum_auto => {2969 .type_enum_auto => {
2970 const enum_auto = ip.extraDataTrail(EnumAuto, data);2970 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 );
2975 return .{ .enum_type = .{2971 return .{ .enum_type = .{
2976 .decl = enum_auto.data.decl,2972 .decl = enum_auto.data.decl,
2977 .namespace = enum_auto.data.namespace,2973 .namespace = enum_auto.data.namespace,
2978 .tag_ty = enum_auto.data.int_tag_type,2974 .tag_ty = enum_auto.data.int_tag_type,
2979 .names = names,2975 .names = .{
2980 .values = &.{},2976 .start = @intCast(enum_auto.end),
2977 .len = enum_auto.data.fields_len,
2978 },
2979 .values = .{
2980 .start = 0,
2981 .len = 0,
2982 },
2981 .tag_mode = .auto,2983 .tag_mode = .auto,
2982 .names_map = enum_auto.data.names_map.toOptional(),2984 .names_map = enum_auto.data.names_map.toOptional(),
2983 .values_map = .none,2985 .values_map = .none,
...@@ -3443,21 +3445,19 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {...@@ -3443,21 +3445,19 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
34433445
3444fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {3446fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
3445 const enum_explicit = ip.extraDataTrail(EnumExplicit, data);3447 const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
3446 const names = @as(3448 const fields_len = enum_explicit.data.fields_len;
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
3455 return .{ .enum_type = .{3449 return .{ .enum_type = .{
3456 .decl = enum_explicit.data.decl,3450 .decl = enum_explicit.data.decl,
3457 .namespace = enum_explicit.data.namespace,3451 .namespace = enum_explicit.data.namespace,
3458 .tag_ty = enum_explicit.data.int_tag_type,3452 .tag_ty = enum_explicit.data.int_tag_type,
3459 .names = names,3453 .names = .{
3460 .values = values,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 },
3461 .tag_mode = tag_mode,3461 .tag_mode = tag_mode,
3462 .names_map = enum_explicit.data.names_map.toOptional(),3462 .names_map = enum_explicit.data.names_map.toOptional(),
3463 .values_map = enum_explicit.data.values_map,3463 .values_map = enum_explicit.data.values_map,
...@@ -3506,7 +3506,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3506,7 +3506,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3506 .tag = .type_slice,3506 .tag = .type_slice,
3507 .data = @intFromEnum(ptr_type_index),3507 .data = @intFromEnum(ptr_type_index),
3508 });3508 });
3509 return @as(Index, @enumFromInt(ip.items.len - 1));3509 return @enumFromInt(ip.items.len - 1);
3510 }3510 }
35113511
3512 var ptr_type_adjusted = ptr_type;3512 var ptr_type_adjusted = ptr_type;
...@@ -3530,7 +3530,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3530,7 +3530,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3530 .child = array_type.child,3530 .child = array_type.child,
3531 }),3531 }),
3532 });3532 });
3533 return @as(Index, @enumFromInt(ip.items.len - 1));3533 return @enumFromInt(ip.items.len - 1);
3534 }3534 }
3535 }3535 }
35363536
...@@ -3643,7 +3643,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3643,7 +3643,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3643 assert(anon_struct_type.types.len == anon_struct_type.values.len);3643 assert(anon_struct_type.types.len == anon_struct_type.values.len);
3644 for (anon_struct_type.types) |elem| assert(elem != .none);3644 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);
3647 if (anon_struct_type.names.len == 0) {3647 if (anon_struct_type.names.len == 0) {
3648 try ip.extra.ensureUnusedCapacity(3648 try ip.extra.ensureUnusedCapacity(
3649 gpa,3649 gpa,
...@@ -3655,9 +3655,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3655,9 +3655,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3655 .fields_len = fields_len,3655 .fields_len = fields_len,
3656 }),3656 }),
3657 });3657 });
3658 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.types)));3658 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
3659 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.values)));3659 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
3660 return @as(Index, @enumFromInt(ip.items.len - 1));3660 return @enumFromInt(ip.items.len - 1);
3661 }3661 }
36623662
3663 assert(anon_struct_type.names.len == anon_struct_type.types.len);3663 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 {...@@ -3672,10 +3672,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3672 .fields_len = fields_len,3672 .fields_len = fields_len,
3673 }),3673 }),
3674 });3674 });
3675 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.types)));3675 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.types));
3676 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.values)));3676 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.values));
3677 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(anon_struct_type.names)));3677 ip.extra.appendSliceAssumeCapacity(@ptrCast(anon_struct_type.names));
3678 return @as(Index, @enumFromInt(ip.items.len - 1));3678 return @enumFromInt(ip.items.len - 1);
3679 },3679 },
36803680
3681 .union_type => |union_type| {3681 .union_type => |union_type| {
...@@ -3696,38 +3696,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3696,38 +3696,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3696 });3696 });
3697 },3697 },
36983698
3699 .enum_type => |enum_type| {3699 .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead
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
3731 .func_type => unreachable, // use getFuncType() instead3700 .func_type => unreachable, // use getFuncType() instead
3732 .extern_func => unreachable, // use getExternFunc() instead3701 .extern_func => unreachable, // use getExternFunc() instead
3733 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead3702 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
...@@ -3915,7 +3884,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3915,7 +3884,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3915 .lazy_ty = lazy_ty,3884 .lazy_ty = lazy_ty,
3916 }),3885 }),
3917 });3886 });
3918 return @as(Index, @enumFromInt(ip.items.len - 1));3887 return @enumFromInt(ip.items.len - 1);
3919 },3888 },
3920 }3889 }
3921 switch (int.ty) {3890 switch (int.ty) {
...@@ -4056,7 +4025,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4056,7 +4025,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4056 .value = casted,4025 .value = casted,
4057 }),4026 }),
4058 });4027 });
4059 return @as(Index, @enumFromInt(ip.items.len - 1));4028 return @enumFromInt(ip.items.len - 1);
4060 } else |_| {}4029 } else |_| {}
40614030
4062 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;4031 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 {...@@ -4071,7 +4040,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4071 .value = casted,4040 .value = casted,
4072 }),4041 }),
4073 });4042 });
4074 return @as(Index, @enumFromInt(ip.items.len - 1));4043 return @enumFromInt(ip.items.len - 1);
4075 }4044 }
40764045
4077 var buf: [2]Limb = undefined;4046 var buf: [2]Limb = undefined;
...@@ -4234,7 +4203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4234,7 +4203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4234 .tag = .only_possible_value,4203 .tag = .only_possible_value,
4235 .data = @intFromEnum(aggregate.ty),4204 .data = @intFromEnum(aggregate.ty),
4236 });4205 });
4237 return @as(Index, @enumFromInt(ip.items.len - 1));4206 return @enumFromInt(ip.items.len - 1);
4238 }4207 }
42394208
4240 switch (ty_key) {4209 switch (ty_key) {
...@@ -4262,7 +4231,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4262,7 +4231,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4262 .tag = .only_possible_value,4231 .tag = .only_possible_value,
4263 .data = @intFromEnum(aggregate.ty),4232 .data = @intFromEnum(aggregate.ty),
4264 });4233 });
4265 return @as(Index, @enumFromInt(ip.items.len - 1));4234 return @enumFromInt(ip.items.len - 1);
4266 },4235 },
4267 else => {},4236 else => {},
4268 }4237 }
...@@ -4301,7 +4270,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4301,7 +4270,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4301 .elem_val = elem,4270 .elem_val = elem,
4302 }),4271 }),
4303 });4272 });
4304 return @as(Index, @enumFromInt(ip.items.len - 1));4273 return @enumFromInt(ip.items.len - 1);
4305 }4274 }
43064275
4307 if (child == .u8_type) bytes: {4276 if (child == .u8_type) bytes: {
...@@ -4345,7 +4314,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4345,7 +4314,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4345 .bytes = string,4314 .bytes = string,
4346 }),4315 }),
4347 });4316 });
4348 return @as(Index, @enumFromInt(ip.items.len - 1));4317 return @enumFromInt(ip.items.len - 1);
4349 }4318 }
43504319
4351 try ip.extra.ensureUnusedCapacity(4320 try ip.extra.ensureUnusedCapacity(
...@@ -4358,7 +4327,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4358,7 +4327,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4358 .ty = aggregate.ty,4327 .ty = aggregate.ty,
4359 }),4328 }),
4360 });4329 });
4361 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(aggregate.storage.elems)));4330 ip.extra.appendSliceAssumeCapacity(@ptrCast(aggregate.storage.elems));
4362 if (sentinel != .none) ip.extra.appendAssumeCapacity(@intFromEnum(sentinel));4331 if (sentinel != .none) ip.extra.appendAssumeCapacity(@intFromEnum(sentinel));
4363 },4332 },
43644333
...@@ -4384,7 +4353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4384,7 +4353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4384 .result = memoized_call.result,4353 .result = memoized_call.result,
4385 }),4354 }),
4386 });4355 });
4387 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values)));4356 ip.extra.appendSliceAssumeCapacity(@ptrCast(memoized_call.arg_values));
4388 },4357 },
4389 }4358 }
4390 return @enumFromInt(ip.items.len - 1);4359 return @enumFromInt(ip.items.len - 1);
...@@ -5017,7 +4986,7 @@ pub const IncompleteEnumType = struct {...@@ -5017,7 +4986,7 @@ pub const IncompleteEnumType = struct {
5017 .strings = @as([]const NullTerminatedString, @ptrCast(strings)),4986 .strings = @as([]const NullTerminatedString, @ptrCast(strings)),
5018 };4987 };
5019 const gop = try map.getOrPutAdapted(gpa, name, adapter);4988 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);
5021 ip.extra.items[self.names_start + field_index] = @intFromEnum(name);4990 ip.extra.items[self.names_start + field_index] = @intFromEnum(name);
5022 return null;4991 return null;
5023 }4992 }
...@@ -5038,7 +5007,7 @@ pub const IncompleteEnumType = struct {...@@ -5038,7 +5007,7 @@ pub const IncompleteEnumType = struct {
5038 .indexes = @as([]const Index, @ptrCast(indexes)),5007 .indexes = @as([]const Index, @ptrCast(indexes)),
5039 };5008 };
5040 const gop = try map.getOrPutAdapted(gpa, value, adapter);5009 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);
5042 ip.extra.items[self.values_start + field_index] = @intFromEnum(value);5011 ip.extra.items[self.values_start + field_index] = @intFromEnum(value);
5043 return null;5012 return null;
5044 }5013 }
...@@ -5158,36 +5127,94 @@ fn getIncompleteEnumExplicit(...@@ -5158,36 +5127,94 @@ fn getIncompleteEnumExplicit(
5158 };5127 };
5159}5128}
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
5161pub fn finishGetEnum(5188pub fn finishGetEnum(
5162 ip: *InternPool,5189 ip: *InternPool,
5163 gpa: Allocator,5190 gpa: Allocator,
5164 enum_type: Key.EnumType,5191 ini: GetEnumInit,
5165 tag: Tag,5192 tag: Tag,
5166) Allocator.Error!Index {5193) Allocator.Error!Index {
5167 const names_map = try ip.addMap(gpa);5194 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: {
5171 const values_map = try ip.addMap(gpa);5198 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);
5173 break :m values_map.toOptional();5200 break :m values_map.toOptional();
5174 };5201 };
5175 const fields_len = @as(u32, @intCast(enum_type.names.len));5202 const fields_len: u32 = @intCast(ini.names.len);
5176 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +5203 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +
5177 fields_len);5204 fields_len);
5178 ip.items.appendAssumeCapacity(.{5205 ip.items.appendAssumeCapacity(.{
5179 .tag = tag,5206 .tag = tag,
5180 .data = ip.addExtraAssumeCapacity(EnumExplicit{5207 .data = ip.addExtraAssumeCapacity(EnumExplicit{
5181 .decl = enum_type.decl,5208 .decl = ini.decl,
5182 .namespace = enum_type.namespace,5209 .namespace = ini.namespace,
5183 .int_tag_type = enum_type.tag_ty,5210 .int_tag_type = ini.tag_ty,
5184 .fields_len = fields_len,5211 .fields_len = fields_len,
5185 .names_map = names_map,5212 .names_map = names_map,
5186 .values_map = values_map,5213 .values_map = values_map,
5187 }),5214 }),
5188 });5215 });
5189 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names));5216 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
5190 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values));5217 ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values));
5191 return @enumFromInt(ip.items.len - 1);5218 return @enumFromInt(ip.items.len - 1);
5192}5219}
51935220
...@@ -5486,7 +5513,7 @@ pub fn slicePtrType(ip: *const InternPool, i: Index) Index {...@@ -5486,7 +5513,7 @@ pub fn slicePtrType(ip: *const InternPool, i: Index) Index {
5486 }5513 }
5487 const item = ip.items.get(@intFromEnum(i));5514 const item = ip.items.get(@intFromEnum(i));
5488 switch (item.tag) {5515 switch (item.tag) {
5489 .type_slice => return @as(Index, @enumFromInt(item.data)),5516 .type_slice => return @enumFromInt(item.data),
5490 else => unreachable, // not a slice type5517 else => unreachable, // not a slice type
5491 }5518 }
5492}5519}
...@@ -5618,7 +5645,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -5618,7 +5645,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
5618 return ip.get(gpa, .{ .enum_tag = .{5645 return ip.get(gpa, .{ .enum_tag = .{
5619 .ty = new_ty,5646 .ty = new_ty,
5620 .int = if (enum_type.values.len != 0)5647 .int = if (enum_type.values.len != 0)
5621 enum_type.values[index]5648 enum_type.values.get(ip)[index]
5622 else5649 else
5623 try ip.get(gpa, .{ .int = .{5650 try ip.get(gpa, .{ .int = .{
5624 .ty = enum_type.tag_ty,5651 .ty = enum_type.tag_ty,
...@@ -6362,7 +6389,7 @@ pub fn createStruct(...@@ -6362,7 +6389,7 @@ pub fn createStruct(
6362 }6389 }
6363 const ptr = try ip.allocated_structs.addOne(gpa);6390 const ptr = try ip.allocated_structs.addOne(gpa);
6364 ptr.* = initialization;6391 ptr.* = initialization;
6365 return @as(Module.Struct.Index, @enumFromInt(ip.allocated_structs.len - 1));6392 return @enumFromInt(ip.allocated_structs.len - 1);
6366}6393}
63676394
6368pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void {6395pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void {
...@@ -6384,7 +6411,7 @@ pub fn createUnion(...@@ -6384,7 +6411,7 @@ pub fn createUnion(
6384 }6411 }
6385 const ptr = try ip.allocated_unions.addOne(gpa);6412 const ptr = try ip.allocated_unions.addOne(gpa);
6386 ptr.* = initialization;6413 ptr.* = initialization;
6387 return @as(Module.Union.Index, @enumFromInt(ip.allocated_unions.len - 1));6414 return @enumFromInt(ip.allocated_unions.len - 1);
6388}6415}
63896416
6390pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) void {6417pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) void {
...@@ -6406,7 +6433,7 @@ pub fn createDecl(...@@ -6406,7 +6433,7 @@ pub fn createDecl(
6406 }6433 }
6407 const ptr = try ip.allocated_decls.addOne(gpa);6434 const ptr = try ip.allocated_decls.addOne(gpa);
6408 ptr.* = initialization;6435 ptr.* = initialization;
6409 return @as(Module.Decl.Index, @enumFromInt(ip.allocated_decls.len - 1));6436 return @enumFromInt(ip.allocated_decls.len - 1);
6410}6437}
64116438
6412pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void {6439pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void {
...@@ -6428,7 +6455,7 @@ pub fn createNamespace(...@@ -6428,7 +6455,7 @@ pub fn createNamespace(
6428 }6455 }
6429 const ptr = try ip.allocated_namespaces.addOne(gpa);6456 const ptr = try ip.allocated_namespaces.addOne(gpa);
6430 ptr.* = initialization;6457 ptr.* = initialization;
6431 return @as(Module.Namespace.Index, @enumFromInt(ip.allocated_namespaces.len - 1));6458 return @enumFromInt(ip.allocated_namespaces.len - 1);
6432}6459}
64336460
6434pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void {6461pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void {
...@@ -6495,11 +6522,11 @@ pub fn getOrPutTrailingString(...@@ -6495,11 +6522,11 @@ pub fn getOrPutTrailingString(
6495 });6522 });
6496 if (gop.found_existing) {6523 if (gop.found_existing) {
6497 string_bytes.shrinkRetainingCapacity(str_index);6524 string_bytes.shrinkRetainingCapacity(str_index);
6498 return @as(NullTerminatedString, @enumFromInt(gop.key_ptr.*));6525 return @enumFromInt(gop.key_ptr.*);
6499 } else {6526 } else {
6500 gop.key_ptr.* = str_index;6527 gop.key_ptr.* = str_index;
6501 string_bytes.appendAssumeCapacity(0);6528 string_bytes.appendAssumeCapacity(0);
6502 return @as(NullTerminatedString, @enumFromInt(str_index));6529 return @enumFromInt(str_index);
6503 }6530 }
6504}6531}
65056532
...@@ -6725,7 +6752,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -6725,7 +6752,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
6725/// Assumes that the enum's field indexes equal its value tags.6752/// Assumes that the enum's field indexes equal its value tags.
6726pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {6753pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
6727 const int = ip.indexToKey(i).enum_tag.int;6754 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);
6729}6756}
67306757
6731pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {6758pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
...@@ -6758,9 +6785,9 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {...@@ -6758,9 +6785,9 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
6758 else => unreachable,6785 else => unreachable,
6759 };6786 };
6760 assert(child_item.tag == .type_function);6787 assert(child_item.tag == .type_function);
6761 return @as(Index, @enumFromInt(ip.extra.items[6788 return @enumFromInt(ip.extra.items[
6762 child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?6789 child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
6763 ]));6790 ]);
6764}6791}
67656792
6766pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {6793pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
...@@ -6791,9 +6818,9 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd...@@ -6791,9 +6818,9 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd
6791 switch (ip.items.items(.tag)[base]) {6818 switch (ip.items.items(.tag)[base]) {
6792 inline .ptr_decl,6819 inline .ptr_decl,
6793 .ptr_mut_decl,6820 .ptr_mut_decl,
6794 => |tag| return @as(Module.Decl.OptionalIndex, @enumFromInt(ip.extra.items[6821 => |tag| return @enumFromInt(ip.extra.items[
6795 ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "decl").?6822 ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "decl").?
6796 ])),6823 ]),
6797 inline .ptr_eu_payload,6824 inline .ptr_eu_payload,
6798 .ptr_opt_payload,6825 .ptr_opt_payload,
6799 .ptr_elem,6826 .ptr_elem,
src/Module.zig+1-1
...@@ -6655,7 +6655,7 @@ pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.E...@@ -6655,7 +6655,7 @@ pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.E
66556655
6656 return (try ip.get(gpa, .{ .enum_tag = .{6656 return (try ip.get(gpa, .{ .enum_tag = .{
6657 .ty = ty.toIntern(),6657 .ty = ty.toIntern(),
6658 .int = enum_type.values[field_index],6658 .int = enum_type.values.get(ip)[field_index],
6659 } })).toValue();6659 } })).toValue();
6660}6660}
66616661
src/Sema.zig+17-14
...@@ -17170,14 +17170,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17170,14 +17170,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17170 for (enum_field_vals, 0..) |*field_val, i| {17170 for (enum_field_vals, 0..) |*field_val, i| {
17171 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;17171 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
17172 const value_val = if (enum_type.values.len > 0)17172 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)
17174 else17174 else
17175 try mod.intern(.{ .int = .{17175 try mod.intern(.{ .int = .{
17176 .ty = .comptime_int_type,17176 .ty = .comptime_int_type,
17177 .storage = .{ .u64 = @as(u64, @intCast(i)) },17177 .storage = .{ .u64 = @as(u64, @intCast(i)) },
17178 } });17178 } });
17179 // TODO: write something like getCoercedInts to avoid needing to dupe17179 // 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]));
17181 const name_val = v: {17181 const name_val = v: {
17182 var anon_decl = try block.startAnonDecl();17182 var anon_decl = try block.startAnonDecl();
17183 defer anon_decl.deinit();17183 defer anon_decl.deinit();
...@@ -20601,7 +20601,7 @@ fn zirReify(...@@ -20601,7 +20601,7 @@ fn zirReify(
20601 errdefer msg.destroy(gpa);20601 errdefer msg.destroy(gpa);
2060220602
20603 const enum_ty = union_obj.tag_ty;20603 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| {
20605 if (explicit_tags_seen[field_index]) continue;20605 if (explicit_tags_seen[field_index]) continue;
20606 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{20606 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
20607 field_name.fmt(ip),20607 field_name.fmt(ip),
...@@ -35420,7 +35420,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -35420,7 +35420,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
35420 errdefer msg.destroy(sema.gpa);35420 errdefer msg.destroy(sema.gpa);
3542135421
35422 const enum_ty = union_obj.tag_ty;35422 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| {
35424 if (explicit_tags_seen[field_index]) continue;35424 if (explicit_tags_seen[field_index]) continue;
35425 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{35425 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
35426 field_name.fmt(ip),35426 field_name.fmt(ip),
...@@ -35452,12 +35452,13 @@ fn generateUnionTagTypeNumbered(...@@ -35452,12 +35452,13 @@ fn generateUnionTagTypeNumbered(
35452) !Type {35452) !Type {
35453 const mod = sema.mod;35453 const mod = sema.mod;
35454 const gpa = sema.gpa;35454 const gpa = sema.gpa;
35455 const ip = &mod.intern_pool;
3545535456
35456 const src_decl = mod.declPtr(block.src_decl);35457 const src_decl = mod.declPtr(block.src_decl);
35457 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);35458 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
35458 errdefer mod.destroyDecl(new_decl_index);35459 errdefer mod.destroyDecl(new_decl_index);
35459 const fqn = try union_obj.getFullyQualifiedName(mod);35460 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)});
35461 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{35462 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
35462 .ty = Type.noreturn,35463 .ty = Type.noreturn,
35463 .val = Value.@"unreachable",35464 .val = Value.@"unreachable",
...@@ -35469,17 +35470,17 @@ fn generateUnionTagTypeNumbered(...@@ -35469,17 +35470,17 @@ fn generateUnionTagTypeNumbered(
35469 new_decl.owns_tv = true;35470 new_decl.owns_tv = true;
35470 new_decl.name_fully_qualified = true;35471 new_decl.name_fully_qualified = true;
3547135472
35472 const enum_ty = try mod.intern(.{ .enum_type = .{35473 const enum_ty = try ip.getEnum(gpa, .{
35473 .decl = new_decl_index,35474 .decl = new_decl_index,
35474 .namespace = .none,35475 .namespace = .none,
35475 .tag_ty = if (enum_field_vals.len == 0)35476 .tag_ty = if (enum_field_vals.len == 0)
35476 (try mod.intType(.unsigned, 0)).toIntern()35477 (try mod.intType(.unsigned, 0)).toIntern()
35477 else35478 else
35478 mod.intern_pool.typeOf(enum_field_vals[0]),35479 ip.typeOf(enum_field_vals[0]),
35479 .names = enum_field_names,35480 .names = enum_field_names,
35480 .values = enum_field_vals,35481 .values = enum_field_vals,
35481 .tag_mode = .explicit,35482 .tag_mode = .explicit,
35482 } });35483 });
3548335484
35484 new_decl.ty = Type.type;35485 new_decl.ty = Type.type;
35485 new_decl.val = enum_ty.toValue();35486 new_decl.val = enum_ty.toValue();
...@@ -35495,6 +35496,7 @@ fn generateUnionTagTypeSimple(...@@ -35495,6 +35496,7 @@ fn generateUnionTagTypeSimple(
35495 maybe_union_obj: ?*Module.Union,35496 maybe_union_obj: ?*Module.Union,
35496) !Type {35497) !Type {
35497 const mod = sema.mod;35498 const mod = sema.mod;
35499 const ip = &mod.intern_pool;
35498 const gpa = sema.gpa;35500 const gpa = sema.gpa;
3549935501
35500 const new_decl_index = new_decl_index: {35502 const new_decl_index = new_decl_index: {
...@@ -35508,7 +35510,7 @@ fn generateUnionTagTypeSimple(...@@ -35508,7 +35510,7 @@ fn generateUnionTagTypeSimple(
35508 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);35510 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
35509 errdefer mod.destroyDecl(new_decl_index);35511 errdefer mod.destroyDecl(new_decl_index);
35510 const fqn = try union_obj.getFullyQualifiedName(mod);35512 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)});
35512 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{35514 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
35513 .ty = Type.noreturn,35515 .ty = Type.noreturn,
35514 .val = Value.@"unreachable",35516 .val = Value.@"unreachable",
...@@ -35518,7 +35520,7 @@ fn generateUnionTagTypeSimple(...@@ -35518,7 +35520,7 @@ fn generateUnionTagTypeSimple(
35518 };35520 };
35519 errdefer mod.abortAnonDecl(new_decl_index);35521 errdefer mod.abortAnonDecl(new_decl_index);
3552035522
35521 const enum_ty = try mod.intern(.{ .enum_type = .{35523 const enum_ty = try ip.getEnum(gpa, .{
35522 .decl = new_decl_index,35524 .decl = new_decl_index,
35523 .namespace = .none,35525 .namespace = .none,
35524 .tag_ty = if (enum_field_names.len == 0)35526 .tag_ty = if (enum_field_names.len == 0)
...@@ -35528,7 +35530,7 @@ fn generateUnionTagTypeSimple(...@@ -35528,7 +35530,7 @@ fn generateUnionTagTypeSimple(
35528 .names = enum_field_names,35530 .names = enum_field_names,
35529 .values = &.{},35531 .values = &.{},
35530 .tag_mode = .auto,35532 .tag_mode = .auto,
35531 } });35533 });
3553235534
35533 const new_decl = mod.declPtr(new_decl_index);35535 const new_decl = mod.declPtr(new_decl_index);
35534 new_decl.owns_tv = true;35536 new_decl.owns_tv = true;
...@@ -35625,6 +35627,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -35625,6 +35627,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
35625/// TODO assert the return value matches `ty.onePossibleValue`35627/// TODO assert the return value matches `ty.onePossibleValue`
35626pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {35628pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35627 const mod = sema.mod;35629 const mod = sema.mod;
35630 const ip = &mod.intern_pool;
35628 return switch (ty.toIntern()) {35631 return switch (ty.toIntern()) {
35629 .u0_type,35632 .u0_type,
35630 .i0_type,35633 .i0_type,
...@@ -35718,7 +35721,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35718,7 +35721,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35718 .none,35721 .none,
35719 => unreachable,35722 => unreachable,
3572035723
35721 _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {35724 _ => switch (ip.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
35722 .type_int_signed, // i0 handled above35725 .type_int_signed, // i0 handled above
35723 .type_int_unsigned, // u0 handled above35726 .type_int_unsigned, // u0 handled above
35724 .type_pointer,35727 .type_pointer,
...@@ -35801,7 +35804,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35801,7 +35804,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35801 .type_union_tagged,35804 .type_union_tagged,
35802 .type_union_untagged,35805 .type_union_untagged,
35803 .type_union_safety,35806 .type_union_safety,
35804 => switch (mod.intern_pool.indexToKey(ty.toIntern())) {35807 => switch (ip.indexToKey(ty.toIntern())) {
35805 inline .array_type, .vector_type => |seq_type, seq_tag| {35808 inline .array_type, .vector_type => |seq_type, seq_tag| {
35806 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;35809 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
35807 if (seq_type.len + @intFromBool(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{35810 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 {...@@ -35930,7 +35933,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35930 .storage = .{ .u64 = 0 },35933 .storage = .{ .u64 = 0 },
35931 } })35934 } })
35932 else35935 else
35933 enum_type.values[0]).toValue(), ty),35936 enum_type.values.get(ip)[0]).toValue(), ty),
35934 else => return null,35937 else => return null,
35935 }35938 }
35936 },35939 },
src/TypedValue.zig+1-1
...@@ -238,7 +238,7 @@ pub fn print(...@@ -238,7 +238,7 @@ pub fn print(
238 }238 }
239 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;239 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
240 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {240 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)});
242 return;242 return;
243 }243 }
244 try writer.writeAll("@enumFromInt(");244 try writer.writeAll("@enumFromInt(");
src/codegen/llvm.zig+7-6
...@@ -1909,12 +1909,12 @@ pub const Object = struct {...@@ -1909,12 +1909,12 @@ pub const Object = struct {
1909 const int_info = ty.intInfo(mod);1909 const int_info = ty.intInfo(mod);
1910 assert(int_info.bits != 0);1910 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| {
1913 const field_name_z = ip.stringToSlice(field_name_ip);1913 const field_name_z = ip.stringToSlice(field_name_ip);
19141914
1915 var bigint_space: Value.BigIntSpace = undefined;1915 var bigint_space: Value.BigIntSpace = undefined;
1916 const bigint = if (enum_type.values.len != 0)1916 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)
1918 else1918 else
1919 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();1919 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
19201920
...@@ -9206,7 +9206,8 @@ pub const FuncGen = struct {...@@ -9206,7 +9206,8 @@ pub const FuncGen = struct {
9206 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {9206 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
9207 const o = self.dg.object;9207 const o = self.dg.object;
9208 const mod = o.module;9208 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
9211 // TODO: detect when the type changes and re-emit this function.9212 // TODO: detect when the type changes and re-emit this function.
9212 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);9213 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
...@@ -9218,7 +9219,7 @@ pub const FuncGen = struct {...@@ -9218,7 +9219,7 @@ pub const FuncGen = struct {
9218 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);9219 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
9219 const function_index = try o.builder.addFunction(9220 const function_index = try o.builder.addFunction(
9220 try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal),9221 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)}),
9222 toLlvmAddressSpace(.generic, mod.getTarget()),9223 toLlvmAddressSpace(.generic, mod.getTarget()),
9223 );9224 );
92249225
...@@ -9241,8 +9242,8 @@ pub const FuncGen = struct {...@@ -9241,8 +9242,8 @@ pub const FuncGen = struct {
9241 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));9242 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len));
9242 defer wip_switch.finish(&wip);9243 defer wip_switch.finish(&wip);
92439244
9244 for (enum_type.names, 0..) |name, field_index| {9245 for (enum_type.names.get(ip), 0..) |name, field_index| {
9245 const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));9246 const name_string = try o.builder.string(ip.stringToSlice(name));
9246 const name_init = try o.builder.stringNullConst(name_string);9247 const name_init = try o.builder.stringNullConst(name_string);
9247 const name_variable_index =9248 const name_variable_index =
9248 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);9249 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 {...@@ -388,9 +388,10 @@ pub const DeclState = struct {
388 try ty.print(dbg_info_buffer.writer(), mod);388 try ty.print(dbg_info_buffer.writer(), mod);
389 try dbg_info_buffer.append(0);389 try dbg_info_buffer.append(0);
390390
391 const enum_type = mod.intern_pool.indexToKey(ty.ip_index).enum_type;391 const ip = &mod.intern_pool;
392 for (enum_type.names, 0..) |field_name_index, field_i| {392 const enum_type = ip.indexToKey(ty.ip_index).enum_type;
393 const field_name = mod.intern_pool.stringToSlice(field_name_index);393 for (enum_type.names.get(ip), 0..) |field_name_index, field_i| {
394 const field_name = ip.stringToSlice(field_name_index);
394 // DW.AT.enumerator395 // DW.AT.enumerator
395 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));396 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
396 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));397 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));
...@@ -400,7 +401,7 @@ pub const DeclState = struct {...@@ -400,7 +401,7 @@ pub const DeclState = struct {
400 // DW.AT.const_value, DW.FORM.data8401 // DW.AT.const_value, DW.FORM.data8
401 const value: u64 = value: {402 const value: u64 = value: {
402 if (enum_type.values.len == 0) break :value field_i; // auto-numbered403 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];
404 // TODO do not assume a 64bit enum value - could be bigger.405 // TODO do not assume a 64bit enum value - could be bigger.
405 // See https://github.com/ziglang/zig/issues/645406 // See https://github.com/ziglang/zig/issues/645
406 const field_int_val = try value.toValue().intFromEnum(ty, mod);407 const field_int_val = try value.toValue().intFromEnum(ty, mod);
src/type.zig+7-5
...@@ -2434,11 +2434,11 @@ pub const Type = struct {...@@ -2434,11 +2434,11 @@ pub const Type = struct {
2434 /// resolves field types rather than asserting they are already resolved.2434 /// resolves field types rather than asserting they are already resolved.
2435 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {2435 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
2436 var ty = starting_type;2436 var ty = starting_type;
24372437 const ip = &mod.intern_pool;
2438 while (true) switch (ty.toIntern()) {2438 while (true) switch (ty.toIntern()) {
2439 .empty_struct_type => return Value.empty_struct,2439 .empty_struct_type => return Value.empty_struct,
24402440
2441 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {2441 else => switch (ip.indexToKey(ty.toIntern())) {
2442 .int_type => |int_type| {2442 .int_type => |int_type| {
2443 if (int_type.bits == 0) {2443 if (int_type.bits == 0) {
2444 return try mod.intValue(ty, 0);2444 return try mod.intValue(ty, 0);
...@@ -2619,7 +2619,7 @@ pub const Type = struct {...@@ -2619,7 +2619,7 @@ pub const Type = struct {
2619 } });2619 } });
2620 return only.toValue();2620 return only.toValue();
2621 } else {2621 } else {
2622 return enum_type.values[0].toValue();2622 return enum_type.values.get(ip)[0].toValue();
2623 }2623 }
2624 },2624 },
2625 else => return null,2625 else => return null,
...@@ -2967,7 +2967,8 @@ pub const Type = struct {...@@ -2967,7 +2967,8 @@ pub const Type = struct {
2967 }2967 }
29682968
2969 pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {2969 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);
2971 }2972 }
29722973
2973 pub fn enumFieldCount(ty: Type, mod: *Module) usize {2974 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
...@@ -2975,7 +2976,8 @@ pub const Type = struct {...@@ -2975,7 +2976,8 @@ pub const Type = struct {
2975 }2976 }
29762977
2977 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {2978 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];
2979 }2981 }
29802982
2981 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {2983 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 {...@@ -426,7 +426,7 @@ pub const Value = struct {
426 // Assume it is already an integer and return it directly.426 // Assume it is already an integer and return it directly.
427 .simple_type, .int_type => val,427 .simple_type, .int_type => val,
428 .enum_type => |enum_type| if (enum_type.values.len != 0)428 .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()
430 else // Field index and integer values are the same.430 else // Field index and integer values are the same.
431 mod.intValue(enum_type.tag_ty.toType(), field_index),431 mod.intValue(enum_type.tag_ty.toType(), field_index),
432 else => unreachable,432 else => unreachable,