| ... | ... | @@ -3,6 +3,9 @@ |
| 3 | 3 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, |
| 4 | 4 | items: std.MultiArrayList(Item) = .{}, |
| 5 | 5 | extra: std.ArrayListUnmanaged(u32) = .{}, |
| 6 | /// On 32-bit systems, this array is ignored and extra is used for everything. |
| 7 | /// On 64-bit systems, this array is used for big integers and associated metadata. |
| 8 | limbs: std.ArrayListUnmanaged(u64) = .{}, |
| 6 | 9 | |
| 7 | 10 | const std = @import("std"); |
| 8 | 11 | const Allocator = std.mem.Allocator; |
| ... | ... | @@ -91,19 +94,43 @@ pub const Key = union(enum) { |
| 91 | 94 | } |
| 92 | 95 | |
| 93 | 96 | pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash) void { |
| 97 | const KeyTag = @typeInfo(Key).Union.tag_type.?; |
| 98 | const key_tag: KeyTag = key; |
| 99 | std.hash.autoHash(hasher, key_tag); |
| 94 | 100 | switch (key) { |
| 95 | | .int_type => |int_type| { |
| 96 | | std.hash.autoHash(hasher, int_type); |
| 101 | inline .int_type, |
| 102 | .ptr_type, |
| 103 | .array_type, |
| 104 | .vector_type, |
| 105 | .optional_type, |
| 106 | .error_union_type, |
| 107 | .simple_type, |
| 108 | .simple_value, |
| 109 | .extern_func, |
| 110 | => |info| std.hash.autoHash(hasher, info), |
| 111 | |
| 112 | .int => |int| { |
| 113 | std.hash.autoHash(hasher, int.ty); |
| 114 | std.hash.autoHash(hasher, int.big_int.positive); |
| 115 | for (int.big_int.limbs) |limb| std.hash.autoHash(hasher, limb); |
| 97 | 116 | }, |
| 98 | | .array_type => |array_type| { |
| 99 | | std.hash.autoHash(hasher, array_type); |
| 117 | |
| 118 | .enum_tag => |enum_tag| { |
| 119 | std.hash.autoHash(hasher, enum_tag.ty); |
| 120 | std.hash.autoHash(hasher, enum_tag.tag.positive); |
| 121 | for (enum_tag.tag.limbs) |limb| std.hash.autoHash(hasher, limb); |
| 122 | }, |
| 123 | |
| 124 | .struct_type => |struct_type| { |
| 125 | if (struct_type.fields_len != 0) { |
| 126 | @panic("TODO"); |
| 127 | } |
| 100 | 128 | }, |
| 101 | | else => @panic("TODO"), |
| 102 | 129 | } |
| 103 | 130 | } |
| 104 | 131 | |
| 105 | 132 | pub fn eql(a: Key, b: Key) bool { |
| 106 | | const KeyTag = std.meta.Tag(Key); |
| 133 | const KeyTag = @typeInfo(Key).Union.tag_type.?; |
| 107 | 134 | const a_tag: KeyTag = a; |
| 108 | 135 | const b_tag: KeyTag = b; |
| 109 | 136 | if (a_tag != b_tag) return false; |
| ... | ... | @@ -112,11 +139,62 @@ pub const Key = union(enum) { |
| 112 | 139 | const b_info = b.int_type; |
| 113 | 140 | return std.meta.eql(a_info, b_info); |
| 114 | 141 | }, |
| 142 | .ptr_type => |a_info| { |
| 143 | const b_info = b.ptr_type; |
| 144 | return std.meta.eql(a_info, b_info); |
| 145 | }, |
| 115 | 146 | .array_type => |a_info| { |
| 116 | 147 | const b_info = b.array_type; |
| 117 | 148 | return std.meta.eql(a_info, b_info); |
| 118 | 149 | }, |
| 119 | | else => @panic("TODO"), |
| 150 | .vector_type => |a_info| { |
| 151 | const b_info = b.vector_type; |
| 152 | return std.meta.eql(a_info, b_info); |
| 153 | }, |
| 154 | .optional_type => |a_info| { |
| 155 | const b_info = b.optional_type; |
| 156 | return std.meta.eql(a_info, b_info); |
| 157 | }, |
| 158 | .error_union_type => |a_info| { |
| 159 | const b_info = b.error_union_type; |
| 160 | return std.meta.eql(a_info, b_info); |
| 161 | }, |
| 162 | .simple_type => |a_info| { |
| 163 | const b_info = b.simple_type; |
| 164 | return a_info == b_info; |
| 165 | }, |
| 166 | .simple_value => |a_info| { |
| 167 | const b_info = b.simple_value; |
| 168 | return a_info == b_info; |
| 169 | }, |
| 170 | .extern_func => |a_info| { |
| 171 | const b_info = b.extern_func; |
| 172 | return std.meta.eql(a_info, b_info); |
| 173 | }, |
| 174 | |
| 175 | .int => |a_info| { |
| 176 | const b_info = b.int; |
| 177 | _ = a_info; |
| 178 | _ = b_info; |
| 179 | @panic("TODO"); |
| 180 | }, |
| 181 | |
| 182 | .enum_tag => |a_info| { |
| 183 | const b_info = b.enum_tag; |
| 184 | _ = a_info; |
| 185 | _ = b_info; |
| 186 | @panic("TODO"); |
| 187 | }, |
| 188 | |
| 189 | .struct_type => |a_info| { |
| 190 | const b_info = b.struct_type; |
| 191 | |
| 192 | // TODO: remove this special case for empty_struct |
| 193 | if (a_info.fields_len == 0 and b_info.fields_len == 0) |
| 194 | return true; |
| 195 | |
| 196 | @panic("TODO"); |
| 197 | }, |
| 120 | 198 | } |
| 121 | 199 | } |
| 122 | 200 | |
| ... | ... | @@ -491,27 +569,65 @@ pub const Tag = enum(u8) { |
| 491 | 569 | /// An integer type. |
| 492 | 570 | /// data is number of bits |
| 493 | 571 | type_int_unsigned, |
| 494 | | /// An array type. |
| 495 | | /// data is payload to Array. |
| 572 | /// An array type that has no sentinel and whose length fits in 32 bits. |
| 573 | /// data is payload to Vector. |
| 496 | 574 | type_array, |
| 575 | /// A vector type. |
| 576 | /// data is payload to Vector. |
| 577 | type_vector, |
| 578 | /// A pointer type along with all its bells and whistles. |
| 579 | /// data is payload to Pointer. |
| 580 | type_pointer, |
| 581 | /// An optional type. |
| 582 | /// data is the child type. |
| 583 | type_optional, |
| 584 | /// An error union type. |
| 585 | /// data is payload to ErrorUnion. |
| 586 | type_error_union, |
| 587 | /// Represents the data that an enum declaration provides, when the fields |
| 588 | /// are auto-numbered, and there are no declarations. |
| 589 | /// data is payload index to `EnumSimple`. |
| 590 | type_enum_simple, |
| 591 | |
| 497 | 592 | /// A type that can be represented with only an enum tag. |
| 498 | 593 | /// data is SimpleType enum value. |
| 499 | 594 | simple_type, |
| 500 | 595 | /// A value that can be represented with only an enum tag. |
| 501 | 596 | /// data is SimpleValue enum value. |
| 502 | 597 | simple_value, |
| 503 | | /// An unsigned integer value that can be represented by u32. |
| 598 | /// The SimpleType and SimpleValue enums are exposed via the InternPool API using |
| 599 | /// SimpleType and SimpleValue as the Key data themselves. |
| 600 | /// This tag is for miscellaneous types and values that can be represented with |
| 601 | /// only an enum tag, but will be presented via the API with a different Key. |
| 602 | /// data is SimpleInternal enum value. |
| 603 | simple_internal, |
| 604 | /// Type: u32 |
| 504 | 605 | /// data is integer value |
| 505 | | int_u32, |
| 506 | | /// An unsigned integer value that can be represented by i32. |
| 606 | int_small_u32, |
| 607 | /// Type: i32 |
| 507 | 608 | /// data is integer value bitcasted to u32. |
| 508 | | int_i32, |
| 509 | | /// A positive integer value that does not fit in 32 bits. |
| 510 | | /// data is a extra index to BigInt. |
| 511 | | int_big_positive, |
| 512 | | /// A negative integer value that does not fit in 32 bits. |
| 513 | | /// data is a extra index to BigInt. |
| 514 | | int_big_negative, |
| 609 | int_small_i32, |
| 610 | /// A usize that fits in 32 bits. |
| 611 | /// data is integer value. |
| 612 | int_small_usize, |
| 613 | /// A comptime_int that fits in a u32. |
| 614 | /// data is integer value. |
| 615 | int_small_comptime_unsigned, |
| 616 | /// A comptime_int that fits in an i32. |
| 617 | /// data is integer value bitcasted to u32. |
| 618 | int_small_comptime_signed, |
| 619 | /// A positive integer value. |
| 620 | /// data is a limbs index to Int. |
| 621 | int_positive, |
| 622 | /// A negative integer value. |
| 623 | /// data is a limbs index to Int. |
| 624 | int_negative, |
| 625 | /// An enum tag identified by a positive integer value. |
| 626 | /// data is a limbs index to Int. |
| 627 | enum_tag_positive, |
| 628 | /// An enum tag identified by a negative integer value. |
| 629 | /// data is a limbs index to Int. |
| 630 | enum_tag_negative, |
| 515 | 631 | /// A float value that can be represented by f32. |
| 516 | 632 | /// data is float value bitcasted to u32. |
| 517 | 633 | float_f32, |
| ... | ... | @@ -525,10 +641,6 @@ pub const Tag = enum(u8) { |
| 525 | 641 | extern_func, |
| 526 | 642 | /// A regular function. |
| 527 | 643 | func, |
| 528 | | /// Represents the data that an enum declaration provides, when the fields |
| 529 | | /// are auto-numbered, and there are no declarations. |
| 530 | | /// data is payload index to `EnumSimple`. |
| 531 | | enum_simple, |
| 532 | 644 | }; |
| 533 | 645 | |
| 534 | 646 | /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to |
| ... | ... | @@ -593,11 +705,43 @@ pub const SimpleValue = enum(u32) { |
| 593 | 705 | generic_poison, |
| 594 | 706 | }; |
| 595 | 707 | |
| 596 | | pub const Array = struct { |
| 708 | pub const SimpleInternal = enum(u32) { |
| 709 | /// This is the empty struct type. Note that empty_struct value is exposed |
| 710 | /// via SimpleValue. |
| 711 | type_empty_struct, |
| 712 | }; |
| 713 | |
| 714 | pub const Pointer = struct { |
| 715 | child: Index, |
| 716 | sentinel: Index, |
| 717 | flags: Flags, |
| 718 | |
| 719 | pub const Flags = packed struct(u32) { |
| 720 | alignment: u16, |
| 721 | is_const: bool, |
| 722 | is_volatile: bool, |
| 723 | is_allowzero: bool, |
| 724 | size: Size, |
| 725 | address_space: AddressSpace, |
| 726 | _: u7 = undefined, |
| 727 | }; |
| 728 | |
| 729 | pub const Size = std.builtin.Type.Pointer.Size; |
| 730 | pub const AddressSpace = std.builtin.AddressSpace; |
| 731 | }; |
| 732 | |
| 733 | /// Used for non-sentineled arrays that have length fitting in u32, as well as |
| 734 | /// vectors. |
| 735 | pub const Vector = struct { |
| 597 | 736 | len: u32, |
| 598 | 737 | child: Index, |
| 599 | 738 | }; |
| 600 | 739 | |
| 740 | pub const ErrorUnion = struct { |
| 741 | error_set_type: Index, |
| 742 | payload_type: Index, |
| 743 | }; |
| 744 | |
| 601 | 745 | /// Trailing: |
| 602 | 746 | /// 0. field name: null-terminated string index for each fields_len; declaration order |
| 603 | 747 | pub const EnumSimple = struct { |
| ... | ... | @@ -612,6 +756,12 @@ pub const EnumSimple = struct { |
| 612 | 756 | fields_len: u32, |
| 613 | 757 | }; |
| 614 | 758 | |
| 759 | /// Trailing: Limb for every limbs_len |
| 760 | pub const Int = struct { |
| 761 | ty: Index, |
| 762 | limbs_len: u32, |
| 763 | }; |
| 764 | |
| 615 | 765 | pub fn init(ip: *InternPool, gpa: Allocator) !void { |
| 616 | 766 | assert(ip.items.len == 0); |
| 617 | 767 | |
| ... | ... | @@ -619,6 +769,7 @@ pub fn init(ip: *InternPool, gpa: Allocator) !void { |
| 619 | 769 | try ip.items.ensureUnusedCapacity(gpa, static_keys.len); |
| 620 | 770 | try ip.map.ensureUnusedCapacity(gpa, static_keys.len); |
| 621 | 771 | try ip.extra.ensureUnusedCapacity(gpa, static_keys.len); |
| 772 | try ip.limbs.ensureUnusedCapacity(gpa, 2); |
| 622 | 773 | |
| 623 | 774 | // This inserts all the statically-known values into the intern pool in the |
| 624 | 775 | // order expected. |
| ... | ... | @@ -635,6 +786,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 635 | 786 | ip.map.deinit(gpa); |
| 636 | 787 | ip.items.deinit(gpa); |
| 637 | 788 | ip.extra.deinit(gpa); |
| 789 | ip.limbs.deinit(gpa); |
| 638 | 790 | ip.* = undefined; |
| 639 | 791 | } |
| 640 | 792 | |
| ... | ... | @@ -655,7 +807,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 655 | 807 | }, |
| 656 | 808 | }, |
| 657 | 809 | .type_array => { |
| 658 | | const array_info = ip.extraData(Array, data); |
| 810 | const array_info = ip.extraData(Vector, data); |
| 659 | 811 | return .{ .array_type = .{ |
| 660 | 812 | .len = array_info.len, |
| 661 | 813 | .child = array_info.child, |
| ... | ... | @@ -675,58 +827,226 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 675 | 827 | if (gop.found_existing) { |
| 676 | 828 | return @intToEnum(Index, gop.index); |
| 677 | 829 | } |
| 830 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 678 | 831 | switch (key) { |
| 679 | 832 | .int_type => |int_type| { |
| 680 | 833 | const t: Tag = switch (int_type.signedness) { |
| 681 | 834 | .signed => .type_int_signed, |
| 682 | 835 | .unsigned => .type_int_unsigned, |
| 683 | 836 | }; |
| 684 | | try ip.items.append(gpa, .{ |
| 837 | ip.items.appendAssumeCapacity(.{ |
| 685 | 838 | .tag = t, |
| 686 | 839 | .data = int_type.bits, |
| 687 | 840 | }); |
| 688 | 841 | }, |
| 842 | .ptr_type => |ptr_type| { |
| 843 | // TODO introduce more pointer encodings |
| 844 | ip.items.appendAssumeCapacity(.{ |
| 845 | .tag = .type_pointer, |
| 846 | .data = try ip.addExtra(gpa, Pointer{ |
| 847 | .child = ptr_type.elem_type, |
| 848 | .sentinel = ptr_type.sentinel, |
| 849 | .flags = .{ |
| 850 | .alignment = ptr_type.alignment, |
| 851 | .is_const = ptr_type.is_const, |
| 852 | .is_volatile = ptr_type.is_volatile, |
| 853 | .is_allowzero = ptr_type.is_allowzero, |
| 854 | .size = ptr_type.size, |
| 855 | .address_space = ptr_type.address_space, |
| 856 | }, |
| 857 | }), |
| 858 | }); |
| 859 | }, |
| 689 | 860 | .array_type => |array_type| { |
| 690 | 861 | const len = @intCast(u32, array_type.len); // TODO have a big_array encoding |
| 691 | 862 | assert(array_type.sentinel == .none); // TODO have a sentinel_array encoding |
| 692 | | try ip.items.append(gpa, .{ |
| 863 | ip.items.appendAssumeCapacity(.{ |
| 693 | 864 | .tag = .type_array, |
| 694 | | .data = try ip.addExtra(gpa, Array{ |
| 865 | .data = try ip.addExtra(gpa, Vector{ |
| 695 | 866 | .len = len, |
| 696 | 867 | .child = array_type.child, |
| 697 | 868 | }), |
| 698 | 869 | }); |
| 699 | 870 | }, |
| 700 | | else => @panic("TODO"), |
| 871 | .vector_type => |vector_type| { |
| 872 | ip.items.appendAssumeCapacity(.{ |
| 873 | .tag = .type_vector, |
| 874 | .data = try ip.addExtra(gpa, Vector{ |
| 875 | .len = vector_type.len, |
| 876 | .child = vector_type.child, |
| 877 | }), |
| 878 | }); |
| 879 | }, |
| 880 | .optional_type => |optional_type| { |
| 881 | ip.items.appendAssumeCapacity(.{ |
| 882 | .tag = .type_optional, |
| 883 | .data = @enumToInt(optional_type.payload_type), |
| 884 | }); |
| 885 | }, |
| 886 | .error_union_type => |error_union_type| { |
| 887 | ip.items.appendAssumeCapacity(.{ |
| 888 | .tag = .type_error_union, |
| 889 | .data = try ip.addExtra(gpa, ErrorUnion{ |
| 890 | .error_set_type = error_union_type.error_set_type, |
| 891 | .payload_type = error_union_type.payload_type, |
| 892 | }), |
| 893 | }); |
| 894 | }, |
| 895 | .simple_type => |simple_type| { |
| 896 | ip.items.appendAssumeCapacity(.{ |
| 897 | .tag = .simple_type, |
| 898 | .data = @enumToInt(simple_type), |
| 899 | }); |
| 900 | }, |
| 901 | .simple_value => |simple_value| { |
| 902 | ip.items.appendAssumeCapacity(.{ |
| 903 | .tag = .simple_value, |
| 904 | .data = @enumToInt(simple_value), |
| 905 | }); |
| 906 | }, |
| 907 | .extern_func => @panic("TODO"), |
| 908 | |
| 909 | .int => |int| b: { |
| 910 | switch (int.ty) { |
| 911 | .u32_type => { |
| 912 | if (int.big_int.fits(u32)) { |
| 913 | ip.items.appendAssumeCapacity(.{ |
| 914 | .tag = .int_small_u32, |
| 915 | .data = int.big_int.to(u32) catch unreachable, |
| 916 | }); |
| 917 | break :b; |
| 918 | } |
| 919 | }, |
| 920 | .i32_type => { |
| 921 | if (int.big_int.fits(i32)) { |
| 922 | ip.items.appendAssumeCapacity(.{ |
| 923 | .tag = .int_small_i32, |
| 924 | .data = @bitCast(u32, int.big_int.to(i32) catch unreachable), |
| 925 | }); |
| 926 | break :b; |
| 927 | } |
| 928 | }, |
| 929 | .usize_type => { |
| 930 | if (int.big_int.fits(u32)) { |
| 931 | ip.items.appendAssumeCapacity(.{ |
| 932 | .tag = .int_small_usize, |
| 933 | .data = int.big_int.to(u32) catch unreachable, |
| 934 | }); |
| 935 | break :b; |
| 936 | } |
| 937 | }, |
| 938 | .comptime_int_type => { |
| 939 | if (int.big_int.fits(u32)) { |
| 940 | ip.items.appendAssumeCapacity(.{ |
| 941 | .tag = .int_small_comptime_unsigned, |
| 942 | .data = int.big_int.to(u32) catch unreachable, |
| 943 | }); |
| 944 | break :b; |
| 945 | } |
| 946 | if (int.big_int.fits(i32)) { |
| 947 | ip.items.appendAssumeCapacity(.{ |
| 948 | .tag = .int_small_comptime_signed, |
| 949 | .data = @bitCast(u32, int.big_int.to(i32) catch unreachable), |
| 950 | }); |
| 951 | break :b; |
| 952 | } |
| 953 | }, |
| 954 | else => {}, |
| 955 | } |
| 956 | |
| 957 | const tag: Tag = if (int.big_int.positive) .int_positive else .int_negative; |
| 958 | try addInt(ip, gpa, int.ty, tag, int.big_int.limbs); |
| 959 | }, |
| 960 | |
| 961 | .enum_tag => |enum_tag| { |
| 962 | const tag: Tag = if (enum_tag.tag.positive) .enum_tag_positive else .enum_tag_negative; |
| 963 | try addInt(ip, gpa, enum_tag.ty, tag, enum_tag.tag.limbs); |
| 964 | }, |
| 965 | |
| 966 | .struct_type => |struct_type| { |
| 967 | if (struct_type.fields_len != 0) { |
| 968 | @panic("TODO"); // handle structs other than empty_struct |
| 969 | } |
| 970 | ip.items.appendAssumeCapacity(.{ |
| 971 | .tag = .simple_internal, |
| 972 | .data = @enumToInt(SimpleInternal.type_empty_struct), |
| 973 | }); |
| 974 | }, |
| 701 | 975 | } |
| 702 | 976 | return @intToEnum(Index, ip.items.len - 1); |
| 703 | 977 | } |
| 704 | 978 | |
| 705 | | pub fn tag(ip: InternPool, index: Index) Tag { |
| 706 | | const tags = ip.items.items(.tag); |
| 707 | | return tags[@enumToInt(index)]; |
| 979 | fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const usize) !void { |
| 980 | const limbs_len = @intCast(u32, limbs.len); |
| 981 | try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len); |
| 982 | ip.items.appendAssumeCapacity(.{ |
| 983 | .tag = tag, |
| 984 | .data = ip.addLimbsExtraAssumeCapacity(Int{ |
| 985 | .ty = ty, |
| 986 | .limbs_len = limbs_len, |
| 987 | }), |
| 988 | }); |
| 989 | ip.addLimbsAssumeCapacity(limbs); |
| 708 | 990 | } |
| 709 | 991 | |
| 710 | 992 | fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 { |
| 711 | | const fields = std.meta.fields(@TypeOf(extra)); |
| 993 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; |
| 712 | 994 | try ip.extra.ensureUnusedCapacity(gpa, fields.len); |
| 713 | 995 | return ip.addExtraAssumeCapacity(extra); |
| 714 | 996 | } |
| 715 | 997 | |
| 716 | 998 | fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 717 | | const fields = std.meta.fields(@TypeOf(extra)); |
| 718 | 999 | const result = @intCast(u32, ip.extra.items.len); |
| 719 | | inline for (fields) |field| { |
| 1000 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { |
| 720 | 1001 | ip.extra.appendAssumeCapacity(switch (field.type) { |
| 721 | 1002 | u32 => @field(extra, field.name), |
| 722 | 1003 | Index => @enumToInt(@field(extra, field.name)), |
| 723 | 1004 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 724 | | else => @compileError("bad field type"), |
| 1005 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), |
| 1006 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 725 | 1007 | }); |
| 726 | 1008 | } |
| 727 | 1009 | return result; |
| 728 | 1010 | } |
| 729 | 1011 | |
| 1012 | fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void { |
| 1013 | switch (@sizeOf(usize)) { |
| 1014 | @sizeOf(u32) => try ip.extra.ensureUnusedCapacity(gpa, n), |
| 1015 | @sizeOf(u64) => try ip.limbs.ensureUnusedCapacity(gpa, n), |
| 1016 | else => @compileError("unsupported host"), |
| 1017 | } |
| 1018 | } |
| 1019 | |
| 1020 | fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 1021 | switch (@sizeOf(usize)) { |
| 1022 | @sizeOf(u32) => return addExtraAssumeCapacity(ip, extra), |
| 1023 | @sizeOf(u64) => {}, |
| 1024 | else => @compileError("unsupported host"), |
| 1025 | } |
| 1026 | const result = @intCast(u32, ip.extra.items.len); |
| 1027 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields, 0..) |field, i| { |
| 1028 | const new: u32 = switch (field.type) { |
| 1029 | u32 => @field(extra, field.name), |
| 1030 | Index => @enumToInt(@field(extra, field.name)), |
| 1031 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 1032 | }; |
| 1033 | if (i % 2 == 0) { |
| 1034 | ip.limbs.appendAssumeCapacity(new); |
| 1035 | } else { |
| 1036 | ip.limbs.items[ip.limbs.items.len - 1] |= @as(u64, new) << 32; |
| 1037 | } |
| 1038 | } |
| 1039 | return result; |
| 1040 | } |
| 1041 | |
| 1042 | fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const usize) void { |
| 1043 | switch (@sizeOf(usize)) { |
| 1044 | @sizeOf(u32) => ip.extra.appendSliceAssumeCapacity(limbs), |
| 1045 | @sizeOf(u64) => ip.limbs.appendSliceAssumeCapacity(limbs), |
| 1046 | else => @compileError("unsupported host"), |
| 1047 | } |
| 1048 | } |
| 1049 | |
| 730 | 1050 | fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 731 | 1051 | const fields = std.meta.fields(T); |
| 732 | 1052 | var i: usize = index; |
| ... | ... | @@ -736,7 +1056,8 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 736 | 1056 | u32 => ip.extra.items[i], |
| 737 | 1057 | Index => @intToEnum(Index, ip.extra.items[i]), |
| 738 | 1058 | i32 => @bitCast(i32, ip.extra.items[i]), |
| 739 | | else => @compileError("bad field type"), |
| 1059 | Pointer.Flags => @bitCast(Pointer.Flags, ip.extra.items[i]), |
| 1060 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 740 | 1061 | }; |
| 741 | 1062 | i += 1; |
| 742 | 1063 | } |