authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-17 01:18:54+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-06 21:26:37+00:00
log975b859377dee450418ae9ed572ec9d3c0b77312
tree08a86de7c929deb2a86deb5b587f35bb980ca500
parenta6ca20b9a1dfc7b6e8d004cb166c0714bb8db2db
signaturelock-open Commit is signed but in an unrecognized format.

InternPool: create specialized functions for loading namespace types

Namespace types (`struct`, `enum`, `union`, `opaque`) do not use structural equality - equivalence is based on their Decl index (and soon will change to AST node + captures). However, we previously stored all other information in the corresponding `InternPool.Key` anyway. For logical consistency, it makes sense to have the key only be the true key (that is, the Decl index) and to load all other data through another function. This introduces those functions, by the name of `loadStructType` etc. It's a big diff, but most of it is no-brainer changes. In future, it might be nice to eliminate a bunch of the loaded state in favour of accessor functions on the `LoadedXyzType` types (like how we have `LoadedUnionType.size()`), but that can be explored at a later date.

16 files changed, 1237 insertions(+), 1288 deletions(-)

src/InternPool.zig+712-801
......@@ -644,348 +644,6 @@ pub const Key = union(enum) {
644644 child: Index,
645645 };
646646
647 pub const OpaqueType = extern struct {
648 /// The Decl that corresponds to the opaque itself.
649 decl: DeclIndex,
650 /// Represents the declarations inside this opaque.
651 namespace: NamespaceIndex,
652 zir_index: TrackedInst.Index.Optional,
653 };
654
655 /// Although packed structs and non-packed structs are encoded differently,
656 /// this struct is used for both categories since they share some common
657 /// functionality.
658 pub const StructType = struct {
659 extra_index: u32,
660 /// `none` when the struct is `@TypeOf(.{})`.
661 decl: OptionalDeclIndex,
662 /// `none` when the struct has no declarations.
663 namespace: OptionalNamespaceIndex,
664 /// Index of the struct_decl ZIR instruction.
665 zir_index: TrackedInst.Index.Optional,
666 layout: std.builtin.Type.ContainerLayout,
667 field_names: NullTerminatedString.Slice,
668 field_types: Index.Slice,
669 field_inits: Index.Slice,
670 field_aligns: Alignment.Slice,
671 runtime_order: RuntimeOrder.Slice,
672 comptime_bits: ComptimeBits,
673 offsets: Offsets,
674 names_map: OptionalMapIndex,
675
676 pub const ComptimeBits = struct {
677 start: u32,
678 /// This is the number of u32 elements, not the number of struct fields.
679 len: u32,
680
681 pub fn get(this: @This(), ip: *const InternPool) []u32 {
682 return ip.extra.items[this.start..][0..this.len];
683 }
684
685 pub fn getBit(this: @This(), ip: *const InternPool, i: usize) bool {
686 if (this.len == 0) return false;
687 return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0;
688 }
689
690 pub fn setBit(this: @This(), ip: *const InternPool, i: usize) void {
691 this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32);
692 }
693
694 pub fn clearBit(this: @This(), ip: *const InternPool, i: usize) void {
695 this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32));
696 }
697 };
698
699 pub const Offsets = struct {
700 start: u32,
701 len: u32,
702
703 pub fn get(this: @This(), ip: *const InternPool) []u32 {
704 return @ptrCast(ip.extra.items[this.start..][0..this.len]);
705 }
706 };
707
708 pub const RuntimeOrder = enum(u32) {
709 /// Placeholder until layout is resolved.
710 unresolved = std.math.maxInt(u32) - 0,
711 /// Field not present at runtime
712 omitted = std.math.maxInt(u32) - 1,
713 _,
714
715 pub const Slice = struct {
716 start: u32,
717 len: u32,
718
719 pub fn get(slice: RuntimeOrder.Slice, ip: *const InternPool) []RuntimeOrder {
720 return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
721 }
722 };
723
724 pub fn toInt(i: @This()) ?u32 {
725 return switch (i) {
726 .omitted => null,
727 .unresolved => unreachable,
728 else => @intFromEnum(i),
729 };
730 }
731 };
732
733 /// Look up field index based on field name.
734 pub fn nameIndex(self: StructType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
735 const names_map = self.names_map.unwrap() orelse {
736 const i = name.toUnsigned(ip) orelse return null;
737 if (i >= self.field_types.len) return null;
738 return i;
739 };
740 const map = &ip.maps.items[@intFromEnum(names_map)];
741 const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) };
742 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
743 return @intCast(field_index);
744 }
745
746 /// Returns the already-existing field with the same name, if any.
747 pub fn addFieldName(
748 self: @This(),
749 ip: *InternPool,
750 name: NullTerminatedString,
751 ) ?u32 {
752 return ip.addFieldName(self.names_map.unwrap().?, self.field_names.start, name);
753 }
754
755 pub fn fieldAlign(s: @This(), ip: *const InternPool, i: usize) Alignment {
756 if (s.field_aligns.len == 0) return .none;
757 return s.field_aligns.get(ip)[i];
758 }
759
760 pub fn fieldInit(s: @This(), ip: *const InternPool, i: usize) Index {
761 if (s.field_inits.len == 0) return .none;
762 assert(s.haveFieldInits(ip));
763 return s.field_inits.get(ip)[i];
764 }
765
766 /// Returns `none` in the case the struct is a tuple.
767 pub fn fieldName(s: @This(), ip: *const InternPool, i: usize) OptionalNullTerminatedString {
768 if (s.field_names.len == 0) return .none;
769 return s.field_names.get(ip)[i].toOptional();
770 }
771
772 pub fn fieldIsComptime(s: @This(), ip: *const InternPool, i: usize) bool {
773 return s.comptime_bits.getBit(ip, i);
774 }
775
776 pub fn setFieldComptime(s: @This(), ip: *InternPool, i: usize) void {
777 s.comptime_bits.setBit(ip, i);
778 }
779
780 /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more
781 /// complicated logic.
782 pub fn knownNonOpv(s: @This(), ip: *InternPool) bool {
783 return switch (s.layout) {
784 .Packed => false,
785 .Auto, .Extern => s.flagsPtr(ip).known_non_opv,
786 };
787 }
788
789 /// The returned pointer expires with any addition to the `InternPool`.
790 /// Asserts the struct is not packed.
791 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStruct.Flags {
792 assert(self.layout != .Packed);
793 const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?;
794 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
795 }
796
797 /// The returned pointer expires with any addition to the `InternPool`.
798 /// Asserts that the struct is packed.
799 pub fn packedFlagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStructPacked.Flags {
800 assert(self.layout == .Packed);
801 const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?;
802 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
803 }
804
805 pub fn assumeRuntimeBitsIfFieldTypesWip(s: @This(), ip: *InternPool) bool {
806 if (s.layout == .Packed) return false;
807 const flags_ptr = s.flagsPtr(ip);
808 if (flags_ptr.field_types_wip) {
809 flags_ptr.assumed_runtime_bits = true;
810 return true;
811 }
812 return false;
813 }
814
815 pub fn setTypesWip(s: @This(), ip: *InternPool) bool {
816 if (s.layout == .Packed) return false;
817 const flags_ptr = s.flagsPtr(ip);
818 if (flags_ptr.field_types_wip) return true;
819 flags_ptr.field_types_wip = true;
820 return false;
821 }
822
823 pub fn clearTypesWip(s: @This(), ip: *InternPool) void {
824 if (s.layout == .Packed) return;
825 s.flagsPtr(ip).field_types_wip = false;
826 }
827
828 pub fn setLayoutWip(s: @This(), ip: *InternPool) bool {
829 if (s.layout == .Packed) return false;
830 const flags_ptr = s.flagsPtr(ip);
831 if (flags_ptr.layout_wip) return true;
832 flags_ptr.layout_wip = true;
833 return false;
834 }
835
836 pub fn clearLayoutWip(s: @This(), ip: *InternPool) void {
837 if (s.layout == .Packed) return;
838 s.flagsPtr(ip).layout_wip = false;
839 }
840
841 pub fn setAlignmentWip(s: @This(), ip: *InternPool) bool {
842 if (s.layout == .Packed) return false;
843 const flags_ptr = s.flagsPtr(ip);
844 if (flags_ptr.alignment_wip) return true;
845 flags_ptr.alignment_wip = true;
846 return false;
847 }
848
849 pub fn clearAlignmentWip(s: @This(), ip: *InternPool) void {
850 if (s.layout == .Packed) return;
851 s.flagsPtr(ip).alignment_wip = false;
852 }
853
854 pub fn setInitsWip(s: @This(), ip: *InternPool) bool {
855 switch (s.layout) {
856 .Packed => {
857 const flag = &s.packedFlagsPtr(ip).field_inits_wip;
858 if (flag.*) return true;
859 flag.* = true;
860 return false;
861 },
862 .Auto, .Extern => {
863 const flag = &s.flagsPtr(ip).field_inits_wip;
864 if (flag.*) return true;
865 flag.* = true;
866 return false;
867 },
868 }
869 }
870
871 pub fn clearInitsWip(s: @This(), ip: *InternPool) void {
872 switch (s.layout) {
873 .Packed => s.packedFlagsPtr(ip).field_inits_wip = false,
874 .Auto, .Extern => s.flagsPtr(ip).field_inits_wip = false,
875 }
876 }
877
878 pub fn setFullyResolved(s: @This(), ip: *InternPool) bool {
879 if (s.layout == .Packed) return true;
880 const flags_ptr = s.flagsPtr(ip);
881 if (flags_ptr.fully_resolved) return true;
882 flags_ptr.fully_resolved = true;
883 return false;
884 }
885
886 pub fn clearFullyResolved(s: @This(), ip: *InternPool) void {
887 s.flagsPtr(ip).fully_resolved = false;
888 }
889
890 /// The returned pointer expires with any addition to the `InternPool`.
891 /// Asserts the struct is not packed.
892 pub fn size(self: @This(), ip: *InternPool) *u32 {
893 assert(self.layout != .Packed);
894 const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?;
895 return @ptrCast(&ip.extra.items[self.extra_index + size_field_index]);
896 }
897
898 /// The backing integer type of the packed struct. Whether zig chooses
899 /// this type or the user specifies it, it is stored here. This will be
900 /// set to `none` until the layout is resolved.
901 /// Asserts the struct is packed.
902 pub fn backingIntType(s: @This(), ip: *const InternPool) *Index {
903 assert(s.layout == .Packed);
904 const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?;
905 return @ptrCast(&ip.extra.items[s.extra_index + field_index]);
906 }
907
908 /// Asserts the struct is not packed.
909 pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
910 assert(s.layout != .Packed);
911 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;
912 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);
913 }
914
915 pub fn haveFieldTypes(s: @This(), ip: *const InternPool) bool {
916 const types = s.field_types.get(ip);
917 return types.len == 0 or types[0] != .none;
918 }
919
920 pub fn haveFieldInits(s: @This(), ip: *const InternPool) bool {
921 return switch (s.layout) {
922 .Packed => s.packedFlagsPtr(ip).inits_resolved,
923 .Auto, .Extern => s.flagsPtr(ip).inits_resolved,
924 };
925 }
926
927 pub fn setHaveFieldInits(s: @This(), ip: *InternPool) void {
928 switch (s.layout) {
929 .Packed => s.packedFlagsPtr(ip).inits_resolved = true,
930 .Auto, .Extern => s.flagsPtr(ip).inits_resolved = true,
931 }
932 }
933
934 pub fn haveLayout(s: @This(), ip: *InternPool) bool {
935 return switch (s.layout) {
936 .Packed => s.backingIntType(ip).* != .none,
937 .Auto, .Extern => s.flagsPtr(ip).layout_resolved,
938 };
939 }
940
941 pub fn isTuple(s: @This(), ip: *InternPool) bool {
942 return s.layout != .Packed and s.flagsPtr(ip).is_tuple;
943 }
944
945 pub fn hasReorderedFields(s: @This()) bool {
946 return s.layout == .Auto;
947 }
948
949 pub const RuntimeOrderIterator = struct {
950 ip: *InternPool,
951 field_index: u32,
952 struct_type: InternPool.Key.StructType,
953
954 pub fn next(it: *@This()) ?u32 {
955 var i = it.field_index;
956
957 if (i >= it.struct_type.field_types.len)
958 return null;
959
960 if (it.struct_type.hasReorderedFields()) {
961 it.field_index += 1;
962 return it.struct_type.runtime_order.get(it.ip)[i].toInt();
963 }
964
965 while (it.struct_type.fieldIsComptime(it.ip, i)) {
966 i += 1;
967 if (i >= it.struct_type.field_types.len)
968 return null;
969 }
970
971 it.field_index = i + 1;
972 return i;
973 }
974 };
975
976 /// Iterates over non-comptime fields in the order they are laid out in memory at runtime.
977 /// May or may not include zero-bit fields.
978 /// Asserts the struct is not packed.
979 pub fn iterateRuntimeOrder(s: @This(), ip: *InternPool) RuntimeOrderIterator {
980 assert(s.layout != .Packed);
981 return .{
982 .ip = ip,
983 .field_index = 0,
984 .struct_type = s,
985 };
986 }
987 };
988
989647 pub const AnonStructType = struct {
990648 types: Index.Slice,
991649 /// This may be empty, indicating this is a tuple.
......@@ -1009,156 +667,28 @@ pub const Key = union(enum) {
1009667 }
1010668 };
1011669
1012 /// Serves two purposes:
1013 /// * Being the key in the InternPool hash map, which only requires the `decl` field.
1014 /// * Provide the other fields that do not require chasing the enum type.
1015 pub const UnionType = struct {
1016 /// The Decl that corresponds to the union itself.
1017 decl: DeclIndex,
1018 /// The index of the `Tag.TypeUnion` payload. Ignored by `get`,
1019 /// populated by `indexToKey`.
1020 extra_index: u32,
1021 namespace: NamespaceIndex,
1022 flags: Tag.TypeUnion.Flags,
1023 /// The enum that provides the list of field names and values.
1024 enum_tag_ty: Index,
1025 zir_index: TrackedInst.Index.Optional,
1026
1027 /// The returned pointer expires with any addition to the `InternPool`.
1028 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags {
1029 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
1030 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
1031 }
1032
1033 /// The returned pointer expires with any addition to the `InternPool`.
1034 pub fn size(self: @This(), ip: *InternPool) *u32 {
1035 const size_field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?;
1036 return &ip.extra.items[self.extra_index + size_field_index];
1037 }
1038
1039 /// The returned pointer expires with any addition to the `InternPool`.
1040 pub fn padding(self: @This(), ip: *InternPool) *u32 {
1041 const padding_field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?;
1042 return &ip.extra.items[self.extra_index + padding_field_index];
1043 }
1044
1045 pub fn haveFieldTypes(self: @This(), ip: *const InternPool) bool {
1046 return self.flagsPtr(ip).status.haveFieldTypes();
1047 }
1048
1049 pub fn hasTag(self: @This(), ip: *const InternPool) bool {
1050 return self.flagsPtr(ip).runtime_tag.hasTag();
1051 }
1052
1053 pub fn getLayout(self: @This(), ip: *const InternPool) std.builtin.Type.ContainerLayout {
1054 return self.flagsPtr(ip).layout;
1055 }
1056
1057 pub fn haveLayout(self: @This(), ip: *const InternPool) bool {
1058 return self.flagsPtr(ip).status.haveLayout();
1059 }
1060
1061 /// Pointer to an enum type which is used for the tag of the union.
1062 /// This type is created even for untagged unions, even when the memory
1063 /// layout does not store the tag.
1064 /// Whether zig chooses this type or the user specifies it, it is stored here.
1065 /// This will be set to the null type until status is `have_field_types`.
1066 /// This accessor is provided so that the tag type can be mutated, and so that
1067 /// when it is mutated, the mutations are observed.
1068 /// The returned pointer is invalidated when something is added to the `InternPool`.
1069 pub fn tagTypePtr(self: @This(), ip: *const InternPool) *Index {
1070 const tag_ty_field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?;
1071 return @ptrCast(&ip.extra.items[self.extra_index + tag_ty_field_index]);
1072 }
670 /// This is the hashmap key. To fetch other data associated with the struct, see `loadStructType`.
671 pub const StructType = struct {
672 /// The struct's owner Decl. `none` when the struct is `@TypeOf(.{})`.
673 decl: OptionalDeclIndex,
674 };
1073675
1074 pub fn setFieldTypes(self: @This(), ip: *InternPool, types: []const Index) void {
1075 @memcpy((Index.Slice{
1076 .start = @intCast(self.extra_index + @typeInfo(Tag.TypeUnion).Struct.fields.len),
1077 .len = @intCast(types.len),
1078 }).get(ip), types);
1079 }
676 /// This is the hashmap key. To fetch other data associated with the opaque, see `loadOpaqueType`.
677 pub const OpaqueType = struct {
678 /// The opaque's owner Decl.
679 decl: DeclIndex,
680 };
1080681
1081 pub fn setFieldAligns(self: @This(), ip: *InternPool, aligns: []const Alignment) void {
1082 if (aligns.len == 0) return;
1083 assert(self.flagsPtr(ip).any_aligned_fields);
1084 @memcpy((Alignment.Slice{
1085 .start = @intCast(
1086 self.extra_index + @typeInfo(Tag.TypeUnion).Struct.fields.len + aligns.len,
1087 ),
1088 .len = @intCast(aligns.len),
1089 }).get(ip), aligns);
1090 }
682 /// This is the hashmap key. To fetch other data associated with the union, see `loadUnionType`.
683 pub const UnionType = struct {
684 /// The union's owner Decl.
685 decl: DeclIndex,
1091686 };
1092687
688 /// This is the hashmap key. To fetch other data associated with the enum, see `loadEnumType`.
1093689 pub const EnumType = struct {
1094 /// The Decl that corresponds to the enum itself.
690 /// The enum's owner Decl.
1095691 decl: DeclIndex,
1096 /// Represents the declarations inside this enum.
1097 namespace: OptionalNamespaceIndex,
1098 /// An integer type which is used for the numerical value of the enum.
1099 /// This field is present regardless of whether the enum has an
1100 /// explicitly provided tag type or auto-numbered.
1101 tag_ty: Index,
1102 /// Set of field names in declaration order.
1103 names: NullTerminatedString.Slice,
1104 /// Maps integer tag value to field index.
1105 /// Entries are in declaration order, same as `fields`.
1106 /// If this is empty, it means the enum tags are auto-numbered.
1107 values: Index.Slice,
1108 tag_mode: TagMode,
1109 /// This is ignored by `get` but will always be provided by `indexToKey`.
1110 names_map: OptionalMapIndex = .none,
1111 /// This is ignored by `get` but will be provided by `indexToKey` when
1112 /// a value map exists.
1113 values_map: OptionalMapIndex = .none,
1114 zir_index: TrackedInst.Index.Optional,
1115
1116 pub const TagMode = enum {
1117 /// The integer tag type was auto-numbered by zig.
1118 auto,
1119 /// The integer tag type was provided by the enum declaration, and the enum
1120 /// is exhaustive.
1121 explicit,
1122 /// The integer tag type was provided by the enum declaration, and the enum
1123 /// is non-exhaustive.
1124 nonexhaustive,
1125 };
1126
1127 /// Look up field index based on field name.
1128 pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
1129 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];
1130 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
1131 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
1132 return @intCast(field_index);
1133 }
1134
1135 /// Look up field index based on tag value.
1136 /// Asserts that `values_map` is not `none`.
1137 /// This function returns `null` when `tag_val` does not have the
1138 /// integer tag type of the enum.
1139 pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 {
1140 assert(tag_val != .none);
1141 // TODO: we should probably decide a single interface for this function, but currently
1142 // it's being called with both tag values and underlying ints. Fix this!
1143 const int_tag_val = switch (ip.indexToKey(tag_val)) {
1144 .enum_tag => |enum_tag| enum_tag.int,
1145 .int => tag_val,
1146 else => unreachable,
1147 };
1148 if (self.values_map.unwrap()) |values_map| {
1149 const map = &ip.maps.items[@intFromEnum(values_map)];
1150 const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };
1151 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
1152 return @intCast(field_index);
1153 }
1154 // Auto-numbered enum. Convert `int_tag_val` to field index.
1155 const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {
1156 inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null,
1157 .big_int => |x| x.to(u32) catch return null,
1158 .lazy_align, .lazy_size => unreachable,
1159 };
1160 return if (field_index < self.names.len) field_index else null;
1161 }
1162692 };
1163693
1164694 pub const IncompleteEnumType = struct {
......@@ -1173,12 +703,13 @@ pub const Key = union(enum) {
1173703 /// later when populating field values.
1174704 has_values: bool,
1175705 /// Same as corresponding `EnumType` field.
1176 tag_mode: EnumType.TagMode,
706 tag_mode: LoadedEnumType.TagMode,
1177707 /// This may be updated via `setTagType` later.
1178708 tag_ty: Index = .none,
1179709 zir_index: TrackedInst.Index.Optional,
1180710
1181 pub fn toEnumType(self: @This()) EnumType {
711 pub fn toEnumType(self: @This()) LoadedEnumType {
712 if (true) @compileError("AHHHH");
1182713 return .{
1183714 .decl = self.decl,
1184715 .namespace = self.namespace,
......@@ -1193,7 +724,7 @@ pub const Key = union(enum) {
1193724 /// Only the decl is used for hashing and equality, so we can construct
1194725 /// this minimal key for use with `map`.
1195726 pub fn toKey(self: @This()) Key {
1196 return .{ .enum_type = self.toEnumType() };
727 return .{ .enum_type = .{ .decl = self.decl } };
1197728 }
1198729 };
1199730
......@@ -2111,21 +1642,15 @@ pub const RequiresComptime = enum(u2) { no, yes, unknown, wip };
21111642// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a
21121643// minimal hashmap key, this type is a convenience type that contains info
21131644// needed by semantic analysis.
2114pub const UnionType = struct {
1645pub const LoadedUnionType = struct {
1646 /// The index of the `Tag.TypeUnion` payload.
1647 extra_index: u32,
21151648 /// The Decl that corresponds to the union itself.
21161649 decl: DeclIndex,
21171650 /// Represents the declarations inside this union.
21181651 namespace: NamespaceIndex,
21191652 /// The enum tag type.
21201653 enum_tag_ty: Index,
2121 /// The integer tag type of the enum.
2122 int_tag_ty: Index,
2123 /// ABI size of the union, including padding
2124 size: u64,
2125 /// Trailing padding bytes
2126 padding: u32,
2127 /// List of field names in declaration order.
2128 field_names: NullTerminatedString.Slice,
21291654 /// List of field types in declaration order.
21301655 /// These are `none` until `status` is `have_field_types` or `have_layout`.
21311656 field_types: Index.Slice,
......@@ -2135,10 +1660,6 @@ pub const UnionType = struct {
21351660 field_aligns: Alignment.Slice,
21361661 /// Index of the union_decl ZIR instruction.
21371662 zir_index: TrackedInst.Index.Optional,
2138 /// Index into extra array of the `flags` field.
2139 flags_index: u32,
2140 /// Copied from `enum_tag_ty`.
2141 names_map: OptionalMapIndex,
21421663
21431664 pub const RuntimeTag = enum(u2) {
21441665 none,
......@@ -2193,68 +1714,92 @@ pub const UnionType = struct {
21931714 }
21941715 };
21951716
1717 pub fn loadTagType(self: LoadedUnionType, ip: *InternPool) LoadedEnumType {
1718 return ip.loadEnumType(self.enum_tag_ty);
1719 }
1720
1721 /// Pointer to an enum type which is used for the tag of the union.
1722 /// This type is created even for untagged unions, even when the memory
1723 /// layout does not store the tag.
1724 /// Whether zig chooses this type or the user specifies it, it is stored here.
1725 /// This will be set to the null type until status is `have_field_types`.
1726 /// This accessor is provided so that the tag type can be mutated, and so that
1727 /// when it is mutated, the mutations are observed.
21961728 /// The returned pointer expires with any addition to the `InternPool`.
2197 pub fn flagsPtr(self: UnionType, ip: *const InternPool) *Tag.TypeUnion.Flags {
2198 return @ptrCast(&ip.extra.items[self.flags_index]);
1729 pub fn tagTypePtr(self: LoadedUnionType, ip: *const InternPool) *Index {
1730 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?;
1731 return @ptrCast(&ip.extra.items[self.extra_index + field_index]);
21991732 }
22001733
2201 /// Look up field index based on field name.
2202 pub fn nameIndex(self: UnionType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
2203 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];
2204 const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) };
2205 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
2206 return @intCast(field_index);
1734 /// The returned pointer expires with any addition to the `InternPool`.
1735 pub fn flagsPtr(self: LoadedUnionType, ip: *const InternPool) *Tag.TypeUnion.Flags {
1736 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
1737 return @ptrCast(&ip.extra.items[self.extra_index + field_index]);
1738 }
1739
1740 /// The returned pointer expires with any addition to the `InternPool`.
1741 pub fn size(self: LoadedUnionType, ip: *const InternPool) *u32 {
1742 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?;
1743 return &ip.extra.items[self.extra_index + field_index];
22071744 }
22081745
2209 pub fn hasTag(self: UnionType, ip: *const InternPool) bool {
1746 /// The returned pointer expires with any addition to the `InternPool`.
1747 pub fn padding(self: LoadedUnionType, ip: *const InternPool) *u32 {
1748 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?;
1749 return &ip.extra.items[self.extra_index + field_index];
1750 }
1751
1752 pub fn hasTag(self: LoadedUnionType, ip: *const InternPool) bool {
22101753 return self.flagsPtr(ip).runtime_tag.hasTag();
22111754 }
22121755
2213 pub fn haveFieldTypes(self: UnionType, ip: *const InternPool) bool {
1756 pub fn haveFieldTypes(self: LoadedUnionType, ip: *const InternPool) bool {
22141757 return self.flagsPtr(ip).status.haveFieldTypes();
22151758 }
22161759
2217 pub fn haveLayout(self: UnionType, ip: *const InternPool) bool {
1760 pub fn haveLayout(self: LoadedUnionType, ip: *const InternPool) bool {
22181761 return self.flagsPtr(ip).status.haveLayout();
22191762 }
22201763
2221 pub fn getLayout(self: UnionType, ip: *const InternPool) std.builtin.Type.ContainerLayout {
1764 pub fn getLayout(self: LoadedUnionType, ip: *const InternPool) std.builtin.Type.ContainerLayout {
22221765 return self.flagsPtr(ip).layout;
22231766 }
22241767
2225 pub fn fieldAlign(self: UnionType, ip: *const InternPool, field_index: u32) Alignment {
1768 pub fn fieldAlign(self: LoadedUnionType, ip: *const InternPool, field_index: u32) Alignment {
22261769 if (self.field_aligns.len == 0) return .none;
22271770 return self.field_aligns.get(ip)[field_index];
22281771 }
22291772
2230 /// This does not mutate the field of UnionType.
2231 pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
1773 /// This does not mutate the field of LoadedUnionType.
1774 pub fn setZirIndex(self: LoadedUnionType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
22321775 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
22331776 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;
22341777 const ptr: *TrackedInst.Index.Optional =
22351778 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);
22361779 ptr.* = new_zir_index;
22371780 }
1781
1782 pub fn setFieldTypes(self: LoadedUnionType, ip: *const InternPool, types: []const Index) void {
1783 @memcpy(self.field_types.get(ip), types);
1784 }
1785
1786 pub fn setFieldAligns(self: LoadedUnionType, ip: *const InternPool, aligns: []const Alignment) void {
1787 if (aligns.len == 0) return;
1788 assert(self.flagsPtr(ip).any_aligned_fields);
1789 @memcpy(self.field_aligns.get(ip), aligns);
1790 }
22381791};
22391792
2240/// Fetch all the interesting fields of a union type into a convenient data
2241/// structure.
2242/// This asserts that the union's enum tag type has been resolved.
2243pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {
2244 const type_union = ip.extraDataTrail(Tag.TypeUnion, key.extra_index);
2245 const enum_ty = type_union.data.tag_ty;
2246 const enum_info = ip.indexToKey(enum_ty).enum_type;
2247 const fields_len: u32 = @intCast(enum_info.names.len);
1793pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
1794 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
1795 const type_union = ip.extraDataTrail(Tag.TypeUnion, extra_index);
1796 const fields_len = type_union.data.fields_len;
22481797
22491798 return .{
1799 .extra_index = extra_index,
22501800 .decl = type_union.data.decl,
22511801 .namespace = type_union.data.namespace,
2252 .enum_tag_ty = enum_ty,
2253 .int_tag_ty = enum_info.tag_ty,
2254 .size = type_union.data.size,
2255 .padding = type_union.data.padding,
2256 .field_names = enum_info.names,
2257 .names_map = enum_info.names_map,
1802 .enum_tag_ty = type_union.data.tag_ty,
22581803 .field_types = .{
22591804 .start = type_union.end,
22601805 .len = fields_len,
......@@ -2264,10 +1809,583 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {
22641809 .len = if (type_union.data.flags.any_aligned_fields) fields_len else 0,
22651810 },
22661811 .zir_index = type_union.data.zir_index,
2267 .flags_index = key.extra_index + std.meta.fieldIndex(Tag.TypeUnion, "flags").?,
22681812 };
22691813}
22701814
1815pub const LoadedStructType = struct {
1816 /// The index of the `Tag.TypeStruct` or `Tag.TypeStructPacked` payload.
1817 extra_index: u32,
1818 /// The struct's owner Decl. `none` when the struct is `@TypeOf(.{})`.
1819 decl: OptionalDeclIndex,
1820 /// `none` when the struct has no declarations.
1821 namespace: OptionalNamespaceIndex,
1822 /// Index of the `struct_decl` ZIR instruction.
1823 zir_index: TrackedInst.Index.Optional,
1824 layout: std.builtin.Type.ContainerLayout,
1825 field_names: NullTerminatedString.Slice,
1826 field_types: Index.Slice,
1827 field_inits: Index.Slice,
1828 field_aligns: Alignment.Slice,
1829 runtime_order: RuntimeOrder.Slice,
1830 comptime_bits: ComptimeBits,
1831 offsets: Offsets,
1832 names_map: OptionalMapIndex,
1833
1834 pub const ComptimeBits = struct {
1835 start: u32,
1836 /// This is the number of u32 elements, not the number of struct fields.
1837 len: u32,
1838
1839 pub fn get(this: ComptimeBits, ip: *const InternPool) []u32 {
1840 return ip.extra.items[this.start..][0..this.len];
1841 }
1842
1843 pub fn getBit(this: ComptimeBits, ip: *const InternPool, i: usize) bool {
1844 if (this.len == 0) return false;
1845 return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0;
1846 }
1847
1848 pub fn setBit(this: ComptimeBits, ip: *const InternPool, i: usize) void {
1849 this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32);
1850 }
1851
1852 pub fn clearBit(this: ComptimeBits, ip: *const InternPool, i: usize) void {
1853 this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32));
1854 }
1855 };
1856
1857 pub const Offsets = struct {
1858 start: u32,
1859 len: u32,
1860
1861 pub fn get(this: Offsets, ip: *const InternPool) []u32 {
1862 return @ptrCast(ip.extra.items[this.start..][0..this.len]);
1863 }
1864 };
1865
1866 pub const RuntimeOrder = enum(u32) {
1867 /// Placeholder until layout is resolved.
1868 unresolved = std.math.maxInt(u32) - 0,
1869 /// Field not present at runtime
1870 omitted = std.math.maxInt(u32) - 1,
1871 _,
1872
1873 pub const Slice = struct {
1874 start: u32,
1875 len: u32,
1876
1877 pub fn get(slice: RuntimeOrder.Slice, ip: *const InternPool) []RuntimeOrder {
1878 return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
1879 }
1880 };
1881
1882 pub fn toInt(i: RuntimeOrder) ?u32 {
1883 return switch (i) {
1884 .omitted => null,
1885 .unresolved => unreachable,
1886 else => @intFromEnum(i),
1887 };
1888 }
1889 };
1890
1891 /// Look up field index based on field name.
1892 pub fn nameIndex(self: LoadedStructType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
1893 const names_map = self.names_map.unwrap() orelse {
1894 const i = name.toUnsigned(ip) orelse return null;
1895 if (i >= self.field_types.len) return null;
1896 return i;
1897 };
1898 const map = &ip.maps.items[@intFromEnum(names_map)];
1899 const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) };
1900 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
1901 return @intCast(field_index);
1902 }
1903
1904 /// Returns the already-existing field with the same name, if any.
1905 pub fn addFieldName(
1906 self: @This(),
1907 ip: *InternPool,
1908 name: NullTerminatedString,
1909 ) ?u32 {
1910 return ip.addFieldName(self.names_map.unwrap().?, self.field_names.start, name);
1911 }
1912
1913 pub fn fieldAlign(s: @This(), ip: *const InternPool, i: usize) Alignment {
1914 if (s.field_aligns.len == 0) return .none;
1915 return s.field_aligns.get(ip)[i];
1916 }
1917
1918 pub fn fieldInit(s: @This(), ip: *const InternPool, i: usize) Index {
1919 if (s.field_inits.len == 0) return .none;
1920 assert(s.haveFieldInits(ip));
1921 return s.field_inits.get(ip)[i];
1922 }
1923
1924 /// Returns `none` in the case the struct is a tuple.
1925 pub fn fieldName(s: @This(), ip: *const InternPool, i: usize) OptionalNullTerminatedString {
1926 if (s.field_names.len == 0) return .none;
1927 return s.field_names.get(ip)[i].toOptional();
1928 }
1929
1930 pub fn fieldIsComptime(s: @This(), ip: *const InternPool, i: usize) bool {
1931 return s.comptime_bits.getBit(ip, i);
1932 }
1933
1934 pub fn setFieldComptime(s: @This(), ip: *InternPool, i: usize) void {
1935 s.comptime_bits.setBit(ip, i);
1936 }
1937
1938 /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more
1939 /// complicated logic.
1940 pub fn knownNonOpv(s: @This(), ip: *InternPool) bool {
1941 return switch (s.layout) {
1942 .Packed => false,
1943 .Auto, .Extern => s.flagsPtr(ip).known_non_opv,
1944 };
1945 }
1946
1947 /// The returned pointer expires with any addition to the `InternPool`.
1948 /// Asserts the struct is not packed.
1949 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStruct.Flags {
1950 assert(self.layout != .Packed);
1951 const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?;
1952 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
1953 }
1954
1955 /// The returned pointer expires with any addition to the `InternPool`.
1956 /// Asserts that the struct is packed.
1957 pub fn packedFlagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeStructPacked.Flags {
1958 assert(self.layout == .Packed);
1959 const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?;
1960 return @ptrCast(&ip.extra.items[self.extra_index + flags_field_index]);
1961 }
1962
1963 pub fn assumeRuntimeBitsIfFieldTypesWip(s: @This(), ip: *InternPool) bool {
1964 if (s.layout == .Packed) return false;
1965 const flags_ptr = s.flagsPtr(ip);
1966 if (flags_ptr.field_types_wip) {
1967 flags_ptr.assumed_runtime_bits = true;
1968 return true;
1969 }
1970 return false;
1971 }
1972
1973 pub fn setTypesWip(s: @This(), ip: *InternPool) bool {
1974 if (s.layout == .Packed) return false;
1975 const flags_ptr = s.flagsPtr(ip);
1976 if (flags_ptr.field_types_wip) return true;
1977 flags_ptr.field_types_wip = true;
1978 return false;
1979 }
1980
1981 pub fn clearTypesWip(s: @This(), ip: *InternPool) void {
1982 if (s.layout == .Packed) return;
1983 s.flagsPtr(ip).field_types_wip = false;
1984 }
1985
1986 pub fn setLayoutWip(s: @This(), ip: *InternPool) bool {
1987 if (s.layout == .Packed) return false;
1988 const flags_ptr = s.flagsPtr(ip);
1989 if (flags_ptr.layout_wip) return true;
1990 flags_ptr.layout_wip = true;
1991 return false;
1992 }
1993
1994 pub fn clearLayoutWip(s: @This(), ip: *InternPool) void {
1995 if (s.layout == .Packed) return;
1996 s.flagsPtr(ip).layout_wip = false;
1997 }
1998
1999 pub fn setAlignmentWip(s: @This(), ip: *InternPool) bool {
2000 if (s.layout == .Packed) return false;
2001 const flags_ptr = s.flagsPtr(ip);
2002 if (flags_ptr.alignment_wip) return true;
2003 flags_ptr.alignment_wip = true;
2004 return false;
2005 }
2006
2007 pub fn clearAlignmentWip(s: @This(), ip: *InternPool) void {
2008 if (s.layout == .Packed) return;
2009 s.flagsPtr(ip).alignment_wip = false;
2010 }
2011
2012 pub fn setInitsWip(s: @This(), ip: *InternPool) bool {
2013 switch (s.layout) {
2014 .Packed => {
2015 const flag = &s.packedFlagsPtr(ip).field_inits_wip;
2016 if (flag.*) return true;
2017 flag.* = true;
2018 return false;
2019 },
2020 .Auto, .Extern => {
2021 const flag = &s.flagsPtr(ip).field_inits_wip;
2022 if (flag.*) return true;
2023 flag.* = true;
2024 return false;
2025 },
2026 }
2027 }
2028
2029 pub fn clearInitsWip(s: @This(), ip: *InternPool) void {
2030 switch (s.layout) {
2031 .Packed => s.packedFlagsPtr(ip).field_inits_wip = false,
2032 .Auto, .Extern => s.flagsPtr(ip).field_inits_wip = false,
2033 }
2034 }
2035
2036 pub fn setFullyResolved(s: @This(), ip: *InternPool) bool {
2037 if (s.layout == .Packed) return true;
2038 const flags_ptr = s.flagsPtr(ip);
2039 if (flags_ptr.fully_resolved) return true;
2040 flags_ptr.fully_resolved = true;
2041 return false;
2042 }
2043
2044 pub fn clearFullyResolved(s: @This(), ip: *InternPool) void {
2045 s.flagsPtr(ip).fully_resolved = false;
2046 }
2047
2048 /// The returned pointer expires with any addition to the `InternPool`.
2049 /// Asserts the struct is not packed.
2050 pub fn size(self: @This(), ip: *InternPool) *u32 {
2051 assert(self.layout != .Packed);
2052 const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?;
2053 return @ptrCast(&ip.extra.items[self.extra_index + size_field_index]);
2054 }
2055
2056 /// The backing integer type of the packed struct. Whether zig chooses
2057 /// this type or the user specifies it, it is stored here. This will be
2058 /// set to `none` until the layout is resolved.
2059 /// Asserts the struct is packed.
2060 pub fn backingIntType(s: @This(), ip: *const InternPool) *Index {
2061 assert(s.layout == .Packed);
2062 const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?;
2063 return @ptrCast(&ip.extra.items[s.extra_index + field_index]);
2064 }
2065
2066 /// Asserts the struct is not packed.
2067 pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
2068 assert(s.layout != .Packed);
2069 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;
2070 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);
2071 }
2072
2073 pub fn haveFieldTypes(s: @This(), ip: *const InternPool) bool {
2074 const types = s.field_types.get(ip);
2075 return types.len == 0 or types[0] != .none;
2076 }
2077
2078 pub fn haveFieldInits(s: @This(), ip: *const InternPool) bool {
2079 return switch (s.layout) {
2080 .Packed => s.packedFlagsPtr(ip).inits_resolved,
2081 .Auto, .Extern => s.flagsPtr(ip).inits_resolved,
2082 };
2083 }
2084
2085 pub fn setHaveFieldInits(s: @This(), ip: *InternPool) void {
2086 switch (s.layout) {
2087 .Packed => s.packedFlagsPtr(ip).inits_resolved = true,
2088 .Auto, .Extern => s.flagsPtr(ip).inits_resolved = true,
2089 }
2090 }
2091
2092 pub fn haveLayout(s: @This(), ip: *InternPool) bool {
2093 return switch (s.layout) {
2094 .Packed => s.backingIntType(ip).* != .none,
2095 .Auto, .Extern => s.flagsPtr(ip).layout_resolved,
2096 };
2097 }
2098
2099 pub fn isTuple(s: @This(), ip: *InternPool) bool {
2100 return s.layout != .Packed and s.flagsPtr(ip).is_tuple;
2101 }
2102
2103 pub fn hasReorderedFields(s: @This()) bool {
2104 return s.layout == .Auto;
2105 }
2106
2107 pub const RuntimeOrderIterator = struct {
2108 ip: *InternPool,
2109 field_index: u32,
2110 struct_type: InternPool.LoadedStructType,
2111
2112 pub fn next(it: *@This()) ?u32 {
2113 var i = it.field_index;
2114
2115 if (i >= it.struct_type.field_types.len)
2116 return null;
2117
2118 if (it.struct_type.hasReorderedFields()) {
2119 it.field_index += 1;
2120 return it.struct_type.runtime_order.get(it.ip)[i].toInt();
2121 }
2122
2123 while (it.struct_type.fieldIsComptime(it.ip, i)) {
2124 i += 1;
2125 if (i >= it.struct_type.field_types.len)
2126 return null;
2127 }
2128
2129 it.field_index = i + 1;
2130 return i;
2131 }
2132 };
2133
2134 /// Iterates over non-comptime fields in the order they are laid out in memory at runtime.
2135 /// May or may not include zero-bit fields.
2136 /// Asserts the struct is not packed.
2137 pub fn iterateRuntimeOrder(s: @This(), ip: *InternPool) RuntimeOrderIterator {
2138 assert(s.layout != .Packed);
2139 return .{
2140 .ip = ip,
2141 .field_index = 0,
2142 .struct_type = s,
2143 };
2144 }
2145};
2146
2147pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
2148 const item = ip.items.get(@intFromEnum(index));
2149 switch (item.tag) {
2150 .type_struct => {
2151 if (item.data == 0) return .{
2152 .extra_index = 0,
2153 .decl = .none,
2154 .namespace = .none,
2155 .zir_index = .none,
2156 .layout = .Auto,
2157 .field_names = .{ .start = 0, .len = 0 },
2158 .field_types = .{ .start = 0, .len = 0 },
2159 .field_inits = .{ .start = 0, .len = 0 },
2160 .field_aligns = .{ .start = 0, .len = 0 },
2161 .runtime_order = .{ .start = 0, .len = 0 },
2162 .comptime_bits = .{ .start = 0, .len = 0 },
2163 .offsets = .{ .start = 0, .len = 0 },
2164 .names_map = .none,
2165 };
2166 const extra = ip.extraDataTrail(Tag.TypeStruct, item.data);
2167 const fields_len = extra.data.fields_len;
2168 var extra_index = extra.end + fields_len; // skip field types
2169 const names_map: OptionalMapIndex, const names: NullTerminatedString.Slice = if (!extra.data.flags.is_tuple) n: {
2170 const names_map: OptionalMapIndex = @enumFromInt(ip.extra.items[extra_index]);
2171 extra_index += 1;
2172 const names: NullTerminatedString.Slice = .{ .start = extra_index, .len = fields_len };
2173 extra_index += fields_len;
2174 break :n .{ names_map, names };
2175 } else .{ .none, .{ .start = 0, .len = 0 } };
2176 const inits: Index.Slice = if (extra.data.flags.any_default_inits) i: {
2177 const inits: Index.Slice = .{ .start = extra_index, .len = fields_len };
2178 extra_index += fields_len;
2179 break :i inits;
2180 } else .{ .start = 0, .len = 0 };
2181 const namespace: OptionalNamespaceIndex = if (extra.data.flags.has_namespace) n: {
2182 const n: NamespaceIndex = @enumFromInt(ip.extra.items[extra_index]);
2183 extra_index += 1;
2184 break :n n.toOptional();
2185 } else .none;
2186 const aligns: Alignment.Slice = if (extra.data.flags.any_aligned_fields) a: {
2187 const a: Alignment.Slice = .{ .start = extra_index, .len = fields_len };
2188 extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;
2189 break :a a;
2190 } else .{ .start = 0, .len = 0 };
2191 const comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) c: {
2192 const len = std.math.divCeil(u32, fields_len, 32) catch unreachable;
2193 const c: LoadedStructType.ComptimeBits = .{ .start = extra_index, .len = len };
2194 extra_index += len;
2195 break :c c;
2196 } else .{ .start = 0, .len = 0 };
2197 const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!extra.data.flags.is_extern) ro: {
2198 const ro: LoadedStructType.RuntimeOrder.Slice = .{ .start = extra_index, .len = fields_len };
2199 extra_index += fields_len;
2200 break :ro ro;
2201 } else .{ .start = 0, .len = 0 };
2202 const offsets: LoadedStructType.Offsets = o: {
2203 const o: LoadedStructType.Offsets = .{ .start = extra_index, .len = fields_len };
2204 extra_index += fields_len;
2205 break :o o;
2206 };
2207 return .{
2208 .extra_index = item.data,
2209 .decl = extra.data.decl.toOptional(),
2210 .namespace = namespace,
2211 .zir_index = extra.data.zir_index,
2212 .layout = if (extra.data.flags.is_extern) .Extern else .Auto,
2213 .field_names = names,
2214 .field_types = .{ .start = extra.end, .len = fields_len },
2215 .field_inits = inits,
2216 .field_aligns = aligns,
2217 .runtime_order = runtime_order,
2218 .comptime_bits = comptime_bits,
2219 .offsets = offsets,
2220 .names_map = names_map,
2221 };
2222 },
2223 .type_struct_packed, .type_struct_packed_inits => {
2224 const extra = ip.extraDataTrail(Tag.TypeStructPacked, item.data);
2225 const has_inits = item.tag == .type_struct_packed_inits;
2226 const fields_len = extra.data.fields_len;
2227 return .{
2228 .extra_index = item.data,
2229 .decl = extra.data.decl.toOptional(),
2230 .namespace = extra.data.namespace,
2231 .zir_index = extra.data.zir_index,
2232 .layout = .Packed,
2233 .field_names = .{
2234 .start = extra.end + fields_len,
2235 .len = fields_len,
2236 },
2237 .field_types = .{
2238 .start = extra.end,
2239 .len = fields_len,
2240 },
2241 .field_inits = if (has_inits) .{
2242 .start = extra.end + 2 * fields_len,
2243 .len = fields_len,
2244 } else .{ .start = 0, .len = 0 },
2245 .field_aligns = .{ .start = 0, .len = 0 },
2246 .runtime_order = .{ .start = 0, .len = 0 },
2247 .comptime_bits = .{ .start = 0, .len = 0 },
2248 .offsets = .{ .start = 0, .len = 0 },
2249 .names_map = extra.data.names_map.toOptional(),
2250 };
2251 },
2252 else => unreachable,
2253 }
2254}
2255
2256const LoadedEnumType = struct {
2257 /// The Decl that corresponds to the enum itself.
2258 decl: DeclIndex,
2259 /// Represents the declarations inside this enum.
2260 namespace: OptionalNamespaceIndex,
2261 /// An integer type which is used for the numerical value of the enum.
2262 /// This field is present regardless of whether the enum has an
2263 /// explicitly provided tag type or auto-numbered.
2264 tag_ty: Index,
2265 /// Set of field names in declaration order.
2266 names: NullTerminatedString.Slice,
2267 /// Maps integer tag value to field index.
2268 /// Entries are in declaration order, same as `fields`.
2269 /// If this is empty, it means the enum tags are auto-numbered.
2270 values: Index.Slice,
2271 tag_mode: TagMode,
2272 names_map: MapIndex,
2273 /// This is guaranteed to not be `.none` if explicit values are provided.
2274 values_map: OptionalMapIndex,
2275 zir_index: TrackedInst.Index.Optional,
2276
2277 pub const TagMode = enum {
2278 /// The integer tag type was auto-numbered by zig.
2279 auto,
2280 /// The integer tag type was provided by the enum declaration, and the enum
2281 /// is exhaustive.
2282 explicit,
2283 /// The integer tag type was provided by the enum declaration, and the enum
2284 /// is non-exhaustive.
2285 nonexhaustive,
2286 };
2287
2288 /// Look up field index based on field name.
2289 pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
2290 const map = &ip.maps.items[@intFromEnum(self.names_map)];
2291 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
2292 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
2293 return @intCast(field_index);
2294 }
2295
2296 /// Look up field index based on tag value.
2297 /// Asserts that `values_map` is not `none`.
2298 /// This function returns `null` when `tag_val` does not have the
2299 /// integer tag type of the enum.
2300 pub fn tagValueIndex(self: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 {
2301 assert(tag_val != .none);
2302 // TODO: we should probably decide a single interface for this function, but currently
2303 // it's being called with both tag values and underlying ints. Fix this!
2304 const int_tag_val = switch (ip.indexToKey(tag_val)) {
2305 .enum_tag => |enum_tag| enum_tag.int,
2306 .int => tag_val,
2307 else => unreachable,
2308 };
2309 if (self.values_map.unwrap()) |values_map| {
2310 const map = &ip.maps.items[@intFromEnum(values_map)];
2311 const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };
2312 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
2313 return @intCast(field_index);
2314 }
2315 // Auto-numbered enum. Convert `int_tag_val` to field index.
2316 const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {
2317 inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null,
2318 .big_int => |x| x.to(u32) catch return null,
2319 .lazy_align, .lazy_size => unreachable,
2320 };
2321 return if (field_index < self.names.len) field_index else null;
2322 }
2323};
2324
2325pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
2326 const item = ip.items.get(@intFromEnum(index));
2327 switch (item.tag) {
2328 .type_enum_auto => {
2329 const extra = ip.extraDataTrail(EnumAuto, item.data);
2330 return .{
2331 .decl = extra.data.decl,
2332 .namespace = extra.data.namespace,
2333 .tag_ty = extra.data.int_tag_type,
2334 .names = .{
2335 .start = @intCast(extra.end),
2336 .len = extra.data.fields_len,
2337 },
2338 .values = .{ .start = 0, .len = 0 },
2339 .tag_mode = .auto,
2340 .names_map = extra.data.names_map,
2341 .values_map = .none,
2342 .zir_index = extra.data.zir_index,
2343 };
2344 },
2345 .type_enum_explicit, .type_enum_nonexhaustive => {
2346 const extra = ip.extraDataTrail(EnumExplicit, item.data);
2347 return .{
2348 .decl = extra.data.decl,
2349 .namespace = extra.data.namespace,
2350 .tag_ty = extra.data.int_tag_type,
2351 .names = .{
2352 .start = @intCast(extra.end),
2353 .len = extra.data.fields_len,
2354 },
2355 .values = .{
2356 .start = @intCast(extra.end + extra.data.fields_len),
2357 .len = if (extra.data.values_map != .none) extra.data.fields_len else 0,
2358 },
2359 .tag_mode = switch (item.tag) {
2360 .type_enum_explicit => .explicit,
2361 .type_enum_nonexhaustive => .nonexhaustive,
2362 else => unreachable,
2363 },
2364 .names_map = extra.data.names_map,
2365 .values_map = extra.data.values_map,
2366 .zir_index = extra.data.zir_index,
2367 };
2368 },
2369 else => unreachable,
2370 }
2371}
2372
2373/// Note that this type doubles as the payload for `Tag.type_opaque`.
2374pub const LoadedOpaqueType = struct {
2375 /// The opaque's owner Decl.
2376 decl: DeclIndex,
2377 /// Contains the declarations inside this opaque.
2378 namespace: NamespaceIndex,
2379 /// The index of the `opaque_decl` instruction.
2380 zir_index: TrackedInst.Index.Optional,
2381};
2382
2383pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
2384 assert(ip.items.items(.tag)[@intFromEnum(index)] == .type_opaque);
2385 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
2386 return ip.extraData(LoadedOpaqueType, extra_index);
2387}
2388
22712389pub const Item = struct {
22722390 tag: Tag,
22732391 /// The doc comments on the respective Tag explain how to interpret this.
......@@ -2485,7 +2603,6 @@ pub const Index = enum(u32) {
24852603 simple_type: struct { data: SimpleType },
24862604 type_opaque: struct { data: *Key.OpaqueType },
24872605 type_struct: struct { data: *Tag.TypeStruct },
2488 type_struct_ns: struct { data: NamespaceIndex },
24892606 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
24902607 type_struct_packed: struct { data: *Tag.TypeStructPacked },
24912608 type_struct_packed_inits: struct { data: *Tag.TypeStructPacked },
......@@ -2925,9 +3042,6 @@ pub const Tag = enum(u8) {
29253042 /// data is 0 or extra index of `TypeStruct`.
29263043 /// data == 0 represents `@TypeOf(.{})`.
29273044 type_struct,
2928 /// A non-packed struct type that has only a namespace; no fields.
2929 /// data is NamespaceIndex.
2930 type_struct_ns,
29313045 /// An AnonStructType which stores types, names, and values for fields.
29323046 /// data is extra index of `TypeStructAnon`.
29333047 type_struct_anon,
......@@ -3125,7 +3239,7 @@ pub const Tag = enum(u8) {
31253239 memoized_call,
31263240
31273241 const ErrorUnionType = Key.ErrorUnionType;
3128 const OpaqueType = Key.OpaqueType;
3242 const OpaqueType = LoadedOpaqueType;
31293243 const TypeValue = Key.TypeValue;
31303244 const Error = Key.Error;
31313245 const EnumTag = Key.EnumTag;
......@@ -3154,7 +3268,6 @@ pub const Tag = enum(u8) {
31543268 .simple_type => unreachable,
31553269 .type_opaque => OpaqueType,
31563270 .type_struct => TypeStruct,
3157 .type_struct_ns => unreachable,
31583271 .type_struct_anon => TypeStructAnon,
31593272 .type_struct_packed, .type_struct_packed_inits => TypeStructPacked,
31603273 .type_tuple_anon => TypeStructAnon,
......@@ -3310,12 +3423,15 @@ pub const Tag = enum(u8) {
33103423 };
33113424 };
33123425
3313 /// The number of fields is provided by the `tag_ty` field.
33143426 /// Trailing:
33153427 /// 0. field type: Index for each field; declaration order
33163428 /// 1. field align: Alignment for each field; declaration order
33173429 pub const TypeUnion = struct {
33183430 flags: Flags,
3431 /// This could be provided through the tag type, but it is more convenient
3432 /// to store it directly. This is also necessary for `dumpStatsFallible` to
3433 /// work on unresolved types.
3434 fields_len: u32,
33193435 /// Only valid after .have_layout
33203436 size: u32,
33213437 /// Only valid after .have_layout
......@@ -3327,11 +3443,11 @@ pub const Tag = enum(u8) {
33273443 zir_index: TrackedInst.Index.Optional,
33283444
33293445 pub const Flags = packed struct(u32) {
3330 runtime_tag: UnionType.RuntimeTag,
3446 runtime_tag: LoadedUnionType.RuntimeTag,
33313447 /// If false, the field alignment trailing data is omitted.
33323448 any_aligned_fields: bool,
33333449 layout: std.builtin.Type.ContainerLayout,
3334 status: UnionType.Status,
3450 status: LoadedUnionType.Status,
33353451 requires_comptime: RequiresComptime,
33363452 assumed_runtime_bits: bool,
33373453 assumed_pointer_aligned: bool,
......@@ -4074,65 +4190,27 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
40744190 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
40754191
40764192 .type_struct => .{ .struct_type = if (data == 0) .{
4077 .extra_index = 0,
4078 .namespace = .none,
40794193 .decl = .none,
4080 .zir_index = undefined,
4081 .layout = .Auto,
4082 .field_names = .{ .start = 0, .len = 0 },
4083 .field_types = .{ .start = 0, .len = 0 },
4084 .field_inits = .{ .start = 0, .len = 0 },
4085 .field_aligns = .{ .start = 0, .len = 0 },
4086 .runtime_order = .{ .start = 0, .len = 0 },
4087 .comptime_bits = .{ .start = 0, .len = 0 },
4088 .offsets = .{ .start = 0, .len = 0 },
4089 .names_map = undefined,
4090 } else extraStructType(ip, data) },
4091
4092 .type_struct_ns => .{ .struct_type = .{
4093 .extra_index = 0,
4094 .namespace = @as(NamespaceIndex, @enumFromInt(data)).toOptional(),
4095 .decl = .none,
4096 .zir_index = undefined,
4097 .layout = .Auto,
4098 .field_names = .{ .start = 0, .len = 0 },
4099 .field_types = .{ .start = 0, .len = 0 },
4100 .field_inits = .{ .start = 0, .len = 0 },
4101 .field_aligns = .{ .start = 0, .len = 0 },
4102 .runtime_order = .{ .start = 0, .len = 0 },
4103 .comptime_bits = .{ .start = 0, .len = 0 },
4104 .offsets = .{ .start = 0, .len = 0 },
4105 .names_map = undefined,
4194 } else .{
4195 .decl = ip.extraData(Tag.TypeStruct, data).decl.toOptional(),
4196 } },
4197
4198 .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = .{
4199 .decl = ip.extraData(Tag.TypeStructPacked, data).decl.toOptional(),
41064200 } },
41074201
41084202 .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(ip, data) },
41094203 .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(ip, data) },
4110 .type_struct_packed => .{ .struct_type = extraPackedStructType(ip, data, false) },
4111 .type_struct_packed_inits => .{ .struct_type = extraPackedStructType(ip, data, true) },
4112 .type_union => .{ .union_type = extraUnionType(ip, data) },
4204 .type_union => .{ .union_type = .{
4205 .decl = ip.extraData(Tag.TypeUnion, data).decl,
4206 } },
41134207
4114 .type_enum_auto => {
4115 const enum_auto = ip.extraDataTrail(EnumAuto, data);
4116 return .{ .enum_type = .{
4117 .decl = enum_auto.data.decl,
4118 .namespace = enum_auto.data.namespace,
4119 .tag_ty = enum_auto.data.int_tag_type,
4120 .names = .{
4121 .start = @intCast(enum_auto.end),
4122 .len = enum_auto.data.fields_len,
4123 },
4124 .values = .{
4125 .start = 0,
4126 .len = 0,
4127 },
4128 .tag_mode = .auto,
4129 .names_map = enum_auto.data.names_map.toOptional(),
4130 .values_map = .none,
4131 .zir_index = enum_auto.data.zir_index,
4132 } };
4133 },
4134 .type_enum_explicit => ip.indexToKeyEnum(data, .explicit),
4135 .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive),
4208 .type_enum_auto => .{ .enum_type = .{
4209 .decl = ip.extraData(EnumAuto, data).decl,
4210 } },
4211 .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = .{
4212 .decl = ip.extraData(EnumExplicit, data).decl,
4213 } },
41364214 .type_function => .{ .func_type = ip.extraFuncType(data) },
41374215
41384216 .undef => .{ .undef = @as(Index, @enumFromInt(data)) },
......@@ -4365,7 +4443,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
43654443 },
43664444 .type_array_small,
43674445 .type_vector,
4368 .type_struct_ns,
43694446 .type_struct_packed,
43704447 => .{ .aggregate = .{
43714448 .ty = ty,
......@@ -4374,16 +4451,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
43744451
43754452 // There is only one possible value precisely due to the
43764453 // fact that this values slice is fully populated!
4377 .type_struct => {
4378 const info = extraStructType(ip, ty_item.data);
4379 return .{ .aggregate = .{
4380 .ty = ty,
4381 .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) },
4382 } };
4383 },
4384
4385 .type_struct_packed_inits => {
4386 const info = extraPackedStructType(ip, ty_item.data, true);
4454 .type_struct, .type_struct_packed_inits => {
4455 const info = loadStructType(ip, ty);
43874456 return .{ .aggregate = .{
43884457 .ty = ty,
43894458 .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) },
......@@ -4475,18 +4544,6 @@ fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType {
44754544 };
44764545}
44774546
4478fn extraUnionType(ip: *const InternPool, extra_index: u32) Key.UnionType {
4479 const type_union = ip.extraData(Tag.TypeUnion, extra_index);
4480 return .{
4481 .decl = type_union.decl,
4482 .namespace = type_union.namespace,
4483 .flags = type_union.flags,
4484 .enum_tag_ty = type_union.tag_ty,
4485 .zir_index = type_union.zir_index,
4486 .extra_index = extra_index,
4487 };
4488}
4489
44904547fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType {
44914548 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index);
44924549 const fields_len = type_struct_anon.data.fields_len;
......@@ -4525,109 +4582,6 @@ fn extraTypeTupleAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructTyp
45254582 };
45264583}
45274584
4528fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
4529 const s = ip.extraDataTrail(Tag.TypeStruct, extra_index);
4530 const fields_len = s.data.fields_len;
4531
4532 var index = s.end;
4533
4534 const field_types = t: {
4535 const types: Index.Slice = .{ .start = index, .len = fields_len };
4536 index += fields_len;
4537 break :t types;
4538 };
4539 const names_map, const field_names: NullTerminatedString.Slice = t: {
4540 if (s.data.flags.is_tuple) break :t .{ .none, .{ .start = 0, .len = 0 } };
4541 const names_map: MapIndex = @enumFromInt(ip.extra.items[index]);
4542 index += 1;
4543 const names: NullTerminatedString.Slice = .{ .start = index, .len = fields_len };
4544 index += fields_len;
4545 break :t .{ names_map.toOptional(), names };
4546 };
4547 const field_inits: Index.Slice = t: {
4548 if (!s.data.flags.any_default_inits) break :t .{ .start = 0, .len = 0 };
4549 const inits: Index.Slice = .{ .start = index, .len = fields_len };
4550 index += fields_len;
4551 break :t inits;
4552 };
4553 const namespace = t: {
4554 if (!s.data.flags.has_namespace) break :t .none;
4555 const namespace: NamespaceIndex = @enumFromInt(ip.extra.items[index]);
4556 index += 1;
4557 break :t namespace.toOptional();
4558 };
4559 const field_aligns: Alignment.Slice = t: {
4560 if (!s.data.flags.any_aligned_fields) break :t .{ .start = 0, .len = 0 };
4561 const aligns: Alignment.Slice = .{ .start = index, .len = fields_len };
4562 index += (fields_len + 3) / 4;
4563 break :t aligns;
4564 };
4565 const comptime_bits: Key.StructType.ComptimeBits = t: {
4566 if (!s.data.flags.any_comptime_fields) break :t .{ .start = 0, .len = 0 };
4567 const comptime_bits: Key.StructType.ComptimeBits = .{ .start = index, .len = fields_len };
4568 index += (fields_len + 31) / 32;
4569 break :t comptime_bits;
4570 };
4571 const runtime_order: Key.StructType.RuntimeOrder.Slice = t: {
4572 if (s.data.flags.is_extern) break :t .{ .start = 0, .len = 0 };
4573 const ro: Key.StructType.RuntimeOrder.Slice = .{ .start = index, .len = fields_len };
4574 index += fields_len;
4575 break :t ro;
4576 };
4577 const offsets = t: {
4578 const offsets: Key.StructType.Offsets = .{ .start = index, .len = fields_len };
4579 index += fields_len;
4580 break :t offsets;
4581 };
4582 return .{
4583 .extra_index = extra_index,
4584 .decl = s.data.decl.toOptional(),
4585 .zir_index = s.data.zir_index,
4586 .layout = if (s.data.flags.is_extern) .Extern else .Auto,
4587 .field_types = field_types,
4588 .names_map = names_map,
4589 .field_names = field_names,
4590 .field_inits = field_inits,
4591 .namespace = namespace,
4592 .field_aligns = field_aligns,
4593 .comptime_bits = comptime_bits,
4594 .runtime_order = runtime_order,
4595 .offsets = offsets,
4596 };
4597}
4598
4599fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) Key.StructType {
4600 const type_struct_packed = ip.extraDataTrail(Tag.TypeStructPacked, extra_index);
4601 const fields_len = type_struct_packed.data.fields_len;
4602 return .{
4603 .extra_index = extra_index,
4604 .decl = type_struct_packed.data.decl.toOptional(),
4605 .namespace = type_struct_packed.data.namespace,
4606 .zir_index = type_struct_packed.data.zir_index,
4607 .layout = .Packed,
4608 .field_types = .{
4609 .start = type_struct_packed.end,
4610 .len = fields_len,
4611 },
4612 .field_names = .{
4613 .start = type_struct_packed.end + fields_len,
4614 .len = fields_len,
4615 },
4616 .field_inits = if (inits) .{
4617 .start = type_struct_packed.end + fields_len * 2,
4618 .len = fields_len,
4619 } else .{
4620 .start = 0,
4621 .len = 0,
4622 },
4623 .field_aligns = .{ .start = 0, .len = 0 },
4624 .runtime_order = .{ .start = 0, .len = 0 },
4625 .comptime_bits = .{ .start = 0, .len = 0 },
4626 .offsets = .{ .start = 0, .len = 0 },
4627 .names_map = type_struct_packed.data.names_map.toOptional(),
4628 };
4629}
4630
46314585fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
46324586 const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index);
46334587 var index: usize = type_function.end;
......@@ -4719,28 +4673,6 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
47194673 return func;
47204674}
47214675
4722fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
4723 const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
4724 const fields_len = enum_explicit.data.fields_len;
4725 return .{ .enum_type = .{
4726 .decl = enum_explicit.data.decl,
4727 .namespace = enum_explicit.data.namespace,
4728 .tag_ty = enum_explicit.data.int_tag_type,
4729 .names = .{
4730 .start = @intCast(enum_explicit.end),
4731 .len = fields_len,
4732 },
4733 .values = .{
4734 .start = @intCast(enum_explicit.end + fields_len),
4735 .len = if (enum_explicit.data.values_map != .none) fields_len else 0,
4736 },
4737 .tag_mode = tag_mode,
4738 .names_map = enum_explicit.data.names_map.toOptional(),
4739 .values_map = enum_explicit.data.values_map,
4740 .zir_index = enum_explicit.data.zir_index,
4741 } };
4742}
4743
47444676fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key {
47454677 const int_info = ip.limbData(Int, limb_index);
47464678 return .{ .int = .{
......@@ -4900,13 +4832,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
49004832 .struct_type => unreachable, // use getStructType() instead
49014833 .anon_struct_type => unreachable, // use getAnonStructType() instead
49024834 .union_type => unreachable, // use getUnionType() instead
4903
4904 .opaque_type => |opaque_type| {
4905 ip.items.appendAssumeCapacity(.{
4906 .tag = .type_opaque,
4907 .data = try ip.addExtra(gpa, opaque_type),
4908 });
4909 },
4835 .opaque_type => unreachable, // use getOpaqueType() instead
49104836
49114837 .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead
49124838 .func_type => unreachable, // use getFuncType() instead
......@@ -5026,14 +4952,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
50264952 assert(ptr.addr == .field);
50274953 assert(base_index.index < anon_struct_type.types.len);
50284954 },
5029 .struct_type => |struct_type| {
4955 .struct_type => {
50304956 assert(ptr.addr == .field);
5031 assert(base_index.index < struct_type.field_types.len);
4957 assert(base_index.index < ip.loadStructType(base_ptr_type.child).field_types.len);
50324958 },
5033 .union_type => |union_key| {
5034 const union_type = ip.loadUnionType(union_key);
4959 .union_type => {
4960 const union_type = ip.loadUnionType(base_ptr_type.child);
50354961 assert(ptr.addr == .field);
5036 assert(base_index.index < union_type.field_names.len);
4962 assert(base_index.index < union_type.field_types.len);
50374963 },
50384964 .ptr_type => |slice_type| {
50394965 assert(ptr.addr == .field);
......@@ -5304,7 +5230,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
53045230 assert(ip.isEnumType(enum_tag.ty));
53055231 switch (ip.indexToKey(enum_tag.ty)) {
53065232 .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))),
5307 .enum_type => |enum_type| assert(ip.typeOf(enum_tag.int) == enum_type.tag_ty),
5233 .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).tag_ty),
53085234 else => unreachable,
53095235 }
53105236 ip.items.appendAssumeCapacity(.{
......@@ -5397,8 +5323,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
53975323 assert(ip.typeOf(elem) == child);
53985324 }
53995325 },
5400 .struct_type => |t| {
5401 for (aggregate.storage.values(), t.field_types.get(ip)) |elem, field_ty| {
5326 .struct_type => {
5327 for (aggregate.storage.values(), ip.loadStructType(aggregate.ty).field_types.get(ip)) |elem, field_ty| {
54025328 assert(ip.typeOf(elem) == field_ty);
54035329 }
54045330 },
......@@ -5596,6 +5522,7 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
55965522
55975523 const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{
55985524 .flags = ini.flags,
5525 .fields_len = ini.fields_len,
55995526 .size = std.math.maxInt(u32),
56005527 .padding = std.math.maxInt(u32),
56015528 .decl = ini.decl,
......@@ -5628,7 +5555,7 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
56285555
56295556 const adapter: KeyAdapter = .{ .intern_pool = ip };
56305557 const gop = try ip.map.getOrPutAdapted(gpa, Key{
5631 .union_type = extraUnionType(ip, union_type_extra_index),
5558 .union_type = .{ .decl = ini.decl },
56325559 }, adapter);
56335560 if (gop.found_existing) {
56345561 ip.extra.items.len = prev_extra_len;
......@@ -5664,23 +5591,7 @@ pub fn getStructType(
56645591) Allocator.Error!Index {
56655592 const adapter: KeyAdapter = .{ .intern_pool = ip };
56665593 const key: Key = .{
5667 .struct_type = .{
5668 // Only the decl matters for hashing and equality purposes.
5669 .decl = ini.decl.toOptional(),
5670
5671 .extra_index = undefined,
5672 .namespace = undefined,
5673 .zir_index = undefined,
5674 .layout = undefined,
5675 .field_names = undefined,
5676 .field_types = undefined,
5677 .field_inits = undefined,
5678 .field_aligns = undefined,
5679 .runtime_order = undefined,
5680 .comptime_bits = undefined,
5681 .offsets = undefined,
5682 .names_map = undefined,
5683 },
5594 .struct_type = .{ .decl = ini.decl.toOptional() },
56845595 };
56855596 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
56865597 if (gop.found_existing) return @enumFromInt(gop.index);
......@@ -5776,7 +5687,7 @@ pub fn getStructType(
57765687 ip.extra.appendNTimesAssumeCapacity(0, comptime_elements_len);
57775688 }
57785689 if (ini.layout == .Auto) {
5779 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Key.StructType.RuntimeOrder.unresolved), ini.fields_len);
5690 ip.extra.appendNTimesAssumeCapacity(@intFromEnum(LoadedStructType.RuntimeOrder.unresolved), ini.fields_len);
57805691 }
57815692 ip.extra.appendNTimesAssumeCapacity(std.math.maxInt(u32), ini.fields_len);
57825693 return @enumFromInt(ip.items.len - 1);
......@@ -6579,26 +6490,14 @@ pub const GetEnumInit = struct {
65796490 tag_ty: Index,
65806491 names: []const NullTerminatedString,
65816492 values: []const Index,
6582 tag_mode: Key.EnumType.TagMode,
6493 tag_mode: LoadedEnumType.TagMode,
65836494 zir_index: TrackedInst.Index.Optional,
65846495};
65856496
65866497pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {
65876498 const adapter: KeyAdapter = .{ .intern_pool = ip };
65886499 const gop = try ip.map.getOrPutAdapted(gpa, Key{
6589 .enum_type = .{
6590 // Only the decl is used for hashing and equality.
6591 .decl = ini.decl,
6592
6593 .namespace = undefined,
6594 .tag_ty = undefined,
6595 .names = undefined,
6596 .values = undefined,
6597 .tag_mode = undefined,
6598 .names_map = undefined,
6599 .values_map = undefined,
6600 .zir_index = undefined,
6601 },
6500 .enum_type = .{ .decl = ini.decl },
66026501 }, adapter);
66036502 if (gop.found_existing) return @enumFromInt(gop.index);
66046503 errdefer _ = ip.map.pop();
......@@ -6668,6 +6567,21 @@ pub fn finishGetEnum(
66686567 return @enumFromInt(ip.items.len - 1);
66696568}
66706569
6570pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, key: LoadedOpaqueType) Allocator.Error!Index {
6571 const adapter: KeyAdapter = .{ .intern_pool = ip };
6572 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(LoadedOpaqueType).Struct.fields.len);
6573 try ip.items.ensureUnusedCapacity(gpa, 1);
6574 const gop = try ip.map.getOrPutAdapted(gpa, Key{
6575 .opaque_type = .{ .decl = key.decl },
6576 }, adapter);
6577 if (gop.found_existing) return @enumFromInt(gop.index);
6578 ip.items.appendAssumeCapacity(.{
6579 .tag = .type_opaque,
6580 .data = ip.addExtraAssumeCapacity(key),
6581 });
6582 return @enumFromInt(gop.index);
6583}
6584
66716585pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
66726586 const adapter: KeyAdapter = .{ .intern_pool = ip };
66736587 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;
......@@ -7075,9 +6989,9 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
70756989 .func => unreachable,
70766990
70776991 .int => |int| switch (ip.indexToKey(new_ty)) {
7078 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
6992 .enum_type => return ip.get(gpa, .{ .enum_tag = .{
70796993 .ty = new_ty,
7080 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
6994 .int = try ip.getCoerced(gpa, val, ip.loadEnumType(new_ty).tag_ty),
70816995 } }),
70826996 .ptr_type => return ip.get(gpa, .{ .ptr = .{
70836997 .ty = new_ty,
......@@ -7106,7 +7020,8 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
71067020 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
71077021 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
71087022 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
7109 .enum_type => |enum_type| {
7023 .enum_type => {
7024 const enum_type = ip.loadEnumType(new_ty);
71107025 const index = enum_type.nameIndex(ip, enum_literal).?;
71117026 return ip.get(gpa, .{ .enum_tag = .{
71127027 .ty = new_ty,
......@@ -7247,7 +7162,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
72477162 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
72487163 inline .array_type, .vector_type => |seq_type| seq_type.child,
72497164 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[i],
7250 .struct_type => |struct_type| struct_type.field_types.get(ip)[i],
7165 .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i],
72517166 else => unreachable,
72527167 };
72537168 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
......@@ -7550,7 +7465,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
75507465 ints += info.fields_len; // offsets
75517466 break :b @sizeOf(u32) * ints;
75527467 },
7553 .type_struct_ns => @sizeOf(Module.Namespace),
75547468 .type_struct_anon => b: {
75557469 const info = ip.extraData(TypeStructAnon, data);
75567470 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
......@@ -7572,7 +7486,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
75727486
75737487 .type_union => b: {
75747488 const info = ip.extraData(Tag.TypeUnion, data);
7575 const enum_info = ip.indexToKey(info.tag_ty).enum_type;
7489 const enum_info = ip.loadEnumType(info.tag_ty);
75767490 const fields_len: u32 = @intCast(enum_info.names.len);
75777491 const per_field = @sizeOf(u32); // field type
75787492 // 1 byte per field for alignment, rounded up to the nearest 4 bytes
......@@ -7716,7 +7630,6 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
77167630 .type_enum_auto,
77177631 .type_opaque,
77187632 .type_struct,
7719 .type_struct_ns,
77207633 .type_struct_anon,
77217634 .type_struct_packed,
77227635 .type_struct_packed_inits,
......@@ -8123,7 +8036,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
81238036 .simple_type,
81248037 .type_opaque,
81258038 .type_struct,
8126 .type_struct_ns,
81278039 .type_struct_anon,
81288040 .type_struct_packed,
81298041 .type_struct_packed_inits,
......@@ -8217,7 +8129,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
82178129
82188130pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
82198131 return switch (ip.indexToKey(ty)) {
8220 .struct_type => |struct_type| struct_type.field_types.len,
8132 .struct_type => ip.loadStructType(ty).field_types.len,
82218133 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
82228134 .array_type => |array_type| array_type.len,
82238135 .vector_type => |vector_type| vector_type.len,
......@@ -8227,7 +8139,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
82278139
82288140pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
82298141 return switch (ip.indexToKey(ty)) {
8230 .struct_type => |struct_type| struct_type.field_types.len,
8142 .struct_type => ip.loadStructType(ty).field_types.len,
82318143 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
82328144 .array_type => |array_type| array_type.len + @intFromBool(array_type.sentinel != .none),
82338145 .vector_type => |vector_type| vector_type.len,
......@@ -8457,7 +8369,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
84578369 .type_opaque => .Opaque,
84588370
84598371 .type_struct,
8460 .type_struct_ns,
84618372 .type_struct_anon,
84628373 .type_struct_packed,
84638374 .type_struct_packed_inits,
src/Liveness.zig+2-2
......@@ -131,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type {
131131 };
132132}
133133
134pub fn analyze(gpa: Allocator, air: Air, intern_pool: *const InternPool) Allocator.Error!Liveness {
134pub fn analyze(gpa: Allocator, air: Air, intern_pool: *InternPool) Allocator.Error!Liveness {
135135 const tracy = trace(@src());
136136 defer tracy.end();
137137
......@@ -836,7 +836,7 @@ pub const BigTomb = struct {
836836const Analysis = struct {
837837 gpa: Allocator,
838838 air: Air,
839 intern_pool: *const InternPool,
839 intern_pool: *InternPool,
840840 tomb_bits: []usize,
841841 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
842842 extra: std.ArrayListUnmanaged(u32),
src/Module.zig+27-29
......@@ -527,7 +527,7 @@ pub const Decl = struct {
527527
528528 /// If the Decl owns its value and it is a union, return it,
529529 /// otherwise null.
530 pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.UnionType {
530 pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.LoadedUnionType {
531531 if (!decl.owns_tv) return null;
532532 if (decl.val.ip_index == .none) return null;
533533 return zcu.typeToUnion(decl.val.toType());
......@@ -563,14 +563,15 @@ pub const Decl = struct {
563563 /// enum, or opaque.
564564 pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex {
565565 if (!decl.has_tv) return .none;
566 const ip = &zcu.intern_pool;
566567 return switch (decl.val.ip_index) {
567568 .empty_struct_type => .none,
568569 .none => .none,
569 else => switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) {
570 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
571 .struct_type => |struct_type| struct_type.namespace,
572 .union_type => |union_type| union_type.namespace.toOptional(),
573 .enum_type => |enum_type| enum_type.namespace,
570 else => switch (ip.indexToKey(decl.val.toIntern())) {
571 .opaque_type => ip.loadOpaqueType(decl.val.toIntern()).namespace.toOptional(),
572 .struct_type => ip.loadStructType(decl.val.toIntern()).namespace,
573 .union_type => ip.loadUnionType(decl.val.toIntern()).namespace.toOptional(),
574 .enum_type => ip.loadEnumType(decl.val.toIntern()).namespace,
574575 else => .none,
575576 },
576577 };
......@@ -5682,7 +5683,7 @@ pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Er
56825683pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value {
56835684 const ip = &mod.intern_pool;
56845685 const gpa = mod.gpa;
5685 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
5686 const enum_type = ip.loadEnumType(ty.toIntern());
56865687
56875688 if (enum_type.values.len == 0) {
56885689 // Auto-numbered fields.
......@@ -5988,28 +5989,26 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
59885989/// * `@TypeOf(.{})`
59895990/// * A struct which has no fields (`struct {}`).
59905991/// * Not a struct.
5991pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType {
5992pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType {
59925993 if (ty.ip_index == .none) return null;
5993 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
5994 .struct_type => |t| t,
5994 const ip = &mod.intern_pool;
5995 return switch (ip.indexToKey(ty.ip_index)) {
5996 .struct_type => ip.loadStructType(ty.ip_index),
59955997 else => null,
59965998 };
59975999}
59986000
5999pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType {
6000 if (ty.ip_index == .none) return null;
6001 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
6002 .struct_type => |t| if (t.layout == .Packed) t else null,
6003 else => null,
6004 };
6001pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType {
6002 const s = mod.typeToStruct(ty) orelse return null;
6003 if (s.layout != .Packed) return null;
6004 return s;
60056005}
60066006
6007/// This asserts that the union's enum tag type has been resolved.
6008pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.UnionType {
6007pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.LoadedUnionType {
60096008 if (ty.ip_index == .none) return null;
60106009 const ip = &mod.intern_pool;
60116010 return switch (ip.indexToKey(ty.ip_index)) {
6012 .union_type => |k| ip.loadUnionType(k),
6011 .union_type => ip.loadUnionType(ty.ip_index),
60136012 else => null,
60146013 };
60156014}
......@@ -6111,7 +6110,7 @@ pub const UnionLayout = struct {
61116110 padding: u32,
61126111};
61136112
6114pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
6113pub fn getUnionLayout(mod: *Module, u: InternPool.LoadedUnionType) UnionLayout {
61156114 const ip = &mod.intern_pool;
61166115 assert(u.haveLayout(ip));
61176116 var most_aligned_field: u32 = undefined;
......@@ -6157,7 +6156,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
61576156 const tag_size = Type.fromInterned(u.enum_tag_ty).abiSize(mod);
61586157 const tag_align = Type.fromInterned(u.enum_tag_ty).abiAlignment(mod).max(.@"1");
61596158 return .{
6160 .abi_size = u.size,
6159 .abi_size = u.size(ip).*,
61616160 .abi_align = tag_align.max(payload_align),
61626161 .most_aligned_field = most_aligned_field,
61636162 .most_aligned_field_size = most_aligned_field_size,
......@@ -6166,16 +6165,16 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
61666165 .payload_align = payload_align,
61676166 .tag_align = tag_align,
61686167 .tag_size = tag_size,
6169 .padding = u.padding,
6168 .padding = u.padding(ip).*,
61706169 };
61716170}
61726171
6173pub fn unionAbiSize(mod: *Module, u: InternPool.UnionType) u64 {
6172pub fn unionAbiSize(mod: *Module, u: InternPool.LoadedUnionType) u64 {
61746173 return mod.getUnionLayout(u).abi_size;
61756174}
61766175
61776176/// Returns 0 if the union is represented with 0 bits at runtime.
6178pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment {
6177pub fn unionAbiAlignment(mod: *Module, u: InternPool.LoadedUnionType) Alignment {
61796178 const ip = &mod.intern_pool;
61806179 const have_tag = u.flagsPtr(ip).runtime_tag.hasTag();
61816180 var max_align: Alignment = .none;
......@@ -6192,7 +6191,7 @@ pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment {
61926191/// Returns the field alignment, assuming the union is not packed.
61936192/// Keep implementation in sync with `Sema.unionFieldAlignment`.
61946193/// Prefer to call that function instead of this one during Sema.
6195pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_index: u32) Alignment {
6194pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.LoadedUnionType, field_index: u32) Alignment {
61966195 const ip = &mod.intern_pool;
61976196 const field_align = u.fieldAlign(ip, field_index);
61986197 if (field_align != .none) return field_align;
......@@ -6201,12 +6200,11 @@ pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_in
62016200}
62026201
62036202/// Returns the index of the active field, given the current tag value
6204pub fn unionTagFieldIndex(mod: *Module, u: InternPool.UnionType, enum_tag: Value) ?u32 {
6203pub fn unionTagFieldIndex(mod: *Module, u: InternPool.LoadedUnionType, enum_tag: Value) ?u32 {
62056204 const ip = &mod.intern_pool;
62066205 if (enum_tag.toIntern() == .none) return null;
62076206 assert(ip.typeOf(enum_tag.toIntern()) == u.enum_tag_ty);
6208 const enum_type = ip.indexToKey(u.enum_tag_ty).enum_type;
6209 return enum_type.tagValueIndex(ip, enum_tag.toIntern());
6207 return u.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern());
62106208}
62116209
62126210/// Returns the field alignment of a non-packed struct in byte units.
......@@ -6253,7 +6251,7 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {
62536251/// projects.
62546252pub fn structPackedFieldBitOffset(
62556253 mod: *Module,
6256 struct_type: InternPool.Key.StructType,
6254 struct_type: InternPool.LoadedStructType,
62576255 field_index: u32,
62586256) u16 {
62596257 const ip = &mod.intern_pool;
src/Sema.zig+158-149
......@@ -3371,11 +3371,11 @@ fn zirOpaqueDecl(
33713371 });
33723372 errdefer mod.destroyNamespace(new_namespace_index);
33733373
3374 const opaque_ty = try mod.intern(.{ .opaque_type = .{
3374 const opaque_ty = try mod.intern_pool.getOpaqueType(sema.gpa, .{
33753375 .decl = new_decl_index,
33763376 .namespace = new_namespace_index,
33773377 .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),
3378 } });
3378 });
33793379 // TODO: figure out InternPool removals for incremental compilation
33803380 //errdefer mod.intern_pool.remove(opaque_ty);
33813381
......@@ -5371,7 +5371,7 @@ fn failWithBadMemberAccess(
53715371fn failWithBadStructFieldAccess(
53725372 sema: *Sema,
53735373 block: *Block,
5374 struct_type: InternPool.Key.StructType,
5374 struct_type: InternPool.LoadedStructType,
53755375 field_src: LazySrcLoc,
53765376 field_name: InternPool.NullTerminatedString,
53775377) CompileError {
......@@ -5397,7 +5397,7 @@ fn failWithBadStructFieldAccess(
53975397fn failWithBadUnionFieldAccess(
53985398 sema: *Sema,
53995399 block: *Block,
5400 union_obj: InternPool.UnionType,
5400 union_obj: InternPool.LoadedUnionType,
54015401 field_src: LazySrcLoc,
54025402 field_name: InternPool.NullTerminatedString,
54035403) CompileError {
......@@ -13348,7 +13348,7 @@ fn validateSwitchItemEnum(
1334813348 const ip = &sema.mod.intern_pool;
1334913349 const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none);
1335013350 const int = ip.indexToKey(item.val).enum_tag.int;
13351 const field_index = ip.indexToKey(ip.typeOf(item.val)).enum_type.tagValueIndex(ip, int) orelse {
13351 const field_index = ip.loadEnumType(ip.typeOf(item.val)).tagValueIndex(ip, int) orelse {
1335213352 const maybe_prev_src = try range_set.add(int, int, switch_prong_src);
1335313353 try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1335413354 return item.ref;
......@@ -13628,15 +13628,15 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1362813628 break :hf field_index < ty.structFieldCount(mod);
1362913629 }
1363013630 },
13631 .struct_type => |struct_type| {
13632 break :hf struct_type.nameIndex(ip, field_name) != null;
13631 .struct_type => {
13632 break :hf ip.loadStructType(ty.toIntern()).nameIndex(ip, field_name) != null;
1363313633 },
13634 .union_type => |union_type| {
13635 const union_obj = ip.loadUnionType(union_type);
13636 break :hf union_obj.nameIndex(ip, field_name) != null;
13634 .union_type => {
13635 const union_type = ip.loadUnionType(ty.toIntern());
13636 break :hf union_type.loadTagType(ip).nameIndex(ip, field_name) != null;
1363713637 },
13638 .enum_type => |enum_type| {
13639 break :hf enum_type.nameIndex(ip, field_name) != null;
13638 .enum_type => {
13639 break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null;
1364013640 },
1364113641 .array_type => break :hf ip.stringEqlSlice(field_name, "len"),
1364213642 else => {},
......@@ -17942,7 +17942,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1794217942 } })));
1794317943 },
1794417944 .Enum => {
17945 const is_exhaustive = Value.makeBool(ip.indexToKey(ty.toIntern()).enum_type.tag_mode != .nonexhaustive);
17945 const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive);
1794617946
1794717947 const enum_field_ty = t: {
1794817948 const enum_field_ty_decl_index = (try sema.namespaceLookup(
......@@ -17956,9 +17956,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1795617956 break :t enum_field_ty_decl.val.toType();
1795717957 };
1795817958
17959 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.indexToKey(ty.toIntern()).enum_type.names.len);
17959 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len);
1796017960 for (enum_field_vals, 0..) |*field_val, i| {
17961 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
17961 const enum_type = ip.loadEnumType(ty.toIntern());
1796217962 const value_val = if (enum_type.values.len > 0)
1796317963 try mod.intern_pool.getCoercedInts(
1796417964 mod.gpa,
......@@ -18033,7 +18033,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1803318033 } });
1803418034 };
1803518035
18036 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.indexToKey(ty.toIntern()).enum_type.namespace);
18036 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace);
1803718037
1803818038 const type_enum_ty = t: {
1803918039 const type_enum_ty_decl_index = (try sema.namespaceLookup(
......@@ -18049,7 +18049,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1804918049
1805018050 const field_values = .{
1805118051 // tag_type: type,
18052 ip.indexToKey(ty.toIntern()).enum_type.tag_ty,
18052 ip.loadEnumType(ty.toIntern()).tag_ty,
1805318053 // fields: []const EnumField,
1805418054 fields_val,
1805518055 // decls: []const Declaration,
......@@ -18093,14 +18093,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1809318093
1809418094 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
1809518095 const union_obj = mod.typeToUnion(ty).?;
18096 const tag_type = union_obj.loadTagType(ip);
1809618097 const layout = union_obj.getLayout(ip);
1809718098
18098 const union_field_vals = try gpa.alloc(InternPool.Index, union_obj.field_names.len);
18099 const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len);
1809918100 defer gpa.free(union_field_vals);
1810018101
1810118102 for (union_field_vals, 0..) |*field_val, i| {
1810218103 // TODO: write something like getCoercedInts to avoid needing to dupe
18103 const name = try sema.arena.dupeZ(u8, ip.stringToSlice(union_obj.field_names.get(ip)[i]));
18104 const name = try sema.arena.dupeZ(u8, ip.stringToSlice(tag_type.names.get(ip)[i]));
1810418105 const name_val = v: {
1810518106 const new_decl_ty = try mod.arrayType(.{
1810618107 .len = name.len,
......@@ -18302,7 +18303,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1830218303 }
1830318304 break :fv;
1830418305 },
18305 .struct_type => |s| s,
18306 .struct_type => ip.loadStructType(ty.toIntern()),
1830618307 else => unreachable,
1830718308 };
1830818309 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);
......@@ -20067,7 +20068,8 @@ fn finishStructInit(
2006720068 }
2006820069 }
2006920070 },
20070 .struct_type => |struct_type| {
20071 .struct_type => {
20072 const struct_type = ip.loadStructType(struct_ty.toIntern());
2007120073 for (0..struct_type.field_types.len) |i| {
2007220074 if (field_inits[i] != .none) {
2007320075 // Coerce the init value to the field type.
......@@ -20668,7 +20670,8 @@ fn fieldType(
2066820670 try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
2066920671 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);
2067020672 },
20671 .struct_type => |struct_type| {
20673 .struct_type => {
20674 const struct_type = ip.loadStructType(cur_ty.toIntern());
2067220675 const field_index = struct_type.nameIndex(ip, field_name) orelse
2067320676 return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name);
2067420677 const field_ty = struct_type.field_types.get(ip)[field_index];
......@@ -20678,7 +20681,7 @@ fn fieldType(
2067820681 },
2067920682 .Union => {
2068020683 const union_obj = mod.typeToUnion(cur_ty).?;
20681 const field_index = union_obj.nameIndex(ip, field_name) orelse
20684 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
2068220685 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
2068320686 const field_ty = union_obj.field_types.get(ip)[field_index];
2068420687 return Air.internedToRef(field_ty);
......@@ -21007,7 +21010,7 @@ fn zirReify(
2100721010 .AnyFrame => return sema.failWithUseOfAsync(block, src),
2100821011 .EnumLiteral => return .enum_literal_type,
2100921012 .Int => {
21010 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21013 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2101121014 const signedness_val = try Value.fromInterned(union_val.val).fieldValue(
2101221015 mod,
2101321016 struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness")).?,
......@@ -21023,7 +21026,7 @@ fn zirReify(
2102321026 return Air.internedToRef(ty.toIntern());
2102421027 },
2102521028 .Vector => {
21026 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21029 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2102721030 const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2102821031 ip,
2102921032 try ip.getOrPutString(gpa, "len"),
......@@ -21045,7 +21048,7 @@ fn zirReify(
2104521048 return Air.internedToRef(ty.toIntern());
2104621049 },
2104721050 .Float => {
21048 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21051 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2104921052 const bits_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2105021053 ip,
2105121054 try ip.getOrPutString(gpa, "bits"),
......@@ -21063,7 +21066,7 @@ fn zirReify(
2106321066 return Air.internedToRef(ty.toIntern());
2106421067 },
2106521068 .Pointer => {
21066 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21069 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2106721070 const size_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2106821071 ip,
2106921072 try ip.getOrPutString(gpa, "size"),
......@@ -21175,7 +21178,7 @@ fn zirReify(
2117521178 return Air.internedToRef(ty.toIntern());
2117621179 },
2117721180 .Array => {
21178 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21181 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2117921182 const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2118021183 ip,
2118121184 try ip.getOrPutString(gpa, "len"),
......@@ -21204,7 +21207,7 @@ fn zirReify(
2120421207 return Air.internedToRef(ty.toIntern());
2120521208 },
2120621209 .Optional => {
21207 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21210 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2120821211 const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2120921212 ip,
2121021213 try ip.getOrPutString(gpa, "child"),
......@@ -21216,7 +21219,7 @@ fn zirReify(
2121621219 return Air.internedToRef(ty.toIntern());
2121721220 },
2121821221 .ErrorUnion => {
21219 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21222 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2122021223 const error_set_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2122121224 ip,
2122221225 try ip.getOrPutString(gpa, "error_set"),
......@@ -21245,7 +21248,7 @@ fn zirReify(
2124521248 try names.ensureUnusedCapacity(sema.arena, len);
2124621249 for (0..len) |i| {
2124721250 const elem_val = try payload_val.elemValue(mod, i);
21248 const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type;
21251 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
2124921252 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
2125021253 ip,
2125121254 try ip.getOrPutString(gpa, "name"),
......@@ -21265,7 +21268,7 @@ fn zirReify(
2126521268 return Air.internedToRef(ty.toIntern());
2126621269 },
2126721270 .Struct => {
21268 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21271 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2126921272 const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2127021273 ip,
2127121274 try ip.getOrPutString(gpa, "layout"),
......@@ -21301,7 +21304,7 @@ fn zirReify(
2130121304 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool());
2130221305 },
2130321306 .Enum => {
21304 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21307 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2130521308 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2130621309 ip,
2130721310 try ip.getOrPutString(gpa, "tag_type"),
......@@ -21366,7 +21369,7 @@ fn zirReify(
2136621369
2136721370 for (0..fields_len) |field_i| {
2136821371 const elem_val = try fields_val.elemValue(mod, field_i);
21369 const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type;
21372 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
2137021373 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
2137121374 ip,
2137221375 try ip.getOrPutString(gpa, "name"),
......@@ -21417,7 +21420,7 @@ fn zirReify(
2141721420 return decl_val;
2141821421 },
2141921422 .Opaque => {
21420 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21423 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2142121424 const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2142221425 ip,
2142321426 try ip.getOrPutString(gpa, "decls"),
......@@ -21451,11 +21454,11 @@ fn zirReify(
2145121454 });
2145221455 errdefer mod.destroyNamespace(new_namespace_index);
2145321456
21454 const opaque_ty = try mod.intern(.{ .opaque_type = .{
21457 const opaque_ty = try ip.getOpaqueType(gpa, .{
2145521458 .decl = new_decl_index,
2145621459 .namespace = new_namespace_index,
2145721460 .zir_index = .none,
21458 } });
21461 });
2145921462 // TODO: figure out InternPool removals for incremental compilation
2146021463 //errdefer ip.remove(opaque_ty);
2146121464
......@@ -21467,7 +21470,7 @@ fn zirReify(
2146721470 return decl_val;
2146821471 },
2146921472 .Union => {
21470 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21473 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2147121474 const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2147221475 ip,
2147321476 try ip.getOrPutString(gpa, "layout"),
......@@ -21500,7 +21503,7 @@ fn zirReify(
2150021503 enum_tag_ty = payload_val.toType().toIntern();
2150121504
2150221505 const enum_type = switch (ip.indexToKey(enum_tag_ty)) {
21503 .enum_type => |x| x,
21506 .enum_type => ip.loadEnumType(enum_tag_ty),
2150421507 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
2150521508 };
2150621509
......@@ -21521,7 +21524,7 @@ fn zirReify(
2152121524
2152221525 for (0..fields_len) |i| {
2152321526 const elem_val = try fields_val.elemValue(mod, i);
21524 const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type;
21527 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
2152521528 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
2152621529 ip,
2152721530 try ip.getOrPutString(gpa, "name"),
......@@ -21542,7 +21545,7 @@ fn zirReify(
2154221545 }
2154321546
2154421547 if (enum_tag_ty != .none) {
21545 const tag_info = ip.indexToKey(enum_tag_ty).enum_type;
21548 const tag_info = ip.loadEnumType(enum_tag_ty);
2154621549 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
2154721550 return sema.fail(block, src, "no field named '{}' in enum '{}'", .{
2154821551 field_name.fmt(ip), Type.fromInterned(enum_tag_ty).fmt(mod),
......@@ -21615,7 +21618,7 @@ fn zirReify(
2161521618 }
2161621619
2161721620 if (enum_tag_ty != .none) {
21618 const tag_info = ip.indexToKey(enum_tag_ty).enum_type;
21621 const tag_info = ip.loadEnumType(enum_tag_ty);
2161921622 if (tag_info.names.len > fields_len) {
2162021623 const msg = msg: {
2162121624 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
......@@ -21695,7 +21698,7 @@ fn zirReify(
2169521698 return decl_val;
2169621699 },
2169721700 .Fn => {
21698 const struct_type = ip.indexToKey(ip.typeOf(union_val.val)).struct_type;
21701 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
2169921702 const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2170021703 ip,
2170121704 try ip.getOrPutString(gpa, "calling_convention"),
......@@ -21746,7 +21749,7 @@ fn zirReify(
2174621749 var noalias_bits: u32 = 0;
2174721750 for (param_types, 0..) |*param_type, i| {
2174821751 const elem_val = try params_val.elemValue(mod, i);
21749 const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type;
21752 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
2175021753 const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
2175121754 ip,
2175221755 try ip.getOrPutString(gpa, "is_generic"),
......@@ -21849,7 +21852,7 @@ fn reifyStruct(
2184921852 });
2185021853 // TODO: figure out InternPool removals for incremental compilation
2185121854 //errdefer ip.remove(ty);
21852 const struct_type = ip.indexToKey(ty).struct_type;
21855 const struct_type = ip.loadStructType(ty);
2185321856
2185421857 new_decl.ty = Type.type;
2185521858 new_decl.val = Value.fromInterned(ty);
......@@ -21857,7 +21860,7 @@ fn reifyStruct(
2185721860 // Fields
2185821861 for (0..fields_len) |i| {
2185921862 const elem_val = try fields_val.elemValue(mod, i);
21860 const elem_struct_type = ip.indexToKey(ip.typeOf(elem_val.toIntern())).struct_type;
21863 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
2186121864 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
2186221865 ip,
2186321866 try ip.getOrPutString(gpa, "name"),
......@@ -23228,7 +23231,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2322823231 switch (ty.containerLayout(mod)) {
2322923232 .Packed => {
2323023233 var bit_sum: u64 = 0;
23231 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;
23234 const struct_type = ip.loadStructType(ty.toIntern());
2323223235 for (0..struct_type.field_types.len) |i| {
2323323236 if (i == field_index) {
2323423237 return bit_sum;
......@@ -27252,8 +27255,7 @@ fn fieldCallBind(
2725227255 .Union => {
2725327256 try sema.resolveTypeFields(concrete_ty);
2725427257 const union_obj = mod.typeToUnion(concrete_ty).?;
27255 _ = union_obj.nameIndex(ip, field_name) orelse break :find_field;
27256
27258 _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field;
2725727259 const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false);
2725827260 return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) };
2725927261 },
......@@ -27627,7 +27629,8 @@ fn structFieldVal(
2762727629 try sema.resolveTypeFields(struct_ty);
2762827630
2762927631 switch (ip.indexToKey(struct_ty.toIntern())) {
27630 .struct_type => |struct_type| {
27632 .struct_type => {
27633 const struct_type = ip.loadStructType(struct_ty.toIntern());
2763127634 if (struct_type.isTuple(ip))
2763227635 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2763327636
......@@ -27833,7 +27836,7 @@ fn unionFieldPtr(
2783327836
2783427837 try sema.requireRuntimeBlock(block, src, null);
2783527838 if (!initializing and union_obj.getLayout(ip) == .Auto and block.wantSafety() and
27836 union_ty.unionTagTypeSafety(mod) != null and union_obj.field_names.len > 1)
27839 union_ty.unionTagTypeSafety(mod) != null and union_obj.field_types.len > 1)
2783727840 {
2783827841 const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
2783927842 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
......@@ -27911,7 +27914,7 @@ fn unionFieldVal(
2791127914
2791227915 try sema.requireRuntimeBlock(block, src, null);
2791327916 if (union_obj.getLayout(ip) == .Auto and block.wantSafety() and
27914 union_ty.unionTagTypeSafety(mod) != null and union_obj.field_names.len > 1)
27917 union_ty.unionTagTypeSafety(mod) != null and union_obj.field_types.len > 1)
2791527918 {
2791627919 const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
2791727920 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
......@@ -31670,7 +31673,7 @@ fn coerceEnumToUnion(
3167031673 const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});
3167131674 errdefer msg.destroy(sema.gpa);
3167231675
31673 const field_name = union_obj.field_names.get(ip)[field_index];
31676 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
3167431677 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
3167531678 field_name.fmt(ip),
3167631679 });
......@@ -31681,7 +31684,7 @@ fn coerceEnumToUnion(
3168131684 }
3168231685 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
3168331686 const msg = msg: {
31684 const field_name = union_obj.field_names.get(ip)[field_index];
31687 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
3168531688 const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{
3168631689 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod),
3168731690 field_ty.fmt(sema.mod), field_name.fmt(ip),
......@@ -31753,8 +31756,8 @@ fn coerceEnumToUnion(
3175331756 );
3175431757 errdefer msg.destroy(sema.gpa);
3175531758
31756 for (0..union_obj.field_names.len) |field_index| {
31757 const field_name = union_obj.field_names.get(ip)[field_index];
31759 for (0..union_obj.field_types.len) |field_index| {
31760 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
3175831761 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
3175931762 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
3176031763 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{
......@@ -31787,8 +31790,8 @@ fn coerceAnonStructToUnion(
3178731790 .{ .name = anon_struct_type.names.get(ip)[0] }
3178831791 else
3178931792 .{ .count = anon_struct_type.names.len },
31790 .struct_type => |struct_type| name: {
31791 const field_names = struct_type.field_names.get(ip);
31793 .struct_type => name: {
31794 const field_names = ip.loadStructType(inst_ty.toIntern()).field_names.get(ip);
3179231795 break :name if (field_names.len == 1)
3179331796 .{ .name = field_names[0] }
3179431797 else
......@@ -32097,7 +32100,7 @@ fn coerceTupleToStruct(
3209732100 var runtime_src: ?LazySrcLoc = null;
3209832101 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
3209932102 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
32100 .struct_type => |s| s.field_types.len,
32103 .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len,
3210132104 else => unreachable,
3210232105 };
3210332106 for (0..field_count) |field_index_usize| {
......@@ -32109,7 +32112,7 @@ fn coerceTupleToStruct(
3210932112 anon_struct_type.names.get(ip)[field_i]
3211032113 else
3211132114 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
32112 .struct_type => |s| s.field_names.get(ip)[field_i],
32115 .struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[field_i],
3211332116 else => unreachable,
3211432117 };
3211532118 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
......@@ -32197,7 +32200,7 @@ fn coerceTupleToTuple(
3219732200 const ip = &mod.intern_pool;
3219832201 const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) {
3219932202 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
32200 .struct_type => |struct_type| struct_type.field_types.len,
32203 .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.len,
3220132204 else => unreachable,
3220232205 };
3220332206 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);
......@@ -32207,7 +32210,7 @@ fn coerceTupleToTuple(
3220732210 const inst_ty = sema.typeOf(inst);
3220832211 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
3220932212 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
32210 .struct_type => |struct_type| struct_type.field_types.len,
32213 .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len,
3221132214 else => unreachable,
3221232215 };
3221332216 if (src_field_count > dest_field_count) return error.NotCoercible;
......@@ -32222,10 +32225,14 @@ fn coerceTupleToTuple(
3222232225 anon_struct_type.names.get(ip)[field_i]
3222332226 else
3222432227 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
32225 .struct_type => |struct_type| if (struct_type.field_names.len > 0)
32226 struct_type.field_names.get(ip)[field_i]
32227 else
32228 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
32228 .struct_type => s: {
32229 const struct_type = ip.loadStructType(inst_ty.toIntern());
32230 if (struct_type.field_names.len > 0) {
32231 break :s struct_type.field_names.get(ip)[field_i];
32232 } else {
32233 break :s try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i});
32234 }
32235 },
3222932236 else => unreachable,
3223032237 };
3223132238
......@@ -32234,12 +32241,12 @@ fn coerceTupleToTuple(
3223432241
3223532242 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
3223632243 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[field_index_usize],
32237 .struct_type => |struct_type| struct_type.field_types.get(ip)[field_index_usize],
32244 .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize],
3223832245 else => unreachable,
3223932246 };
3224032247 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
3224132248 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize],
32242 .struct_type => |struct_type| struct_type.fieldInit(ip, field_index_usize),
32249 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize),
3224332250 else => unreachable,
3224432251 };
3224532252
......@@ -32278,7 +32285,7 @@ fn coerceTupleToTuple(
3227832285
3227932286 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
3228032287 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i],
32281 .struct_type => |struct_type| struct_type.fieldInit(ip, i),
32288 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i),
3228232289 else => unreachable,
3228332290 };
3228432291
......@@ -35518,7 +35525,7 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3551835525pub fn resolveStructAlignment(
3551935526 sema: *Sema,
3552035527 ty: InternPool.Index,
35521 struct_type: InternPool.Key.StructType,
35528 struct_type: InternPool.LoadedStructType,
3552235529) CompileError!Alignment {
3552335530 const mod = sema.mod;
3552435531 const ip = &mod.intern_pool;
......@@ -35658,7 +35665,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3565835665 }
3565935666 }
3566035667
35661 const RuntimeOrder = InternPool.Key.StructType.RuntimeOrder;
35668 const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder;
3566235669
3566335670 const AlignSortContext = struct {
3566435671 aligns: []const Alignment,
......@@ -35710,7 +35717,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3571035717 _ = try sema.typeRequiresComptime(ty);
3571135718}
3571235719
35713fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) CompileError!void {
35720fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) CompileError!void {
3571435721 const gpa = mod.gpa;
3571535722 const ip = &mod.intern_pool;
3571635723
......@@ -35869,7 +35876,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
3586935876pub fn resolveUnionAlignment(
3587035877 sema: *Sema,
3587135878 ty: Type,
35872 union_type: InternPool.Key.UnionType,
35879 union_type: InternPool.LoadedUnionType,
3587335880) CompileError!Alignment {
3587435881 const mod = sema.mod;
3587535882 const ip = &mod.intern_pool;
......@@ -35889,13 +35896,12 @@ pub fn resolveUnionAlignment(
3588935896
3589035897 try sema.resolveTypeFieldsUnion(ty, union_type);
3589135898
35892 const union_obj = ip.loadUnionType(union_type);
3589335899 var max_align: Alignment = .@"1";
35894 for (0..union_obj.field_names.len) |field_index| {
35895 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
35900 for (0..union_type.field_types.len) |field_index| {
35901 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
3589635902 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
3589735903
35898 const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index));
35904 const explicit_align = union_type.fieldAlign(ip, @intCast(field_index));
3589935905 const field_align = if (explicit_align != .none)
3590035906 explicit_align
3590135907 else
......@@ -35913,16 +35919,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3591335919 const mod = sema.mod;
3591435920 const ip = &mod.intern_pool;
3591535921
35916 const union_type = ip.indexToKey(ty.ip_index).union_type;
35917 try sema.resolveTypeFieldsUnion(ty, union_type);
35922 try sema.resolveTypeFieldsUnion(ty, ip.loadUnionType(ty.ip_index));
3591835923
35919 const union_obj = ip.loadUnionType(union_type);
35920 switch (union_obj.flagsPtr(ip).status) {
35924 // Load again, since the tag type might have changed due to resolution.
35925 const union_type = ip.loadUnionType(ty.ip_index);
35926
35927 switch (union_type.flagsPtr(ip).status) {
3592135928 .none, .have_field_types => {},
3592235929 .field_types_wip, .layout_wip => {
3592335930 const msg = try Module.ErrorMsg.create(
3592435931 sema.gpa,
35925 mod.declPtr(union_obj.decl).srcLoc(mod),
35932 mod.declPtr(union_type.decl).srcLoc(mod),
3592635933 "union '{}' depends on itself",
3592735934 .{ty.fmt(mod)},
3592835935 );
......@@ -35931,17 +35938,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3593135938 .have_layout, .fully_resolved_wip, .fully_resolved => return,
3593235939 }
3593335940
35934 const prev_status = union_obj.flagsPtr(ip).status;
35935 errdefer if (union_obj.flagsPtr(ip).status == .layout_wip) {
35936 union_obj.flagsPtr(ip).status = prev_status;
35941 const prev_status = union_type.flagsPtr(ip).status;
35942 errdefer if (union_type.flagsPtr(ip).status == .layout_wip) {
35943 union_type.flagsPtr(ip).status = prev_status;
3593735944 };
3593835945
35939 union_obj.flagsPtr(ip).status = .layout_wip;
35946 union_type.flagsPtr(ip).status = .layout_wip;
3594035947
3594135948 var max_size: u64 = 0;
3594235949 var max_align: Alignment = .@"1";
35943 for (0..union_obj.field_names.len) |field_index| {
35944 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
35950 for (0..union_type.field_types.len) |field_index| {
35951 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
3594535952 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
3594635953
3594735954 max_size = @max(max_size, sema.typeAbiSize(field_ty) catch |err| switch (err) {
......@@ -35953,7 +35960,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3595335960 else => return err,
3595435961 });
3595535962
35956 const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index));
35963 const explicit_align = union_type.fieldAlign(ip, @intCast(field_index));
3595735964 const field_align = if (explicit_align != .none)
3595835965 explicit_align
3595935966 else
......@@ -35962,10 +35969,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3596235969 max_align = max_align.max(field_align);
3596335970 }
3596435971
35965 const flags = union_obj.flagsPtr(ip);
35966 const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_obj.enum_tag_ty));
35972 const flags = union_type.flagsPtr(ip);
35973 const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_type.enum_tag_ty));
3596735974 const size, const alignment, const padding = if (has_runtime_tag) layout: {
35968 const enum_tag_type = Type.fromInterned(union_obj.enum_tag_ty);
35975 const enum_tag_type = Type.fromInterned(union_type.enum_tag_ty);
3596935976 const tag_align = try sema.typeAbiAlignment(enum_tag_type);
3597035977 const tag_size = try sema.typeAbiSize(enum_tag_type);
3597135978
......@@ -35999,22 +36006,22 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3599936006 flags.alignment = alignment;
3600036007 flags.status = .have_layout;
3600136008
36002 if (union_obj.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
36009 if (union_type.flagsPtr(ip).assumed_runtime_bits and !(try sema.typeHasRuntimeBits(ty))) {
3600336010 const msg = try Module.ErrorMsg.create(
3600436011 sema.gpa,
36005 mod.declPtr(union_obj.decl).srcLoc(mod),
36012 mod.declPtr(union_type.decl).srcLoc(mod),
3600636013 "union layout depends on it having runtime bits",
3600736014 .{},
3600836015 );
3600936016 return sema.failWithOwnedErrorMsg(null, msg);
3601036017 }
3601136018
36012 if (union_obj.flagsPtr(ip).assumed_pointer_aligned and
36019 if (union_type.flagsPtr(ip).assumed_pointer_aligned and
3601336020 alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8))))
3601436021 {
3601536022 const msg = try Module.ErrorMsg.create(
3601636023 sema.gpa,
36017 mod.declPtr(union_obj.decl).srcLoc(mod),
36024 mod.declPtr(union_type.decl).srcLoc(mod),
3601836025 "union layout depends on being pointer aligned",
3601936026 .{},
3602036027 );
......@@ -36202,12 +36209,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {
3620236209
3620336210 else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) {
3620436211 .type_struct,
36205 .type_struct_ns,
3620636212 .type_struct_packed,
3620736213 .type_struct_packed_inits,
36208 => try sema.resolveTypeFieldsStruct(ty_ip, ip.indexToKey(ty_ip).struct_type),
36214 => try sema.resolveTypeFieldsStruct(ty_ip, ip.loadStructType(ty_ip)),
3620936215
36210 .type_union => try sema.resolveTypeFieldsUnion(Type.fromInterned(ty_ip), ip.indexToKey(ty_ip).union_type),
36216 .type_union => try sema.resolveTypeFieldsUnion(Type.fromInterned(ty_ip), ip.loadUnionType(ty_ip)),
3621136217 .simple_type => try sema.resolveSimpleType(ip.indexToKey(ty_ip).simple_type),
3621236218 else => {},
3621336219 },
......@@ -36239,7 +36245,7 @@ fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileErr
3623936245pub fn resolveTypeFieldsStruct(
3624036246 sema: *Sema,
3624136247 ty: InternPool.Index,
36242 struct_type: InternPool.Key.StructType,
36248 struct_type: InternPool.LoadedStructType,
3624336249) CompileError!void {
3624436250 const mod = sema.mod;
3624536251 const ip = &mod.intern_pool;
......@@ -36299,7 +36305,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void {
3629936305 struct_type.setHaveFieldInits(ip);
3630036306}
3630136307
36302pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key.UnionType) CompileError!void {
36308pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) CompileError!void {
3630336309 const mod = sema.mod;
3630436310 const ip = &mod.intern_pool;
3630536311 const owner_decl = mod.declPtr(union_type.decl);
......@@ -36530,7 +36536,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {
3653036536fn semaStructFields(
3653136537 mod: *Module,
3653236538 arena: Allocator,
36533 struct_type: InternPool.Key.StructType,
36539 struct_type: InternPool.LoadedStructType,
3653436540) CompileError!void {
3653536541 const gpa = mod.gpa;
3653636542 const ip = &mod.intern_pool;
......@@ -36797,7 +36803,7 @@ fn semaStructFields(
3679736803fn semaStructFieldInits(
3679836804 mod: *Module,
3679936805 arena: Allocator,
36800 struct_type: InternPool.Key.StructType,
36806 struct_type: InternPool.LoadedStructType,
3680136807) CompileError!void {
3680236808 const gpa = mod.gpa;
3680336809 const ip = &mod.intern_pool;
......@@ -36948,7 +36954,7 @@ fn semaStructFieldInits(
3694836954 }
3694936955}
3695036956
36951fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.UnionType) CompileError!void {
36957fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void {
3695236958 const tracy = trace(@src());
3695336959 defer tracy.end();
3695436960
......@@ -37080,7 +37086,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3708037086 // The provided type is the enum tag type.
3708137087 union_type.tagTypePtr(ip).* = provided_ty.toIntern();
3708237088 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
37083 .enum_type => |x| x,
37089 .enum_type => ip.loadEnumType(provided_ty.toIntern()),
3708437090 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(mod)}),
3708537091 };
3708637092 // The fields of the union must match the enum exactly.
......@@ -37217,7 +37223,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3721737223 }
3721837224
3721937225 if (explicit_tags_seen.len > 0) {
37220 const tag_info = ip.indexToKey(union_type.tagTypePtr(ip).*).enum_type;
37226 const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*);
3722137227 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
3722237228 const ty_src = mod.fieldSrcLoc(union_type.decl, .{
3722337229 .index = field_i,
......@@ -37328,7 +37334,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3732837334 union_type.setFieldAligns(ip, field_aligns.items);
3732937335
3733037336 if (explicit_tags_seen.len > 0) {
37331 const tag_info = ip.indexToKey(union_type.tagTypePtr(ip).*).enum_type;
37337 const tag_info = ip.loadEnumType(union_type.tagTypePtr(ip).*);
3733237338 if (tag_info.names.len > fields_len) {
3733337339 const msg = msg: {
3733437340 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});
......@@ -37710,7 +37716,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3771037716 .type_enum_explicit,
3771137717 .type_enum_nonexhaustive,
3771237718 .type_struct,
37713 .type_struct_ns,
3771437719 .type_struct_anon,
3771537720 .type_struct_packed,
3771637721 .type_struct_packed_inits,
......@@ -37733,8 +37738,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3773337738 return null;
3773437739 },
3773537740
37736 .struct_type => |struct_type| {
37737 try sema.resolveTypeFields(ty);
37741 .struct_type => {
37742 const struct_type = ip.loadStructType(ty.toIntern());
37743 try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
3773837744
3773937745 if (struct_type.field_types.len == 0) {
3774037746 // In this case the struct has no fields at all and
......@@ -37792,10 +37798,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3779237798 } })));
3779337799 },
3779437800
37795 .union_type => |union_type| {
37796 try sema.resolveTypeFields(ty);
37797 const union_obj = ip.loadUnionType(union_type);
37798 const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.enum_tag_ty))) orelse
37801 .union_type => {
37802 const union_obj = ip.loadUnionType(ty.toIntern());
37803 try sema.resolveTypeFieldsUnion(ty, union_obj);
37804 const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse
3779937805 return null;
3780037806 if (union_obj.field_types.len == 0) {
3780137807 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
......@@ -37822,39 +37828,42 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3782237828 return Value.fromInterned(only);
3782337829 },
3782437830
37825 .enum_type => |enum_type| switch (enum_type.tag_mode) {
37826 .nonexhaustive => {
37827 if (enum_type.tag_ty == .comptime_int_type) return null;
37831 .enum_type => {
37832 const enum_type = ip.loadEnumType(ty.toIntern());
37833 switch (enum_type.tag_mode) {
37834 .nonexhaustive => {
37835 if (enum_type.tag_ty == .comptime_int_type) return null;
3782837836
37829 if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| {
37830 const only = try mod.intern(.{ .enum_tag = .{
37831 .ty = ty.toIntern(),
37832 .int = int_opv.toIntern(),
37833 } });
37834 return Value.fromInterned(only);
37835 }
37837 if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| {
37838 const only = try mod.intern(.{ .enum_tag = .{
37839 .ty = ty.toIntern(),
37840 .int = int_opv.toIntern(),
37841 } });
37842 return Value.fromInterned(only);
37843 }
3783637844
37837 return null;
37838 },
37839 .auto, .explicit => {
37840 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
37841
37842 return Value.fromInterned(switch (enum_type.names.len) {
37843 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }),
37844 1 => try mod.intern(.{ .enum_tag = .{
37845 .ty = ty.toIntern(),
37846 .int = if (enum_type.values.len == 0)
37847 (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern()
37848 else
37849 try mod.intern_pool.getCoercedInts(
37850 mod.gpa,
37851 mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int,
37852 enum_type.tag_ty,
37853 ),
37854 } }),
37855 else => return null,
37856 });
37857 },
37845 return null;
37846 },
37847 .auto, .explicit => {
37848 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
37849
37850 return Value.fromInterned(switch (enum_type.names.len) {
37851 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }),
37852 1 => try mod.intern(.{ .enum_tag = .{
37853 .ty = ty.toIntern(),
37854 .int = if (enum_type.values.len == 0)
37855 (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern()
37856 else
37857 try mod.intern_pool.getCoercedInts(
37858 mod.gpa,
37859 mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int,
37860 enum_type.tag_ty,
37861 ),
37862 } }),
37863 else => return null,
37864 });
37865 },
37866 }
3785837867 },
3785937868
3786037869 else => unreachable,
......@@ -38186,7 +38195,7 @@ fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment {
3818638195
3818738196/// Not valid to call for packed unions.
3818838197/// Keep implementation in sync with `Module.unionFieldNormalAlignment`.
38189fn unionFieldAlignment(sema: *Sema, u: InternPool.UnionType, field_index: u32) !Alignment {
38198fn unionFieldAlignment(sema: *Sema, u: InternPool.LoadedUnionType, field_index: u32) !Alignment {
3819038199 const mod = sema.mod;
3819138200 const ip = &mod.intern_pool;
3819238201 const field_align = u.fieldAlign(ip, field_index);
......@@ -38234,7 +38243,7 @@ fn unionFieldIndex(
3823438243 const ip = &mod.intern_pool;
3823538244 try sema.resolveTypeFields(union_ty);
3823638245 const union_obj = mod.typeToUnion(union_ty).?;
38237 const field_index = union_obj.nameIndex(ip, field_name) orelse
38246 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
3823838247 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
3823938248 return @intCast(field_index);
3824038249}
......@@ -38271,7 +38280,7 @@ fn anonStructFieldIndex(
3827138280 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| {
3827238281 if (name == field_name) return @intCast(i);
3827338282 },
38274 .struct_type => |struct_type| if (struct_type.nameIndex(ip, field_name)) |i| return i,
38283 .struct_type => if (ip.loadStructType(struct_ty.toIntern()).nameIndex(ip, field_name)) |i| return i,
3827538284 else => unreachable,
3827638285 }
3827738286 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{
......@@ -38707,7 +38716,7 @@ fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {
3870738716/// Asserts the type is an enum.
3870838717fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {
3870938718 const mod = sema.mod;
38710 const enum_type = mod.intern_pool.indexToKey(ty.toIntern()).enum_type;
38719 const enum_type = mod.intern_pool.loadEnumType(ty.toIntern());
3871138720 assert(enum_type.tag_mode != .nonexhaustive);
3871238721 // The `tagValueIndex` function call below relies on the type being the integer tag type.
3871338722 // `getCoerced` assumes the value will fit the new type.
src/TypedValue.zig+4-8
......@@ -89,7 +89,7 @@ pub fn print(
8989
9090 if (payload.tag) |tag| {
9191 try print(.{
92 .ty = Type.fromInterned(ip.indexToKey(ty.toIntern()).union_type.enum_tag_ty),
92 .ty = Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty),
9393 .val = tag,
9494 }, writer, level - 1, mod);
9595 try writer.writeAll(" = ");
......@@ -247,7 +247,7 @@ pub fn print(
247247 if (level == 0) {
248248 return writer.writeAll("(enum)");
249249 }
250 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
250 const enum_type = ip.loadEnumType(ty.toIntern());
251251 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
252252 try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
253253 return;
......@@ -398,7 +398,7 @@ pub fn print(
398398 }
399399 },
400400 .Union => {
401 const field_name = mod.typeToUnion(container_ty).?.field_names.get(ip)[@intCast(field.index)];
401 const field_name = mod.typeToUnion(container_ty).?.loadTagType(ip).names.get(ip)[@intCast(field.index)];
402402 try writer.print(".{i}", .{field_name.fmt(ip)});
403403 },
404404 .Pointer => {
......@@ -482,11 +482,7 @@ fn printAggregate(
482482 for (0..max_len) |i| {
483483 if (i != 0) try writer.writeAll(", ");
484484
485 const field_name = switch (ip.indexToKey(ty.toIntern())) {
486 .struct_type => |x| x.fieldName(ip, i),
487 .anon_struct_type => |x| if (x.isTuple()) .none else x.names.get(ip)[i].toOptional(),
488 else => unreachable,
489 };
485 const field_name = ty.structFieldName(@intCast(i), mod);
490486
491487 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)});
492488 try print(.{
src/Value.zig+16-10
......@@ -424,22 +424,28 @@ pub fn toType(self: Value) Type {
424424
425425pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
426426 const ip = &mod.intern_pool;
427 return switch (ip.indexToKey(ip.typeOf(val.toIntern()))) {
427 const enum_ty = ip.typeOf(val.toIntern());
428 return switch (ip.indexToKey(enum_ty)) {
428429 // Assume it is already an integer and return it directly.
429430 .simple_type, .int_type => val,
430431 .enum_literal => |enum_literal| {
431432 const field_index = ty.enumFieldIndex(enum_literal, mod).?;
432 return switch (ip.indexToKey(ty.toIntern())) {
433 switch (ip.indexToKey(ty.toIntern())) {
433434 // Assume it is already an integer and return it directly.
434 .simple_type, .int_type => val,
435 .enum_type => |enum_type| if (enum_type.values.len != 0)
436 Value.fromInterned(enum_type.values.get(ip)[field_index])
437 else // Field index and integer values are the same.
438 mod.intValue(Type.fromInterned(enum_type.tag_ty), field_index),
435 .simple_type, .int_type => return val,
436 .enum_type => {
437 const enum_type = ip.loadEnumType(ty.toIntern());
438 if (enum_type.values.len != 0) {
439 return Value.fromInterned(enum_type.values.get(ip)[field_index]);
440 } else {
441 // Field index and integer values are the same.
442 return mod.intValue(Type.fromInterned(enum_type.tag_ty), field_index);
443 }
444 },
439445 else => unreachable,
440 };
446 }
441447 },
442 .enum_type => |enum_type| try mod.getCoerced(val, Type.fromInterned(enum_type.tag_ty)),
448 .enum_type => try mod.getCoerced(val, Type.fromInterned(ip.loadEnumType(enum_ty).tag_ty)),
443449 else => unreachable,
444450 };
445451}
......@@ -832,7 +838,7 @@ pub fn writeToPackedMemory(
832838 }
833839 },
834840 .Struct => {
835 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;
841 const struct_type = ip.loadStructType(ty.toIntern());
836842 // Sema is supposed to have emitted a compile error already in the case of Auto,
837843 // and Extern is handled in non-packed writeToMemory.
838844 assert(struct_type.layout == .Packed);
src/arch/wasm/CodeGen.zig+3-2
......@@ -3354,7 +3354,8 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
33543354 val.writeToMemory(ty, mod, &buf) catch unreachable;
33553355 return func.storeSimdImmd(buf);
33563356 },
3357 .struct_type => |struct_type| {
3357 .struct_type => {
3358 const struct_type = ip.loadStructType(ty.toIntern());
33583359 // non-packed structs are not handled in this function because they
33593360 // are by-ref types.
33603361 assert(struct_type.layout == .Packed);
......@@ -5411,7 +5412,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
54115412 const layout = union_ty.unionGetLayout(mod);
54125413 const union_obj = mod.typeToUnion(union_ty).?;
54135414 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
5414 const field_name = union_obj.field_names.get(ip)[extra.field_index];
5415 const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
54155416
54165417 const tag_int = blk: {
54175418 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
src/arch/wasm/abi.zig+1-1
......@@ -76,7 +76,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
7676 }
7777 const layout = ty.unionGetLayout(mod);
7878 assert(layout.tag_size == 0);
79 if (union_obj.field_names.len > 1) return memory;
79 if (union_obj.field_types.len > 1) return memory;
8080 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
8181 return classifyType(first_field_ty, mod);
8282 },
src/arch/x86_64/CodeGen.zig+1-1
......@@ -18183,7 +18183,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
1818318183 const dst_mcv = try self.allocRegOrMem(inst, false);
1818418184
1818518185 const union_obj = mod.typeToUnion(union_ty).?;
18186 const field_name = union_obj.field_names.get(ip)[extra.field_index];
18186 const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
1818718187 const tag_ty = Type.fromInterned(union_obj.enum_tag_ty);
1818818188 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
1818918189 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
src/codegen.zig+73-70
......@@ -510,88 +510,91 @@ pub fn generateSymbol(
510510 }
511511 }
512512 },
513 .struct_type => |struct_type| switch (struct_type.layout) {
514 .Packed => {
515 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
516 return error.Overflow;
517 const current_pos = code.items.len;
518 try code.resize(current_pos + abi_size);
519 var bits: u16 = 0;
520
521 for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
522 const field_val = switch (aggregate.storage) {
523 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
524 .ty = field_ty,
525 .storage = .{ .u64 = bytes[index] },
526 } }),
527 .elems => |elems| elems[index],
528 .repeated_elem => |elem| elem,
529 };
513 .struct_type => {
514 const struct_type = ip.loadStructType(typed_value.ty.toIntern());
515 switch (struct_type.layout) {
516 .Packed => {
517 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
518 return error.Overflow;
519 const current_pos = code.items.len;
520 try code.resize(current_pos + abi_size);
521 var bits: u16 = 0;
522
523 for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
524 const field_val = switch (aggregate.storage) {
525 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
526 .ty = field_ty,
527 .storage = .{ .u64 = bytes[index] },
528 } }),
529 .elems => |elems| elems[index],
530 .repeated_elem => |elem| elem,
531 };
532
533 // pointer may point to a decl which must be marked used
534 // but can also result in a relocation. Therefore we handle those separately.
535 if (Type.fromInterned(field_ty).zigTypeTag(mod) == .Pointer) {
536 const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(mod)) orelse
537 return error.Overflow;
538 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
539 defer tmp_list.deinit();
540 switch (try generateSymbol(bin_file, src_loc, .{
541 .ty = Type.fromInterned(field_ty),
542 .val = Value.fromInterned(field_val),
543 }, &tmp_list, debug_output, reloc_info)) {
544 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
545 .fail => |em| return Result{ .fail = em },
546 }
547 } else {
548 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable;
549 }
550 bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod)));
551 }
552 },
553 .Auto, .Extern => {
554 const struct_begin = code.items.len;
555 const field_types = struct_type.field_types.get(ip);
556 const offsets = struct_type.offsets.get(ip);
557
558 var it = struct_type.iterateRuntimeOrder(ip);
559 while (it.next()) |field_index| {
560 const field_ty = field_types[field_index];
561 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
562
563 const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
564 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
565 .ty = field_ty,
566 .storage = .{ .u64 = bytes[field_index] },
567 } }),
568 .elems => |elems| elems[field_index],
569 .repeated_elem => |elem| elem,
570 };
571
572 const padding = math.cast(
573 usize,
574 offsets[field_index] - (code.items.len - struct_begin),
575 ) orelse return error.Overflow;
576 if (padding > 0) try code.appendNTimes(0, padding);
530577
531 // pointer may point to a decl which must be marked used
532 // but can also result in a relocation. Therefore we handle those separately.
533 if (Type.fromInterned(field_ty).zigTypeTag(mod) == .Pointer) {
534 const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(mod)) orelse
535 return error.Overflow;
536 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
537 defer tmp_list.deinit();
538578 switch (try generateSymbol(bin_file, src_loc, .{
539579 .ty = Type.fromInterned(field_ty),
540580 .val = Value.fromInterned(field_val),
541 }, &tmp_list, debug_output, reloc_info)) {
542 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
581 }, code, debug_output, reloc_info)) {
582 .ok => {},
543583 .fail => |em| return Result{ .fail = em },
544584 }
545 } else {
546 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable;
547585 }
548 bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod)));
549 }
550 },
551 .Auto, .Extern => {
552 const struct_begin = code.items.len;
553 const field_types = struct_type.field_types.get(ip);
554 const offsets = struct_type.offsets.get(ip);
555
556 var it = struct_type.iterateRuntimeOrder(ip);
557 while (it.next()) |field_index| {
558 const field_ty = field_types[field_index];
559 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
560
561 const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
562 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
563 .ty = field_ty,
564 .storage = .{ .u64 = bytes[field_index] },
565 } }),
566 .elems => |elems| elems[field_index],
567 .repeated_elem => |elem| elem,
568 };
586
587 const size = struct_type.size(ip).*;
588 const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?;
569589
570590 const padding = math.cast(
571591 usize,
572 offsets[field_index] - (code.items.len - struct_begin),
592 std.mem.alignForward(u64, size, @max(alignment, 1)) -
593 (code.items.len - struct_begin),
573594 ) orelse return error.Overflow;
574595 if (padding > 0) try code.appendNTimes(0, padding);
575
576 switch (try generateSymbol(bin_file, src_loc, .{
577 .ty = Type.fromInterned(field_ty),
578 .val = Value.fromInterned(field_val),
579 }, code, debug_output, reloc_info)) {
580 .ok => {},
581 .fail => |em| return Result{ .fail = em },
582 }
583 }
584
585 const size = struct_type.size(ip).*;
586 const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?;
587
588 const padding = math.cast(
589 usize,
590 std.mem.alignForward(u64, size, @max(alignment, 1)) -
591 (code.items.len - struct_begin),
592 ) orelse return error.Overflow;
593 if (padding > 0) try code.appendNTimes(0, padding);
594 },
596 },
597 }
595598 },
596599 else => unreachable,
597600 },
src/codegen/c.zig+11-13
......@@ -1475,13 +1475,10 @@ pub const DeclGen = struct {
14751475 var empty = true;
14761476 for (0..struct_type.field_types.len) |field_index| {
14771477 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1478 if (struct_type.fieldIsComptime(ip, field_index)) continue;
14781479 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14791480
1480 if (!empty) try writer.writeAll(" | ");
1481 try writer.writeByte('(');
1482 try dg.renderType(writer, ty);
1483 try writer.writeByte(')');
1484
1481 if (!empty) try writer.writeByte(',');
14851482 const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
14861483 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
14871484 .ty = field_ty.toIntern(),
......@@ -1490,6 +1487,7 @@ pub const DeclGen = struct {
14901487 .elems => |elems| elems[field_index],
14911488 .repeated_elem => |elem| elem,
14921489 };
1490 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type);
14931491
14941492 if (bit_offset != 0) {
14951493 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other);
......@@ -1503,7 +1501,7 @@ pub const DeclGen = struct {
15031501 bit_offset += field_ty.bitSize(mod);
15041502 empty = false;
15051503 }
1506 try writer.writeByte(')');
1504 try writer.writeByte('}');
15071505 }
15081506 },
15091507 },
......@@ -1547,7 +1545,7 @@ pub const DeclGen = struct {
15471545
15481546 const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
15491547 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
1550 const field_name = union_obj.field_names.get(ip)[field_index];
1548 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
15511549 if (union_obj.getLayout(ip) == .Packed) {
15521550 if (field_ty.hasRuntimeBits(mod)) {
15531551 if (field_ty.isPtrAtRuntime(mod)) {
......@@ -5502,7 +5500,7 @@ fn fieldLocation(
55025500 .{ .field = .{ .identifier = "payload" } }
55035501 else
55045502 .begin;
5505 const field_name = union_obj.field_names.get(ip)[field_index];
5503 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
55065504 return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|
55075505 .{ .payload_identifier = ip.stringToSlice(field_name) }
55085506 else
......@@ -5735,8 +5733,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
57355733 else
57365734 .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
57375735
5738 .union_type => |union_type| field_name: {
5739 const union_obj = ip.loadUnionType(union_type);
5736 .union_type => field_name: {
5737 const union_obj = ip.loadUnionType(struct_ty.toIntern());
57405738 if (union_obj.flagsPtr(ip).layout == .Packed) {
57415739 const operand_lval = if (struct_byval == .constant) blk: {
57425740 const operand_local = try f.allocLocal(inst, struct_ty);
......@@ -5762,8 +5760,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
57625760
57635761 return local;
57645762 } else {
5765 const name = union_obj.field_names.get(ip)[extra.field_index];
5766 break :field_name if (union_type.hasTag(ip)) .{
5763 const name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
5764 break :field_name if (union_obj.hasTag(ip)) .{
57675765 .payload_identifier = ip.stringToSlice(name),
57685766 } else .{
57695767 .identifier = ip.stringToSlice(name),
......@@ -7171,7 +7169,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71717169
71727170 const union_ty = f.typeOfIndex(inst);
71737171 const union_obj = mod.typeToUnion(union_ty).?;
7174 const field_name = union_obj.field_names.get(ip)[extra.field_index];
7172 const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
71757173 const payload_ty = f.typeOf(extra.init);
71767174 const payload = try f.resolveInst(extra.init);
71777175 try reap(f, inst, &.{extra.init});
src/codegen/c/type.zig+8-8
......@@ -1507,7 +1507,7 @@ pub const CType = extern union {
15071507 if (lookup.isMutable()) {
15081508 for (0..switch (zig_ty_tag) {
15091509 .Struct => ty.structFieldCount(mod),
1510 .Union => mod.typeToUnion(ty).?.field_names.len,
1510 .Union => mod.typeToUnion(ty).?.field_types.len,
15111511 else => unreachable,
15121512 }) |field_i| {
15131513 const field_ty = ty.structFieldType(field_i, mod);
......@@ -1589,7 +1589,7 @@ pub const CType = extern union {
15891589 var is_packed = false;
15901590 for (0..switch (zig_ty_tag) {
15911591 .Struct => ty.structFieldCount(mod),
1592 .Union => mod.typeToUnion(ty).?.field_names.len,
1592 .Union => mod.typeToUnion(ty).?.field_types.len,
15931593 else => unreachable,
15941594 }) |field_i| {
15951595 const field_ty = ty.structFieldType(field_i, mod);
......@@ -1940,7 +1940,7 @@ pub const CType = extern union {
19401940 const zig_ty_tag = ty.zigTypeTag(mod);
19411941 const fields_len = switch (zig_ty_tag) {
19421942 .Struct => ty.structFieldCount(mod),
1943 .Union => mod.typeToUnion(ty).?.field_names.len,
1943 .Union => mod.typeToUnion(ty).?.field_types.len,
19441944 else => unreachable,
19451945 };
19461946
......@@ -1967,7 +1967,7 @@ pub const CType = extern union {
19671967 else
19681968 arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) {
19691969 .Struct => ty.legacyStructFieldName(field_i, mod),
1970 .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i],
1970 .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i],
19711971 else => unreachable,
19721972 })),
19731973 .type = store.set.typeToIndex(field_ty, mod, switch (kind) {
......@@ -2097,7 +2097,7 @@ pub const CType = extern union {
20972097 var c_field_i: usize = 0;
20982098 for (0..switch (zig_ty_tag) {
20992099 .Struct => ty.structFieldCount(mod),
2100 .Union => mod.typeToUnion(ty).?.field_names.len,
2100 .Union => mod.typeToUnion(ty).?.field_types.len,
21012101 else => unreachable,
21022102 }) |field_i_usize| {
21032103 const field_i: u32 = @intCast(field_i_usize);
......@@ -2120,7 +2120,7 @@ pub const CType = extern union {
21202120 else
21212121 ip.stringToSlice(switch (zig_ty_tag) {
21222122 .Struct => ty.legacyStructFieldName(field_i, mod),
2123 .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i],
2123 .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i],
21242124 else => unreachable,
21252125 }),
21262126 mem.span(c_field.name),
......@@ -2226,7 +2226,7 @@ pub const CType = extern union {
22262226 const zig_ty_tag = ty.zigTypeTag(mod);
22272227 for (0..switch (ty.zigTypeTag(mod)) {
22282228 .Struct => ty.structFieldCount(mod),
2229 .Union => mod.typeToUnion(ty).?.field_names.len,
2229 .Union => mod.typeToUnion(ty).?.field_types.len,
22302230 else => unreachable,
22312231 }) |field_i_usize| {
22322232 const field_i: u32 = @intCast(field_i_usize);
......@@ -2245,7 +2245,7 @@ pub const CType = extern union {
22452245 else
22462246 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
22472247 .Struct => ty.legacyStructFieldName(field_i, mod),
2248 .Union => mod.typeToUnion(ty).?.field_names.get(ip)[field_i],
2248 .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i],
22492249 else => unreachable,
22502250 }));
22512251 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align");
src/codegen/llvm.zig+30-24
......@@ -1997,7 +1997,7 @@ pub const Object = struct {
19971997 return debug_enum_type;
19981998 }
19991999
2000 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
2000 const enum_type = ip.loadEnumType(ty.toIntern());
20012001
20022002 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
20032003 defer gpa.free(enumerators);
......@@ -2507,8 +2507,8 @@ pub const Object = struct {
25072507 try o.debug_type_map.put(gpa, ty, debug_struct_type);
25082508 return debug_struct_type;
25092509 },
2510 .struct_type => |struct_type| {
2511 if (!struct_type.haveFieldTypes(ip)) {
2510 .struct_type => {
2511 if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) {
25122512 // This can happen if a struct type makes it all the way to
25132513 // flush() without ever being instantiated or referenced (even
25142514 // via pointer). The only reason we are hearing about it now is
......@@ -2597,15 +2597,14 @@ pub const Object = struct {
25972597 const name = try o.allocTypeName(ty);
25982598 defer gpa.free(name);
25992599
2600 const union_type = ip.indexToKey(ty.toIntern()).union_type;
2600 const union_type = ip.loadUnionType(ty.toIntern());
26012601 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
26022602 const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
26032603 try o.debug_type_map.put(gpa, ty, debug_union_type);
26042604 return debug_union_type;
26052605 }
26062606
2607 const union_obj = ip.loadUnionType(union_type);
2608 const layout = mod.getUnionLayout(union_obj);
2607 const layout = mod.getUnionLayout(union_type);
26092608
26102609 const debug_fwd_ref = try o.builder.debugForwardReference();
26112610
......@@ -2622,7 +2621,7 @@ pub const Object = struct {
26222621 ty.abiSize(mod) * 8,
26232622 ty.abiAlignment(mod).toByteUnits(0) * 8,
26242623 try o.builder.debugTuple(
2625 &.{try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty))},
2624 &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))},
26262625 ),
26272626 );
26282627
......@@ -2636,21 +2635,23 @@ pub const Object = struct {
26362635 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
26372636 defer fields.deinit(gpa);
26382637
2639 try fields.ensureUnusedCapacity(gpa, union_obj.field_names.len);
2638 try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len);
26402639
26412640 const debug_union_fwd_ref = if (layout.tag_size == 0)
26422641 debug_fwd_ref
26432642 else
26442643 try o.builder.debugForwardReference();
26452644
2646 for (0..union_obj.field_names.len) |field_index| {
2647 const field_ty = union_obj.field_types.get(ip)[field_index];
2645 const tag_type = union_type.loadTagType();
2646
2647 for (0..tag_type.names.len) |field_index| {
2648 const field_ty = union_type.field_types.get(ip)[field_index];
26482649 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
26492650
26502651 const field_size = Type.fromInterned(field_ty).abiSize(mod);
2651 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));
2652 const field_align = mod.unionFieldNormalAlignment(union_type, @intCast(field_index));
26522653
2653 const field_name = union_obj.field_names.get(ip)[field_index];
2654 const field_name = tag_type.names.get(ip)[field_index];
26542655 fields.appendAssumeCapacity(try o.builder.debugMemberType(
26552656 try o.builder.metadataString(ip.stringToSlice(field_name)),
26562657 .none, // File
......@@ -2706,7 +2707,7 @@ pub const Object = struct {
27062707 .none, // File
27072708 debug_fwd_ref,
27082709 0, // Line
2709 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)),
2710 try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)),
27102711 layout.tag_size * 8,
27112712 layout.tag_align.toByteUnits(0) * 8,
27122713 tag_offset * 8,
......@@ -3321,9 +3322,11 @@ pub const Object = struct {
33213322 return o.builder.structType(.normal, fields[0..fields_len]);
33223323 },
33233324 .simple_type => unreachable,
3324 .struct_type => |struct_type| {
3325 .struct_type => {
33253326 if (o.type_map.get(t.toIntern())) |value| return value;
33263327
3328 const struct_type = ip.loadStructType(t.toIntern());
3329
33273330 if (struct_type.layout == .Packed) {
33283331 const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*));
33293332 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
......@@ -3468,10 +3471,10 @@ pub const Object = struct {
34683471 }
34693472 return o.builder.structType(.normal, llvm_field_types.items);
34703473 },
3471 .union_type => |union_type| {
3474 .union_type => {
34723475 if (o.type_map.get(t.toIntern())) |value| return value;
34733476
3474 const union_obj = ip.loadUnionType(union_type);
3477 const union_obj = ip.loadUnionType(t.toIntern());
34753478 const layout = mod.getUnionLayout(union_obj);
34763479
34773480 if (union_obj.flagsPtr(ip).layout == .Packed) {
......@@ -3555,7 +3558,7 @@ pub const Object = struct {
35553558 }
35563559 return gop.value_ptr.*;
35573560 },
3558 .enum_type => |enum_type| try o.lowerType(Type.fromInterned(enum_type.tag_ty)),
3561 .enum_type => try o.lowerType(Type.fromInterned(ip.loadEnumType(t.toIntern()).tag_ty)),
35593562 .func_type => |func_type| try o.lowerTypeFn(func_type),
35603563 .error_set_type, .inferred_error_set_type => try o.errorIntType(),
35613564 // values, not types
......@@ -4032,7 +4035,8 @@ pub const Object = struct {
40324035 else
40334036 struct_ty, vals);
40344037 },
4035 .struct_type => |struct_type| {
4038 .struct_type => {
4039 const struct_type = ip.loadStructType(ty.toIntern());
40364040 assert(struct_type.haveLayout(ip));
40374041 const struct_ty = try o.lowerType(ty);
40384042 if (struct_type.layout == .Packed) {
......@@ -4596,7 +4600,7 @@ pub const Object = struct {
45964600 fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index {
45974601 const zcu = o.module;
45984602 const ip = &zcu.intern_pool;
4599 const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type;
4603 const enum_type = ip.loadEnumType(enum_ty.toIntern());
46004604
46014605 // TODO: detect when the type changes and re-emit this function.
46024606 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
......@@ -9620,7 +9624,7 @@ pub const FuncGen = struct {
96209624 fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
96219625 const o = self.dg.object;
96229626 const zcu = o.module;
9623 const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
9627 const enum_type = zcu.intern_pool.loadEnumType(enum_ty.toIntern());
96249628
96259629 // TODO: detect when the type changes and re-emit this function.
96269630 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);
......@@ -10092,7 +10096,7 @@ pub const FuncGen = struct {
1009210096
1009310097 const tag_int = blk: {
1009410098 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
10095 const union_field_name = union_obj.field_names.get(ip)[extra.field_index];
10099 const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
1009610100 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
1009710101 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
1009810102 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);
......@@ -11154,7 +11158,8 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E
1115411158 if (first_non_integer == null or classes[first_non_integer.?] == .none) {
1115511159 assert(first_non_integer orelse classes.len == types_index);
1115611160 switch (ip.indexToKey(return_type.toIntern())) {
11157 .struct_type => |struct_type| {
11161 .struct_type => {
11162 const struct_type = ip.loadStructType(return_type.toIntern());
1115811163 assert(struct_type.haveLayout(ip));
1115911164 const size: u64 = struct_type.size(ip).*;
1116011165 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
......@@ -11446,7 +11451,8 @@ const ParamTypeIterator = struct {
1144611451 return .byref;
1144711452 }
1144811453 switch (ip.indexToKey(ty.toIntern())) {
11449 .struct_type => |struct_type| {
11454 .struct_type => {
11455 const struct_type = ip.loadStructType(ty.toIntern());
1145011456 assert(struct_type.haveLayout(ip));
1145111457 const size: u64 = struct_type.size(ip).*;
1145211458 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
......@@ -11562,7 +11568,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
1156211568 }
1156311569 return false;
1156411570 },
11565 .struct_type => |s| s,
11571 .struct_type => ip.loadStructType(ty.toIntern()),
1156611572 else => unreachable,
1156711573 };
1156811574
src/codegen/spirv.zig+9-11
......@@ -1528,7 +1528,7 @@ const DeclGen = struct {
15281528 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
15291529 return ty_ref;
15301530 },
1531 .struct_type => |struct_type| struct_type,
1531 .struct_type => ip.loadStructType(ty.toIntern()),
15321532 else => unreachable,
15331533 };
15341534
......@@ -3633,7 +3633,8 @@ const DeclGen = struct {
36333633 index += 1;
36343634 }
36353635 },
3636 .struct_type => |struct_type| {
3636 .struct_type => {
3637 const struct_type = ip.loadStructType(result_ty.toIntern());
36373638 var it = struct_type.iterateRuntimeOrder(ip);
36383639 for (elements, 0..) |element, i| {
36393640 const field_index = it.next().?;
......@@ -3901,36 +3902,33 @@ const DeclGen = struct {
39013902 const mod = self.module;
39023903 const ip = &mod.intern_pool;
39033904 const union_ty = mod.typeToUnion(ty).?;
3905 const tag_ty = Type.fromInterned(union_ty.enum_tag_ty);
39043906
39053907 if (union_ty.getLayout(ip) == .Packed) {
39063908 unreachable; // TODO
39073909 }
39083910
3909 const maybe_tag_ty = ty.unionTagTypeSafety(mod);
39103911 const layout = self.unionLayout(ty);
39113912
39123913 const tag_int = if (layout.tag_size != 0) blk: {
3913 const tag_ty = maybe_tag_ty.?;
3914 const union_field_name = union_ty.field_names.get(ip)[active_field];
3915 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
3916 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
3914 const tag_val = try mod.enumValueFieldIndex(tag_ty, active_field);
39173915 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);
39183916 break :blk tag_int_val.toUnsignedInt(mod);
39193917 } else 0;
39203918
39213919 if (!layout.has_payload) {
3922 const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct);
3920 const tag_ty_ref = try self.resolveType(tag_ty, .direct);
39233921 return try self.constInt(tag_ty_ref, tag_int);
39243922 }
39253923
39263924 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });
39273925
39283926 if (layout.tag_size != 0) {
3929 const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct);
3930 const tag_ptr_ty_ref = try self.ptrType(maybe_tag_ty.?, .Function);
3927 const tag_ty_ref = try self.resolveType(tag_ty, .direct);
3928 const tag_ptr_ty_ref = try self.ptrType(tag_ty, .Function);
39313929 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
39323930 const tag_id = try self.constInt(tag_ty_ref, tag_int);
3933 try self.store(maybe_tag_ty.?, ptr_id, tag_id, .{});
3931 try self.store(tag_ty, ptr_id, tag_id, .{});
39343932 }
39353933
39363934 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);
src/link/Dwarf.zig+4-3
......@@ -311,7 +311,8 @@ pub const DeclState = struct {
311311 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
312312 }
313313 },
314 .struct_type => |struct_type| {
314 .struct_type => {
315 const struct_type = ip.loadStructType(ty.toIntern());
315316 // DW.AT.name, DW.FORM.string
316317 try ty.print(dbg_info_buffer.writer(), mod);
317318 try dbg_info_buffer.append(0);
......@@ -374,7 +375,7 @@ pub const DeclState = struct {
374375 try ty.print(dbg_info_buffer.writer(), mod);
375376 try dbg_info_buffer.append(0);
376377
377 const enum_type = ip.indexToKey(ty.ip_index).enum_type;
378 const enum_type = ip.loadEnumType(ty.ip_index);
378379 for (enum_type.names.get(ip), 0..) |field_name_index, field_i| {
379380 const field_name = ip.stringToSlice(field_name_index);
380381 // DW.AT.enumerator
......@@ -442,7 +443,7 @@ pub const DeclState = struct {
442443 try dbg_info_buffer.append(0);
443444 }
444445
445 for (union_obj.field_types.get(ip), union_obj.field_names.get(ip)) |field_ty, field_name| {
446 for (union_obj.field_types.get(ip), union_obj.loadTagType(ip).names.get(ip)) |field_ty, field_name| {
446447 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
447448 // DW.AT.member
448449 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member));
src/type.zig+178-156
......@@ -320,11 +320,12 @@ pub const Type = struct {
320320
321321 .generic_poison => unreachable,
322322 },
323 .struct_type => |struct_type| {
323 .struct_type => {
324 const struct_type = ip.loadStructType(ty.toIntern());
324325 if (struct_type.decl.unwrap()) |decl_index| {
325326 const decl = mod.declPtr(decl_index);
326327 try decl.renderFullyQualifiedName(mod, writer);
327 } else if (struct_type.namespace.unwrap()) |namespace_index| {
328 } else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| {
328329 const namespace = mod.namespacePtr(namespace_index);
329330 try namespace.renderFullyQualifiedName(mod, .empty, writer);
330331 } else {
......@@ -573,7 +574,8 @@ pub const Type = struct {
573574
574575 .generic_poison => unreachable,
575576 },
576 .struct_type => |struct_type| {
577 .struct_type => {
578 const struct_type = ip.loadStructType(ty.toIntern());
577579 if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {
578580 // In this case, we guess that hasRuntimeBits() for this type is true,
579581 // and then later if our guess was incorrect, we emit a compile error.
......@@ -601,7 +603,8 @@ pub const Type = struct {
601603 return false;
602604 },
603605
604 .union_type => |union_type| {
606 .union_type => {
607 const union_type = ip.loadUnionType(ty.toIntern());
605608 switch (union_type.flagsPtr(ip).runtime_tag) {
606609 .none => {
607610 if (union_type.flagsPtr(ip).status == .field_types_wip) {
......@@ -628,9 +631,8 @@ pub const Type = struct {
628631 .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes())
629632 return error.NeedLazy,
630633 }
631 const union_obj = ip.loadUnionType(union_type);
632 for (0..union_obj.field_types.len) |field_index| {
633 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
634 for (0..union_type.field_types.len) |field_index| {
635 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
634636 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
635637 return true;
636638 } else {
......@@ -639,7 +641,7 @@ pub const Type = struct {
639641 },
640642
641643 .opaque_type => true,
642 .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
644 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
643645
644646 // values, not types
645647 .undef,
......@@ -736,15 +738,19 @@ pub const Type = struct {
736738 .generic_poison,
737739 => false,
738740 },
739 .struct_type => |struct_type| {
741 .struct_type => {
742 const struct_type = ip.loadStructType(ty.toIntern());
740743 // Struct with no fields have a well-defined layout of no bits.
741744 return struct_type.layout != .Auto or struct_type.field_types.len == 0;
742745 },
743 .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) {
744 .none, .safety => union_type.flagsPtr(ip).layout != .Auto,
745 .tagged => false,
746 .union_type => {
747 const union_type = ip.loadUnionType(ty.toIntern());
748 return switch (union_type.flagsPtr(ip).runtime_tag) {
749 .none, .safety => union_type.flagsPtr(ip).layout != .Auto,
750 .tagged => false,
751 };
746752 },
747 .enum_type => |enum_type| switch (enum_type.tag_mode) {
753 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
748754 .auto => false,
749755 .explicit, .nonexhaustive => true,
750756 },
......@@ -1019,7 +1025,8 @@ pub const Type = struct {
10191025 .noreturn => unreachable,
10201026 .generic_poison => unreachable,
10211027 },
1022 .struct_type => |struct_type| {
1028 .struct_type => {
1029 const struct_type = ip.loadStructType(ty.toIntern());
10231030 if (struct_type.layout == .Packed) {
10241031 switch (strat) {
10251032 .sema => |sema| try sema.resolveTypeLayout(ty),
......@@ -1066,7 +1073,8 @@ pub const Type = struct {
10661073 }
10671074 return .{ .scalar = big_align };
10681075 },
1069 .union_type => |union_type| {
1076 .union_type => {
1077 const union_type = ip.loadUnionType(ty.toIntern());
10701078 const flags = union_type.flagsPtr(ip).*;
10711079 if (flags.alignment != .none) return .{ .scalar = flags.alignment };
10721080
......@@ -1082,8 +1090,8 @@ pub const Type = struct {
10821090 return .{ .scalar = union_type.flagsPtr(ip).alignment };
10831091 },
10841092 .opaque_type => return .{ .scalar = .@"1" },
1085 .enum_type => |enum_type| return .{
1086 .scalar = Type.fromInterned(enum_type.tag_ty).abiAlignment(mod),
1093 .enum_type => return .{
1094 .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(mod),
10871095 },
10881096
10891097 // values, not types
......@@ -1394,7 +1402,8 @@ pub const Type = struct {
13941402 .noreturn => unreachable,
13951403 .generic_poison => unreachable,
13961404 },
1397 .struct_type => |struct_type| {
1405 .struct_type => {
1406 const struct_type = ip.loadStructType(ty.toIntern());
13981407 switch (strat) {
13991408 .sema => |sema| try sema.resolveTypeLayout(ty),
14001409 .lazy => switch (struct_type.layout) {
......@@ -1439,7 +1448,8 @@ pub const Type = struct {
14391448 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
14401449 },
14411450
1442 .union_type => |union_type| {
1451 .union_type => {
1452 const union_type = ip.loadUnionType(ty.toIntern());
14431453 switch (strat) {
14441454 .sema => |sema| try sema.resolveTypeLayout(ty),
14451455 .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{
......@@ -1455,7 +1465,7 @@ pub const Type = struct {
14551465 return .{ .scalar = union_type.size(ip).* };
14561466 },
14571467 .opaque_type => unreachable, // no size available
1458 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = Type.fromInterned(enum_type.tag_ty).abiSize(mod) },
1468 .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(mod) },
14591469
14601470 // values, not types
14611471 .undef,
......@@ -1644,7 +1654,8 @@ pub const Type = struct {
16441654 .extern_options => unreachable,
16451655 .type_info => unreachable,
16461656 },
1647 .struct_type => |struct_type| {
1657 .struct_type => {
1658 const struct_type = ip.loadStructType(ty.toIntern());
16481659 const is_packed = struct_type.layout == .Packed;
16491660 if (opt_sema) |sema| {
16501661 try sema.resolveTypeFields(ty);
......@@ -1661,7 +1672,8 @@ pub const Type = struct {
16611672 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
16621673 },
16631674
1664 .union_type => |union_type| {
1675 .union_type => {
1676 const union_type = ip.loadUnionType(ty.toIntern());
16651677 const is_packed = ty.containerLayout(mod) == .Packed;
16661678 if (opt_sema) |sema| {
16671679 try sema.resolveTypeFields(ty);
......@@ -1670,19 +1682,18 @@ pub const Type = struct {
16701682 if (!is_packed) {
16711683 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
16721684 }
1673 const union_obj = ip.loadUnionType(union_type);
1674 assert(union_obj.flagsPtr(ip).status.haveFieldTypes());
1685 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
16751686
16761687 var size: u64 = 0;
1677 for (0..union_obj.field_types.len) |field_index| {
1678 const field_ty = union_obj.field_types.get(ip)[field_index];
1688 for (0..union_type.field_types.len) |field_index| {
1689 const field_ty = union_type.field_types.get(ip)[field_index];
16791690 size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema));
16801691 }
16811692
16821693 return size;
16831694 },
16841695 .opaque_type => unreachable,
1685 .enum_type => |enum_type| return bitSizeAdvanced(Type.fromInterned(enum_type.tag_ty), mod, opt_sema),
1696 .enum_type => return bitSizeAdvanced(Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), mod, opt_sema),
16861697
16871698 // values, not types
16881699 .undef,
......@@ -1713,8 +1724,8 @@ pub const Type = struct {
17131724 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
17141725 const ip = &mod.intern_pool;
17151726 return switch (ip.indexToKey(ty.toIntern())) {
1716 .struct_type => |struct_type| struct_type.haveLayout(ip),
1717 .union_type => |union_type| union_type.haveLayout(ip),
1727 .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip),
1728 .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip),
17181729 .array_type => |array_type| {
17191730 if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true;
17201731 return Type.fromInterned(array_type.child).layoutIsResolved(mod);
......@@ -1914,16 +1925,18 @@ pub const Type = struct {
19141925 /// Otherwise, returns `null`.
19151926 pub fn unionTagType(ty: Type, mod: *Module) ?Type {
19161927 const ip = &mod.intern_pool;
1917 return switch (ip.indexToKey(ty.toIntern())) {
1918 .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) {
1919 .tagged => {
1920 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
1921 return Type.fromInterned(union_type.enum_tag_ty);
1922 },
1923 else => null,
1928 switch (ip.indexToKey(ty.toIntern())) {
1929 .union_type => {},
1930 else => return null,
1931 }
1932 const union_type = ip.loadUnionType(ty.toIntern());
1933 switch (union_type.flagsPtr(ip).runtime_tag) {
1934 .tagged => {
1935 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
1936 return Type.fromInterned(union_type.enum_tag_ty);
19241937 },
1925 else => null,
1926 };
1938 else => return null,
1939 }
19271940 }
19281941
19291942 /// Same as `unionTagType` but includes safety tag.
......@@ -1931,7 +1944,8 @@ pub const Type = struct {
19311944 pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
19321945 const ip = &mod.intern_pool;
19331946 return switch (ip.indexToKey(ty.toIntern())) {
1934 .union_type => |union_type| {
1947 .union_type => {
1948 const union_type = ip.loadUnionType(ty.toIntern());
19351949 if (!union_type.hasTag(ip)) return null;
19361950 assert(union_type.haveFieldTypes(ip));
19371951 return Type.fromInterned(union_type.enum_tag_ty);
......@@ -1981,17 +1995,16 @@ pub const Type = struct {
19811995
19821996 pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout {
19831997 const ip = &mod.intern_pool;
1984 const union_type = ip.indexToKey(ty.toIntern()).union_type;
1985 const union_obj = ip.loadUnionType(union_type);
1998 const union_obj = ip.loadUnionType(ty.toIntern());
19861999 return mod.getUnionLayout(union_obj);
19872000 }
19882001
19892002 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
19902003 const ip = &mod.intern_pool;
19912004 return switch (ip.indexToKey(ty.toIntern())) {
1992 .struct_type => |struct_type| struct_type.layout,
2005 .struct_type => ip.loadStructType(ty.toIntern()).layout,
19932006 .anon_struct_type => .Auto,
1994 .union_type => |union_type| union_type.flagsPtr(ip).layout,
2007 .union_type => ip.loadUnionType(ty.toIntern()).flagsPtr(ip).layout,
19952008 else => unreachable,
19962009 };
19972010 }
......@@ -2095,22 +2108,15 @@ pub const Type = struct {
20952108
20962109 /// Asserts the type is an array or vector or struct.
20972110 pub fn arrayLen(ty: Type, mod: *const Module) u64 {
2098 return arrayLenIp(ty, &mod.intern_pool);
2111 return ty.arrayLenIp(&mod.intern_pool);
20992112 }
21002113
21012114 pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
2102 return switch (ip.indexToKey(ty.toIntern())) {
2103 .vector_type => |vector_type| vector_type.len,
2104 .array_type => |array_type| array_type.len,
2105 .struct_type => |struct_type| struct_type.field_types.len,
2106 .anon_struct_type => |tuple| tuple.types.len,
2107
2108 else => unreachable,
2109 };
2115 return ip.aggregateTypeLen(ty.toIntern());
21102116 }
21112117
21122118 pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {
2113 return ty.arrayLen(mod) + @intFromBool(ty.sentinel(mod) != null);
2119 return mod.intern_pool.aggregateTypeLenIncludingSentinel(ty.toIntern());
21142120 }
21152121
21162122 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
......@@ -2199,8 +2205,8 @@ pub const Type = struct {
21992205 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
22002206 else => switch (ip.indexToKey(ty.toIntern())) {
22012207 .int_type => |int_type| return int_type,
2202 .struct_type => |t| ty = Type.fromInterned(t.backingIntType(ip).*),
2203 .enum_type => |enum_type| ty = Type.fromInterned(enum_type.tag_ty),
2208 .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntType(ip).*),
2209 .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
22042210 .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),
22052211
22062212 .error_set_type, .inferred_error_set_type => {
......@@ -2463,7 +2469,8 @@ pub const Type = struct {
24632469
24642470 .generic_poison => unreachable,
24652471 },
2466 .struct_type => |struct_type| {
2472 .struct_type => {
2473 const struct_type = ip.loadStructType(ty.toIntern());
24672474 assert(struct_type.haveFieldTypes(ip));
24682475 if (struct_type.knownNonOpv(ip))
24692476 return null;
......@@ -2505,11 +2512,11 @@ pub const Type = struct {
25052512 } })));
25062513 },
25072514
2508 .union_type => |union_type| {
2509 const union_obj = ip.loadUnionType(union_type);
2515 .union_type => {
2516 const union_obj = ip.loadUnionType(ty.toIntern());
25102517 const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse
25112518 return null;
2512 if (union_obj.field_names.len == 0) {
2519 if (union_obj.field_types.len == 0) {
25132520 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
25142521 return Value.fromInterned(only);
25152522 }
......@@ -2524,45 +2531,48 @@ pub const Type = struct {
25242531 return Value.fromInterned(only);
25252532 },
25262533 .opaque_type => return null,
2527 .enum_type => |enum_type| switch (enum_type.tag_mode) {
2528 .nonexhaustive => {
2529 if (enum_type.tag_ty == .comptime_int_type) return null;
2530
2531 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
2532 const only = try mod.intern(.{ .enum_tag = .{
2533 .ty = ty.toIntern(),
2534 .int = int_opv.toIntern(),
2535 } });
2536 return Value.fromInterned(only);
2537 }
2534 .enum_type => {
2535 const enum_type = ip.loadEnumType(ty.toIntern());
2536 switch (enum_type.tag_mode) {
2537 .nonexhaustive => {
2538 if (enum_type.tag_ty == .comptime_int_type) return null;
2539
2540 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
2541 const only = try mod.intern(.{ .enum_tag = .{
2542 .ty = ty.toIntern(),
2543 .int = int_opv.toIntern(),
2544 } });
2545 return Value.fromInterned(only);
2546 }
25382547
2539 return null;
2540 },
2541 .auto, .explicit => {
2542 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
2548 return null;
2549 },
2550 .auto, .explicit => {
2551 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
25432552
2544 switch (enum_type.names.len) {
2545 0 => {
2546 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2547 return Value.fromInterned(only);
2548 },
2549 1 => {
2550 if (enum_type.values.len == 0) {
2551 const only = try mod.intern(.{ .enum_tag = .{
2552 .ty = ty.toIntern(),
2553 .int = try mod.intern(.{ .int = .{
2554 .ty = enum_type.tag_ty,
2555 .storage = .{ .u64 = 0 },
2556 } }),
2557 } });
2553 switch (enum_type.names.len) {
2554 0 => {
2555 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
25582556 return Value.fromInterned(only);
2559 } else {
2560 return Value.fromInterned(enum_type.values.get(ip)[0]);
2561 }
2562 },
2563 else => return null,
2564 }
2565 },
2557 },
2558 1 => {
2559 if (enum_type.values.len == 0) {
2560 const only = try mod.intern(.{ .enum_tag = .{
2561 .ty = ty.toIntern(),
2562 .int = try mod.intern(.{ .int = .{
2563 .ty = enum_type.tag_ty,
2564 .storage = .{ .u64 = 0 },
2565 } }),
2566 } });
2567 return Value.fromInterned(only);
2568 } else {
2569 return Value.fromInterned(enum_type.values.get(ip)[0]);
2570 }
2571 },
2572 else => return null,
2573 }
2574 },
2575 }
25662576 },
25672577
25682578 // values, not types
......@@ -2676,7 +2686,8 @@ pub const Type = struct {
26762686 .type_info,
26772687 => true,
26782688 },
2679 .struct_type => |struct_type| {
2689 .struct_type => {
2690 const struct_type = ip.loadStructType(ty.toIntern());
26802691 // packed structs cannot be comptime-only because they have a well-defined
26812692 // memory layout and every field has a well-defined bit pattern.
26822693 if (struct_type.layout == .Packed)
......@@ -2726,38 +2737,40 @@ pub const Type = struct {
27262737 return false;
27272738 },
27282739
2729 .union_type => |union_type| switch (union_type.flagsPtr(ip).requires_comptime) {
2730 .no, .wip => false,
2731 .yes => true,
2732 .unknown => {
2733 // The type is not resolved; assert that we have a Sema.
2734 const sema = opt_sema.?;
2740 .union_type => {
2741 const union_type = ip.loadUnionType(ty.toIntern());
2742 switch (union_type.flagsPtr(ip).requires_comptime) {
2743 .no, .wip => return false,
2744 .yes => return true,
2745 .unknown => {
2746 // The type is not resolved; assert that we have a Sema.
2747 const sema = opt_sema.?;
27352748
2736 if (union_type.flagsPtr(ip).status == .field_types_wip)
2737 return false;
2749 if (union_type.flagsPtr(ip).status == .field_types_wip)
2750 return false;
27382751
2739 union_type.flagsPtr(ip).requires_comptime = .wip;
2740 errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
2752 union_type.flagsPtr(ip).requires_comptime = .wip;
2753 errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
27412754
2742 try sema.resolveTypeFieldsUnion(ty, union_type);
2755 try sema.resolveTypeFieldsUnion(ty, union_type);
27432756
2744 const union_obj = ip.loadUnionType(union_type);
2745 for (0..union_obj.field_types.len) |field_idx| {
2746 const field_ty = union_obj.field_types.get(ip)[field_idx];
2747 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
2748 union_obj.flagsPtr(ip).requires_comptime = .yes;
2749 return true;
2757 for (0..union_type.field_types.len) |field_idx| {
2758 const field_ty = union_type.field_types.get(ip)[field_idx];
2759 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
2760 union_type.flagsPtr(ip).requires_comptime = .yes;
2761 return true;
2762 }
27502763 }
2751 }
27522764
2753 union_obj.flagsPtr(ip).requires_comptime = .no;
2754 return false;
2755 },
2765 union_type.flagsPtr(ip).requires_comptime = .no;
2766 return false;
2767 },
2768 }
27562769 },
27572770
27582771 .opaque_type => false,
27592772
2760 .enum_type => |enum_type| return Type.fromInterned(enum_type.tag_ty).comptimeOnlyAdvanced(mod, opt_sema),
2773 .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyAdvanced(mod, opt_sema),
27612774
27622775 // values, not types
27632776 .undef,
......@@ -2830,11 +2843,12 @@ pub const Type = struct {
28302843
28312844 /// Returns null if the type has no namespace.
28322845 pub fn getNamespaceIndex(ty: Type, mod: *Module) InternPool.OptionalNamespaceIndex {
2833 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2834 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
2835 .struct_type => |struct_type| struct_type.namespace,
2836 .union_type => |union_type| union_type.namespace.toOptional(),
2837 .enum_type => |enum_type| enum_type.namespace,
2846 const ip = &mod.intern_pool;
2847 return switch (ip.indexToKey(ty.toIntern())) {
2848 .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace.toOptional(),
2849 .struct_type => ip.loadStructType(ty.toIntern()).namespace,
2850 .union_type => ip.loadUnionType(ty.toIntern()).namespace.toOptional(),
2851 .enum_type => ip.loadEnumType(ty.toIntern()).namespace,
28382852
28392853 else => .none,
28402854 };
......@@ -2920,16 +2934,18 @@ pub const Type = struct {
29202934
29212935 /// Asserts the type is an enum or a union.
29222936 pub fn intTagType(ty: Type, mod: *Module) Type {
2923 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2924 .union_type => |union_type| Type.fromInterned(union_type.enum_tag_ty).intTagType(mod),
2925 .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty),
2937 const ip = &mod.intern_pool;
2938 return switch (ip.indexToKey(ty.toIntern())) {
2939 .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(mod),
2940 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
29262941 else => unreachable,
29272942 };
29282943 }
29292944
29302945 pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
2931 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2932 .enum_type => |enum_type| switch (enum_type.tag_mode) {
2946 const ip = &mod.intern_pool;
2947 return switch (ip.indexToKey(ty.toIntern())) {
2948 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
29332949 .nonexhaustive => true,
29342950 .auto, .explicit => false,
29352951 },
......@@ -2953,21 +2969,21 @@ pub const Type = struct {
29532969 }
29542970
29552971 pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
2956 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
2972 return mod.intern_pool.loadEnumType(ty.toIntern()).names;
29572973 }
29582974
29592975 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
2960 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names.len;
2976 return mod.intern_pool.loadEnumType(ty.toIntern()).names.len;
29612977 }
29622978
29632979 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
29642980 const ip = &mod.intern_pool;
2965 return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip)[field_index];
2981 return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index];
29662982 }
29672983
29682984 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
29692985 const ip = &mod.intern_pool;
2970 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
2986 const enum_type = ip.loadEnumType(ty.toIntern());
29712987 return enum_type.nameIndex(ip, field_name);
29722988 }
29732989
......@@ -2976,7 +2992,7 @@ pub const Type = struct {
29762992 /// declaration order, or `null` if `enum_tag` does not match any field.
29772993 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
29782994 const ip = &mod.intern_pool;
2979 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
2995 const enum_type = ip.loadEnumType(ty.toIntern());
29802996 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
29812997 .int => enum_tag.toIntern(),
29822998 .enum_tag => |info| info.int,
......@@ -2990,7 +3006,7 @@ pub const Type = struct {
29903006 pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString {
29913007 const ip = &mod.intern_pool;
29923008 return switch (ip.indexToKey(ty.toIntern())) {
2993 .struct_type => |struct_type| struct_type.fieldName(ip, field_index),
3009 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index),
29943010 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index),
29953011 else => unreachable,
29963012 };
......@@ -3010,7 +3026,7 @@ pub const Type = struct {
30103026 pub fn structFieldCount(ty: Type, mod: *Module) u32 {
30113027 const ip = &mod.intern_pool;
30123028 return switch (ip.indexToKey(ty.toIntern())) {
3013 .struct_type => |struct_type| struct_type.field_types.len,
3029 .struct_type => ip.loadStructType(ty.toIntern()).field_types.len,
30143030 .anon_struct_type => |anon_struct| anon_struct.types.len,
30153031 else => unreachable,
30163032 };
......@@ -3020,9 +3036,9 @@ pub const Type = struct {
30203036 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
30213037 const ip = &mod.intern_pool;
30223038 return switch (ip.indexToKey(ty.toIntern())) {
3023 .struct_type => |struct_type| Type.fromInterned(struct_type.field_types.get(ip)[index]),
3024 .union_type => |union_type| {
3025 const union_obj = ip.loadUnionType(union_type);
3039 .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]),
3040 .union_type => {
3041 const union_obj = ip.loadUnionType(ty.toIntern());
30263042 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
30273043 },
30283044 .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),
......@@ -3033,7 +3049,8 @@ pub const Type = struct {
30333049 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) Alignment {
30343050 const ip = &mod.intern_pool;
30353051 switch (ip.indexToKey(ty.toIntern())) {
3036 .struct_type => |struct_type| {
3052 .struct_type => {
3053 const struct_type = ip.loadStructType(ty.toIntern());
30373054 assert(struct_type.layout != .Packed);
30383055 const explicit_align = struct_type.fieldAlign(ip, index);
30393056 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
......@@ -3042,8 +3059,8 @@ pub const Type = struct {
30423059 .anon_struct_type => |anon_struct| {
30433060 return Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignment(mod);
30443061 },
3045 .union_type => |union_type| {
3046 const union_obj = ip.loadUnionType(union_type);
3062 .union_type => {
3063 const union_obj = ip.loadUnionType(ty.toIntern());
30473064 return mod.unionFieldNormalAlignment(union_obj, @intCast(index));
30483065 },
30493066 else => unreachable,
......@@ -3053,7 +3070,8 @@ pub const Type = struct {
30533070 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
30543071 const ip = &mod.intern_pool;
30553072 switch (ip.indexToKey(ty.toIntern())) {
3056 .struct_type => |struct_type| {
3073 .struct_type => {
3074 const struct_type = ip.loadStructType(ty.toIntern());
30573075 const val = struct_type.fieldInit(ip, index);
30583076 // TODO: avoid using `unreachable` to indicate this.
30593077 if (val == .none) return Value.@"unreachable";
......@@ -3072,7 +3090,8 @@ pub const Type = struct {
30723090 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
30733091 const ip = &mod.intern_pool;
30743092 switch (ip.indexToKey(ty.toIntern())) {
3075 .struct_type => |struct_type| {
3093 .struct_type => {
3094 const struct_type = ip.loadStructType(ty.toIntern());
30763095 if (struct_type.fieldIsComptime(ip, index)) {
30773096 assert(struct_type.haveFieldInits(ip));
30783097 return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
......@@ -3095,7 +3114,7 @@ pub const Type = struct {
30953114 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
30963115 const ip = &mod.intern_pool;
30973116 return switch (ip.indexToKey(ty.toIntern())) {
3098 .struct_type => |struct_type| struct_type.fieldIsComptime(ip, index),
3117 .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),
30993118 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,
31003119 else => unreachable,
31013120 };
......@@ -3110,7 +3129,8 @@ pub const Type = struct {
31103129 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
31113130 const ip = &mod.intern_pool;
31123131 switch (ip.indexToKey(ty.toIntern())) {
3113 .struct_type => |struct_type| {
3132 .struct_type => {
3133 const struct_type = ip.loadStructType(ty.toIntern());
31143134 assert(struct_type.haveLayout(ip));
31153135 assert(struct_type.layout != .Packed);
31163136 return struct_type.offsets.get(ip)[index];
......@@ -3137,11 +3157,11 @@ pub const Type = struct {
31373157 return offset;
31383158 },
31393159
3140 .union_type => |union_type| {
3160 .union_type => {
3161 const union_type = ip.loadUnionType(ty.toIntern());
31413162 if (!union_type.hasTag(ip))
31423163 return 0;
3143 const union_obj = ip.loadUnionType(union_type);
3144 const layout = mod.getUnionLayout(union_obj);
3164 const layout = mod.getUnionLayout(union_type);
31453165 if (layout.tag_align.compare(.gte, layout.payload_align)) {
31463166 // {Tag, Payload}
31473167 return layout.payload_align.forward(layout.tag_size);
......@@ -3194,7 +3214,8 @@ pub const Type = struct {
31943214 pub fn isTuple(ty: Type, mod: *Module) bool {
31953215 const ip = &mod.intern_pool;
31963216 return switch (ip.indexToKey(ty.toIntern())) {
3197 .struct_type => |struct_type| {
3217 .struct_type => {
3218 const struct_type = ip.loadStructType(ty.toIntern());
31983219 if (struct_type.layout == .Packed) return false;
31993220 if (struct_type.decl == .none) return false;
32003221 return struct_type.flagsPtr(ip).is_tuple;
......@@ -3215,7 +3236,8 @@ pub const Type = struct {
32153236 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
32163237 const ip = &mod.intern_pool;
32173238 return switch (ip.indexToKey(ty.toIntern())) {
3218 .struct_type => |struct_type| {
3239 .struct_type => {
3240 const struct_type = ip.loadStructType(ty.toIntern());
32193241 if (struct_type.layout == .Packed) return false;
32203242 if (struct_type.decl == .none) return false;
32213243 return struct_type.flagsPtr(ip).is_tuple;
......@@ -3262,12 +3284,12 @@ pub const Type = struct {
32623284 }
32633285
32643286 pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3265 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
3266 inline .struct_type,
3267 .union_type,
3268 .enum_type,
3269 .opaque_type,
3270 => |info| info.zir_index.unwrap(),
3287 const ip = &zcu.intern_pool;
3288 return switch (ip.indexToKey(ty.toIntern())) {
3289 .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),
3290 .union_type => ip.loadUnionType(ty.toIntern()).zir_index.unwrap(),
3291 .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),
3292 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index.unwrap(),
32713293 else => null,
32723294 };
32733295 }