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) {...@@ -644,348 +644,6 @@ pub const Key = union(enum) {
644 child: Index,644 child: Index,
645 };645 };
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
989 pub const AnonStructType = struct {647 pub const AnonStructType = struct {
990 types: Index.Slice,648 types: Index.Slice,
991 /// This may be empty, indicating this is a tuple.649 /// This may be empty, indicating this is a tuple.
...@@ -1009,156 +667,28 @@ pub const Key = union(enum) {...@@ -1009,156 +667,28 @@ pub const Key = union(enum) {
1009 }667 }
1010 };668 };
1011669
1012 /// Serves two purposes:670 /// This is the hashmap key. To fetch other data associated with the struct, see `loadStructType`.
1013 /// * Being the key in the InternPool hash map, which only requires the `decl` field.671 pub const StructType = struct {
1014 /// * Provide the other fields that do not require chasing the enum type.672 /// The struct's owner Decl. `none` when the struct is `@TypeOf(.{})`.
1015 pub const UnionType = struct {673 decl: OptionalDeclIndex,
1016 /// The Decl that corresponds to the union itself.674 };
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 }
1073675
1074 pub fn setFieldTypes(self: @This(), ip: *InternPool, types: []const Index) void {676 /// This is the hashmap key. To fetch other data associated with the opaque, see `loadOpaqueType`.
1075 @memcpy((Index.Slice{677 pub const OpaqueType = struct {
1076 .start = @intCast(self.extra_index + @typeInfo(Tag.TypeUnion).Struct.fields.len),678 /// The opaque's owner Decl.
1077 .len = @intCast(types.len),679 decl: DeclIndex,
1078 }).get(ip), types);680 };
1079 }
1080681
1081 pub fn setFieldAligns(self: @This(), ip: *InternPool, aligns: []const Alignment) void {682 /// This is the hashmap key. To fetch other data associated with the union, see `loadUnionType`.
1082 if (aligns.len == 0) return;683 pub const UnionType = struct {
1083 assert(self.flagsPtr(ip).any_aligned_fields);684 /// The union's owner Decl.
1084 @memcpy((Alignment.Slice{685 decl: DeclIndex,
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 }
1091 };686 };
1092687
688 /// This is the hashmap key. To fetch other data associated with the enum, see `loadEnumType`.
1093 pub const EnumType = struct {689 pub const EnumType = struct {
1094 /// The Decl that corresponds to the enum itself.690 /// The enum's owner Decl.
1095 decl: DeclIndex,691 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 }
1162 };692 };
1163693
1164 pub const IncompleteEnumType = struct {694 pub const IncompleteEnumType = struct {
...@@ -1173,12 +703,13 @@ pub const Key = union(enum) {...@@ -1173,12 +703,13 @@ pub const Key = union(enum) {
1173 /// later when populating field values.703 /// later when populating field values.
1174 has_values: bool,704 has_values: bool,
1175 /// Same as corresponding `EnumType` field.705 /// Same as corresponding `EnumType` field.
1176 tag_mode: EnumType.TagMode,706 tag_mode: LoadedEnumType.TagMode,
1177 /// This may be updated via `setTagType` later.707 /// This may be updated via `setTagType` later.
1178 tag_ty: Index = .none,708 tag_ty: Index = .none,
1179 zir_index: TrackedInst.Index.Optional,709 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");
1182 return .{713 return .{
1183 .decl = self.decl,714 .decl = self.decl,
1184 .namespace = self.namespace,715 .namespace = self.namespace,
...@@ -1193,7 +724,7 @@ pub const Key = union(enum) {...@@ -1193,7 +724,7 @@ pub const Key = union(enum) {
1193 /// Only the decl is used for hashing and equality, so we can construct724 /// Only the decl is used for hashing and equality, so we can construct
1194 /// this minimal key for use with `map`.725 /// this minimal key for use with `map`.
1195 pub fn toKey(self: @This()) Key {726 pub fn toKey(self: @This()) Key {
1196 return .{ .enum_type = self.toEnumType() };727 return .{ .enum_type = .{ .decl = self.decl } };
1197 }728 }
1198 };729 };
1199730
...@@ -2111,21 +1642,15 @@ pub const RequiresComptime = enum(u2) { no, yes, unknown, wip };...@@ -2111,21 +1642,15 @@ pub const RequiresComptime = enum(u2) { no, yes, unknown, wip };
2111// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a1642// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a
2112// minimal hashmap key, this type is a convenience type that contains info1643// minimal hashmap key, this type is a convenience type that contains info
2113// needed by semantic analysis.1644// needed by semantic analysis.
2114pub const UnionType = struct {1645pub const LoadedUnionType = struct {
1646 /// The index of the `Tag.TypeUnion` payload.
1647 extra_index: u32,
2115 /// The Decl that corresponds to the union itself.1648 /// The Decl that corresponds to the union itself.
2116 decl: DeclIndex,1649 decl: DeclIndex,
2117 /// Represents the declarations inside this union.1650 /// Represents the declarations inside this union.
2118 namespace: NamespaceIndex,1651 namespace: NamespaceIndex,
2119 /// The enum tag type.1652 /// The enum tag type.
2120 enum_tag_ty: Index,1653 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,
2129 /// List of field types in declaration order.1654 /// List of field types in declaration order.
2130 /// These are `none` until `status` is `have_field_types` or `have_layout`.1655 /// These are `none` until `status` is `have_field_types` or `have_layout`.
2131 field_types: Index.Slice,1656 field_types: Index.Slice,
...@@ -2135,10 +1660,6 @@ pub const UnionType = struct {...@@ -2135,10 +1660,6 @@ pub const UnionType = struct {
2135 field_aligns: Alignment.Slice,1660 field_aligns: Alignment.Slice,
2136 /// Index of the union_decl ZIR instruction.1661 /// Index of the union_decl ZIR instruction.
2137 zir_index: TrackedInst.Index.Optional,1662 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
2143 pub const RuntimeTag = enum(u2) {1664 pub const RuntimeTag = enum(u2) {
2144 none,1665 none,
...@@ -2193,68 +1714,92 @@ pub const UnionType = struct {...@@ -2193,68 +1714,92 @@ pub const UnionType = struct {
2193 }1714 }
2194 };1715 };
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.
2196 /// The returned pointer expires with any addition to the `InternPool`.1728 /// The returned pointer expires with any addition to the `InternPool`.
2197 pub fn flagsPtr(self: UnionType, ip: *const InternPool) *Tag.TypeUnion.Flags {1729 pub fn tagTypePtr(self: LoadedUnionType, ip: *const InternPool) *Index {
2198 return @ptrCast(&ip.extra.items[self.flags_index]);1730 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?;
1731 return @ptrCast(&ip.extra.items[self.extra_index + field_index]);
2199 }1732 }
22001733
2201 /// Look up field index based on field name.1734 /// The returned pointer expires with any addition to the `InternPool`.
2202 pub fn nameIndex(self: UnionType, ip: *const InternPool, name: NullTerminatedString) ?u32 {1735 pub fn flagsPtr(self: LoadedUnionType, ip: *const InternPool) *Tag.TypeUnion.Flags {
2203 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];1736 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
2204 const adapter: NullTerminatedString.Adapter = .{ .strings = self.field_names.get(ip) };1737 return @ptrCast(&ip.extra.items[self.extra_index + field_index]);
2205 const field_index = map.getIndexAdapted(name, adapter) orelse return null;1738 }
2206 return @intCast(field_index);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];
2207 }1744 }
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 {
2210 return self.flagsPtr(ip).runtime_tag.hasTag();1753 return self.flagsPtr(ip).runtime_tag.hasTag();
2211 }1754 }
22121755
2213 pub fn haveFieldTypes(self: UnionType, ip: *const InternPool) bool {1756 pub fn haveFieldTypes(self: LoadedUnionType, ip: *const InternPool) bool {
2214 return self.flagsPtr(ip).status.haveFieldTypes();1757 return self.flagsPtr(ip).status.haveFieldTypes();
2215 }1758 }
22161759
2217 pub fn haveLayout(self: UnionType, ip: *const InternPool) bool {1760 pub fn haveLayout(self: LoadedUnionType, ip: *const InternPool) bool {
2218 return self.flagsPtr(ip).status.haveLayout();1761 return self.flagsPtr(ip).status.haveLayout();
2219 }1762 }
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 {
2222 return self.flagsPtr(ip).layout;1765 return self.flagsPtr(ip).layout;
2223 }1766 }
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 {
2226 if (self.field_aligns.len == 0) return .none;1769 if (self.field_aligns.len == 0) return .none;
2227 return self.field_aligns.get(ip)[field_index];1770 return self.field_aligns.get(ip)[field_index];
2228 }1771 }
22291772
2230 /// This does not mutate the field of UnionType.1773 /// This does not mutate the field of LoadedUnionType.
2231 pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {1774 pub fn setZirIndex(self: LoadedUnionType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
2232 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;1775 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
2233 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;1776 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;
2234 const ptr: *TrackedInst.Index.Optional =1777 const ptr: *TrackedInst.Index.Optional =
2235 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);1778 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);
2236 ptr.* = new_zir_index;1779 ptr.* = new_zir_index;
2237 }1780 }
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 }
2238};1791};
22391792
2240/// Fetch all the interesting fields of a union type into a convenient data1793pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
2241/// structure.1794 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
2242/// This asserts that the union's enum tag type has been resolved.1795 const type_union = ip.extraDataTrail(Tag.TypeUnion, extra_index);
2243pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {1796 const fields_len = type_union.data.fields_len;
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);
22481797
2249 return .{1798 return .{
1799 .extra_index = extra_index,
2250 .decl = type_union.data.decl,1800 .decl = type_union.data.decl,
2251 .namespace = type_union.data.namespace,1801 .namespace = type_union.data.namespace,
2252 .enum_tag_ty = enum_ty,1802 .enum_tag_ty = type_union.data.tag_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,
2258 .field_types = .{1803 .field_types = .{
2259 .start = type_union.end,1804 .start = type_union.end,
2260 .len = fields_len,1805 .len = fields_len,
...@@ -2264,10 +1809,583 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {...@@ -2264,10 +1809,583 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {
2264 .len = if (type_union.data.flags.any_aligned_fields) fields_len else 0,1809 .len = if (type_union.data.flags.any_aligned_fields) fields_len else 0,
2265 },1810 },
2266 .zir_index = type_union.data.zir_index,1811 .zir_index = type_union.data.zir_index,
2267 .flags_index = key.extra_index + std.meta.fieldIndex(Tag.TypeUnion, "flags").?,
2268 };1812 };
2269}1813}
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
2271pub const Item = struct {2389pub const Item = struct {
2272 tag: Tag,2390 tag: Tag,
2273 /// The doc comments on the respective Tag explain how to interpret this.2391 /// The doc comments on the respective Tag explain how to interpret this.
...@@ -2485,7 +2603,6 @@ pub const Index = enum(u32) {...@@ -2485,7 +2603,6 @@ pub const Index = enum(u32) {
2485 simple_type: struct { data: SimpleType },2603 simple_type: struct { data: SimpleType },
2486 type_opaque: struct { data: *Key.OpaqueType },2604 type_opaque: struct { data: *Key.OpaqueType },
2487 type_struct: struct { data: *Tag.TypeStruct },2605 type_struct: struct { data: *Tag.TypeStruct },
2488 type_struct_ns: struct { data: NamespaceIndex },
2489 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,2606 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
2490 type_struct_packed: struct { data: *Tag.TypeStructPacked },2607 type_struct_packed: struct { data: *Tag.TypeStructPacked },
2491 type_struct_packed_inits: struct { data: *Tag.TypeStructPacked },2608 type_struct_packed_inits: struct { data: *Tag.TypeStructPacked },
...@@ -2925,9 +3042,6 @@ pub const Tag = enum(u8) {...@@ -2925,9 +3042,6 @@ pub const Tag = enum(u8) {
2925 /// data is 0 or extra index of `TypeStruct`.3042 /// data is 0 or extra index of `TypeStruct`.
2926 /// data == 0 represents `@TypeOf(.{})`.3043 /// data == 0 represents `@TypeOf(.{})`.
2927 type_struct,3044 type_struct,
2928 /// A non-packed struct type that has only a namespace; no fields.
2929 /// data is NamespaceIndex.
2930 type_struct_ns,
2931 /// An AnonStructType which stores types, names, and values for fields.3045 /// An AnonStructType which stores types, names, and values for fields.
2932 /// data is extra index of `TypeStructAnon`.3046 /// data is extra index of `TypeStructAnon`.
2933 type_struct_anon,3047 type_struct_anon,
...@@ -3125,7 +3239,7 @@ pub const Tag = enum(u8) {...@@ -3125,7 +3239,7 @@ pub const Tag = enum(u8) {
3125 memoized_call,3239 memoized_call,
31263240
3127 const ErrorUnionType = Key.ErrorUnionType;3241 const ErrorUnionType = Key.ErrorUnionType;
3128 const OpaqueType = Key.OpaqueType;3242 const OpaqueType = LoadedOpaqueType;
3129 const TypeValue = Key.TypeValue;3243 const TypeValue = Key.TypeValue;
3130 const Error = Key.Error;3244 const Error = Key.Error;
3131 const EnumTag = Key.EnumTag;3245 const EnumTag = Key.EnumTag;
...@@ -3154,7 +3268,6 @@ pub const Tag = enum(u8) {...@@ -3154,7 +3268,6 @@ pub const Tag = enum(u8) {
3154 .simple_type => unreachable,3268 .simple_type => unreachable,
3155 .type_opaque => OpaqueType,3269 .type_opaque => OpaqueType,
3156 .type_struct => TypeStruct,3270 .type_struct => TypeStruct,
3157 .type_struct_ns => unreachable,
3158 .type_struct_anon => TypeStructAnon,3271 .type_struct_anon => TypeStructAnon,
3159 .type_struct_packed, .type_struct_packed_inits => TypeStructPacked,3272 .type_struct_packed, .type_struct_packed_inits => TypeStructPacked,
3160 .type_tuple_anon => TypeStructAnon,3273 .type_tuple_anon => TypeStructAnon,
...@@ -3310,12 +3423,15 @@ pub const Tag = enum(u8) {...@@ -3310,12 +3423,15 @@ pub const Tag = enum(u8) {
3310 };3423 };
3311 };3424 };
33123425
3313 /// The number of fields is provided by the `tag_ty` field.
3314 /// Trailing:3426 /// Trailing:
3315 /// 0. field type: Index for each field; declaration order3427 /// 0. field type: Index for each field; declaration order
3316 /// 1. field align: Alignment for each field; declaration order3428 /// 1. field align: Alignment for each field; declaration order
3317 pub const TypeUnion = struct {3429 pub const TypeUnion = struct {
3318 flags: Flags,3430 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,
3319 /// Only valid after .have_layout3435 /// Only valid after .have_layout
3320 size: u32,3436 size: u32,
3321 /// Only valid after .have_layout3437 /// Only valid after .have_layout
...@@ -3327,11 +3443,11 @@ pub const Tag = enum(u8) {...@@ -3327,11 +3443,11 @@ pub const Tag = enum(u8) {
3327 zir_index: TrackedInst.Index.Optional,3443 zir_index: TrackedInst.Index.Optional,
33283444
3329 pub const Flags = packed struct(u32) {3445 pub const Flags = packed struct(u32) {
3330 runtime_tag: UnionType.RuntimeTag,3446 runtime_tag: LoadedUnionType.RuntimeTag,
3331 /// If false, the field alignment trailing data is omitted.3447 /// If false, the field alignment trailing data is omitted.
3332 any_aligned_fields: bool,3448 any_aligned_fields: bool,
3333 layout: std.builtin.Type.ContainerLayout,3449 layout: std.builtin.Type.ContainerLayout,
3334 status: UnionType.Status,3450 status: LoadedUnionType.Status,
3335 requires_comptime: RequiresComptime,3451 requires_comptime: RequiresComptime,
3336 assumed_runtime_bits: bool,3452 assumed_runtime_bits: bool,
3337 assumed_pointer_aligned: bool,3453 assumed_pointer_aligned: bool,
...@@ -4074,65 +4190,27 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -4074,65 +4190,27 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
4074 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },4190 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
40754191
4076 .type_struct => .{ .struct_type = if (data == 0) .{4192 .type_struct => .{ .struct_type = if (data == 0) .{
4077 .extra_index = 0,
4078 .namespace = .none,
4079 .decl = .none,4193 .decl = .none,
4080 .zir_index = undefined,4194 } else .{
4081 .layout = .Auto,4195 .decl = ip.extraData(Tag.TypeStruct, data).decl.toOptional(),
4082 .field_names = .{ .start = 0, .len = 0 },4196 } },
4083 .field_types = .{ .start = 0, .len = 0 },4197
4084 .field_inits = .{ .start = 0, .len = 0 },4198 .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = .{
4085 .field_aligns = .{ .start = 0, .len = 0 },4199 .decl = ip.extraData(Tag.TypeStructPacked, data).decl.toOptional(),
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,
4106 } },4200 } },
41074201
4108 .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(ip, data) },4202 .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(ip, data) },
4109 .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(ip, data) },4203 .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(ip, data) },
4110 .type_struct_packed => .{ .struct_type = extraPackedStructType(ip, data, false) },4204 .type_union => .{ .union_type = .{
4111 .type_struct_packed_inits => .{ .struct_type = extraPackedStructType(ip, data, true) },4205 .decl = ip.extraData(Tag.TypeUnion, data).decl,
4112 .type_union => .{ .union_type = extraUnionType(ip, data) },4206 } },
41134207
4114 .type_enum_auto => {4208 .type_enum_auto => .{ .enum_type = .{
4115 const enum_auto = ip.extraDataTrail(EnumAuto, data);4209 .decl = ip.extraData(EnumAuto, data).decl,
4116 return .{ .enum_type = .{4210 } },
4117 .decl = enum_auto.data.decl,4211 .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = .{
4118 .namespace = enum_auto.data.namespace,4212 .decl = ip.extraData(EnumExplicit, data).decl,
4119 .tag_ty = enum_auto.data.int_tag_type,4213 } },
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),
4136 .type_function => .{ .func_type = ip.extraFuncType(data) },4214 .type_function => .{ .func_type = ip.extraFuncType(data) },
41374215
4138 .undef => .{ .undef = @as(Index, @enumFromInt(data)) },4216 .undef => .{ .undef = @as(Index, @enumFromInt(data)) },
...@@ -4365,7 +4443,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -4365,7 +4443,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
4365 },4443 },
4366 .type_array_small,4444 .type_array_small,
4367 .type_vector,4445 .type_vector,
4368 .type_struct_ns,
4369 .type_struct_packed,4446 .type_struct_packed,
4370 => .{ .aggregate = .{4447 => .{ .aggregate = .{
4371 .ty = ty,4448 .ty = ty,
...@@ -4374,16 +4451,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -4374,16 +4451,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
43744451
4375 // There is only one possible value precisely due to the4452 // There is only one possible value precisely due to the
4376 // fact that this values slice is fully populated!4453 // fact that this values slice is fully populated!
4377 .type_struct => {4454 .type_struct, .type_struct_packed_inits => {
4378 const info = extraStructType(ip, ty_item.data);4455 const info = loadStructType(ip, ty);
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);
4387 return .{ .aggregate = .{4456 return .{ .aggregate = .{
4388 .ty = ty,4457 .ty = ty,
4389 .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) },4458 .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) },
...@@ -4475,18 +4544,6 @@ fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType {...@@ -4475,18 +4544,6 @@ fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType {
4475 };4544 };
4476}4545}
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
4490fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType {4547fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType {
4491 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index);4548 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, extra_index);
4492 const fields_len = type_struct_anon.data.fields_len;4549 const fields_len = type_struct_anon.data.fields_len;
...@@ -4525,109 +4582,6 @@ fn extraTypeTupleAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructTyp...@@ -4525,109 +4582,6 @@ fn extraTypeTupleAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructTyp
4525 };4582 };
4526}4583}
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
4631fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {4585fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
4632 const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index);4586 const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index);
4633 var index: usize = type_function.end;4587 var index: usize = type_function.end;
...@@ -4719,28 +4673,6 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {...@@ -4719,28 +4673,6 @@ fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
4719 return func;4673 return func;
4720}4674}
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
4744fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key {4676fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key {
4745 const int_info = ip.limbData(Int, limb_index);4677 const int_info = ip.limbData(Int, limb_index);
4746 return .{ .int = .{4678 return .{ .int = .{
...@@ -4900,13 +4832,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4900,13 +4832,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4900 .struct_type => unreachable, // use getStructType() instead4832 .struct_type => unreachable, // use getStructType() instead
4901 .anon_struct_type => unreachable, // use getAnonStructType() instead4833 .anon_struct_type => unreachable, // use getAnonStructType() instead
4902 .union_type => unreachable, // use getUnionType() instead4834 .union_type => unreachable, // use getUnionType() instead
49034835 .opaque_type => unreachable, // use getOpaqueType() instead
4904 .opaque_type => |opaque_type| {
4905 ip.items.appendAssumeCapacity(.{
4906 .tag = .type_opaque,
4907 .data = try ip.addExtra(gpa, opaque_type),
4908 });
4909 },
49104836
4911 .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead4837 .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead
4912 .func_type => unreachable, // use getFuncType() instead4838 .func_type => unreachable, // use getFuncType() instead
...@@ -5026,14 +4952,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -5026,14 +4952,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
5026 assert(ptr.addr == .field);4952 assert(ptr.addr == .field);
5027 assert(base_index.index < anon_struct_type.types.len);4953 assert(base_index.index < anon_struct_type.types.len);
5028 },4954 },
5029 .struct_type => |struct_type| {4955 .struct_type => {
5030 assert(ptr.addr == .field);4956 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);
5032 },4958 },
5033 .union_type => |union_key| {4959 .union_type => {
5034 const union_type = ip.loadUnionType(union_key);4960 const union_type = ip.loadUnionType(base_ptr_type.child);
5035 assert(ptr.addr == .field);4961 assert(ptr.addr == .field);
5036 assert(base_index.index < union_type.field_names.len);4962 assert(base_index.index < union_type.field_types.len);
5037 },4963 },
5038 .ptr_type => |slice_type| {4964 .ptr_type => |slice_type| {
5039 assert(ptr.addr == .field);4965 assert(ptr.addr == .field);
...@@ -5304,7 +5230,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -5304,7 +5230,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
5304 assert(ip.isEnumType(enum_tag.ty));5230 assert(ip.isEnumType(enum_tag.ty));
5305 switch (ip.indexToKey(enum_tag.ty)) {5231 switch (ip.indexToKey(enum_tag.ty)) {
5306 .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))),5232 .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),
5308 else => unreachable,5234 else => unreachable,
5309 }5235 }
5310 ip.items.appendAssumeCapacity(.{5236 ip.items.appendAssumeCapacity(.{
...@@ -5397,8 +5323,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -5397,8 +5323,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
5397 assert(ip.typeOf(elem) == child);5323 assert(ip.typeOf(elem) == child);
5398 }5324 }
5399 },5325 },
5400 .struct_type => |t| {5326 .struct_type => {
5401 for (aggregate.storage.values(), t.field_types.get(ip)) |elem, field_ty| {5327 for (aggregate.storage.values(), ip.loadStructType(aggregate.ty).field_types.get(ip)) |elem, field_ty| {
5402 assert(ip.typeOf(elem) == field_ty);5328 assert(ip.typeOf(elem) == field_ty);
5403 }5329 }
5404 },5330 },
...@@ -5596,6 +5522,7 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat...@@ -5596,6 +5522,7 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
55965522
5597 const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{5523 const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{
5598 .flags = ini.flags,5524 .flags = ini.flags,
5525 .fields_len = ini.fields_len,
5599 .size = std.math.maxInt(u32),5526 .size = std.math.maxInt(u32),
5600 .padding = std.math.maxInt(u32),5527 .padding = std.math.maxInt(u32),
5601 .decl = ini.decl,5528 .decl = ini.decl,
...@@ -5628,7 +5555,7 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat...@@ -5628,7 +5555,7 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
56285555
5629 const adapter: KeyAdapter = .{ .intern_pool = ip };5556 const adapter: KeyAdapter = .{ .intern_pool = ip };
5630 const gop = try ip.map.getOrPutAdapted(gpa, Key{5557 const gop = try ip.map.getOrPutAdapted(gpa, Key{
5631 .union_type = extraUnionType(ip, union_type_extra_index),5558 .union_type = .{ .decl = ini.decl },
5632 }, adapter);5559 }, adapter);
5633 if (gop.found_existing) {5560 if (gop.found_existing) {
5634 ip.extra.items.len = prev_extra_len;5561 ip.extra.items.len = prev_extra_len;
...@@ -5664,23 +5591,7 @@ pub fn getStructType(...@@ -5664,23 +5591,7 @@ pub fn getStructType(
5664) Allocator.Error!Index {5591) Allocator.Error!Index {
5665 const adapter: KeyAdapter = .{ .intern_pool = ip };5592 const adapter: KeyAdapter = .{ .intern_pool = ip };
5666 const key: Key = .{5593 const key: Key = .{
5667 .struct_type = .{5594 .struct_type = .{ .decl = ini.decl.toOptional() },
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 },
5684 };5595 };
5685 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);5596 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
5686 if (gop.found_existing) return @enumFromInt(gop.index);5597 if (gop.found_existing) return @enumFromInt(gop.index);
...@@ -5776,7 +5687,7 @@ pub fn getStructType(...@@ -5776,7 +5687,7 @@ pub fn getStructType(
5776 ip.extra.appendNTimesAssumeCapacity(0, comptime_elements_len);5687 ip.extra.appendNTimesAssumeCapacity(0, comptime_elements_len);
5777 }5688 }
5778 if (ini.layout == .Auto) {5689 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);
5780 }5691 }
5781 ip.extra.appendNTimesAssumeCapacity(std.math.maxInt(u32), ini.fields_len);5692 ip.extra.appendNTimesAssumeCapacity(std.math.maxInt(u32), ini.fields_len);
5782 return @enumFromInt(ip.items.len - 1);5693 return @enumFromInt(ip.items.len - 1);
...@@ -6579,26 +6490,14 @@ pub const GetEnumInit = struct {...@@ -6579,26 +6490,14 @@ pub const GetEnumInit = struct {
6579 tag_ty: Index,6490 tag_ty: Index,
6580 names: []const NullTerminatedString,6491 names: []const NullTerminatedString,
6581 values: []const Index,6492 values: []const Index,
6582 tag_mode: Key.EnumType.TagMode,6493 tag_mode: LoadedEnumType.TagMode,
6583 zir_index: TrackedInst.Index.Optional,6494 zir_index: TrackedInst.Index.Optional,
6584};6495};
65856496
6586pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {6497pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {
6587 const adapter: KeyAdapter = .{ .intern_pool = ip };6498 const adapter: KeyAdapter = .{ .intern_pool = ip };
6588 const gop = try ip.map.getOrPutAdapted(gpa, Key{6499 const gop = try ip.map.getOrPutAdapted(gpa, Key{
6589 .enum_type = .{6500 .enum_type = .{ .decl = ini.decl },
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 },
6602 }, adapter);6501 }, adapter);
6603 if (gop.found_existing) return @enumFromInt(gop.index);6502 if (gop.found_existing) return @enumFromInt(gop.index);
6604 errdefer _ = ip.map.pop();6503 errdefer _ = ip.map.pop();
...@@ -6668,6 +6567,21 @@ pub fn finishGetEnum(...@@ -6668,6 +6567,21 @@ pub fn finishGetEnum(
6668 return @enumFromInt(ip.items.len - 1);6567 return @enumFromInt(ip.items.len - 1);
6669}6568}
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
6671pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {6585pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
6672 const adapter: KeyAdapter = .{ .intern_pool = ip };6586 const adapter: KeyAdapter = .{ .intern_pool = ip };
6673 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;6587 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...@@ -7075,9 +6989,9 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
7075 .func => unreachable,6989 .func => unreachable,
70766990
7077 .int => |int| switch (ip.indexToKey(new_ty)) {6991 .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 = .{
7079 .ty = new_ty,6993 .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),
7081 } }),6995 } }),
7082 .ptr_type => return ip.get(gpa, .{ .ptr = .{6996 .ptr_type => return ip.get(gpa, .{ .ptr = .{
7083 .ty = new_ty,6997 .ty = new_ty,
...@@ -7106,7 +7020,8 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -7106,7 +7020,8 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
7106 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))7020 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
7107 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),7021 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
7108 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {7022 .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);
7110 const index = enum_type.nameIndex(ip, enum_literal).?;7025 const index = enum_type.nameIndex(ip, enum_literal).?;
7111 return ip.get(gpa, .{ .enum_tag = .{7026 return ip.get(gpa, .{ .enum_tag = .{
7112 .ty = new_ty,7027 .ty = new_ty,
...@@ -7247,7 +7162,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -7247,7 +7162,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
7247 const new_elem_ty = switch (ip.indexToKey(new_ty)) {7162 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
7248 inline .array_type, .vector_type => |seq_type| seq_type.child,7163 inline .array_type, .vector_type => |seq_type| seq_type.child,
7249 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[i],7164 .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],
7251 else => unreachable,7166 else => unreachable,
7252 };7167 };
7253 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);7168 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
...@@ -7550,7 +7465,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -7550,7 +7465,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
7550 ints += info.fields_len; // offsets7465 ints += info.fields_len; // offsets
7551 break :b @sizeOf(u32) * ints;7466 break :b @sizeOf(u32) * ints;
7552 },7467 },
7553 .type_struct_ns => @sizeOf(Module.Namespace),
7554 .type_struct_anon => b: {7468 .type_struct_anon => b: {
7555 const info = ip.extraData(TypeStructAnon, data);7469 const info = ip.extraData(TypeStructAnon, data);
7556 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);7470 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
...@@ -7572,7 +7486,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -7572,7 +7486,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
75727486
7573 .type_union => b: {7487 .type_union => b: {
7574 const info = ip.extraData(Tag.TypeUnion, data);7488 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);
7576 const fields_len: u32 = @intCast(enum_info.names.len);7490 const fields_len: u32 = @intCast(enum_info.names.len);
7577 const per_field = @sizeOf(u32); // field type7491 const per_field = @sizeOf(u32); // field type
7578 // 1 byte per field for alignment, rounded up to the nearest 4 bytes7492 // 1 byte per field for alignment, rounded up to the nearest 4 bytes
...@@ -7716,7 +7630,6 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -7716,7 +7630,6 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
7716 .type_enum_auto,7630 .type_enum_auto,
7717 .type_opaque,7631 .type_opaque,
7718 .type_struct,7632 .type_struct,
7719 .type_struct_ns,
7720 .type_struct_anon,7633 .type_struct_anon,
7721 .type_struct_packed,7634 .type_struct_packed,
7722 .type_struct_packed_inits,7635 .type_struct_packed_inits,
...@@ -8123,7 +8036,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -8123,7 +8036,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
8123 .simple_type,8036 .simple_type,
8124 .type_opaque,8037 .type_opaque,
8125 .type_struct,8038 .type_struct,
8126 .type_struct_ns,
8127 .type_struct_anon,8039 .type_struct_anon,
8128 .type_struct_packed,8040 .type_struct_packed,
8129 .type_struct_packed_inits,8041 .type_struct_packed_inits,
...@@ -8217,7 +8129,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {...@@ -8217,7 +8129,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
82178129
8218pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {8130pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
8219 return switch (ip.indexToKey(ty)) {8131 return switch (ip.indexToKey(ty)) {
8220 .struct_type => |struct_type| struct_type.field_types.len,8132 .struct_type => ip.loadStructType(ty).field_types.len,
8221 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,8133 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
8222 .array_type => |array_type| array_type.len,8134 .array_type => |array_type| array_type.len,
8223 .vector_type => |vector_type| vector_type.len,8135 .vector_type => |vector_type| vector_type.len,
...@@ -8227,7 +8139,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {...@@ -8227,7 +8139,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
82278139
8228pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {8140pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
8229 return switch (ip.indexToKey(ty)) {8141 return switch (ip.indexToKey(ty)) {
8230 .struct_type => |struct_type| struct_type.field_types.len,8142 .struct_type => ip.loadStructType(ty).field_types.len,
8231 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,8143 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
8232 .array_type => |array_type| array_type.len + @intFromBool(array_type.sentinel != .none),8144 .array_type => |array_type| array_type.len + @intFromBool(array_type.sentinel != .none),
8233 .vector_type => |vector_type| vector_type.len,8145 .vector_type => |vector_type| vector_type.len,
...@@ -8457,7 +8369,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -8457,7 +8369,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
8457 .type_opaque => .Opaque,8369 .type_opaque => .Opaque,
84588370
8459 .type_struct,8371 .type_struct,
8460 .type_struct_ns,
8461 .type_struct_anon,8372 .type_struct_anon,
8462 .type_struct_packed,8373 .type_struct_packed,
8463 .type_struct_packed_inits,8374 .type_struct_packed_inits,
src/Liveness.zig+2-2
...@@ -131,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type {...@@ -131,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type {
131 };131 };
132}132}
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 {
135 const tracy = trace(@src());135 const tracy = trace(@src());
136 defer tracy.end();136 defer tracy.end();
137137
...@@ -836,7 +836,7 @@ pub const BigTomb = struct {...@@ -836,7 +836,7 @@ pub const BigTomb = struct {
836const Analysis = struct {836const Analysis = struct {
837 gpa: Allocator,837 gpa: Allocator,
838 air: Air,838 air: Air,
839 intern_pool: *const InternPool,839 intern_pool: *InternPool,
840 tomb_bits: []usize,840 tomb_bits: []usize,
841 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),841 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
842 extra: std.ArrayListUnmanaged(u32),842 extra: std.ArrayListUnmanaged(u32),
src/Module.zig+27-29
...@@ -527,7 +527,7 @@ pub const Decl = struct {...@@ -527,7 +527,7 @@ pub const Decl = struct {
527527
528 /// If the Decl owns its value and it is a union, return it,528 /// If the Decl owns its value and it is a union, return it,
529 /// otherwise null.529 /// otherwise null.
530 pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.UnionType {530 pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.LoadedUnionType {
531 if (!decl.owns_tv) return null;531 if (!decl.owns_tv) return null;
532 if (decl.val.ip_index == .none) return null;532 if (decl.val.ip_index == .none) return null;
533 return zcu.typeToUnion(decl.val.toType());533 return zcu.typeToUnion(decl.val.toType());
...@@ -563,14 +563,15 @@ pub const Decl = struct {...@@ -563,14 +563,15 @@ pub const Decl = struct {
563 /// enum, or opaque.563 /// enum, or opaque.
564 pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex {564 pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex {
565 if (!decl.has_tv) return .none;565 if (!decl.has_tv) return .none;
566 const ip = &zcu.intern_pool;
566 return switch (decl.val.ip_index) {567 return switch (decl.val.ip_index) {
567 .empty_struct_type => .none,568 .empty_struct_type => .none,
568 .none => .none,569 .none => .none,
569 else => switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) {570 else => switch (ip.indexToKey(decl.val.toIntern())) {
570 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),571 .opaque_type => ip.loadOpaqueType(decl.val.toIntern()).namespace.toOptional(),
571 .struct_type => |struct_type| struct_type.namespace,572 .struct_type => ip.loadStructType(decl.val.toIntern()).namespace,
572 .union_type => |union_type| union_type.namespace.toOptional(),573 .union_type => ip.loadUnionType(decl.val.toIntern()).namespace.toOptional(),
573 .enum_type => |enum_type| enum_type.namespace,574 .enum_type => ip.loadEnumType(decl.val.toIntern()).namespace,
574 else => .none,575 else => .none,
575 },576 },
576 };577 };
...@@ -5682,7 +5683,7 @@ pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Er...@@ -5682,7 +5683,7 @@ pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Er
5682pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value {5683pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value {
5683 const ip = &mod.intern_pool;5684 const ip = &mod.intern_pool;
5684 const gpa = mod.gpa;5685 const gpa = mod.gpa;
5685 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;5686 const enum_type = ip.loadEnumType(ty.toIntern());
56865687
5687 if (enum_type.values.len == 0) {5688 if (enum_type.values.len == 0) {
5688 // Auto-numbered fields.5689 // Auto-numbered fields.
...@@ -5988,28 +5989,26 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {...@@ -5988,28 +5989,26 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
5988/// * `@TypeOf(.{})`5989/// * `@TypeOf(.{})`
5989/// * A struct which has no fields (`struct {}`).5990/// * A struct which has no fields (`struct {}`).
5990/// * Not a struct.5991/// * Not a struct.
5991pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType {5992pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType {
5992 if (ty.ip_index == .none) return null;5993 if (ty.ip_index == .none) return null;
5993 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {5994 const ip = &mod.intern_pool;
5994 .struct_type => |t| t,5995 return switch (ip.indexToKey(ty.ip_index)) {
5996 .struct_type => ip.loadStructType(ty.ip_index),
5995 else => null,5997 else => null,
5996 };5998 };
5997}5999}
59986000
5999pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType {6001pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType {
6000 if (ty.ip_index == .none) return null;6002 const s = mod.typeToStruct(ty) orelse return null;
6001 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {6003 if (s.layout != .Packed) return null;
6002 .struct_type => |t| if (t.layout == .Packed) t else null,6004 return s;
6003 else => null,
6004 };
6005}6005}
60066006
6007/// This asserts that the union's enum tag type has been resolved.6007pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.LoadedUnionType {
6008pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.UnionType {
6009 if (ty.ip_index == .none) return null;6008 if (ty.ip_index == .none) return null;
6010 const ip = &mod.intern_pool;6009 const ip = &mod.intern_pool;
6011 return switch (ip.indexToKey(ty.ip_index)) {6010 return switch (ip.indexToKey(ty.ip_index)) {
6012 .union_type => |k| ip.loadUnionType(k),6011 .union_type => ip.loadUnionType(ty.ip_index),
6013 else => null,6012 else => null,
6014 };6013 };
6015}6014}
...@@ -6111,7 +6110,7 @@ pub const UnionLayout = struct {...@@ -6111,7 +6110,7 @@ pub const UnionLayout = struct {
6111 padding: u32,6110 padding: u32,
6112};6111};
61136112
6114pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {6113pub fn getUnionLayout(mod: *Module, u: InternPool.LoadedUnionType) UnionLayout {
6115 const ip = &mod.intern_pool;6114 const ip = &mod.intern_pool;
6116 assert(u.haveLayout(ip));6115 assert(u.haveLayout(ip));
6117 var most_aligned_field: u32 = undefined;6116 var most_aligned_field: u32 = undefined;
...@@ -6157,7 +6156,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {...@@ -6157,7 +6156,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
6157 const tag_size = Type.fromInterned(u.enum_tag_ty).abiSize(mod);6156 const tag_size = Type.fromInterned(u.enum_tag_ty).abiSize(mod);
6158 const tag_align = Type.fromInterned(u.enum_tag_ty).abiAlignment(mod).max(.@"1");6157 const tag_align = Type.fromInterned(u.enum_tag_ty).abiAlignment(mod).max(.@"1");
6159 return .{6158 return .{
6160 .abi_size = u.size,6159 .abi_size = u.size(ip).*,
6161 .abi_align = tag_align.max(payload_align),6160 .abi_align = tag_align.max(payload_align),
6162 .most_aligned_field = most_aligned_field,6161 .most_aligned_field = most_aligned_field,
6163 .most_aligned_field_size = most_aligned_field_size,6162 .most_aligned_field_size = most_aligned_field_size,
...@@ -6166,16 +6165,16 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {...@@ -6166,16 +6165,16 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
6166 .payload_align = payload_align,6165 .payload_align = payload_align,
6167 .tag_align = tag_align,6166 .tag_align = tag_align,
6168 .tag_size = tag_size,6167 .tag_size = tag_size,
6169 .padding = u.padding,6168 .padding = u.padding(ip).*,
6170 };6169 };
6171}6170}
61726171
6173pub fn unionAbiSize(mod: *Module, u: InternPool.UnionType) u64 {6172pub fn unionAbiSize(mod: *Module, u: InternPool.LoadedUnionType) u64 {
6174 return mod.getUnionLayout(u).abi_size;6173 return mod.getUnionLayout(u).abi_size;
6175}6174}
61766175
6177/// Returns 0 if the union is represented with 0 bits at runtime.6176/// 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 {
6179 const ip = &mod.intern_pool;6178 const ip = &mod.intern_pool;
6180 const have_tag = u.flagsPtr(ip).runtime_tag.hasTag();6179 const have_tag = u.flagsPtr(ip).runtime_tag.hasTag();
6181 var max_align: Alignment = .none;6180 var max_align: Alignment = .none;
...@@ -6192,7 +6191,7 @@ pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment {...@@ -6192,7 +6191,7 @@ pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment {
6192/// Returns the field alignment, assuming the union is not packed.6191/// Returns the field alignment, assuming the union is not packed.
6193/// Keep implementation in sync with `Sema.unionFieldAlignment`.6192/// Keep implementation in sync with `Sema.unionFieldAlignment`.
6194/// Prefer to call that function instead of this one during Sema.6193/// 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 {
6196 const ip = &mod.intern_pool;6195 const ip = &mod.intern_pool;
6197 const field_align = u.fieldAlign(ip, field_index);6196 const field_align = u.fieldAlign(ip, field_index);
6198 if (field_align != .none) return field_align;6197 if (field_align != .none) return field_align;
...@@ -6201,12 +6200,11 @@ pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_in...@@ -6201,12 +6200,11 @@ pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_in
6201}6200}
62026201
6203/// Returns the index of the active field, given the current tag value6202/// 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 {
6205 const ip = &mod.intern_pool;6204 const ip = &mod.intern_pool;
6206 if (enum_tag.toIntern() == .none) return null;6205 if (enum_tag.toIntern() == .none) return null;
6207 assert(ip.typeOf(enum_tag.toIntern()) == u.enum_tag_ty);6206 assert(ip.typeOf(enum_tag.toIntern()) == u.enum_tag_ty);
6208 const enum_type = ip.indexToKey(u.enum_tag_ty).enum_type;6207 return u.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern());
6209 return enum_type.tagValueIndex(ip, enum_tag.toIntern());
6210}6208}
62116209
6212/// Returns the field alignment of a non-packed struct in byte units.6210/// 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 {...@@ -6253,7 +6251,7 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {
6253/// projects.6251/// projects.
6254pub fn structPackedFieldBitOffset(6252pub fn structPackedFieldBitOffset(
6255 mod: *Module,6253 mod: *Module,
6256 struct_type: InternPool.Key.StructType,6254 struct_type: InternPool.LoadedStructType,
6257 field_index: u32,6255 field_index: u32,
6258) u16 {6256) u16 {
6259 const ip = &mod.intern_pool;6257 const ip = &mod.intern_pool;
src/Sema.zig+158-149
...@@ -3371,11 +3371,11 @@ fn zirOpaqueDecl(...@@ -3371,11 +3371,11 @@ fn zirOpaqueDecl(
3371 });3371 });
3372 errdefer mod.destroyNamespace(new_namespace_index);3372 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, .{
3375 .decl = new_decl_index,3375 .decl = new_decl_index,
3376 .namespace = new_namespace_index,3376 .namespace = new_namespace_index,
3377 .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),3377 .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),
3378 } });3378 });
3379 // TODO: figure out InternPool removals for incremental compilation3379 // TODO: figure out InternPool removals for incremental compilation
3380 //errdefer mod.intern_pool.remove(opaque_ty);3380 //errdefer mod.intern_pool.remove(opaque_ty);
33813381
...@@ -5371,7 +5371,7 @@ fn failWithBadMemberAccess(...@@ -5371,7 +5371,7 @@ fn failWithBadMemberAccess(
5371fn failWithBadStructFieldAccess(5371fn failWithBadStructFieldAccess(
5372 sema: *Sema,5372 sema: *Sema,
5373 block: *Block,5373 block: *Block,
5374 struct_type: InternPool.Key.StructType,5374 struct_type: InternPool.LoadedStructType,
5375 field_src: LazySrcLoc,5375 field_src: LazySrcLoc,
5376 field_name: InternPool.NullTerminatedString,5376 field_name: InternPool.NullTerminatedString,
5377) CompileError {5377) CompileError {
...@@ -5397,7 +5397,7 @@ fn failWithBadStructFieldAccess(...@@ -5397,7 +5397,7 @@ fn failWithBadStructFieldAccess(
5397fn failWithBadUnionFieldAccess(5397fn failWithBadUnionFieldAccess(
5398 sema: *Sema,5398 sema: *Sema,
5399 block: *Block,5399 block: *Block,
5400 union_obj: InternPool.UnionType,5400 union_obj: InternPool.LoadedUnionType,
5401 field_src: LazySrcLoc,5401 field_src: LazySrcLoc,
5402 field_name: InternPool.NullTerminatedString,5402 field_name: InternPool.NullTerminatedString,
5403) CompileError {5403) CompileError {
...@@ -13348,7 +13348,7 @@ fn validateSwitchItemEnum(...@@ -13348,7 +13348,7 @@ fn validateSwitchItemEnum(
13348 const ip = &sema.mod.intern_pool;13348 const ip = &sema.mod.intern_pool;
13349 const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none);13349 const item = try sema.resolveSwitchItemVal(block, item_ref, operand_ty, src_node_offset, switch_prong_src, .none);
13350 const int = ip.indexToKey(item.val).enum_tag.int;13350 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 {
13352 const maybe_prev_src = try range_set.add(int, int, switch_prong_src);13352 const maybe_prev_src = try range_set.add(int, int, switch_prong_src);
13353 try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);13353 try sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
13354 return item.ref;13354 return item.ref;
...@@ -13628,15 +13628,15 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13628,15 +13628,15 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13628 break :hf field_index < ty.structFieldCount(mod);13628 break :hf field_index < ty.structFieldCount(mod);
13629 }13629 }
13630 },13630 },
13631 .struct_type => |struct_type| {13631 .struct_type => {
13632 break :hf struct_type.nameIndex(ip, field_name) != null;13632 break :hf ip.loadStructType(ty.toIntern()).nameIndex(ip, field_name) != null;
13633 },13633 },
13634 .union_type => |union_type| {13634 .union_type => {
13635 const union_obj = ip.loadUnionType(union_type);13635 const union_type = ip.loadUnionType(ty.toIntern());
13636 break :hf union_obj.nameIndex(ip, field_name) != null;13636 break :hf union_type.loadTagType(ip).nameIndex(ip, field_name) != null;
13637 },13637 },
13638 .enum_type => |enum_type| {13638 .enum_type => {
13639 break :hf enum_type.nameIndex(ip, field_name) != null;13639 break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null;
13640 },13640 },
13641 .array_type => break :hf ip.stringEqlSlice(field_name, "len"),13641 .array_type => break :hf ip.stringEqlSlice(field_name, "len"),
13642 else => {},13642 else => {},
...@@ -17942,7 +17942,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17942,7 +17942,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17942 } })));17942 } })));
17943 },17943 },
17944 .Enum => {17944 .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
17947 const enum_field_ty = t: {17947 const enum_field_ty = t: {
17948 const enum_field_ty_decl_index = (try sema.namespaceLookup(17948 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...@@ -17956,9 +17956,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17956 break :t enum_field_ty_decl.val.toType();17956 break :t enum_field_ty_decl.val.toType();
17957 };17957 };
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);
17960 for (enum_field_vals, 0..) |*field_val, i| {17960 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());
17962 const value_val = if (enum_type.values.len > 0)17962 const value_val = if (enum_type.values.len > 0)
17963 try mod.intern_pool.getCoercedInts(17963 try mod.intern_pool.getCoercedInts(
17964 mod.gpa,17964 mod.gpa,
...@@ -18033,7 +18033,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18033,7 +18033,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18033 } });18033 } });
18034 };18034 };
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
18038 const type_enum_ty = t: {18038 const type_enum_ty = t: {
18039 const type_enum_ty_decl_index = (try sema.namespaceLookup(18039 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...@@ -18049,7 +18049,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1804918049
18050 const field_values = .{18050 const field_values = .{
18051 // tag_type: type,18051 // tag_type: type,
18052 ip.indexToKey(ty.toIntern()).enum_type.tag_ty,18052 ip.loadEnumType(ty.toIntern()).tag_ty,
18053 // fields: []const EnumField,18053 // fields: []const EnumField,
18054 fields_val,18054 fields_val,
18055 // decls: []const Declaration,18055 // decls: []const Declaration,
...@@ -18093,14 +18093,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18093,14 +18093,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1809318093
18094 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout18094 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
18095 const union_obj = mod.typeToUnion(ty).?;18095 const union_obj = mod.typeToUnion(ty).?;
18096 const tag_type = union_obj.loadTagType(ip);
18096 const layout = union_obj.getLayout(ip);18097 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);
18099 defer gpa.free(union_field_vals);18100 defer gpa.free(union_field_vals);
1810018101
18101 for (union_field_vals, 0..) |*field_val, i| {18102 for (union_field_vals, 0..) |*field_val, i| {
18102 // TODO: write something like getCoercedInts to avoid needing to dupe18103 // 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]));
18104 const name_val = v: {18105 const name_val = v: {
18105 const new_decl_ty = try mod.arrayType(.{18106 const new_decl_ty = try mod.arrayType(.{
18106 .len = name.len,18107 .len = name.len,
...@@ -18302,7 +18303,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18302,7 +18303,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18302 }18303 }
18303 break :fv;18304 break :fv;
18304 },18305 },
18305 .struct_type => |s| s,18306 .struct_type => ip.loadStructType(ty.toIntern()),
18306 else => unreachable,18307 else => unreachable,
18307 };18308 };
18308 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);18309 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);
...@@ -20067,7 +20068,8 @@ fn finishStructInit(...@@ -20067,7 +20068,8 @@ fn finishStructInit(
20067 }20068 }
20068 }20069 }
20069 },20070 },
20070 .struct_type => |struct_type| {20071 .struct_type => {
20072 const struct_type = ip.loadStructType(struct_ty.toIntern());
20071 for (0..struct_type.field_types.len) |i| {20073 for (0..struct_type.field_types.len) |i| {
20072 if (field_inits[i] != .none) {20074 if (field_inits[i] != .none) {
20073 // Coerce the init value to the field type.20075 // Coerce the init value to the field type.
...@@ -20668,7 +20670,8 @@ fn fieldType(...@@ -20668,7 +20670,8 @@ fn fieldType(
20668 try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);20670 try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
20669 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);20671 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);
20670 },20672 },
20671 .struct_type => |struct_type| {20673 .struct_type => {
20674 const struct_type = ip.loadStructType(cur_ty.toIntern());
20672 const field_index = struct_type.nameIndex(ip, field_name) orelse20675 const field_index = struct_type.nameIndex(ip, field_name) orelse
20673 return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name);20676 return sema.failWithBadStructFieldAccess(block, struct_type, field_src, field_name);
20674 const field_ty = struct_type.field_types.get(ip)[field_index];20677 const field_ty = struct_type.field_types.get(ip)[field_index];
...@@ -20678,7 +20681,7 @@ fn fieldType(...@@ -20678,7 +20681,7 @@ fn fieldType(
20678 },20681 },
20679 .Union => {20682 .Union => {
20680 const union_obj = mod.typeToUnion(cur_ty).?;20683 const union_obj = mod.typeToUnion(cur_ty).?;
20681 const field_index = union_obj.nameIndex(ip, field_name) orelse20684 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
20682 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);20685 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
20683 const field_ty = union_obj.field_types.get(ip)[field_index];20686 const field_ty = union_obj.field_types.get(ip)[field_index];
20684 return Air.internedToRef(field_ty);20687 return Air.internedToRef(field_ty);
...@@ -21007,7 +21010,7 @@ fn zirReify(...@@ -21007,7 +21010,7 @@ fn zirReify(
21007 .AnyFrame => return sema.failWithUseOfAsync(block, src),21010 .AnyFrame => return sema.failWithUseOfAsync(block, src),
21008 .EnumLiteral => return .enum_literal_type,21011 .EnumLiteral => return .enum_literal_type,
21009 .Int => {21012 .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));
21011 const signedness_val = try Value.fromInterned(union_val.val).fieldValue(21014 const signedness_val = try Value.fromInterned(union_val.val).fieldValue(
21012 mod,21015 mod,
21013 struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness")).?,21016 struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness")).?,
...@@ -21023,7 +21026,7 @@ fn zirReify(...@@ -21023,7 +21026,7 @@ fn zirReify(
21023 return Air.internedToRef(ty.toIntern());21026 return Air.internedToRef(ty.toIntern());
21024 },21027 },
21025 .Vector => {21028 .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));
21027 const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21030 const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21028 ip,21031 ip,
21029 try ip.getOrPutString(gpa, "len"),21032 try ip.getOrPutString(gpa, "len"),
...@@ -21045,7 +21048,7 @@ fn zirReify(...@@ -21045,7 +21048,7 @@ fn zirReify(
21045 return Air.internedToRef(ty.toIntern());21048 return Air.internedToRef(ty.toIntern());
21046 },21049 },
21047 .Float => {21050 .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));
21049 const bits_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21052 const bits_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21050 ip,21053 ip,
21051 try ip.getOrPutString(gpa, "bits"),21054 try ip.getOrPutString(gpa, "bits"),
...@@ -21063,7 +21066,7 @@ fn zirReify(...@@ -21063,7 +21066,7 @@ fn zirReify(
21063 return Air.internedToRef(ty.toIntern());21066 return Air.internedToRef(ty.toIntern());
21064 },21067 },
21065 .Pointer => {21068 .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));
21067 const size_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21070 const size_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21068 ip,21071 ip,
21069 try ip.getOrPutString(gpa, "size"),21072 try ip.getOrPutString(gpa, "size"),
...@@ -21175,7 +21178,7 @@ fn zirReify(...@@ -21175,7 +21178,7 @@ fn zirReify(
21175 return Air.internedToRef(ty.toIntern());21178 return Air.internedToRef(ty.toIntern());
21176 },21179 },
21177 .Array => {21180 .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));
21179 const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21182 const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21180 ip,21183 ip,
21181 try ip.getOrPutString(gpa, "len"),21184 try ip.getOrPutString(gpa, "len"),
...@@ -21204,7 +21207,7 @@ fn zirReify(...@@ -21204,7 +21207,7 @@ fn zirReify(
21204 return Air.internedToRef(ty.toIntern());21207 return Air.internedToRef(ty.toIntern());
21205 },21208 },
21206 .Optional => {21209 .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));
21208 const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21211 const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21209 ip,21212 ip,
21210 try ip.getOrPutString(gpa, "child"),21213 try ip.getOrPutString(gpa, "child"),
...@@ -21216,7 +21219,7 @@ fn zirReify(...@@ -21216,7 +21219,7 @@ fn zirReify(
21216 return Air.internedToRef(ty.toIntern());21219 return Air.internedToRef(ty.toIntern());
21217 },21220 },
21218 .ErrorUnion => {21221 .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));
21220 const error_set_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21223 const error_set_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21221 ip,21224 ip,
21222 try ip.getOrPutString(gpa, "error_set"),21225 try ip.getOrPutString(gpa, "error_set"),
...@@ -21245,7 +21248,7 @@ fn zirReify(...@@ -21245,7 +21248,7 @@ fn zirReify(
21245 try names.ensureUnusedCapacity(sema.arena, len);21248 try names.ensureUnusedCapacity(sema.arena, len);
21246 for (0..len) |i| {21249 for (0..len) |i| {
21247 const elem_val = try payload_val.elemValue(mod, i);21250 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()));
21249 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21252 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21250 ip,21253 ip,
21251 try ip.getOrPutString(gpa, "name"),21254 try ip.getOrPutString(gpa, "name"),
...@@ -21265,7 +21268,7 @@ fn zirReify(...@@ -21265,7 +21268,7 @@ fn zirReify(
21265 return Air.internedToRef(ty.toIntern());21268 return Air.internedToRef(ty.toIntern());
21266 },21269 },
21267 .Struct => {21270 .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));
21269 const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21272 const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21270 ip,21273 ip,
21271 try ip.getOrPutString(gpa, "layout"),21274 try ip.getOrPutString(gpa, "layout"),
...@@ -21301,7 +21304,7 @@ fn zirReify(...@@ -21301,7 +21304,7 @@ fn zirReify(
21301 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool());21304 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool());
21302 },21305 },
21303 .Enum => {21306 .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));
21305 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21308 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21306 ip,21309 ip,
21307 try ip.getOrPutString(gpa, "tag_type"),21310 try ip.getOrPutString(gpa, "tag_type"),
...@@ -21366,7 +21369,7 @@ fn zirReify(...@@ -21366,7 +21369,7 @@ fn zirReify(
2136621369
21367 for (0..fields_len) |field_i| {21370 for (0..fields_len) |field_i| {
21368 const elem_val = try fields_val.elemValue(mod, field_i);21371 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()));
21370 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21373 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21371 ip,21374 ip,
21372 try ip.getOrPutString(gpa, "name"),21375 try ip.getOrPutString(gpa, "name"),
...@@ -21417,7 +21420,7 @@ fn zirReify(...@@ -21417,7 +21420,7 @@ fn zirReify(
21417 return decl_val;21420 return decl_val;
21418 },21421 },
21419 .Opaque => {21422 .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));
21421 const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21424 const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21422 ip,21425 ip,
21423 try ip.getOrPutString(gpa, "decls"),21426 try ip.getOrPutString(gpa, "decls"),
...@@ -21451,11 +21454,11 @@ fn zirReify(...@@ -21451,11 +21454,11 @@ fn zirReify(
21451 });21454 });
21452 errdefer mod.destroyNamespace(new_namespace_index);21455 errdefer mod.destroyNamespace(new_namespace_index);
2145321456
21454 const opaque_ty = try mod.intern(.{ .opaque_type = .{21457 const opaque_ty = try ip.getOpaqueType(gpa, .{
21455 .decl = new_decl_index,21458 .decl = new_decl_index,
21456 .namespace = new_namespace_index,21459 .namespace = new_namespace_index,
21457 .zir_index = .none,21460 .zir_index = .none,
21458 } });21461 });
21459 // TODO: figure out InternPool removals for incremental compilation21462 // TODO: figure out InternPool removals for incremental compilation
21460 //errdefer ip.remove(opaque_ty);21463 //errdefer ip.remove(opaque_ty);
2146121464
...@@ -21467,7 +21470,7 @@ fn zirReify(...@@ -21467,7 +21470,7 @@ fn zirReify(
21467 return decl_val;21470 return decl_val;
21468 },21471 },
21469 .Union => {21472 .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));
21471 const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21474 const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21472 ip,21475 ip,
21473 try ip.getOrPutString(gpa, "layout"),21476 try ip.getOrPutString(gpa, "layout"),
...@@ -21500,7 +21503,7 @@ fn zirReify(...@@ -21500,7 +21503,7 @@ fn zirReify(
21500 enum_tag_ty = payload_val.toType().toIntern();21503 enum_tag_ty = payload_val.toType().toIntern();
2150121504
21502 const enum_type = switch (ip.indexToKey(enum_tag_ty)) {21505 const enum_type = switch (ip.indexToKey(enum_tag_ty)) {
21503 .enum_type => |x| x,21506 .enum_type => ip.loadEnumType(enum_tag_ty),
21504 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),21507 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
21505 };21508 };
2150621509
...@@ -21521,7 +21524,7 @@ fn zirReify(...@@ -21521,7 +21524,7 @@ fn zirReify(
2152121524
21522 for (0..fields_len) |i| {21525 for (0..fields_len) |i| {
21523 const elem_val = try fields_val.elemValue(mod, i);21526 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()));
21525 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21528 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21526 ip,21529 ip,
21527 try ip.getOrPutString(gpa, "name"),21530 try ip.getOrPutString(gpa, "name"),
...@@ -21542,7 +21545,7 @@ fn zirReify(...@@ -21542,7 +21545,7 @@ fn zirReify(
21542 }21545 }
2154321546
21544 if (enum_tag_ty != .none) {21547 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);
21546 const enum_index = tag_info.nameIndex(ip, field_name) orelse {21549 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
21547 return sema.fail(block, src, "no field named '{}' in enum '{}'", .{21550 return sema.fail(block, src, "no field named '{}' in enum '{}'", .{
21548 field_name.fmt(ip), Type.fromInterned(enum_tag_ty).fmt(mod),21551 field_name.fmt(ip), Type.fromInterned(enum_tag_ty).fmt(mod),
...@@ -21615,7 +21618,7 @@ fn zirReify(...@@ -21615,7 +21618,7 @@ fn zirReify(
21615 }21618 }
2161621619
21617 if (enum_tag_ty != .none) {21620 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);
21619 if (tag_info.names.len > fields_len) {21622 if (tag_info.names.len > fields_len) {
21620 const msg = msg: {21623 const msg = msg: {
21621 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});21624 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
...@@ -21695,7 +21698,7 @@ fn zirReify(...@@ -21695,7 +21698,7 @@ fn zirReify(
21695 return decl_val;21698 return decl_val;
21696 },21699 },
21697 .Fn => {21700 .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));
21699 const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21702 const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21700 ip,21703 ip,
21701 try ip.getOrPutString(gpa, "calling_convention"),21704 try ip.getOrPutString(gpa, "calling_convention"),
...@@ -21746,7 +21749,7 @@ fn zirReify(...@@ -21746,7 +21749,7 @@ fn zirReify(
21746 var noalias_bits: u32 = 0;21749 var noalias_bits: u32 = 0;
21747 for (param_types, 0..) |*param_type, i| {21750 for (param_types, 0..) |*param_type, i| {
21748 const elem_val = try params_val.elemValue(mod, i);21751 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()));
21750 const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21753 const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21751 ip,21754 ip,
21752 try ip.getOrPutString(gpa, "is_generic"),21755 try ip.getOrPutString(gpa, "is_generic"),
...@@ -21849,7 +21852,7 @@ fn reifyStruct(...@@ -21849,7 +21852,7 @@ fn reifyStruct(
21849 });21852 });
21850 // TODO: figure out InternPool removals for incremental compilation21853 // TODO: figure out InternPool removals for incremental compilation
21851 //errdefer ip.remove(ty);21854 //errdefer ip.remove(ty);
21852 const struct_type = ip.indexToKey(ty).struct_type;21855 const struct_type = ip.loadStructType(ty);
2185321856
21854 new_decl.ty = Type.type;21857 new_decl.ty = Type.type;
21855 new_decl.val = Value.fromInterned(ty);21858 new_decl.val = Value.fromInterned(ty);
...@@ -21857,7 +21860,7 @@ fn reifyStruct(...@@ -21857,7 +21860,7 @@ fn reifyStruct(
21857 // Fields21860 // Fields
21858 for (0..fields_len) |i| {21861 for (0..fields_len) |i| {
21859 const elem_val = try fields_val.elemValue(mod, i);21862 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()));
21861 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(21864 const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex(
21862 ip,21865 ip,
21863 try ip.getOrPutString(gpa, "name"),21866 try ip.getOrPutString(gpa, "name"),
...@@ -23228,7 +23231,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -23228,7 +23231,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
23228 switch (ty.containerLayout(mod)) {23231 switch (ty.containerLayout(mod)) {
23229 .Packed => {23232 .Packed => {
23230 var bit_sum: u64 = 0;23233 var bit_sum: u64 = 0;
23231 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;23234 const struct_type = ip.loadStructType(ty.toIntern());
23232 for (0..struct_type.field_types.len) |i| {23235 for (0..struct_type.field_types.len) |i| {
23233 if (i == field_index) {23236 if (i == field_index) {
23234 return bit_sum;23237 return bit_sum;
...@@ -27252,8 +27255,7 @@ fn fieldCallBind(...@@ -27252,8 +27255,7 @@ fn fieldCallBind(
27252 .Union => {27255 .Union => {
27253 try sema.resolveTypeFields(concrete_ty);27256 try sema.resolveTypeFields(concrete_ty);
27254 const union_obj = mod.typeToUnion(concrete_ty).?;27257 const union_obj = mod.typeToUnion(concrete_ty).?;
27255 _ = union_obj.nameIndex(ip, field_name) orelse break :find_field;27258 _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field;
27256
27257 const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false);27259 const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false);
27258 return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) };27260 return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) };
27259 },27261 },
...@@ -27627,7 +27629,8 @@ fn structFieldVal(...@@ -27627,7 +27629,8 @@ fn structFieldVal(
27627 try sema.resolveTypeFields(struct_ty);27629 try sema.resolveTypeFields(struct_ty);
2762827630
27629 switch (ip.indexToKey(struct_ty.toIntern())) {27631 switch (ip.indexToKey(struct_ty.toIntern())) {
27630 .struct_type => |struct_type| {27632 .struct_type => {
27633 const struct_type = ip.loadStructType(struct_ty.toIntern());
27631 if (struct_type.isTuple(ip))27634 if (struct_type.isTuple(ip))
27632 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);27635 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2763327636
...@@ -27833,7 +27836,7 @@ fn unionFieldPtr(...@@ -27833,7 +27836,7 @@ fn unionFieldPtr(
2783327836
27834 try sema.requireRuntimeBlock(block, src, null);27837 try sema.requireRuntimeBlock(block, src, null);
27835 if (!initializing and union_obj.getLayout(ip) == .Auto and block.wantSafety() and27838 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)
27837 {27840 {
27838 const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);27841 const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
27839 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());27842 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
...@@ -27911,7 +27914,7 @@ fn unionFieldVal(...@@ -27911,7 +27914,7 @@ fn unionFieldVal(
2791127914
27912 try sema.requireRuntimeBlock(block, src, null);27915 try sema.requireRuntimeBlock(block, src, null);
27913 if (union_obj.getLayout(ip) == .Auto and block.wantSafety() and27916 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)
27915 {27918 {
27916 const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);27919 const wanted_tag_val = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
27917 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());27920 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
...@@ -31670,7 +31673,7 @@ fn coerceEnumToUnion(...@@ -31670,7 +31673,7 @@ fn coerceEnumToUnion(
31670 const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});31673 const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});
31671 errdefer msg.destroy(sema.gpa);31674 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];
31674 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{31677 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
31675 field_name.fmt(ip),31678 field_name.fmt(ip),
31676 });31679 });
...@@ -31681,7 +31684,7 @@ fn coerceEnumToUnion(...@@ -31681,7 +31684,7 @@ fn coerceEnumToUnion(
31681 }31684 }
31682 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {31685 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
31683 const msg = msg: {31686 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];
31685 const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{31688 const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{
31686 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod),31689 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod),
31687 field_ty.fmt(sema.mod), field_name.fmt(ip),31690 field_ty.fmt(sema.mod), field_name.fmt(ip),
...@@ -31753,8 +31756,8 @@ fn coerceEnumToUnion(...@@ -31753,8 +31756,8 @@ fn coerceEnumToUnion(
31753 );31756 );
31754 errdefer msg.destroy(sema.gpa);31757 errdefer msg.destroy(sema.gpa);
3175531758
31756 for (0..union_obj.field_names.len) |field_index| {31759 for (0..union_obj.field_types.len) |field_index| {
31757 const field_name = union_obj.field_names.get(ip)[field_index];31760 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31758 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);31761 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
31759 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;31762 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
31760 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{31763 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{
...@@ -31787,8 +31790,8 @@ fn coerceAnonStructToUnion(...@@ -31787,8 +31790,8 @@ fn coerceAnonStructToUnion(
31787 .{ .name = anon_struct_type.names.get(ip)[0] }31790 .{ .name = anon_struct_type.names.get(ip)[0] }
31788 else31791 else
31789 .{ .count = anon_struct_type.names.len },31792 .{ .count = anon_struct_type.names.len },
31790 .struct_type => |struct_type| name: {31793 .struct_type => name: {
31791 const field_names = struct_type.field_names.get(ip);31794 const field_names = ip.loadStructType(inst_ty.toIntern()).field_names.get(ip);
31792 break :name if (field_names.len == 1)31795 break :name if (field_names.len == 1)
31793 .{ .name = field_names[0] }31796 .{ .name = field_names[0] }
31794 else31797 else
...@@ -32097,7 +32100,7 @@ fn coerceTupleToStruct(...@@ -32097,7 +32100,7 @@ fn coerceTupleToStruct(
32097 var runtime_src: ?LazySrcLoc = null;32100 var runtime_src: ?LazySrcLoc = null;
32098 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {32101 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
32099 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,32102 .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,
32101 else => unreachable,32104 else => unreachable,
32102 };32105 };
32103 for (0..field_count) |field_index_usize| {32106 for (0..field_count) |field_index_usize| {
...@@ -32109,7 +32112,7 @@ fn coerceTupleToStruct(...@@ -32109,7 +32112,7 @@ fn coerceTupleToStruct(
32109 anon_struct_type.names.get(ip)[field_i]32112 anon_struct_type.names.get(ip)[field_i]
32110 else32113 else
32111 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),32114 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],
32113 else => unreachable,32116 else => unreachable,
32114 };32117 };
32115 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);32118 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
...@@ -32197,7 +32200,7 @@ fn coerceTupleToTuple(...@@ -32197,7 +32200,7 @@ fn coerceTupleToTuple(
32197 const ip = &mod.intern_pool;32200 const ip = &mod.intern_pool;
32198 const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) {32201 const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) {
32199 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,32202 .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,
32201 else => unreachable,32204 else => unreachable,
32202 };32205 };
32203 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);32206 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);
...@@ -32207,7 +32210,7 @@ fn coerceTupleToTuple(...@@ -32207,7 +32210,7 @@ fn coerceTupleToTuple(
32207 const inst_ty = sema.typeOf(inst);32210 const inst_ty = sema.typeOf(inst);
32208 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {32211 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
32209 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,32212 .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,
32211 else => unreachable,32214 else => unreachable,
32212 };32215 };
32213 if (src_field_count > dest_field_count) return error.NotCoercible;32216 if (src_field_count > dest_field_count) return error.NotCoercible;
...@@ -32222,10 +32225,14 @@ fn coerceTupleToTuple(...@@ -32222,10 +32225,14 @@ fn coerceTupleToTuple(
32222 anon_struct_type.names.get(ip)[field_i]32225 anon_struct_type.names.get(ip)[field_i]
32223 else32226 else
32224 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),32227 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
32225 .struct_type => |struct_type| if (struct_type.field_names.len > 0)32228 .struct_type => s: {
32226 struct_type.field_names.get(ip)[field_i]32229 const struct_type = ip.loadStructType(inst_ty.toIntern());
32227 else32230 if (struct_type.field_names.len > 0) {
32228 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),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 },
32229 else => unreachable,32236 else => unreachable,
32230 };32237 };
3223132238
...@@ -32234,12 +32241,12 @@ fn coerceTupleToTuple(...@@ -32234,12 +32241,12 @@ fn coerceTupleToTuple(
3223432241
32235 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {32242 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
32236 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[field_index_usize],32243 .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],
32238 else => unreachable,32245 else => unreachable,
32239 };32246 };
32240 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {32247 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
32241 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize],32248 .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),
32243 else => unreachable,32250 else => unreachable,
32244 };32251 };
3224532252
...@@ -32278,7 +32285,7 @@ fn coerceTupleToTuple(...@@ -32278,7 +32285,7 @@ fn coerceTupleToTuple(
3227832285
32279 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {32286 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
32280 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i],32287 .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),
32282 else => unreachable,32289 else => unreachable,
32283 };32290 };
3228432291
...@@ -35518,7 +35525,7 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35518,7 +35525,7 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
35518pub fn resolveStructAlignment(35525pub fn resolveStructAlignment(
35519 sema: *Sema,35526 sema: *Sema,
35520 ty: InternPool.Index,35527 ty: InternPool.Index,
35521 struct_type: InternPool.Key.StructType,35528 struct_type: InternPool.LoadedStructType,
35522) CompileError!Alignment {35529) CompileError!Alignment {
35523 const mod = sema.mod;35530 const mod = sema.mod;
35524 const ip = &mod.intern_pool;35531 const ip = &mod.intern_pool;
...@@ -35658,7 +35665,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35658,7 +35665,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
35658 }35665 }
35659 }35666 }
3566035667
35661 const RuntimeOrder = InternPool.Key.StructType.RuntimeOrder;35668 const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder;
3566235669
35663 const AlignSortContext = struct {35670 const AlignSortContext = struct {
35664 aligns: []const Alignment,35671 aligns: []const Alignment,
...@@ -35710,7 +35717,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35710,7 +35717,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
35710 _ = try sema.typeRequiresComptime(ty);35717 _ = try sema.typeRequiresComptime(ty);
35711}35718}
3571235719
35713fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) CompileError!void {35720fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) CompileError!void {
35714 const gpa = mod.gpa;35721 const gpa = mod.gpa;
35715 const ip = &mod.intern_pool;35722 const ip = &mod.intern_pool;
3571635723
...@@ -35869,7 +35876,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void...@@ -35869,7 +35876,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
35869pub fn resolveUnionAlignment(35876pub fn resolveUnionAlignment(
35870 sema: *Sema,35877 sema: *Sema,
35871 ty: Type,35878 ty: Type,
35872 union_type: InternPool.Key.UnionType,35879 union_type: InternPool.LoadedUnionType,
35873) CompileError!Alignment {35880) CompileError!Alignment {
35874 const mod = sema.mod;35881 const mod = sema.mod;
35875 const ip = &mod.intern_pool;35882 const ip = &mod.intern_pool;
...@@ -35889,13 +35896,12 @@ pub fn resolveUnionAlignment(...@@ -35889,13 +35896,12 @@ pub fn resolveUnionAlignment(
3588935896
35890 try sema.resolveTypeFieldsUnion(ty, union_type);35897 try sema.resolveTypeFieldsUnion(ty, union_type);
3589135898
35892 const union_obj = ip.loadUnionType(union_type);
35893 var max_align: Alignment = .@"1";35899 var max_align: Alignment = .@"1";
35894 for (0..union_obj.field_names.len) |field_index| {35900 for (0..union_type.field_types.len) |field_index| {
35895 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);35901 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
35896 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;35902 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));
35899 const field_align = if (explicit_align != .none)35905 const field_align = if (explicit_align != .none)
35900 explicit_align35906 explicit_align
35901 else35907 else
...@@ -35913,16 +35919,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35913,16 +35919,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
35913 const mod = sema.mod;35919 const mod = sema.mod;
35914 const ip = &mod.intern_pool;35920 const ip = &mod.intern_pool;
3591535921
35916 const union_type = ip.indexToKey(ty.ip_index).union_type;35922 try sema.resolveTypeFieldsUnion(ty, ip.loadUnionType(ty.ip_index));
35917 try sema.resolveTypeFieldsUnion(ty, union_type);
3591835923
35919 const union_obj = ip.loadUnionType(union_type);35924 // Load again, since the tag type might have changed due to resolution.
35920 switch (union_obj.flagsPtr(ip).status) {35925 const union_type = ip.loadUnionType(ty.ip_index);
35926
35927 switch (union_type.flagsPtr(ip).status) {
35921 .none, .have_field_types => {},35928 .none, .have_field_types => {},
35922 .field_types_wip, .layout_wip => {35929 .field_types_wip, .layout_wip => {
35923 const msg = try Module.ErrorMsg.create(35930 const msg = try Module.ErrorMsg.create(
35924 sema.gpa,35931 sema.gpa,
35925 mod.declPtr(union_obj.decl).srcLoc(mod),35932 mod.declPtr(union_type.decl).srcLoc(mod),
35926 "union '{}' depends on itself",35933 "union '{}' depends on itself",
35927 .{ty.fmt(mod)},35934 .{ty.fmt(mod)},
35928 );35935 );
...@@ -35931,17 +35938,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35931,17 +35938,17 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
35931 .have_layout, .fully_resolved_wip, .fully_resolved => return,35938 .have_layout, .fully_resolved_wip, .fully_resolved => return,
35932 }35939 }
3593335940
35934 const prev_status = union_obj.flagsPtr(ip).status;35941 const prev_status = union_type.flagsPtr(ip).status;
35935 errdefer if (union_obj.flagsPtr(ip).status == .layout_wip) {35942 errdefer if (union_type.flagsPtr(ip).status == .layout_wip) {
35936 union_obj.flagsPtr(ip).status = prev_status;35943 union_type.flagsPtr(ip).status = prev_status;
35937 };35944 };
3593835945
35939 union_obj.flagsPtr(ip).status = .layout_wip;35946 union_type.flagsPtr(ip).status = .layout_wip;
3594035947
35941 var max_size: u64 = 0;35948 var max_size: u64 = 0;
35942 var max_align: Alignment = .@"1";35949 var max_align: Alignment = .@"1";
35943 for (0..union_obj.field_names.len) |field_index| {35950 for (0..union_type.field_types.len) |field_index| {
35944 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);35951 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
35945 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;35952 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
3594635953
35947 max_size = @max(max_size, sema.typeAbiSize(field_ty) catch |err| switch (err) {35954 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 {...@@ -35953,7 +35960,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
35953 else => return err,35960 else => return err,
35954 });35961 });
3595535962
35956 const explicit_align = union_obj.fieldAlign(ip, @intCast(field_index));35963 const explicit_align = union_type.fieldAlign(ip, @intCast(field_index));
35957 const field_align = if (explicit_align != .none)35964 const field_align = if (explicit_align != .none)
35958 explicit_align35965 explicit_align
35959 else35966 else
...@@ -35962,10 +35969,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35962,10 +35969,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
35962 max_align = max_align.max(field_align);35969 max_align = max_align.max(field_align);
35963 }35970 }
3596435971
35965 const flags = union_obj.flagsPtr(ip);35972 const flags = union_type.flagsPtr(ip);
35966 const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_obj.enum_tag_ty));35973 const has_runtime_tag = flags.runtime_tag.hasTag() and try sema.typeHasRuntimeBits(Type.fromInterned(union_type.enum_tag_ty));
35967 const size, const alignment, const padding = if (has_runtime_tag) layout: {35974 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);
35969 const tag_align = try sema.typeAbiAlignment(enum_tag_type);35976 const tag_align = try sema.typeAbiAlignment(enum_tag_type);
35970 const tag_size = try sema.typeAbiSize(enum_tag_type);35977 const tag_size = try sema.typeAbiSize(enum_tag_type);
3597135978
...@@ -35999,22 +36006,22 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35999,22 +36006,22 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
35999 flags.alignment = alignment;36006 flags.alignment = alignment;
36000 flags.status = .have_layout;36007 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))) {
36003 const msg = try Module.ErrorMsg.create(36010 const msg = try Module.ErrorMsg.create(
36004 sema.gpa,36011 sema.gpa,
36005 mod.declPtr(union_obj.decl).srcLoc(mod),36012 mod.declPtr(union_type.decl).srcLoc(mod),
36006 "union layout depends on it having runtime bits",36013 "union layout depends on it having runtime bits",
36007 .{},36014 .{},
36008 );36015 );
36009 return sema.failWithOwnedErrorMsg(null, msg);36016 return sema.failWithOwnedErrorMsg(null, msg);
36010 }36017 }
3601136018
36012 if (union_obj.flagsPtr(ip).assumed_pointer_aligned and36019 if (union_type.flagsPtr(ip).assumed_pointer_aligned and
36013 alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8))))36020 alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8))))
36014 {36021 {
36015 const msg = try Module.ErrorMsg.create(36022 const msg = try Module.ErrorMsg.create(
36016 sema.gpa,36023 sema.gpa,
36017 mod.declPtr(union_obj.decl).srcLoc(mod),36024 mod.declPtr(union_type.decl).srcLoc(mod),
36018 "union layout depends on being pointer aligned",36025 "union layout depends on being pointer aligned",
36019 .{},36026 .{},
36020 );36027 );
...@@ -36202,12 +36209,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {...@@ -36202,12 +36209,11 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {
3620236209
36203 else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) {36210 else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) {
36204 .type_struct,36211 .type_struct,
36205 .type_struct_ns,
36206 .type_struct_packed,36212 .type_struct_packed,
36207 .type_struct_packed_inits,36213 .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)),
36211 .simple_type => try sema.resolveSimpleType(ip.indexToKey(ty_ip).simple_type),36217 .simple_type => try sema.resolveSimpleType(ip.indexToKey(ty_ip).simple_type),
36212 else => {},36218 else => {},
36213 },36219 },
...@@ -36239,7 +36245,7 @@ fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileErr...@@ -36239,7 +36245,7 @@ fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileErr
36239pub fn resolveTypeFieldsStruct(36245pub fn resolveTypeFieldsStruct(
36240 sema: *Sema,36246 sema: *Sema,
36241 ty: InternPool.Index,36247 ty: InternPool.Index,
36242 struct_type: InternPool.Key.StructType,36248 struct_type: InternPool.LoadedStructType,
36243) CompileError!void {36249) CompileError!void {
36244 const mod = sema.mod;36250 const mod = sema.mod;
36245 const ip = &mod.intern_pool;36251 const ip = &mod.intern_pool;
...@@ -36299,7 +36305,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void {...@@ -36299,7 +36305,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void {
36299 struct_type.setHaveFieldInits(ip);36305 struct_type.setHaveFieldInits(ip);
36300}36306}
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 {
36303 const mod = sema.mod;36309 const mod = sema.mod;
36304 const ip = &mod.intern_pool;36310 const ip = &mod.intern_pool;
36305 const owner_decl = mod.declPtr(union_type.decl);36311 const owner_decl = mod.declPtr(union_type.decl);
...@@ -36530,7 +36536,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {...@@ -36530,7 +36536,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {
36530fn semaStructFields(36536fn semaStructFields(
36531 mod: *Module,36537 mod: *Module,
36532 arena: Allocator,36538 arena: Allocator,
36533 struct_type: InternPool.Key.StructType,36539 struct_type: InternPool.LoadedStructType,
36534) CompileError!void {36540) CompileError!void {
36535 const gpa = mod.gpa;36541 const gpa = mod.gpa;
36536 const ip = &mod.intern_pool;36542 const ip = &mod.intern_pool;
...@@ -36797,7 +36803,7 @@ fn semaStructFields(...@@ -36797,7 +36803,7 @@ fn semaStructFields(
36797fn semaStructFieldInits(36803fn semaStructFieldInits(
36798 mod: *Module,36804 mod: *Module,
36799 arena: Allocator,36805 arena: Allocator,
36800 struct_type: InternPool.Key.StructType,36806 struct_type: InternPool.LoadedStructType,
36801) CompileError!void {36807) CompileError!void {
36802 const gpa = mod.gpa;36808 const gpa = mod.gpa;
36803 const ip = &mod.intern_pool;36809 const ip = &mod.intern_pool;
...@@ -36948,7 +36954,7 @@ fn semaStructFieldInits(...@@ -36948,7 +36954,7 @@ fn semaStructFieldInits(
36948 }36954 }
36949}36955}
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 {
36952 const tracy = trace(@src());36958 const tracy = trace(@src());
36953 defer tracy.end();36959 defer tracy.end();
3695436960
...@@ -37080,7 +37086,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -37080,7 +37086,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
37080 // The provided type is the enum tag type.37086 // The provided type is the enum tag type.
37081 union_type.tagTypePtr(ip).* = provided_ty.toIntern();37087 union_type.tagTypePtr(ip).* = provided_ty.toIntern();
37082 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {37088 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
37083 .enum_type => |x| x,37089 .enum_type => ip.loadEnumType(provided_ty.toIntern()),
37084 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(mod)}),37090 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(mod)}),
37085 };37091 };
37086 // The fields of the union must match the enum exactly.37092 // 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...@@ -37217,7 +37223,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
37217 }37223 }
3721837224
37219 if (explicit_tags_seen.len > 0) {37225 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).*);
37221 const enum_index = tag_info.nameIndex(ip, field_name) orelse {37227 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
37222 const ty_src = mod.fieldSrcLoc(union_type.decl, .{37228 const ty_src = mod.fieldSrcLoc(union_type.decl, .{
37223 .index = field_i,37229 .index = field_i,
...@@ -37328,7 +37334,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -37328,7 +37334,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
37328 union_type.setFieldAligns(ip, field_aligns.items);37334 union_type.setFieldAligns(ip, field_aligns.items);
3732937335
37330 if (explicit_tags_seen.len > 0) {37336 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).*);
37332 if (tag_info.names.len > fields_len) {37338 if (tag_info.names.len > fields_len) {
37333 const msg = msg: {37339 const msg = msg: {
37334 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});37340 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 {...@@ -37710,7 +37716,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37710 .type_enum_explicit,37716 .type_enum_explicit,
37711 .type_enum_nonexhaustive,37717 .type_enum_nonexhaustive,
37712 .type_struct,37718 .type_struct,
37713 .type_struct_ns,
37714 .type_struct_anon,37719 .type_struct_anon,
37715 .type_struct_packed,37720 .type_struct_packed,
37716 .type_struct_packed_inits,37721 .type_struct_packed_inits,
...@@ -37733,8 +37738,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37733,8 +37738,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37733 return null;37738 return null;
37734 },37739 },
3773537740
37736 .struct_type => |struct_type| {37741 .struct_type => {
37737 try sema.resolveTypeFields(ty);37742 const struct_type = ip.loadStructType(ty.toIntern());
37743 try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
3773837744
37739 if (struct_type.field_types.len == 0) {37745 if (struct_type.field_types.len == 0) {
37740 // In this case the struct has no fields at all and37746 // In this case the struct has no fields at all and
...@@ -37792,10 +37798,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37792,10 +37798,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37792 } })));37798 } })));
37793 },37799 },
3779437800
37795 .union_type => |union_type| {37801 .union_type => {
37796 try sema.resolveTypeFields(ty);37802 const union_obj = ip.loadUnionType(ty.toIntern());
37797 const union_obj = ip.loadUnionType(union_type);37803 try sema.resolveTypeFieldsUnion(ty, union_obj);
37798 const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.enum_tag_ty))) orelse37804 const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse
37799 return null;37805 return null;
37800 if (union_obj.field_types.len == 0) {37806 if (union_obj.field_types.len == 0) {
37801 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });37807 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
...@@ -37822,39 +37828,42 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37822,39 +37828,42 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37822 return Value.fromInterned(only);37828 return Value.fromInterned(only);
37823 },37829 },
3782437830
37825 .enum_type => |enum_type| switch (enum_type.tag_mode) {37831 .enum_type => {
37826 .nonexhaustive => {37832 const enum_type = ip.loadEnumType(ty.toIntern());
37827 if (enum_type.tag_ty == .comptime_int_type) return null;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| {37837 if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| {
37830 const only = try mod.intern(.{ .enum_tag = .{37838 const only = try mod.intern(.{ .enum_tag = .{
37831 .ty = ty.toIntern(),37839 .ty = ty.toIntern(),
37832 .int = int_opv.toIntern(),37840 .int = int_opv.toIntern(),
37833 } });37841 } });
37834 return Value.fromInterned(only);37842 return Value.fromInterned(only);
37835 }37843 }
3783637844
37837 return null;37845 return null;
37838 },37846 },
37839 .auto, .explicit => {37847 .auto, .explicit => {
37840 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;37848 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
3784137849
37842 return Value.fromInterned(switch (enum_type.names.len) {37850 return Value.fromInterned(switch (enum_type.names.len) {
37843 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }),37851 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }),
37844 1 => try mod.intern(.{ .enum_tag = .{37852 1 => try mod.intern(.{ .enum_tag = .{
37845 .ty = ty.toIntern(),37853 .ty = ty.toIntern(),
37846 .int = if (enum_type.values.len == 0)37854 .int = if (enum_type.values.len == 0)
37847 (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern()37855 (try mod.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern()
37848 else37856 else
37849 try mod.intern_pool.getCoercedInts(37857 try mod.intern_pool.getCoercedInts(
37850 mod.gpa,37858 mod.gpa,
37851 mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int,37859 mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int,
37852 enum_type.tag_ty,37860 enum_type.tag_ty,
37853 ),37861 ),
37854 } }),37862 } }),
37855 else => return null,37863 else => return null,
37856 });37864 });
37857 },37865 },
37866 }
37858 },37867 },
3785937868
37860 else => unreachable,37869 else => unreachable,
...@@ -38186,7 +38195,7 @@ fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment {...@@ -38186,7 +38195,7 @@ fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment {
3818638195
38187/// Not valid to call for packed unions.38196/// Not valid to call for packed unions.
38188/// Keep implementation in sync with `Module.unionFieldNormalAlignment`.38197/// 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 {
38190 const mod = sema.mod;38199 const mod = sema.mod;
38191 const ip = &mod.intern_pool;38200 const ip = &mod.intern_pool;
38192 const field_align = u.fieldAlign(ip, field_index);38201 const field_align = u.fieldAlign(ip, field_index);
...@@ -38234,7 +38243,7 @@ fn unionFieldIndex(...@@ -38234,7 +38243,7 @@ fn unionFieldIndex(
38234 const ip = &mod.intern_pool;38243 const ip = &mod.intern_pool;
38235 try sema.resolveTypeFields(union_ty);38244 try sema.resolveTypeFields(union_ty);
38236 const union_obj = mod.typeToUnion(union_ty).?;38245 const union_obj = mod.typeToUnion(union_ty).?;
38237 const field_index = union_obj.nameIndex(ip, field_name) orelse38246 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
38238 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);38247 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
38239 return @intCast(field_index);38248 return @intCast(field_index);
38240}38249}
...@@ -38271,7 +38280,7 @@ fn anonStructFieldIndex(...@@ -38271,7 +38280,7 @@ fn anonStructFieldIndex(
38271 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| {38280 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| {
38272 if (name == field_name) return @intCast(i);38281 if (name == field_name) return @intCast(i);
38273 },38282 },
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,
38275 else => unreachable,38284 else => unreachable,
38276 }38285 }
38277 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{38286 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 {...@@ -38707,7 +38716,7 @@ fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {
38707/// Asserts the type is an enum.38716/// Asserts the type is an enum.
38708fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {38717fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {
38709 const mod = sema.mod;38718 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());
38711 assert(enum_type.tag_mode != .nonexhaustive);38720 assert(enum_type.tag_mode != .nonexhaustive);
38712 // The `tagValueIndex` function call below relies on the type being the integer tag type.38721 // The `tagValueIndex` function call below relies on the type being the integer tag type.
38713 // `getCoerced` assumes the value will fit the new type.38722 // `getCoerced` assumes the value will fit the new type.
src/TypedValue.zig+4-8
...@@ -89,7 +89,7 @@ pub fn print(...@@ -89,7 +89,7 @@ pub fn print(
8989
90 if (payload.tag) |tag| {90 if (payload.tag) |tag| {
91 try print(.{91 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),
93 .val = tag,93 .val = tag,
94 }, writer, level - 1, mod);94 }, writer, level - 1, mod);
95 try writer.writeAll(" = ");95 try writer.writeAll(" = ");
...@@ -247,7 +247,7 @@ pub fn print(...@@ -247,7 +247,7 @@ pub fn print(
247 if (level == 0) {247 if (level == 0) {
248 return writer.writeAll("(enum)");248 return writer.writeAll("(enum)");
249 }249 }
250 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;250 const enum_type = ip.loadEnumType(ty.toIntern());
251 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {251 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
252 try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});252 try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
253 return;253 return;
...@@ -398,7 +398,7 @@ pub fn print(...@@ -398,7 +398,7 @@ pub fn print(
398 }398 }
399 },399 },
400 .Union => {400 .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)];
402 try writer.print(".{i}", .{field_name.fmt(ip)});402 try writer.print(".{i}", .{field_name.fmt(ip)});
403 },403 },
404 .Pointer => {404 .Pointer => {
...@@ -482,11 +482,7 @@ fn printAggregate(...@@ -482,11 +482,7 @@ fn printAggregate(
482 for (0..max_len) |i| {482 for (0..max_len) |i| {
483 if (i != 0) try writer.writeAll(", ");483 if (i != 0) try writer.writeAll(", ");
484484
485 const field_name = switch (ip.indexToKey(ty.toIntern())) {485 const field_name = ty.structFieldName(@intCast(i), mod);
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 };
490486
491 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)});487 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(ip)});
492 try print(.{488 try print(.{
src/Value.zig+16-10
...@@ -424,22 +424,28 @@ pub fn toType(self: Value) Type {...@@ -424,22 +424,28 @@ pub fn toType(self: Value) Type {
424424
425pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {425pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
426 const ip = &mod.intern_pool;426 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)) {
428 // Assume it is already an integer and return it directly.429 // Assume it is already an integer and return it directly.
429 .simple_type, .int_type => val,430 .simple_type, .int_type => val,
430 .enum_literal => |enum_literal| {431 .enum_literal => |enum_literal| {
431 const field_index = ty.enumFieldIndex(enum_literal, mod).?;432 const field_index = ty.enumFieldIndex(enum_literal, mod).?;
432 return switch (ip.indexToKey(ty.toIntern())) {433 switch (ip.indexToKey(ty.toIntern())) {
433 // Assume it is already an integer and return it directly.434 // Assume it is already an integer and return it directly.
434 .simple_type, .int_type => val,435 .simple_type, .int_type => return val,
435 .enum_type => |enum_type| if (enum_type.values.len != 0)436 .enum_type => {
436 Value.fromInterned(enum_type.values.get(ip)[field_index])437 const enum_type = ip.loadEnumType(ty.toIntern());
437 else // Field index and integer values are the same.438 if (enum_type.values.len != 0) {
438 mod.intValue(Type.fromInterned(enum_type.tag_ty), field_index),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 },
439 else => unreachable,445 else => unreachable,
440 };446 }
441 },447 },
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)),
443 else => unreachable,449 else => unreachable,
444 };450 };
445}451}
...@@ -832,7 +838,7 @@ pub fn writeToPackedMemory(...@@ -832,7 +838,7 @@ pub fn writeToPackedMemory(
832 }838 }
833 },839 },
834 .Struct => {840 .Struct => {
835 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;841 const struct_type = ip.loadStructType(ty.toIntern());
836 // Sema is supposed to have emitted a compile error already in the case of Auto,842 // Sema is supposed to have emitted a compile error already in the case of Auto,
837 // and Extern is handled in non-packed writeToMemory.843 // and Extern is handled in non-packed writeToMemory.
838 assert(struct_type.layout == .Packed);844 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 {...@@ -3354,7 +3354,8 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3354 val.writeToMemory(ty, mod, &buf) catch unreachable;3354 val.writeToMemory(ty, mod, &buf) catch unreachable;
3355 return func.storeSimdImmd(buf);3355 return func.storeSimdImmd(buf);
3356 },3356 },
3357 .struct_type => |struct_type| {3357 .struct_type => {
3358 const struct_type = ip.loadStructType(ty.toIntern());
3358 // non-packed structs are not handled in this function because they3359 // non-packed structs are not handled in this function because they
3359 // are by-ref types.3360 // are by-ref types.
3360 assert(struct_type.layout == .Packed);3361 assert(struct_type.layout == .Packed);
...@@ -5411,7 +5412,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5411,7 +5412,7 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5411 const layout = union_ty.unionGetLayout(mod);5412 const layout = union_ty.unionGetLayout(mod);
5412 const union_obj = mod.typeToUnion(union_ty).?;5413 const union_obj = mod.typeToUnion(union_ty).?;
5413 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);5414 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
5416 const tag_int = blk: {5417 const tag_int = blk: {
5417 const tag_ty = union_ty.unionTagTypeHypothetical(mod);5418 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 {...@@ -76,7 +76,7 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class {
76 }76 }
77 const layout = ty.unionGetLayout(mod);77 const layout = ty.unionGetLayout(mod);
78 assert(layout.tag_size == 0);78 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;
80 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);80 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
81 return classifyType(first_field_ty, mod);81 return classifyType(first_field_ty, mod);
82 },82 },
src/arch/x86_64/CodeGen.zig+1-1
...@@ -18183,7 +18183,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -18183,7 +18183,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
18183 const dst_mcv = try self.allocRegOrMem(inst, false);18183 const dst_mcv = try self.allocRegOrMem(inst, false);
1818418184
18185 const union_obj = mod.typeToUnion(union_ty).?;18185 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];
18187 const tag_ty = Type.fromInterned(union_obj.enum_tag_ty);18187 const tag_ty = Type.fromInterned(union_obj.enum_tag_ty);
18188 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;18188 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
18189 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);18189 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
src/codegen.zig+73-70
...@@ -510,88 +510,91 @@ pub fn generateSymbol(...@@ -510,88 +510,91 @@ pub fn generateSymbol(
510 }510 }
511 }511 }
512 },512 },
513 .struct_type => |struct_type| switch (struct_type.layout) {513 .struct_type => {
514 .Packed => {514 const struct_type = ip.loadStructType(typed_value.ty.toIntern());
515 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse515 switch (struct_type.layout) {
516 return error.Overflow;516 .Packed => {
517 const current_pos = code.items.len;517 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
518 try code.resize(current_pos + abi_size);518 return error.Overflow;
519 var bits: u16 = 0;519 const current_pos = code.items.len;
520520 try code.resize(current_pos + abi_size);
521 for (struct_type.field_types.get(ip), 0..) |field_ty, index| {521 var bits: u16 = 0;
522 const field_val = switch (aggregate.storage) {522
523 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{523 for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
524 .ty = field_ty,524 const field_val = switch (aggregate.storage) {
525 .storage = .{ .u64 = bytes[index] },525 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
526 } }),526 .ty = field_ty,
527 .elems => |elems| elems[index],527 .storage = .{ .u64 = bytes[index] },
528 .repeated_elem => |elem| elem,528 } }),
529 };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();
538 switch (try generateSymbol(bin_file, src_loc, .{578 switch (try generateSymbol(bin_file, src_loc, .{
539 .ty = Type.fromInterned(field_ty),579 .ty = Type.fromInterned(field_ty),
540 .val = Value.fromInterned(field_val),580 .val = Value.fromInterned(field_val),
541 }, &tmp_list, debug_output, reloc_info)) {581 }, code, debug_output, reloc_info)) {
542 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),582 .ok => {},
543 .fail => |em| return Result{ .fail = em },583 .fail => |em| return Result{ .fail = em },
544 }584 }
545 } else {
546 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable;
547 }585 }
548 bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod)));586
549 }587 const size = struct_type.size(ip).*;
550 },588 const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?;
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 };
569589
570 const padding = math.cast(590 const padding = math.cast(
571 usize,591 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),
573 ) orelse return error.Overflow;594 ) orelse return error.Overflow;
574 if (padding > 0) try code.appendNTimes(0, padding);595 if (padding > 0) try code.appendNTimes(0, padding);
575596 },
576 switch (try generateSymbol(bin_file, src_loc, .{597 }
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 },
595 },598 },
596 else => unreachable,599 else => unreachable,
597 },600 },
src/codegen/c.zig+11-13
...@@ -1475,13 +1475,10 @@ pub const DeclGen = struct {...@@ -1475,13 +1475,10 @@ pub const DeclGen = struct {
1475 var empty = true;1475 var empty = true;
1476 for (0..struct_type.field_types.len) |field_index| {1476 for (0..struct_type.field_types.len) |field_index| {
1477 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);1477 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1478 if (struct_type.fieldIsComptime(ip, field_index)) continue;
1478 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1479 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14791480
1480 if (!empty) try writer.writeAll(" | ");1481 if (!empty) try writer.writeByte(',');
1481 try writer.writeByte('(');
1482 try dg.renderType(writer, ty);
1483 try writer.writeByte(')');
1484
1485 const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {1482 const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
1486 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{1483 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
1487 .ty = field_ty.toIntern(),1484 .ty = field_ty.toIntern(),
...@@ -1490,6 +1487,7 @@ pub const DeclGen = struct {...@@ -1490,6 +1487,7 @@ pub const DeclGen = struct {
1490 .elems => |elems| elems[field_index],1487 .elems => |elems| elems[field_index],
1491 .repeated_elem => |elem| elem,1488 .repeated_elem => |elem| elem,
1492 };1489 };
1490 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type);
14931491
1494 if (bit_offset != 0) {1492 if (bit_offset != 0) {
1495 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other);1493 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other);
...@@ -1503,7 +1501,7 @@ pub const DeclGen = struct {...@@ -1503,7 +1501,7 @@ pub const DeclGen = struct {
1503 bit_offset += field_ty.bitSize(mod);1501 bit_offset += field_ty.bitSize(mod);
1504 empty = false;1502 empty = false;
1505 }1503 }
1506 try writer.writeByte(')');1504 try writer.writeByte('}');
1507 }1505 }
1508 },1506 },
1509 },1507 },
...@@ -1547,7 +1545,7 @@ pub const DeclGen = struct {...@@ -1547,7 +1545,7 @@ pub const DeclGen = struct {
15471545
1548 const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;1546 const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
1549 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);1547 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];
1551 if (union_obj.getLayout(ip) == .Packed) {1549 if (union_obj.getLayout(ip) == .Packed) {
1552 if (field_ty.hasRuntimeBits(mod)) {1550 if (field_ty.hasRuntimeBits(mod)) {
1553 if (field_ty.isPtrAtRuntime(mod)) {1551 if (field_ty.isPtrAtRuntime(mod)) {
...@@ -5502,7 +5500,7 @@ fn fieldLocation(...@@ -5502,7 +5500,7 @@ fn fieldLocation(
5502 .{ .field = .{ .identifier = "payload" } }5500 .{ .field = .{ .identifier = "payload" } }
5503 else5501 else
5504 .begin;5502 .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];
5506 return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|5504 return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|
5507 .{ .payload_identifier = ip.stringToSlice(field_name) }5505 .{ .payload_identifier = ip.stringToSlice(field_name) }
5508 else5506 else
...@@ -5735,8 +5733,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5735,8 +5733,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5735 else5733 else
5736 .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },5734 .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
57375735
5738 .union_type => |union_type| field_name: {5736 .union_type => field_name: {
5739 const union_obj = ip.loadUnionType(union_type);5737 const union_obj = ip.loadUnionType(struct_ty.toIntern());
5740 if (union_obj.flagsPtr(ip).layout == .Packed) {5738 if (union_obj.flagsPtr(ip).layout == .Packed) {
5741 const operand_lval = if (struct_byval == .constant) blk: {5739 const operand_lval = if (struct_byval == .constant) blk: {
5742 const operand_local = try f.allocLocal(inst, struct_ty);5740 const operand_local = try f.allocLocal(inst, struct_ty);
...@@ -5762,8 +5760,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5762,8 +5760,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
57625760
5763 return local;5761 return local;
5764 } else {5762 } else {
5765 const name = union_obj.field_names.get(ip)[extra.field_index];5763 const name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
5766 break :field_name if (union_type.hasTag(ip)) .{5764 break :field_name if (union_obj.hasTag(ip)) .{
5767 .payload_identifier = ip.stringToSlice(name),5765 .payload_identifier = ip.stringToSlice(name),
5768 } else .{5766 } else .{
5769 .identifier = ip.stringToSlice(name),5767 .identifier = ip.stringToSlice(name),
...@@ -7171,7 +7169,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7171,7 +7169,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71717169
7172 const union_ty = f.typeOfIndex(inst);7170 const union_ty = f.typeOfIndex(inst);
7173 const union_obj = mod.typeToUnion(union_ty).?;7171 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];
7175 const payload_ty = f.typeOf(extra.init);7173 const payload_ty = f.typeOf(extra.init);
7176 const payload = try f.resolveInst(extra.init);7174 const payload = try f.resolveInst(extra.init);
7177 try reap(f, inst, &.{extra.init});7175 try reap(f, inst, &.{extra.init});
src/codegen/c/type.zig+8-8
...@@ -1507,7 +1507,7 @@ pub const CType = extern union {...@@ -1507,7 +1507,7 @@ pub const CType = extern union {
1507 if (lookup.isMutable()) {1507 if (lookup.isMutable()) {
1508 for (0..switch (zig_ty_tag) {1508 for (0..switch (zig_ty_tag) {
1509 .Struct => ty.structFieldCount(mod),1509 .Struct => ty.structFieldCount(mod),
1510 .Union => mod.typeToUnion(ty).?.field_names.len,1510 .Union => mod.typeToUnion(ty).?.field_types.len,
1511 else => unreachable,1511 else => unreachable,
1512 }) |field_i| {1512 }) |field_i| {
1513 const field_ty = ty.structFieldType(field_i, mod);1513 const field_ty = ty.structFieldType(field_i, mod);
...@@ -1589,7 +1589,7 @@ pub const CType = extern union {...@@ -1589,7 +1589,7 @@ pub const CType = extern union {
1589 var is_packed = false;1589 var is_packed = false;
1590 for (0..switch (zig_ty_tag) {1590 for (0..switch (zig_ty_tag) {
1591 .Struct => ty.structFieldCount(mod),1591 .Struct => ty.structFieldCount(mod),
1592 .Union => mod.typeToUnion(ty).?.field_names.len,1592 .Union => mod.typeToUnion(ty).?.field_types.len,
1593 else => unreachable,1593 else => unreachable,
1594 }) |field_i| {1594 }) |field_i| {
1595 const field_ty = ty.structFieldType(field_i, mod);1595 const field_ty = ty.structFieldType(field_i, mod);
...@@ -1940,7 +1940,7 @@ pub const CType = extern union {...@@ -1940,7 +1940,7 @@ pub const CType = extern union {
1940 const zig_ty_tag = ty.zigTypeTag(mod);1940 const zig_ty_tag = ty.zigTypeTag(mod);
1941 const fields_len = switch (zig_ty_tag) {1941 const fields_len = switch (zig_ty_tag) {
1942 .Struct => ty.structFieldCount(mod),1942 .Struct => ty.structFieldCount(mod),
1943 .Union => mod.typeToUnion(ty).?.field_names.len,1943 .Union => mod.typeToUnion(ty).?.field_types.len,
1944 else => unreachable,1944 else => unreachable,
1945 };1945 };
19461946
...@@ -1967,7 +1967,7 @@ pub const CType = extern union {...@@ -1967,7 +1967,7 @@ pub const CType = extern union {
1967 else1967 else
1968 arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) {1968 arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) {
1969 .Struct => ty.legacyStructFieldName(field_i, mod),1969 .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],
1971 else => unreachable,1971 else => unreachable,
1972 })),1972 })),
1973 .type = store.set.typeToIndex(field_ty, mod, switch (kind) {1973 .type = store.set.typeToIndex(field_ty, mod, switch (kind) {
...@@ -2097,7 +2097,7 @@ pub const CType = extern union {...@@ -2097,7 +2097,7 @@ pub const CType = extern union {
2097 var c_field_i: usize = 0;2097 var c_field_i: usize = 0;
2098 for (0..switch (zig_ty_tag) {2098 for (0..switch (zig_ty_tag) {
2099 .Struct => ty.structFieldCount(mod),2099 .Struct => ty.structFieldCount(mod),
2100 .Union => mod.typeToUnion(ty).?.field_names.len,2100 .Union => mod.typeToUnion(ty).?.field_types.len,
2101 else => unreachable,2101 else => unreachable,
2102 }) |field_i_usize| {2102 }) |field_i_usize| {
2103 const field_i: u32 = @intCast(field_i_usize);2103 const field_i: u32 = @intCast(field_i_usize);
...@@ -2120,7 +2120,7 @@ pub const CType = extern union {...@@ -2120,7 +2120,7 @@ pub const CType = extern union {
2120 else2120 else
2121 ip.stringToSlice(switch (zig_ty_tag) {2121 ip.stringToSlice(switch (zig_ty_tag) {
2122 .Struct => ty.legacyStructFieldName(field_i, mod),2122 .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],
2124 else => unreachable,2124 else => unreachable,
2125 }),2125 }),
2126 mem.span(c_field.name),2126 mem.span(c_field.name),
...@@ -2226,7 +2226,7 @@ pub const CType = extern union {...@@ -2226,7 +2226,7 @@ pub const CType = extern union {
2226 const zig_ty_tag = ty.zigTypeTag(mod);2226 const zig_ty_tag = ty.zigTypeTag(mod);
2227 for (0..switch (ty.zigTypeTag(mod)) {2227 for (0..switch (ty.zigTypeTag(mod)) {
2228 .Struct => ty.structFieldCount(mod),2228 .Struct => ty.structFieldCount(mod),
2229 .Union => mod.typeToUnion(ty).?.field_names.len,2229 .Union => mod.typeToUnion(ty).?.field_types.len,
2230 else => unreachable,2230 else => unreachable,
2231 }) |field_i_usize| {2231 }) |field_i_usize| {
2232 const field_i: u32 = @intCast(field_i_usize);2232 const field_i: u32 = @intCast(field_i_usize);
...@@ -2245,7 +2245,7 @@ pub const CType = extern union {...@@ -2245,7 +2245,7 @@ pub const CType = extern union {
2245 else2245 else
2246 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {2246 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
2247 .Struct => ty.legacyStructFieldName(field_i, mod),2247 .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],
2249 else => unreachable,2249 else => unreachable,
2250 }));2250 }));
2251 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align");2251 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align");
src/codegen/llvm.zig+30-24
...@@ -1997,7 +1997,7 @@ pub const Object = struct {...@@ -1997,7 +1997,7 @@ pub const Object = struct {
1997 return debug_enum_type;1997 return debug_enum_type;
1998 }1998 }
19991999
2000 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;2000 const enum_type = ip.loadEnumType(ty.toIntern());
20012001
2002 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);2002 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
2003 defer gpa.free(enumerators);2003 defer gpa.free(enumerators);
...@@ -2507,8 +2507,8 @@ pub const Object = struct {...@@ -2507,8 +2507,8 @@ pub const Object = struct {
2507 try o.debug_type_map.put(gpa, ty, debug_struct_type);2507 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2508 return debug_struct_type;2508 return debug_struct_type;
2509 },2509 },
2510 .struct_type => |struct_type| {2510 .struct_type => {
2511 if (!struct_type.haveFieldTypes(ip)) {2511 if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) {
2512 // This can happen if a struct type makes it all the way to2512 // This can happen if a struct type makes it all the way to
2513 // flush() without ever being instantiated or referenced (even2513 // flush() without ever being instantiated or referenced (even
2514 // via pointer). The only reason we are hearing about it now is2514 // via pointer). The only reason we are hearing about it now is
...@@ -2597,15 +2597,14 @@ pub const Object = struct {...@@ -2597,15 +2597,14 @@ pub const Object = struct {
2597 const name = try o.allocTypeName(ty);2597 const name = try o.allocTypeName(ty);
2598 defer gpa.free(name);2598 defer gpa.free(name);
25992599
2600 const union_type = ip.indexToKey(ty.toIntern()).union_type;2600 const union_type = ip.loadUnionType(ty.toIntern());
2601 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {2601 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
2602 const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);2602 const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2603 try o.debug_type_map.put(gpa, ty, debug_union_type);2603 try o.debug_type_map.put(gpa, ty, debug_union_type);
2604 return debug_union_type;2604 return debug_union_type;
2605 }2605 }
26062606
2607 const union_obj = ip.loadUnionType(union_type);2607 const layout = mod.getUnionLayout(union_type);
2608 const layout = mod.getUnionLayout(union_obj);
26092608
2610 const debug_fwd_ref = try o.builder.debugForwardReference();2609 const debug_fwd_ref = try o.builder.debugForwardReference();
26112610
...@@ -2622,7 +2621,7 @@ pub const Object = struct {...@@ -2622,7 +2621,7 @@ pub const Object = struct {
2622 ty.abiSize(mod) * 8,2621 ty.abiSize(mod) * 8,
2623 ty.abiAlignment(mod).toByteUnits(0) * 8,2622 ty.abiAlignment(mod).toByteUnits(0) * 8,
2624 try o.builder.debugTuple(2623 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))},
2626 ),2625 ),
2627 );2626 );
26282627
...@@ -2636,21 +2635,23 @@ pub const Object = struct {...@@ -2636,21 +2635,23 @@ pub const Object = struct {
2636 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};2635 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2637 defer fields.deinit(gpa);2636 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
2641 const debug_union_fwd_ref = if (layout.tag_size == 0)2640 const debug_union_fwd_ref = if (layout.tag_size == 0)
2642 debug_fwd_ref2641 debug_fwd_ref
2643 else2642 else
2644 try o.builder.debugForwardReference();2643 try o.builder.debugForwardReference();
26452644
2646 for (0..union_obj.field_names.len) |field_index| {2645 const tag_type = union_type.loadTagType();
2647 const field_ty = union_obj.field_types.get(ip)[field_index];2646
2647 for (0..tag_type.names.len) |field_index| {
2648 const field_ty = union_type.field_types.get(ip)[field_index];
2648 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;2649 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
26492650
2650 const field_size = Type.fromInterned(field_ty).abiSize(mod);2651 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];
2654 fields.appendAssumeCapacity(try o.builder.debugMemberType(2655 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2655 try o.builder.metadataString(ip.stringToSlice(field_name)),2656 try o.builder.metadataString(ip.stringToSlice(field_name)),
2656 .none, // File2657 .none, // File
...@@ -2706,7 +2707,7 @@ pub const Object = struct {...@@ -2706,7 +2707,7 @@ pub const Object = struct {
2706 .none, // File2707 .none, // File
2707 debug_fwd_ref,2708 debug_fwd_ref,
2708 0, // Line2709 0, // Line
2709 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)),2710 try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)),
2710 layout.tag_size * 8,2711 layout.tag_size * 8,
2711 layout.tag_align.toByteUnits(0) * 8,2712 layout.tag_align.toByteUnits(0) * 8,
2712 tag_offset * 8,2713 tag_offset * 8,
...@@ -3321,9 +3322,11 @@ pub const Object = struct {...@@ -3321,9 +3322,11 @@ pub const Object = struct {
3321 return o.builder.structType(.normal, fields[0..fields_len]);3322 return o.builder.structType(.normal, fields[0..fields_len]);
3322 },3323 },
3323 .simple_type => unreachable,3324 .simple_type => unreachable,
3324 .struct_type => |struct_type| {3325 .struct_type => {
3325 if (o.type_map.get(t.toIntern())) |value| return value;3326 if (o.type_map.get(t.toIntern())) |value| return value;
33263327
3328 const struct_type = ip.loadStructType(t.toIntern());
3329
3327 if (struct_type.layout == .Packed) {3330 if (struct_type.layout == .Packed) {
3328 const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*));3331 const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*));
3329 try o.type_map.put(o.gpa, t.toIntern(), int_ty);3332 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
...@@ -3468,10 +3471,10 @@ pub const Object = struct {...@@ -3468,10 +3471,10 @@ pub const Object = struct {
3468 }3471 }
3469 return o.builder.structType(.normal, llvm_field_types.items);3472 return o.builder.structType(.normal, llvm_field_types.items);
3470 },3473 },
3471 .union_type => |union_type| {3474 .union_type => {
3472 if (o.type_map.get(t.toIntern())) |value| return value;3475 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());
3475 const layout = mod.getUnionLayout(union_obj);3478 const layout = mod.getUnionLayout(union_obj);
34763479
3477 if (union_obj.flagsPtr(ip).layout == .Packed) {3480 if (union_obj.flagsPtr(ip).layout == .Packed) {
...@@ -3555,7 +3558,7 @@ pub const Object = struct {...@@ -3555,7 +3558,7 @@ pub const Object = struct {
3555 }3558 }
3556 return gop.value_ptr.*;3559 return gop.value_ptr.*;
3557 },3560 },
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)),
3559 .func_type => |func_type| try o.lowerTypeFn(func_type),3562 .func_type => |func_type| try o.lowerTypeFn(func_type),
3560 .error_set_type, .inferred_error_set_type => try o.errorIntType(),3563 .error_set_type, .inferred_error_set_type => try o.errorIntType(),
3561 // values, not types3564 // values, not types
...@@ -4032,7 +4035,8 @@ pub const Object = struct {...@@ -4032,7 +4035,8 @@ pub const Object = struct {
4032 else4035 else
4033 struct_ty, vals);4036 struct_ty, vals);
4034 },4037 },
4035 .struct_type => |struct_type| {4038 .struct_type => {
4039 const struct_type = ip.loadStructType(ty.toIntern());
4036 assert(struct_type.haveLayout(ip));4040 assert(struct_type.haveLayout(ip));
4037 const struct_ty = try o.lowerType(ty);4041 const struct_ty = try o.lowerType(ty);
4038 if (struct_type.layout == .Packed) {4042 if (struct_type.layout == .Packed) {
...@@ -4596,7 +4600,7 @@ pub const Object = struct {...@@ -4596,7 +4600,7 @@ pub const Object = struct {
4596 fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index {4600 fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index {
4597 const zcu = o.module;4601 const zcu = o.module;
4598 const ip = &zcu.intern_pool;4602 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
4601 // TODO: detect when the type changes and re-emit this function.4605 // TODO: detect when the type changes and re-emit this function.
4602 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);4606 const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl);
...@@ -9620,7 +9624,7 @@ pub const FuncGen = struct {...@@ -9620,7 +9624,7 @@ pub const FuncGen = struct {
9620 fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {9624 fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index {
9621 const o = self.dg.object;9625 const o = self.dg.object;
9622 const zcu = o.module;9626 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
9625 // TODO: detect when the type changes and re-emit this function.9629 // TODO: detect when the type changes and re-emit this function.
9626 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);9630 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);
...@@ -10092,7 +10096,7 @@ pub const FuncGen = struct {...@@ -10092,7 +10096,7 @@ pub const FuncGen = struct {
1009210096
10093 const tag_int = blk: {10097 const tag_int = blk: {
10094 const tag_ty = union_ty.unionTagTypeHypothetical(mod);10098 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];
10096 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;10100 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
10097 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);10101 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
10098 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);10102 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...@@ -11154,7 +11158,8 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E
11154 if (first_non_integer == null or classes[first_non_integer.?] == .none) {11158 if (first_non_integer == null or classes[first_non_integer.?] == .none) {
11155 assert(first_non_integer orelse classes.len == types_index);11159 assert(first_non_integer orelse classes.len == types_index);
11156 switch (ip.indexToKey(return_type.toIntern())) {11160 switch (ip.indexToKey(return_type.toIntern())) {
11157 .struct_type => |struct_type| {11161 .struct_type => {
11162 const struct_type = ip.loadStructType(return_type.toIntern());
11158 assert(struct_type.haveLayout(ip));11163 assert(struct_type.haveLayout(ip));
11159 const size: u64 = struct_type.size(ip).*;11164 const size: u64 = struct_type.size(ip).*;
11160 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);11165 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
...@@ -11446,7 +11451,8 @@ const ParamTypeIterator = struct {...@@ -11446,7 +11451,8 @@ const ParamTypeIterator = struct {
11446 return .byref;11451 return .byref;
11447 }11452 }
11448 switch (ip.indexToKey(ty.toIntern())) {11453 switch (ip.indexToKey(ty.toIntern())) {
11449 .struct_type => |struct_type| {11454 .struct_type => {
11455 const struct_type = ip.loadStructType(ty.toIntern());
11450 assert(struct_type.haveLayout(ip));11456 assert(struct_type.haveLayout(ip));
11451 const size: u64 = struct_type.size(ip).*;11457 const size: u64 = struct_type.size(ip).*;
11452 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);11458 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
...@@ -11562,7 +11568,7 @@ fn isByRef(ty: Type, mod: *Module) bool {...@@ -11562,7 +11568,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
11562 }11568 }
11563 return false;11569 return false;
11564 },11570 },
11565 .struct_type => |s| s,11571 .struct_type => ip.loadStructType(ty.toIntern()),
11566 else => unreachable,11572 else => unreachable,
11567 };11573 };
1156811574
src/codegen/spirv.zig+9-11
...@@ -1528,7 +1528,7 @@ const DeclGen = struct {...@@ -1528,7 +1528,7 @@ const DeclGen = struct {
1528 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });1528 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1529 return ty_ref;1529 return ty_ref;
1530 },1530 },
1531 .struct_type => |struct_type| struct_type,1531 .struct_type => ip.loadStructType(ty.toIntern()),
1532 else => unreachable,1532 else => unreachable,
1533 };1533 };
15341534
...@@ -3633,7 +3633,8 @@ const DeclGen = struct {...@@ -3633,7 +3633,8 @@ const DeclGen = struct {
3633 index += 1;3633 index += 1;
3634 }3634 }
3635 },3635 },
3636 .struct_type => |struct_type| {3636 .struct_type => {
3637 const struct_type = ip.loadStructType(result_ty.toIntern());
3637 var it = struct_type.iterateRuntimeOrder(ip);3638 var it = struct_type.iterateRuntimeOrder(ip);
3638 for (elements, 0..) |element, i| {3639 for (elements, 0..) |element, i| {
3639 const field_index = it.next().?;3640 const field_index = it.next().?;
...@@ -3901,36 +3902,33 @@ const DeclGen = struct {...@@ -3901,36 +3902,33 @@ const DeclGen = struct {
3901 const mod = self.module;3902 const mod = self.module;
3902 const ip = &mod.intern_pool;3903 const ip = &mod.intern_pool;
3903 const union_ty = mod.typeToUnion(ty).?;3904 const union_ty = mod.typeToUnion(ty).?;
3905 const tag_ty = Type.fromInterned(union_ty.enum_tag_ty);
39043906
3905 if (union_ty.getLayout(ip) == .Packed) {3907 if (union_ty.getLayout(ip) == .Packed) {
3906 unreachable; // TODO3908 unreachable; // TODO
3907 }3909 }
39083910
3909 const maybe_tag_ty = ty.unionTagTypeSafety(mod);
3910 const layout = self.unionLayout(ty);3911 const layout = self.unionLayout(ty);
39113912
3912 const tag_int = if (layout.tag_size != 0) blk: {3913 const tag_int = if (layout.tag_size != 0) blk: {
3913 const tag_ty = maybe_tag_ty.?;3914 const tag_val = try mod.enumValueFieldIndex(tag_ty, active_field);
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);
3917 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);3915 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);
3918 break :blk tag_int_val.toUnsignedInt(mod);3916 break :blk tag_int_val.toUnsignedInt(mod);
3919 } else 0;3917 } else 0;
39203918
3921 if (!layout.has_payload) {3919 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);
3923 return try self.constInt(tag_ty_ref, tag_int);3921 return try self.constInt(tag_ty_ref, tag_int);
3924 }3922 }
39253923
3926 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });3924 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });
39273925
3928 if (layout.tag_size != 0) {3926 if (layout.tag_size != 0) {
3929 const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct);3927 const tag_ty_ref = try self.resolveType(tag_ty, .direct);
3930 const tag_ptr_ty_ref = try self.ptrType(maybe_tag_ty.?, .Function);3928 const tag_ptr_ty_ref = try self.ptrType(tag_ty, .Function);
3931 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});3929 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
3932 const tag_id = try self.constInt(tag_ty_ref, tag_int);3930 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, .{});
3934 }3932 }
39353933
3936 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);3934 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 {...@@ -311,7 +311,8 @@ pub const DeclState = struct {
311 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);311 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
312 }312 }
313 },313 },
314 .struct_type => |struct_type| {314 .struct_type => {
315 const struct_type = ip.loadStructType(ty.toIntern());
315 // DW.AT.name, DW.FORM.string316 // DW.AT.name, DW.FORM.string
316 try ty.print(dbg_info_buffer.writer(), mod);317 try ty.print(dbg_info_buffer.writer(), mod);
317 try dbg_info_buffer.append(0);318 try dbg_info_buffer.append(0);
...@@ -374,7 +375,7 @@ pub const DeclState = struct {...@@ -374,7 +375,7 @@ pub const DeclState = struct {
374 try ty.print(dbg_info_buffer.writer(), mod);375 try ty.print(dbg_info_buffer.writer(), mod);
375 try dbg_info_buffer.append(0);376 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);
378 for (enum_type.names.get(ip), 0..) |field_name_index, field_i| {379 for (enum_type.names.get(ip), 0..) |field_name_index, field_i| {
379 const field_name = ip.stringToSlice(field_name_index);380 const field_name = ip.stringToSlice(field_name_index);
380 // DW.AT.enumerator381 // DW.AT.enumerator
...@@ -442,7 +443,7 @@ pub const DeclState = struct {...@@ -442,7 +443,7 @@ pub const DeclState = struct {
442 try dbg_info_buffer.append(0);443 try dbg_info_buffer.append(0);
443 }444 }
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| {
446 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;447 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
447 // DW.AT.member448 // DW.AT.member
448 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member));449 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member));
src/type.zig+178-156
...@@ -320,11 +320,12 @@ pub const Type = struct {...@@ -320,11 +320,12 @@ pub const Type = struct {
320320
321 .generic_poison => unreachable,321 .generic_poison => unreachable,
322 },322 },
323 .struct_type => |struct_type| {323 .struct_type => {
324 const struct_type = ip.loadStructType(ty.toIntern());
324 if (struct_type.decl.unwrap()) |decl_index| {325 if (struct_type.decl.unwrap()) |decl_index| {
325 const decl = mod.declPtr(decl_index);326 const decl = mod.declPtr(decl_index);
326 try decl.renderFullyQualifiedName(mod, writer);327 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| {
328 const namespace = mod.namespacePtr(namespace_index);329 const namespace = mod.namespacePtr(namespace_index);
329 try namespace.renderFullyQualifiedName(mod, .empty, writer);330 try namespace.renderFullyQualifiedName(mod, .empty, writer);
330 } else {331 } else {
...@@ -573,7 +574,8 @@ pub const Type = struct {...@@ -573,7 +574,8 @@ pub const Type = struct {
573574
574 .generic_poison => unreachable,575 .generic_poison => unreachable,
575 },576 },
576 .struct_type => |struct_type| {577 .struct_type => {
578 const struct_type = ip.loadStructType(ty.toIntern());
577 if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {579 if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {
578 // In this case, we guess that hasRuntimeBits() for this type is true,580 // In this case, we guess that hasRuntimeBits() for this type is true,
579 // and then later if our guess was incorrect, we emit a compile error.581 // and then later if our guess was incorrect, we emit a compile error.
...@@ -601,7 +603,8 @@ pub const Type = struct {...@@ -601,7 +603,8 @@ pub const Type = struct {
601 return false;603 return false;
602 },604 },
603605
604 .union_type => |union_type| {606 .union_type => {
607 const union_type = ip.loadUnionType(ty.toIntern());
605 switch (union_type.flagsPtr(ip).runtime_tag) {608 switch (union_type.flagsPtr(ip).runtime_tag) {
606 .none => {609 .none => {
607 if (union_type.flagsPtr(ip).status == .field_types_wip) {610 if (union_type.flagsPtr(ip).status == .field_types_wip) {
...@@ -628,9 +631,8 @@ pub const Type = struct {...@@ -628,9 +631,8 @@ pub const Type = struct {
628 .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes())631 .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes())
629 return error.NeedLazy,632 return error.NeedLazy,
630 }633 }
631 const union_obj = ip.loadUnionType(union_type);634 for (0..union_type.field_types.len) |field_index| {
632 for (0..union_obj.field_types.len) |field_index| {635 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
633 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
634 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))636 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
635 return true;637 return true;
636 } else {638 } else {
...@@ -639,7 +641,7 @@ pub const Type = struct {...@@ -639,7 +641,7 @@ pub const Type = struct {
639 },641 },
640642
641 .opaque_type => true,643 .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
644 // values, not types646 // values, not types
645 .undef,647 .undef,
...@@ -736,15 +738,19 @@ pub const Type = struct {...@@ -736,15 +738,19 @@ pub const Type = struct {
736 .generic_poison,738 .generic_poison,
737 => false,739 => false,
738 },740 },
739 .struct_type => |struct_type| {741 .struct_type => {
742 const struct_type = ip.loadStructType(ty.toIntern());
740 // Struct with no fields have a well-defined layout of no bits.743 // Struct with no fields have a well-defined layout of no bits.
741 return struct_type.layout != .Auto or struct_type.field_types.len == 0;744 return struct_type.layout != .Auto or struct_type.field_types.len == 0;
742 },745 },
743 .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) {746 .union_type => {
744 .none, .safety => union_type.flagsPtr(ip).layout != .Auto,747 const union_type = ip.loadUnionType(ty.toIntern());
745 .tagged => false,748 return switch (union_type.flagsPtr(ip).runtime_tag) {
749 .none, .safety => union_type.flagsPtr(ip).layout != .Auto,
750 .tagged => false,
751 };
746 },752 },
747 .enum_type => |enum_type| switch (enum_type.tag_mode) {753 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
748 .auto => false,754 .auto => false,
749 .explicit, .nonexhaustive => true,755 .explicit, .nonexhaustive => true,
750 },756 },
...@@ -1019,7 +1025,8 @@ pub const Type = struct {...@@ -1019,7 +1025,8 @@ pub const Type = struct {
1019 .noreturn => unreachable,1025 .noreturn => unreachable,
1020 .generic_poison => unreachable,1026 .generic_poison => unreachable,
1021 },1027 },
1022 .struct_type => |struct_type| {1028 .struct_type => {
1029 const struct_type = ip.loadStructType(ty.toIntern());
1023 if (struct_type.layout == .Packed) {1030 if (struct_type.layout == .Packed) {
1024 switch (strat) {1031 switch (strat) {
1025 .sema => |sema| try sema.resolveTypeLayout(ty),1032 .sema => |sema| try sema.resolveTypeLayout(ty),
...@@ -1066,7 +1073,8 @@ pub const Type = struct {...@@ -1066,7 +1073,8 @@ pub const Type = struct {
1066 }1073 }
1067 return .{ .scalar = big_align };1074 return .{ .scalar = big_align };
1068 },1075 },
1069 .union_type => |union_type| {1076 .union_type => {
1077 const union_type = ip.loadUnionType(ty.toIntern());
1070 const flags = union_type.flagsPtr(ip).*;1078 const flags = union_type.flagsPtr(ip).*;
1071 if (flags.alignment != .none) return .{ .scalar = flags.alignment };1079 if (flags.alignment != .none) return .{ .scalar = flags.alignment };
10721080
...@@ -1082,8 +1090,8 @@ pub const Type = struct {...@@ -1082,8 +1090,8 @@ pub const Type = struct {
1082 return .{ .scalar = union_type.flagsPtr(ip).alignment };1090 return .{ .scalar = union_type.flagsPtr(ip).alignment };
1083 },1091 },
1084 .opaque_type => return .{ .scalar = .@"1" },1092 .opaque_type => return .{ .scalar = .@"1" },
1085 .enum_type => |enum_type| return .{1093 .enum_type => return .{
1086 .scalar = Type.fromInterned(enum_type.tag_ty).abiAlignment(mod),1094 .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(mod),
1087 },1095 },
10881096
1089 // values, not types1097 // values, not types
...@@ -1394,7 +1402,8 @@ pub const Type = struct {...@@ -1394,7 +1402,8 @@ pub const Type = struct {
1394 .noreturn => unreachable,1402 .noreturn => unreachable,
1395 .generic_poison => unreachable,1403 .generic_poison => unreachable,
1396 },1404 },
1397 .struct_type => |struct_type| {1405 .struct_type => {
1406 const struct_type = ip.loadStructType(ty.toIntern());
1398 switch (strat) {1407 switch (strat) {
1399 .sema => |sema| try sema.resolveTypeLayout(ty),1408 .sema => |sema| try sema.resolveTypeLayout(ty),
1400 .lazy => switch (struct_type.layout) {1409 .lazy => switch (struct_type.layout) {
...@@ -1439,7 +1448,8 @@ pub const Type = struct {...@@ -1439,7 +1448,8 @@ pub const Type = struct {
1439 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };1448 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
1440 },1449 },
14411450
1442 .union_type => |union_type| {1451 .union_type => {
1452 const union_type = ip.loadUnionType(ty.toIntern());
1443 switch (strat) {1453 switch (strat) {
1444 .sema => |sema| try sema.resolveTypeLayout(ty),1454 .sema => |sema| try sema.resolveTypeLayout(ty),
1445 .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{1455 .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{
...@@ -1455,7 +1465,7 @@ pub const Type = struct {...@@ -1455,7 +1465,7 @@ pub const Type = struct {
1455 return .{ .scalar = union_type.size(ip).* };1465 return .{ .scalar = union_type.size(ip).* };
1456 },1466 },
1457 .opaque_type => unreachable, // no size available1467 .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
1460 // values, not types1470 // values, not types
1461 .undef,1471 .undef,
...@@ -1644,7 +1654,8 @@ pub const Type = struct {...@@ -1644,7 +1654,8 @@ pub const Type = struct {
1644 .extern_options => unreachable,1654 .extern_options => unreachable,
1645 .type_info => unreachable,1655 .type_info => unreachable,
1646 },1656 },
1647 .struct_type => |struct_type| {1657 .struct_type => {
1658 const struct_type = ip.loadStructType(ty.toIntern());
1648 const is_packed = struct_type.layout == .Packed;1659 const is_packed = struct_type.layout == .Packed;
1649 if (opt_sema) |sema| {1660 if (opt_sema) |sema| {
1650 try sema.resolveTypeFields(ty);1661 try sema.resolveTypeFields(ty);
...@@ -1661,7 +1672,8 @@ pub const Type = struct {...@@ -1661,7 +1672,8 @@ pub const Type = struct {
1661 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;1672 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
1662 },1673 },
16631674
1664 .union_type => |union_type| {1675 .union_type => {
1676 const union_type = ip.loadUnionType(ty.toIntern());
1665 const is_packed = ty.containerLayout(mod) == .Packed;1677 const is_packed = ty.containerLayout(mod) == .Packed;
1666 if (opt_sema) |sema| {1678 if (opt_sema) |sema| {
1667 try sema.resolveTypeFields(ty);1679 try sema.resolveTypeFields(ty);
...@@ -1670,19 +1682,18 @@ pub const Type = struct {...@@ -1670,19 +1682,18 @@ pub const Type = struct {
1670 if (!is_packed) {1682 if (!is_packed) {
1671 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;1683 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
1672 }1684 }
1673 const union_obj = ip.loadUnionType(union_type);1685 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
1674 assert(union_obj.flagsPtr(ip).status.haveFieldTypes());
16751686
1676 var size: u64 = 0;1687 var size: u64 = 0;
1677 for (0..union_obj.field_types.len) |field_index| {1688 for (0..union_type.field_types.len) |field_index| {
1678 const field_ty = union_obj.field_types.get(ip)[field_index];1689 const field_ty = union_type.field_types.get(ip)[field_index];
1679 size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema));1690 size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema));
1680 }1691 }
16811692
1682 return size;1693 return size;
1683 },1694 },
1684 .opaque_type => unreachable,1695 .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
1687 // values, not types1698 // values, not types
1688 .undef,1699 .undef,
...@@ -1713,8 +1724,8 @@ pub const Type = struct {...@@ -1713,8 +1724,8 @@ pub const Type = struct {
1713 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {1724 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
1714 const ip = &mod.intern_pool;1725 const ip = &mod.intern_pool;
1715 return switch (ip.indexToKey(ty.toIntern())) {1726 return switch (ip.indexToKey(ty.toIntern())) {
1716 .struct_type => |struct_type| struct_type.haveLayout(ip),1727 .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip),
1717 .union_type => |union_type| union_type.haveLayout(ip),1728 .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip),
1718 .array_type => |array_type| {1729 .array_type => |array_type| {
1719 if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true;1730 if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true;
1720 return Type.fromInterned(array_type.child).layoutIsResolved(mod);1731 return Type.fromInterned(array_type.child).layoutIsResolved(mod);
...@@ -1914,16 +1925,18 @@ pub const Type = struct {...@@ -1914,16 +1925,18 @@ pub const Type = struct {
1914 /// Otherwise, returns `null`.1925 /// Otherwise, returns `null`.
1915 pub fn unionTagType(ty: Type, mod: *Module) ?Type {1926 pub fn unionTagType(ty: Type, mod: *Module) ?Type {
1916 const ip = &mod.intern_pool;1927 const ip = &mod.intern_pool;
1917 return switch (ip.indexToKey(ty.toIntern())) {1928 switch (ip.indexToKey(ty.toIntern())) {
1918 .union_type => |union_type| switch (union_type.flagsPtr(ip).runtime_tag) {1929 .union_type => {},
1919 .tagged => {1930 else => return null,
1920 assert(union_type.flagsPtr(ip).status.haveFieldTypes());1931 }
1921 return Type.fromInterned(union_type.enum_tag_ty);1932 const union_type = ip.loadUnionType(ty.toIntern());
1922 },1933 switch (union_type.flagsPtr(ip).runtime_tag) {
1923 else => null,1934 .tagged => {
1935 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
1936 return Type.fromInterned(union_type.enum_tag_ty);
1924 },1937 },
1925 else => null,1938 else => return null,
1926 };1939 }
1927 }1940 }
19281941
1929 /// Same as `unionTagType` but includes safety tag.1942 /// Same as `unionTagType` but includes safety tag.
...@@ -1931,7 +1944,8 @@ pub const Type = struct {...@@ -1931,7 +1944,8 @@ pub const Type = struct {
1931 pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {1944 pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
1932 const ip = &mod.intern_pool;1945 const ip = &mod.intern_pool;
1933 return switch (ip.indexToKey(ty.toIntern())) {1946 return switch (ip.indexToKey(ty.toIntern())) {
1934 .union_type => |union_type| {1947 .union_type => {
1948 const union_type = ip.loadUnionType(ty.toIntern());
1935 if (!union_type.hasTag(ip)) return null;1949 if (!union_type.hasTag(ip)) return null;
1936 assert(union_type.haveFieldTypes(ip));1950 assert(union_type.haveFieldTypes(ip));
1937 return Type.fromInterned(union_type.enum_tag_ty);1951 return Type.fromInterned(union_type.enum_tag_ty);
...@@ -1981,17 +1995,16 @@ pub const Type = struct {...@@ -1981,17 +1995,16 @@ pub const Type = struct {
19811995
1982 pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout {1996 pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout {
1983 const ip = &mod.intern_pool;1997 const ip = &mod.intern_pool;
1984 const union_type = ip.indexToKey(ty.toIntern()).union_type;1998 const union_obj = ip.loadUnionType(ty.toIntern());
1985 const union_obj = ip.loadUnionType(union_type);
1986 return mod.getUnionLayout(union_obj);1999 return mod.getUnionLayout(union_obj);
1987 }2000 }
19882001
1989 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {2002 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
1990 const ip = &mod.intern_pool;2003 const ip = &mod.intern_pool;
1991 return switch (ip.indexToKey(ty.toIntern())) {2004 return switch (ip.indexToKey(ty.toIntern())) {
1992 .struct_type => |struct_type| struct_type.layout,2005 .struct_type => ip.loadStructType(ty.toIntern()).layout,
1993 .anon_struct_type => .Auto,2006 .anon_struct_type => .Auto,
1994 .union_type => |union_type| union_type.flagsPtr(ip).layout,2007 .union_type => ip.loadUnionType(ty.toIntern()).flagsPtr(ip).layout,
1995 else => unreachable,2008 else => unreachable,
1996 };2009 };
1997 }2010 }
...@@ -2095,22 +2108,15 @@ pub const Type = struct {...@@ -2095,22 +2108,15 @@ pub const Type = struct {
20952108
2096 /// Asserts the type is an array or vector or struct.2109 /// Asserts the type is an array or vector or struct.
2097 pub fn arrayLen(ty: Type, mod: *const Module) u64 {2110 pub fn arrayLen(ty: Type, mod: *const Module) u64 {
2098 return arrayLenIp(ty, &mod.intern_pool);2111 return ty.arrayLenIp(&mod.intern_pool);
2099 }2112 }
21002113
2101 pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {2114 pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
2102 return switch (ip.indexToKey(ty.toIntern())) {2115 return ip.aggregateTypeLen(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 };
2110 }2116 }
21112117
2112 pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {2118 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());
2114 }2120 }
21152121
2116 pub fn vectorLen(ty: Type, mod: *const Module) u32 {2122 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
...@@ -2199,8 +2205,8 @@ pub const Type = struct {...@@ -2199,8 +2205,8 @@ pub const Type = struct {
2199 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },2205 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
2200 else => switch (ip.indexToKey(ty.toIntern())) {2206 else => switch (ip.indexToKey(ty.toIntern())) {
2201 .int_type => |int_type| return int_type,2207 .int_type => |int_type| return int_type,
2202 .struct_type => |t| ty = Type.fromInterned(t.backingIntType(ip).*),2208 .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntType(ip).*),
2203 .enum_type => |enum_type| ty = Type.fromInterned(enum_type.tag_ty),2209 .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
2204 .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),2210 .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),
22052211
2206 .error_set_type, .inferred_error_set_type => {2212 .error_set_type, .inferred_error_set_type => {
...@@ -2463,7 +2469,8 @@ pub const Type = struct {...@@ -2463,7 +2469,8 @@ pub const Type = struct {
24632469
2464 .generic_poison => unreachable,2470 .generic_poison => unreachable,
2465 },2471 },
2466 .struct_type => |struct_type| {2472 .struct_type => {
2473 const struct_type = ip.loadStructType(ty.toIntern());
2467 assert(struct_type.haveFieldTypes(ip));2474 assert(struct_type.haveFieldTypes(ip));
2468 if (struct_type.knownNonOpv(ip))2475 if (struct_type.knownNonOpv(ip))
2469 return null;2476 return null;
...@@ -2505,11 +2512,11 @@ pub const Type = struct {...@@ -2505,11 +2512,11 @@ pub const Type = struct {
2505 } })));2512 } })));
2506 },2513 },
25072514
2508 .union_type => |union_type| {2515 .union_type => {
2509 const union_obj = ip.loadUnionType(union_type);2516 const union_obj = ip.loadUnionType(ty.toIntern());
2510 const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse2517 const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse
2511 return null;2518 return null;
2512 if (union_obj.field_names.len == 0) {2519 if (union_obj.field_types.len == 0) {
2513 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });2520 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2514 return Value.fromInterned(only);2521 return Value.fromInterned(only);
2515 }2522 }
...@@ -2524,45 +2531,48 @@ pub const Type = struct {...@@ -2524,45 +2531,48 @@ pub const Type = struct {
2524 return Value.fromInterned(only);2531 return Value.fromInterned(only);
2525 },2532 },
2526 .opaque_type => return null,2533 .opaque_type => return null,
2527 .enum_type => |enum_type| switch (enum_type.tag_mode) {2534 .enum_type => {
2528 .nonexhaustive => {2535 const enum_type = ip.loadEnumType(ty.toIntern());
2529 if (enum_type.tag_ty == .comptime_int_type) return null;2536 switch (enum_type.tag_mode) {
25302537 .nonexhaustive => {
2531 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {2538 if (enum_type.tag_ty == .comptime_int_type) return null;
2532 const only = try mod.intern(.{ .enum_tag = .{2539
2533 .ty = ty.toIntern(),2540 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
2534 .int = int_opv.toIntern(),2541 const only = try mod.intern(.{ .enum_tag = .{
2535 } });2542 .ty = ty.toIntern(),
2536 return Value.fromInterned(only);2543 .int = int_opv.toIntern(),
2537 }2544 } });
2545 return Value.fromInterned(only);
2546 }
25382547
2539 return null;2548 return null;
2540 },2549 },
2541 .auto, .explicit => {2550 .auto, .explicit => {
2542 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;2551 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
25432552
2544 switch (enum_type.names.len) {2553 switch (enum_type.names.len) {
2545 0 => {2554 0 => {
2546 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });2555 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 } });
2558 return Value.fromInterned(only);2556 return Value.fromInterned(only);
2559 } else {2557 },
2560 return Value.fromInterned(enum_type.values.get(ip)[0]);2558 1 => {
2561 }2559 if (enum_type.values.len == 0) {
2562 },2560 const only = try mod.intern(.{ .enum_tag = .{
2563 else => return null,2561 .ty = ty.toIntern(),
2564 }2562 .int = try mod.intern(.{ .int = .{
2565 },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 }
2566 },2576 },
25672577
2568 // values, not types2578 // values, not types
...@@ -2676,7 +2686,8 @@ pub const Type = struct {...@@ -2676,7 +2686,8 @@ pub const Type = struct {
2676 .type_info,2686 .type_info,
2677 => true,2687 => true,
2678 },2688 },
2679 .struct_type => |struct_type| {2689 .struct_type => {
2690 const struct_type = ip.loadStructType(ty.toIntern());
2680 // packed structs cannot be comptime-only because they have a well-defined2691 // packed structs cannot be comptime-only because they have a well-defined
2681 // memory layout and every field has a well-defined bit pattern.2692 // memory layout and every field has a well-defined bit pattern.
2682 if (struct_type.layout == .Packed)2693 if (struct_type.layout == .Packed)
...@@ -2726,38 +2737,40 @@ pub const Type = struct {...@@ -2726,38 +2737,40 @@ pub const Type = struct {
2726 return false;2737 return false;
2727 },2738 },
27282739
2729 .union_type => |union_type| switch (union_type.flagsPtr(ip).requires_comptime) {2740 .union_type => {
2730 .no, .wip => false,2741 const union_type = ip.loadUnionType(ty.toIntern());
2731 .yes => true,2742 switch (union_type.flagsPtr(ip).requires_comptime) {
2732 .unknown => {2743 .no, .wip => return false,
2733 // The type is not resolved; assert that we have a Sema.2744 .yes => return true,
2734 const sema = opt_sema.?;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)2749 if (union_type.flagsPtr(ip).status == .field_types_wip)
2737 return false;2750 return false;
27382751
2739 union_type.flagsPtr(ip).requires_comptime = .wip;2752 union_type.flagsPtr(ip).requires_comptime = .wip;
2740 errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;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);2757 for (0..union_type.field_types.len) |field_idx| {
2745 for (0..union_obj.field_types.len) |field_idx| {2758 const field_ty = union_type.field_types.get(ip)[field_idx];
2746 const field_ty = union_obj.field_types.get(ip)[field_idx];2759 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
2747 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {2760 union_type.flagsPtr(ip).requires_comptime = .yes;
2748 union_obj.flagsPtr(ip).requires_comptime = .yes;2761 return true;
2749 return true;2762 }
2750 }2763 }
2751 }
27522764
2753 union_obj.flagsPtr(ip).requires_comptime = .no;2765 union_type.flagsPtr(ip).requires_comptime = .no;
2754 return false;2766 return false;
2755 },2767 },
2768 }
2756 },2769 },
27572770
2758 .opaque_type => false,2771 .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
2762 // values, not types2775 // values, not types
2763 .undef,2776 .undef,
...@@ -2830,11 +2843,12 @@ pub const Type = struct {...@@ -2830,11 +2843,12 @@ pub const Type = struct {
28302843
2831 /// Returns null if the type has no namespace.2844 /// Returns null if the type has no namespace.
2832 pub fn getNamespaceIndex(ty: Type, mod: *Module) InternPool.OptionalNamespaceIndex {2845 pub fn getNamespaceIndex(ty: Type, mod: *Module) InternPool.OptionalNamespaceIndex {
2833 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {2846 const ip = &mod.intern_pool;
2834 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),2847 return switch (ip.indexToKey(ty.toIntern())) {
2835 .struct_type => |struct_type| struct_type.namespace,2848 .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace.toOptional(),
2836 .union_type => |union_type| union_type.namespace.toOptional(),2849 .struct_type => ip.loadStructType(ty.toIntern()).namespace,
2837 .enum_type => |enum_type| enum_type.namespace,2850 .union_type => ip.loadUnionType(ty.toIntern()).namespace.toOptional(),
2851 .enum_type => ip.loadEnumType(ty.toIntern()).namespace,
28382852
2839 else => .none,2853 else => .none,
2840 };2854 };
...@@ -2920,16 +2934,18 @@ pub const Type = struct {...@@ -2920,16 +2934,18 @@ pub const Type = struct {
29202934
2921 /// Asserts the type is an enum or a union.2935 /// Asserts the type is an enum or a union.
2922 pub fn intTagType(ty: Type, mod: *Module) Type {2936 pub fn intTagType(ty: Type, mod: *Module) Type {
2923 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {2937 const ip = &mod.intern_pool;
2924 .union_type => |union_type| Type.fromInterned(union_type.enum_tag_ty).intTagType(mod),2938 return switch (ip.indexToKey(ty.toIntern())) {
2925 .enum_type => |enum_type| Type.fromInterned(enum_type.tag_ty),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),
2926 else => unreachable,2941 else => unreachable,
2927 };2942 };
2928 }2943 }
29292944
2930 pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {2945 pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
2931 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {2946 const ip = &mod.intern_pool;
2932 .enum_type => |enum_type| switch (enum_type.tag_mode) {2947 return switch (ip.indexToKey(ty.toIntern())) {
2948 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
2933 .nonexhaustive => true,2949 .nonexhaustive => true,
2934 .auto, .explicit => false,2950 .auto, .explicit => false,
2935 },2951 },
...@@ -2953,21 +2969,21 @@ pub const Type = struct {...@@ -2953,21 +2969,21 @@ pub const Type = struct {
2953 }2969 }
29542970
2955 pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {2971 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;
2957 }2973 }
29582974
2959 pub fn enumFieldCount(ty: Type, mod: *Module) usize {2975 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;
2961 }2977 }
29622978
2963 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {2979 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
2964 const ip = &mod.intern_pool;2980 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];
2966 }2982 }
29672983
2968 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {2984 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
2969 const ip = &mod.intern_pool;2985 const ip = &mod.intern_pool;
2970 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;2986 const enum_type = ip.loadEnumType(ty.toIntern());
2971 return enum_type.nameIndex(ip, field_name);2987 return enum_type.nameIndex(ip, field_name);
2972 }2988 }
29732989
...@@ -2976,7 +2992,7 @@ pub const Type = struct {...@@ -2976,7 +2992,7 @@ pub const Type = struct {
2976 /// declaration order, or `null` if `enum_tag` does not match any field.2992 /// declaration order, or `null` if `enum_tag` does not match any field.
2977 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {2993 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
2978 const ip = &mod.intern_pool;2994 const ip = &mod.intern_pool;
2979 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;2995 const enum_type = ip.loadEnumType(ty.toIntern());
2980 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {2996 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
2981 .int => enum_tag.toIntern(),2997 .int => enum_tag.toIntern(),
2982 .enum_tag => |info| info.int,2998 .enum_tag => |info| info.int,
...@@ -2990,7 +3006,7 @@ pub const Type = struct {...@@ -2990,7 +3006,7 @@ pub const Type = struct {
2990 pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString {3006 pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString {
2991 const ip = &mod.intern_pool;3007 const ip = &mod.intern_pool;
2992 return switch (ip.indexToKey(ty.toIntern())) {3008 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),
2994 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index),3010 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index),
2995 else => unreachable,3011 else => unreachable,
2996 };3012 };
...@@ -3010,7 +3026,7 @@ pub const Type = struct {...@@ -3010,7 +3026,7 @@ pub const Type = struct {
3010 pub fn structFieldCount(ty: Type, mod: *Module) u32 {3026 pub fn structFieldCount(ty: Type, mod: *Module) u32 {
3011 const ip = &mod.intern_pool;3027 const ip = &mod.intern_pool;
3012 return switch (ip.indexToKey(ty.toIntern())) {3028 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,
3014 .anon_struct_type => |anon_struct| anon_struct.types.len,3030 .anon_struct_type => |anon_struct| anon_struct.types.len,
3015 else => unreachable,3031 else => unreachable,
3016 };3032 };
...@@ -3020,9 +3036,9 @@ pub const Type = struct {...@@ -3020,9 +3036,9 @@ pub const Type = struct {
3020 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {3036 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
3021 const ip = &mod.intern_pool;3037 const ip = &mod.intern_pool;
3022 return switch (ip.indexToKey(ty.toIntern())) {3038 return switch (ip.indexToKey(ty.toIntern())) {
3023 .struct_type => |struct_type| Type.fromInterned(struct_type.field_types.get(ip)[index]),3039 .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]),
3024 .union_type => |union_type| {3040 .union_type => {
3025 const union_obj = ip.loadUnionType(union_type);3041 const union_obj = ip.loadUnionType(ty.toIntern());
3026 return Type.fromInterned(union_obj.field_types.get(ip)[index]);3042 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
3027 },3043 },
3028 .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),3044 .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),
...@@ -3033,7 +3049,8 @@ pub const Type = struct {...@@ -3033,7 +3049,8 @@ pub const Type = struct {
3033 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) Alignment {3049 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) Alignment {
3034 const ip = &mod.intern_pool;3050 const ip = &mod.intern_pool;
3035 switch (ip.indexToKey(ty.toIntern())) {3051 switch (ip.indexToKey(ty.toIntern())) {
3036 .struct_type => |struct_type| {3052 .struct_type => {
3053 const struct_type = ip.loadStructType(ty.toIntern());
3037 assert(struct_type.layout != .Packed);3054 assert(struct_type.layout != .Packed);
3038 const explicit_align = struct_type.fieldAlign(ip, index);3055 const explicit_align = struct_type.fieldAlign(ip, index);
3039 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);3056 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
...@@ -3042,8 +3059,8 @@ pub const Type = struct {...@@ -3042,8 +3059,8 @@ pub const Type = struct {
3042 .anon_struct_type => |anon_struct| {3059 .anon_struct_type => |anon_struct| {
3043 return Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignment(mod);3060 return Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignment(mod);
3044 },3061 },
3045 .union_type => |union_type| {3062 .union_type => {
3046 const union_obj = ip.loadUnionType(union_type);3063 const union_obj = ip.loadUnionType(ty.toIntern());
3047 return mod.unionFieldNormalAlignment(union_obj, @intCast(index));3064 return mod.unionFieldNormalAlignment(union_obj, @intCast(index));
3048 },3065 },
3049 else => unreachable,3066 else => unreachable,
...@@ -3053,7 +3070,8 @@ pub const Type = struct {...@@ -3053,7 +3070,8 @@ pub const Type = struct {
3053 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {3070 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
3054 const ip = &mod.intern_pool;3071 const ip = &mod.intern_pool;
3055 switch (ip.indexToKey(ty.toIntern())) {3072 switch (ip.indexToKey(ty.toIntern())) {
3056 .struct_type => |struct_type| {3073 .struct_type => {
3074 const struct_type = ip.loadStructType(ty.toIntern());
3057 const val = struct_type.fieldInit(ip, index);3075 const val = struct_type.fieldInit(ip, index);
3058 // TODO: avoid using `unreachable` to indicate this.3076 // TODO: avoid using `unreachable` to indicate this.
3059 if (val == .none) return Value.@"unreachable";3077 if (val == .none) return Value.@"unreachable";
...@@ -3072,7 +3090,8 @@ pub const Type = struct {...@@ -3072,7 +3090,8 @@ pub const Type = struct {
3072 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {3090 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
3073 const ip = &mod.intern_pool;3091 const ip = &mod.intern_pool;
3074 switch (ip.indexToKey(ty.toIntern())) {3092 switch (ip.indexToKey(ty.toIntern())) {
3075 .struct_type => |struct_type| {3093 .struct_type => {
3094 const struct_type = ip.loadStructType(ty.toIntern());
3076 if (struct_type.fieldIsComptime(ip, index)) {3095 if (struct_type.fieldIsComptime(ip, index)) {
3077 assert(struct_type.haveFieldInits(ip));3096 assert(struct_type.haveFieldInits(ip));
3078 return Value.fromInterned(struct_type.field_inits.get(ip)[index]);3097 return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
...@@ -3095,7 +3114,7 @@ pub const Type = struct {...@@ -3095,7 +3114,7 @@ pub const Type = struct {
3095 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {3114 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
3096 const ip = &mod.intern_pool;3115 const ip = &mod.intern_pool;
3097 return switch (ip.indexToKey(ty.toIntern())) {3116 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),
3099 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,3118 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,
3100 else => unreachable,3119 else => unreachable,
3101 };3120 };
...@@ -3110,7 +3129,8 @@ pub const Type = struct {...@@ -3110,7 +3129,8 @@ pub const Type = struct {
3110 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {3129 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
3111 const ip = &mod.intern_pool;3130 const ip = &mod.intern_pool;
3112 switch (ip.indexToKey(ty.toIntern())) {3131 switch (ip.indexToKey(ty.toIntern())) {
3113 .struct_type => |struct_type| {3132 .struct_type => {
3133 const struct_type = ip.loadStructType(ty.toIntern());
3114 assert(struct_type.haveLayout(ip));3134 assert(struct_type.haveLayout(ip));
3115 assert(struct_type.layout != .Packed);3135 assert(struct_type.layout != .Packed);
3116 return struct_type.offsets.get(ip)[index];3136 return struct_type.offsets.get(ip)[index];
...@@ -3137,11 +3157,11 @@ pub const Type = struct {...@@ -3137,11 +3157,11 @@ pub const Type = struct {
3137 return offset;3157 return offset;
3138 },3158 },
31393159
3140 .union_type => |union_type| {3160 .union_type => {
3161 const union_type = ip.loadUnionType(ty.toIntern());
3141 if (!union_type.hasTag(ip))3162 if (!union_type.hasTag(ip))
3142 return 0;3163 return 0;
3143 const union_obj = ip.loadUnionType(union_type);3164 const layout = mod.getUnionLayout(union_type);
3144 const layout = mod.getUnionLayout(union_obj);
3145 if (layout.tag_align.compare(.gte, layout.payload_align)) {3165 if (layout.tag_align.compare(.gte, layout.payload_align)) {
3146 // {Tag, Payload}3166 // {Tag, Payload}
3147 return layout.payload_align.forward(layout.tag_size);3167 return layout.payload_align.forward(layout.tag_size);
...@@ -3194,7 +3214,8 @@ pub const Type = struct {...@@ -3194,7 +3214,8 @@ pub const Type = struct {
3194 pub fn isTuple(ty: Type, mod: *Module) bool {3214 pub fn isTuple(ty: Type, mod: *Module) bool {
3195 const ip = &mod.intern_pool;3215 const ip = &mod.intern_pool;
3196 return switch (ip.indexToKey(ty.toIntern())) {3216 return switch (ip.indexToKey(ty.toIntern())) {
3197 .struct_type => |struct_type| {3217 .struct_type => {
3218 const struct_type = ip.loadStructType(ty.toIntern());
3198 if (struct_type.layout == .Packed) return false;3219 if (struct_type.layout == .Packed) return false;
3199 if (struct_type.decl == .none) return false;3220 if (struct_type.decl == .none) return false;
3200 return struct_type.flagsPtr(ip).is_tuple;3221 return struct_type.flagsPtr(ip).is_tuple;
...@@ -3215,7 +3236,8 @@ pub const Type = struct {...@@ -3215,7 +3236,8 @@ pub const Type = struct {
3215 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {3236 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3216 const ip = &mod.intern_pool;3237 const ip = &mod.intern_pool;
3217 return switch (ip.indexToKey(ty.toIntern())) {3238 return switch (ip.indexToKey(ty.toIntern())) {
3218 .struct_type => |struct_type| {3239 .struct_type => {
3240 const struct_type = ip.loadStructType(ty.toIntern());
3219 if (struct_type.layout == .Packed) return false;3241 if (struct_type.layout == .Packed) return false;
3220 if (struct_type.decl == .none) return false;3242 if (struct_type.decl == .none) return false;
3221 return struct_type.flagsPtr(ip).is_tuple;3243 return struct_type.flagsPtr(ip).is_tuple;
...@@ -3262,12 +3284,12 @@ pub const Type = struct {...@@ -3262,12 +3284,12 @@ pub const Type = struct {
3262 }3284 }
32633285
3264 pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {3286 pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3265 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {3287 const ip = &zcu.intern_pool;
3266 inline .struct_type,3288 return switch (ip.indexToKey(ty.toIntern())) {
3267 .union_type,3289 .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),
3268 .enum_type,3290 .union_type => ip.loadUnionType(ty.toIntern()).zir_index.unwrap(),
3269 .opaque_type,3291 .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),
3270 => |info| info.zir_index.unwrap(),3292 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index.unwrap(),
3271 else => null,3293 else => null,
3272 };3294 };
3273 }3295 }