| author | |
| committer | |
| log | 975b859377dee450418ae9ed572ec9d3c0b77312 |
| tree | 08a86de7c929deb2a86deb5b587f35bb980ca500 |
| parent | a6ca20b9a1dfc7b6e8d004cb166c0714bb8db2db |
| signature |
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 | }; |
| 646 | 646 | ||
| 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 | }; |
| 1011 | 669 | ||
| 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 | } | ||
| 1073 | 675 | ||
| 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 | } | ||
| 1080 | 681 | ||
| 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 | }; |
| 1092 | 687 | ||
| 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 | }; |
| 1163 | 693 | ||
| 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, |
| 1180 | 710 | ||
| 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 construct | 724 | /// 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 | }; |
| 1199 | 730 | ||
| ... | @@ -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 a | 1642 | // 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 info | 1643 | // minimal hashmap key, this type is a convenience type that contains info |
| 2113 | // needed by semantic analysis. | 1644 | // needed by semantic analysis. |
| 2114 | pub const UnionType = struct { | 1645 | pub 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, | ||
| 2142 | 1663 | ||
| 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 | }; |
| 2195 | 1716 | ||
| 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 | } |
| 2200 | 1733 | ||
| 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 | } |
| 2208 | 1745 | ||
| 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 | } |
| 2212 | 1755 | ||
| 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 | } |
| 2216 | 1759 | ||
| 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 | } |
| 2220 | 1763 | ||
| 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 | } |
| 2224 | 1767 | ||
| 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 | } |
| 2229 | 1772 | ||
| 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 | }; |
| 2239 | 1792 | ||
| 2240 | /// Fetch all the interesting fields of a union type into a convenient data | 1793 | pub 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); |
| 2243 | pub 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); | ||
| 2248 | 1797 | ||
| 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 | } |
| 2270 | 1814 | ||
| 1815 | pub 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 | |||
| 2147 | pub 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 | |||
| 2256 | const 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 | |||
| 2325 | pub 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`. | ||
| 2374 | pub 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 | |||
| 2383 | pub 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 | |||
| 2271 | pub const Item = struct { | 2389 | pub 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, |
| 3126 | 3240 | ||
| 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 | }; |
| 3312 | 3425 | ||
| 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 order | 3427 | /// 0. field type: Index for each field; declaration order |
| 3316 | /// 1. field align: Alignment for each field; declaration order | 3428 | /// 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_layout | 3435 | /// Only valid after .have_layout |
| 3320 | size: u32, | 3436 | size: u32, |
| 3321 | /// Only valid after .have_layout | 3437 | /// 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, |
| 3328 | 3444 | ||
| 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) }, |
| 4075 | 4191 | ||
| 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 | } }, |
| 4107 | 4201 | ||
| 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 | } }, |
| 4113 | 4207 | ||
| 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) }, |
| 4137 | 4215 | ||
| 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 { |
| 4374 | 4451 | ||
| 4375 | // There is only one possible value precisely due to the | 4452 | // 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 | } |
| 4477 | 4546 | ||
| 4478 | fn 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 | |||
| 4490 | fn extraTypeStructAnon(ip: *const InternPool, extra_index: u32) Key.AnonStructType { | 4547 | fn 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 | } |
| 4527 | 4584 | ||
| 4528 | fn 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 | |||
| 4599 | fn 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 | |||
| 4631 | fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType { | 4585 | fn 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 | } |
| 4721 | 4675 | ||
| 4722 | fn 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 | |||
| 4744 | fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key { | 4676 | fn 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() instead | 4832 | .struct_type => unreachable, // use getStructType() instead |
| 4901 | .anon_struct_type => unreachable, // use getAnonStructType() instead | 4833 | .anon_struct_type => unreachable, // use getAnonStructType() instead |
| 4902 | .union_type => unreachable, // use getUnionType() instead | 4834 | .union_type => unreachable, // use getUnionType() instead |
| 4903 | 4835 | .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 | }, | ||
| 4910 | 4836 | ||
| 4911 | .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead | 4837 | .enum_type => unreachable, // use getEnum() or getIncompleteEnum() instead |
| 4912 | .func_type => unreachable, // use getFuncType() instead | 4838 | .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 |
| 5596 | 5522 | ||
| 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 |
| 5628 | 5555 | ||
| 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 | }; |
| 6585 | 6496 | ||
| 6586 | pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index { | 6497 | pub 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 | } |
| 6670 | 6569 | ||
| 6570 | pub 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 | |||
| 6671 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { | 6585 | pub 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, |
| 7076 | 6990 | ||
| 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; // offsets | 7465 | 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 { |
| 7572 | 7486 | ||
| 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 type | 7491 | const per_field = @sizeOf(u32); // field type |
| 7578 | // 1 byte per field for alignment, rounded up to the nearest 4 bytes | 7492 | // 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 { |
| 8217 | 8129 | ||
| 8218 | pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 { | 8130 | pub 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 { |
| 8227 | 8139 | ||
| 8228 | pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { | 8140 | pub 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, |
| 8458 | 8370 | ||
| 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 | } |
| 133 | 133 | ||
| 134 | pub fn analyze(gpa: Allocator, air: Air, intern_pool: *const InternPool) Allocator.Error!Liveness { | 134 | pub 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(); |
| 137 | 137 | ||
| ... | @@ -836,7 +836,7 @@ pub const BigTomb = struct { | ... | @@ -836,7 +836,7 @@ pub const BigTomb = struct { |
| 836 | const Analysis = struct { | 836 | const 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 { |
| 527 | 527 | ||
| 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 |
| 5682 | pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value { | 5683 | pub 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()); |
| 5686 | 5687 | ||
| 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. |
| 5991 | pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType { | 5992 | pub 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 | } |
| 5998 | 6000 | ||
| 5999 | pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType { | 6001 | pub 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 | } |
| 6006 | 6006 | ||
| 6007 | /// This asserts that the union's enum tag type has been resolved. | 6007 | pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.LoadedUnionType { |
| 6008 | pub 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 | }; |
| 6113 | 6112 | ||
| 6114 | pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout { | 6113 | pub 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 | } |
| 6172 | 6171 | ||
| 6173 | pub fn unionAbiSize(mod: *Module, u: InternPool.UnionType) u64 { | 6172 | pub fn unionAbiSize(mod: *Module, u: InternPool.LoadedUnionType) u64 { |
| 6174 | return mod.getUnionLayout(u).abi_size; | 6173 | return mod.getUnionLayout(u).abi_size; |
| 6175 | } | 6174 | } |
| 6176 | 6175 | ||
| 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. |
| 6178 | pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment { | 6177 | pub 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. |
| 6195 | pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_index: u32) Alignment { | 6194 | pub 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 | } |
| 6202 | 6201 | ||
| 6203 | /// Returns the index of the active field, given the current tag value | 6202 | /// Returns the index of the active field, given the current tag value |
| 6204 | pub fn unionTagFieldIndex(mod: *Module, u: InternPool.UnionType, enum_tag: Value) ?u32 { | 6203 | pub 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 | } |
| 6211 | 6209 | ||
| 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. |
| 6254 | pub fn structPackedFieldBitOffset( | 6252 | pub 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); |
| 3373 | 3373 | ||
| 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 compilation | 3379 | // TODO: figure out InternPool removals for incremental compilation |
| 3380 | //errdefer mod.intern_pool.remove(opaque_ty); | 3380 | //errdefer mod.intern_pool.remove(opaque_ty); |
| 3381 | 3381 | ||
| ... | @@ -5371,7 +5371,7 @@ fn failWithBadMemberAccess( | ... | @@ -5371,7 +5371,7 @@ fn failWithBadMemberAccess( |
| 5371 | fn failWithBadStructFieldAccess( | 5371 | fn 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( |
| 5397 | fn failWithBadUnionFieldAccess( | 5397 | fn 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); |
| 17946 | 17946 | ||
| 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 | }; |
| 17958 | 17958 | ||
| 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 | }; |
| 18035 | 18035 | ||
| 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); |
| 18037 | 18037 | ||
| 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 |
| 18049 | 18049 | ||
| 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 |
| 18093 | 18093 | ||
| 18094 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 18094 | 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); |
| 18097 | 18098 | ||
| 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); |
| 18100 | 18101 | ||
| 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 dupe | 18103 | // 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) orelse | 20675 | 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) orelse | 20684 | 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( |
| 21366 | 21369 | ||
| 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); |
| 21453 | 21456 | ||
| 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 compilation | 21462 | // TODO: figure out InternPool removals for incremental compilation |
| 21460 | //errdefer ip.remove(opaque_ty); | 21463 | //errdefer ip.remove(opaque_ty); |
| 21461 | 21464 | ||
| ... | @@ -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(); |
| 21501 | 21504 | ||
| 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 | }; |
| 21506 | 21509 | ||
| ... | @@ -21521,7 +21524,7 @@ fn zirReify( | ... | @@ -21521,7 +21524,7 @@ fn zirReify( |
| 21521 | 21524 | ||
| 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 | } |
| 21543 | 21546 | ||
| 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 | } |
| 21616 | 21619 | ||
| 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 compilation | 21853 | // 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); |
| 21853 | 21856 | ||
| 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 | // Fields | 21860 | // 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); |
| 27628 | 27630 | ||
| 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); |
| 27633 | 27636 | ||
| ... | @@ -27833,7 +27836,7 @@ fn unionFieldPtr( | ... | @@ -27833,7 +27836,7 @@ fn unionFieldPtr( |
| 27833 | 27836 | ||
| 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() and | 27838 | 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( |
| 27911 | 27914 | ||
| 27912 | try sema.requireRuntimeBlock(block, src, null); | 27915 | try sema.requireRuntimeBlock(block, src, null); |
| 27913 | if (union_obj.getLayout(ip) == .Auto and block.wantSafety() and | 27916 | 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); |
| 31672 | 31675 | ||
| 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); |
| 31755 | 31758 | ||
| 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 | else | 31791 | 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 | else | 31797 | 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 | else | 32113 | 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 | else | 32226 | 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 | else | 32230 | 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 | }; |
| 32231 | 32238 | ||
| ... | @@ -32234,12 +32241,12 @@ fn coerceTupleToTuple( | ... | @@ -32234,12 +32241,12 @@ fn coerceTupleToTuple( |
| 32234 | 32241 | ||
| 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 | }; |
| 32245 | 32252 | ||
| ... | @@ -32278,7 +32285,7 @@ fn coerceTupleToTuple( | ... | @@ -32278,7 +32285,7 @@ fn coerceTupleToTuple( |
| 32278 | 32285 | ||
| 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 | }; |
| 32284 | 32291 | ||
| ... | @@ -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 { |
| 35518 | pub fn resolveStructAlignment( | 35525 | pub 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 | } |
| 35660 | 35667 | ||
| 35661 | const RuntimeOrder = InternPool.Key.StructType.RuntimeOrder; | 35668 | const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder; |
| 35662 | 35669 | ||
| 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 | } |
| 35712 | 35719 | ||
| 35713 | fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) CompileError!void { | 35720 | fn 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; |
| 35716 | 35723 | ||
| ... | @@ -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 |
| 35869 | pub fn resolveUnionAlignment( | 35876 | pub 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( |
| 35889 | 35896 | ||
| 35890 | try sema.resolveTypeFieldsUnion(ty, union_type); | 35897 | try sema.resolveTypeFieldsUnion(ty, union_type); |
| 35891 | 35898 | ||
| 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; |
| 35897 | 35903 | ||
| 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_align | 35906 | explicit_align |
| 35901 | else | 35907 | 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; |
| 35915 | 35921 | ||
| 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); | ||
| 35918 | 35923 | ||
| 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 | } |
| 35933 | 35940 | ||
| 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 | }; |
| 35938 | 35945 | ||
| 35939 | union_obj.flagsPtr(ip).status = .layout_wip; | 35946 | union_type.flagsPtr(ip).status = .layout_wip; |
| 35940 | 35947 | ||
| 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; |
| 35946 | 35953 | ||
| 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 | }); |
| 35955 | 35962 | ||
| 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_align | 35965 | explicit_align |
| 35959 | else | 35966 | 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 | } |
| 35964 | 35971 | ||
| 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); |
| 35971 | 35978 | ||
| ... | @@ -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; |
| 36001 | 36008 | ||
| 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 | } |
| 36011 | 36018 | ||
| 36012 | if (union_obj.flagsPtr(ip).assumed_pointer_aligned and | 36019 | 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 { |
| 36202 | 36209 | ||
| 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)), |
| 36209 | 36215 | ||
| 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 |
| 36239 | pub fn resolveTypeFieldsStruct( | 36245 | pub 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 | } |
| 36301 | 36307 | ||
| 36302 | pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key.UnionType) CompileError!void { | 36308 | pub 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 { |
| 36530 | fn semaStructFields( | 36536 | fn 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( |
| 36797 | fn semaStructFieldInits( | 36803 | fn 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 | } |
| 36950 | 36956 | ||
| 36951 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.UnionType) CompileError!void { | 36957 | fn 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(); |
| 36954 | 36960 | ||
| ... | @@ -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 | } |
| 37218 | 37224 | ||
| 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); |
| 37329 | 37335 | ||
| 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 | }, |
| 37735 | 37740 | ||
| 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); | ||
| 37738 | 37744 | ||
| 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 and | 37746 | // 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 | }, |
| 37794 | 37800 | ||
| 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))) orelse | 37804 | 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 | }, |
| 37824 | 37830 | ||
| 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; | ||
| 37828 | 37836 | ||
| 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 | } |
| 37836 | 37844 | ||
| 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; |
| 37841 | 37849 | ||
| 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 | else | 37856 | 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 | }, |
| 37859 | 37868 | ||
| 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 { |
| 38186 | 38195 | ||
| 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`. |
| 38189 | fn unionFieldAlignment(sema: *Sema, u: InternPool.UnionType, field_index: u32) !Alignment { | 38198 | fn 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) orelse | 38246 | 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. |
| 38708 | fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { | 38717 | fn 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( |
| 89 | 89 | ||
| 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(", "); |
| 484 | 484 | ||
| 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 | }; | ||
| 490 | 486 | ||
| 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 { |
| 424 | 424 | ||
| 425 | pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value { | 425 | pub 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 they | 3359 | // 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]; |
| 5415 | 5416 | ||
| 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); |
| 18184 | 18184 | ||
| 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)) orelse | 515 | 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; |
| 520 | 520 | 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); | ||
| 530 | 577 | ||
| 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 | }; | ||
| 569 | 589 | ||
| 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); |
| 575 | 596 | }, | |
| 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; |
| 1479 | 1480 | ||
| 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); | ||
| 1493 | 1491 | ||
| 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 { |
| 1547 | 1545 | ||
| 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 | else | 5501 | 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 | else | 5506 | 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 | else | 5733 | else |
| 5736 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, | 5734 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, |
| 5737 | 5735 | ||
| 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 { |
| 5762 | 5760 | ||
| 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 { |
| 7171 | 7169 | ||
| 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 | }; |
| 1946 | 1946 | ||
| ... | @@ -1967,7 +1967,7 @@ pub const CType = extern union { | ... | @@ -1967,7 +1967,7 @@ pub const CType = extern union { |
| 1967 | else | 1967 | 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 | else | 2120 | 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 | else | 2245 | 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 | } |
| 1999 | 1999 | ||
| 2000 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; | 2000 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 2001 | 2001 | ||
| 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 to | 2512 | // This can happen if a struct type makes it all the way to |
| 2513 | // flush() without ever being instantiated or referenced (even | 2513 | // flush() without ever being instantiated or referenced (even |
| 2514 | // via pointer). The only reason we are hearing about it now is | 2514 | // 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); |
| 2599 | 2599 | ||
| 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 | } |
| 2606 | 2606 | ||
| 2607 | const union_obj = ip.loadUnionType(union_type); | 2607 | const layout = mod.getUnionLayout(union_type); |
| 2608 | const layout = mod.getUnionLayout(union_obj); | ||
| 2609 | 2608 | ||
| 2610 | const debug_fwd_ref = try o.builder.debugForwardReference(); | 2609 | const debug_fwd_ref = try o.builder.debugForwardReference(); |
| 2611 | 2610 | ||
| ... | @@ -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 | ); |
| 2628 | 2627 | ||
| ... | @@ -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); |
| 2638 | 2637 | ||
| 2639 | try fields.ensureUnusedCapacity(gpa, union_obj.field_names.len); | 2638 | try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len); |
| 2640 | 2639 | ||
| 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_ref | 2641 | debug_fwd_ref |
| 2643 | else | 2642 | else |
| 2644 | try o.builder.debugForwardReference(); | 2643 | try o.builder.debugForwardReference(); |
| 2645 | 2644 | ||
| 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; |
| 2649 | 2650 | ||
| 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)); |
| 2652 | 2653 | ||
| 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, // File | 2657 | .none, // File |
| ... | @@ -2706,7 +2707,7 @@ pub const Object = struct { | ... | @@ -2706,7 +2707,7 @@ pub const Object = struct { |
| 2706 | .none, // File | 2707 | .none, // File |
| 2707 | debug_fwd_ref, | 2708 | debug_fwd_ref, |
| 2708 | 0, // Line | 2709 | 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; |
| 3326 | 3327 | ||
| 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; |
| 3473 | 3476 | ||
| 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); |
| 3476 | 3479 | ||
| 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 types | 3564 | // values, not types |
| ... | @@ -4032,7 +4035,8 @@ pub const Object = struct { | ... | @@ -4032,7 +4035,8 @@ pub const Object = struct { |
| 4032 | else | 4035 | 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()); |
| 4600 | 4604 | ||
| 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()); |
| 9624 | 9628 | ||
| 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 { |
| 10092 | 10096 | ||
| 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 | }; |
| 11568 | 11574 |
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 | }; |
| 1534 | 1534 | ||
| ... | @@ -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); | ||
| 3904 | 3906 | ||
| 3905 | if (union_ty.getLayout(ip) == .Packed) { | 3907 | if (union_ty.getLayout(ip) == .Packed) { |
| 3906 | unreachable; // TODO | 3908 | unreachable; // TODO |
| 3907 | } | 3909 | } |
| 3908 | 3910 | ||
| 3909 | const maybe_tag_ty = ty.unionTagTypeSafety(mod); | ||
| 3910 | const layout = self.unionLayout(ty); | 3911 | const layout = self.unionLayout(ty); |
| 3911 | 3912 | ||
| 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; |
| 3920 | 3918 | ||
| 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 | } |
| 3925 | 3923 | ||
| 3926 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); | 3924 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 3927 | 3925 | ||
| 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 | } |
| 3935 | 3933 | ||
| 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.string | 316 | // 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); |
| 376 | 377 | ||
| 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.enumerator | 381 | // 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 | } |
| 444 | 445 | ||
| 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.member | 448 | // 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 { |
| 320 | 320 | ||
| 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 { |
| 573 | 574 | ||
| 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 | }, |
| 603 | 605 | ||
| 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 | }, |
| 640 | 642 | ||
| 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), |
| 643 | 645 | ||
| 644 | // values, not types | 646 | // 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 }; |
| 1072 | 1080 | ||
| ... | @@ -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 | }, |
| 1088 | 1096 | ||
| 1089 | // values, not types | 1097 | // 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 | }, |
| 1441 | 1450 | ||
| 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 available | 1467 | .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) }, |
| 1459 | 1469 | ||
| 1460 | // values, not types | 1470 | // 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 | }, |
| 1663 | 1674 | ||
| 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()); | ||
| 1675 | 1686 | ||
| 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 | } |
| 1681 | 1692 | ||
| 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), |
| 1686 | 1697 | ||
| 1687 | // values, not types | 1698 | // 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 | } |
| 1928 | 1941 | ||
| 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 { |
| 1981 | 1995 | ||
| 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 | } |
| 1988 | 2001 | ||
| 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 { |
| 2095 | 2108 | ||
| 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 | } |
| 2100 | 2113 | ||
| 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 | } |
| 2111 | 2117 | ||
| 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 | } |
| 2115 | 2121 | ||
| 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), |
| 2205 | 2211 | ||
| 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 { |
| 2463 | 2469 | ||
| 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 | }, |
| 2507 | 2514 | ||
| 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)) orelse | 2517 | 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) { |
| 2530 | 2537 | .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 | } | ||
| 2538 | 2547 | ||
| 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; |
| 2543 | 2552 | ||
| 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 | }, |
| 2567 | 2577 | ||
| 2568 | // values, not types | 2578 | // 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-defined | 2691 | // 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 | }, |
| 2728 | 2739 | ||
| 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.?; | ||
| 2735 | 2748 | ||
| 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; |
| 2738 | 2751 | ||
| 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; |
| 2741 | 2754 | ||
| 2742 | try sema.resolveTypeFieldsUnion(ty, union_type); | 2755 | try sema.resolveTypeFieldsUnion(ty, union_type); |
| 2743 | 2756 | ||
| 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 | } | ||
| 2752 | 2764 | ||
| 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 | }, |
| 2757 | 2770 | ||
| 2758 | .opaque_type => false, | 2771 | .opaque_type => false, |
| 2759 | 2772 | ||
| 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), |
| 2761 | 2774 | ||
| 2762 | // values, not types | 2775 | // values, not types |
| 2763 | .undef, | 2776 | .undef, |
| ... | @@ -2830,11 +2843,12 @@ pub const Type = struct { | ... | @@ -2830,11 +2843,12 @@ pub const Type = struct { |
| 2830 | 2843 | ||
| 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, | ||
| 2838 | 2852 | ||
| 2839 | else => .none, | 2853 | else => .none, |
| 2840 | }; | 2854 | }; |
| ... | @@ -2920,16 +2934,18 @@ pub const Type = struct { | ... | @@ -2920,16 +2934,18 @@ pub const Type = struct { |
| 2920 | 2934 | ||
| 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 | } |
| 2929 | 2944 | ||
| 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 | } |
| 2954 | 2970 | ||
| 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 | } |
| 2958 | 2974 | ||
| 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 | } |
| 2962 | 2978 | ||
| 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 | } |
| 2967 | 2983 | ||
| 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 | } |
| 2973 | 2989 | ||
| ... | @@ -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 | }, |
| 3139 | 3159 | ||
| 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 | } |
| 3263 | 3285 | ||
| 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 | } |