authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-30 20:23:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:57-07:00
log82f6f164a1af6557451e580dcf3197ad94e5437e
tree6a88050cac9da741c2ae8434ef0fe2989c411ee5
parentc7d65fa3685a5f48cfedaa7a1adf758e1dc6d219

InternPool: improve hashing performance

Key.PtrType is now an extern struct so that hashing it can be done by reinterpreting bytes directly. It also uses the same representation for type_pointer Tag encoding and the Key. Accessing pointer attributes now requires packed struct access, however, many operations are now a copy of a u32 rather than several independent fields. This function moves the top two most used Key variants - pointer types and pointer values - to use a single-shot hash function that branches for small keys instead of calling memcpy. As a result, perf against merge-base went from 1.17x ± 0.04 slower to 1.12x ± 0.04 slower. After the pointer value hashing was changed, total CPU instructions spent in memcpy went from 4.40% to 4.08%, and after additionally improving pointer type hashing, it further decreased to 3.72%.

8 files changed, 527 insertions(+), 392 deletions(-)

src/InternPool.zig+282-202
......@@ -249,35 +249,47 @@ pub const Key = union(enum) {
249249 }
250250 };
251251
252 pub const PtrType = struct {
253 elem_type: Index,
252 /// Extern layout so it can be hashed with `std.mem.asBytes`.
253 pub const PtrType = extern struct {
254 child: Index,
254255 sentinel: Index = .none,
255 /// `none` indicates the ABI alignment of the pointee_type. In this
256 /// case, this field *must* be set to `none`, otherwise the
257 /// `InternPool` equality and hashing functions will return incorrect
258 /// results.
259 alignment: Alignment = .none,
260 /// If this is non-zero it means the pointer points to a sub-byte
261 /// range of data, which is backed by a "host integer" with this
262 /// number of bytes.
263 /// When host_size=pointee_abi_size and bit_offset=0, this must be
264 /// represented with host_size=0 instead.
265 host_size: u16 = 0,
266 bit_offset: u16 = 0,
267 vector_index: VectorIndex = .none,
268 size: std.builtin.Type.Pointer.Size = .One,
269 is_const: bool = false,
270 is_volatile: bool = false,
271 is_allowzero: bool = false,
272 /// See src/target.zig defaultAddressSpace function for how to obtain
273 /// an appropriate value for this field.
274 address_space: std.builtin.AddressSpace = .generic,
256 flags: Flags = .{},
257 packed_offset: PackedOffset = .{ .bit_offset = 0, .host_size = 0 },
275258
276259 pub const VectorIndex = enum(u16) {
277260 none = std.math.maxInt(u16),
278261 runtime = std.math.maxInt(u16) - 1,
279262 _,
280263 };
264
265 pub const Flags = packed struct(u32) {
266 size: Size = .One,
267 /// `none` indicates the ABI alignment of the pointee_type. In this
268 /// case, this field *must* be set to `none`, otherwise the
269 /// `InternPool` equality and hashing functions will return incorrect
270 /// results.
271 alignment: Alignment = .none,
272 is_const: bool = false,
273 is_volatile: bool = false,
274 is_allowzero: bool = false,
275 /// See src/target.zig defaultAddressSpace function for how to obtain
276 /// an appropriate value for this field.
277 address_space: AddressSpace = .generic,
278 vector_index: VectorIndex = .none,
279 };
280
281 pub const PackedOffset = packed struct(u32) {
282 /// If this is non-zero it means the pointer points to a sub-byte
283 /// range of data, which is backed by a "host integer" with this
284 /// number of bytes.
285 /// When host_size=pointee_abi_size and bit_offset=0, this must be
286 /// represented with host_size=0 instead.
287 host_size: u16,
288 bit_offset: u16,
289 };
290
291 pub const Size = std.builtin.Type.Pointer.Size;
292 pub const AddressSpace = std.builtin.AddressSpace;
281293 };
282294
283295 pub const ArrayType = struct {
......@@ -635,17 +647,13 @@ pub const Key = union(enum) {
635647 }
636648
637649 pub fn hash64(key: Key, ip: *const InternPool) u64 {
638 var hasher = std.hash.Wyhash.init(0);
639 key.hashWithHasher(&hasher, ip);
640 return hasher.final();
641 }
642
643 pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash, ip: *const InternPool) void {
650 const asBytes = std.mem.asBytes;
644651 const KeyTag = @typeInfo(Key).Union.tag_type.?;
645 std.hash.autoHash(hasher, @as(KeyTag, key));
652 const seed = @enumToInt(@as(KeyTag, key));
646653 switch (key) {
654 .ptr_type => |x| return WyhashKing.hash(seed, asBytes(&x)),
655
647656 inline .int_type,
648 .ptr_type,
649657 .array_type,
650658 .vector_type,
651659 .opt_type,
......@@ -663,73 +671,110 @@ pub const Key = union(enum) {
663671 .enum_literal,
664672 .enum_tag,
665673 .inferred_error_set_type,
666 => |info| std.hash.autoHash(hasher, info),
674 => |info| {
675 var hasher = std.hash.Wyhash.init(seed);
676 std.hash.autoHash(&hasher, info);
677 return hasher.final();
678 },
667679
668 .runtime_value => |runtime_value| std.hash.autoHash(hasher, runtime_value.val),
669 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
670 .enum_type => |enum_type| std.hash.autoHash(hasher, enum_type.decl),
680 .runtime_value => |runtime_value| {
681 var hasher = std.hash.Wyhash.init(seed);
682 std.hash.autoHash(&hasher, runtime_value.val);
683 return hasher.final();
684 },
685 .opaque_type => |opaque_type| {
686 var hasher = std.hash.Wyhash.init(seed);
687 std.hash.autoHash(&hasher, opaque_type.decl);
688 return hasher.final();
689 },
690 .enum_type => |enum_type| {
691 var hasher = std.hash.Wyhash.init(seed);
692 std.hash.autoHash(&hasher, enum_type.decl);
693 return hasher.final();
694 },
671695
672 .variable => |variable| std.hash.autoHash(hasher, variable.decl),
696 .variable => |variable| {
697 var hasher = std.hash.Wyhash.init(seed);
698 std.hash.autoHash(&hasher, variable.decl);
699 return hasher.final();
700 },
673701 .extern_func => |extern_func| {
674 std.hash.autoHash(hasher, extern_func.ty);
675 std.hash.autoHash(hasher, extern_func.decl);
702 var hasher = std.hash.Wyhash.init(seed);
703 std.hash.autoHash(&hasher, extern_func.ty);
704 std.hash.autoHash(&hasher, extern_func.decl);
705 return hasher.final();
676706 },
677707 .func => |func| {
678 std.hash.autoHash(hasher, func.ty);
679 std.hash.autoHash(hasher, func.index);
708 var hasher = std.hash.Wyhash.init(seed);
709 std.hash.autoHash(&hasher, func.ty);
710 std.hash.autoHash(&hasher, func.index);
711 return hasher.final();
680712 },
681713
682714 .int => |int| {
715 var hasher = std.hash.Wyhash.init(seed);
683716 // Canonicalize all integers by converting them to BigIntConst.
684717 switch (int.storage) {
685718 .u64, .i64, .big_int => {
686719 var buffer: Key.Int.Storage.BigIntSpace = undefined;
687720 const big_int = int.storage.toBigInt(&buffer);
688721
689 std.hash.autoHash(hasher, int.ty);
690 std.hash.autoHash(hasher, big_int.positive);
691 for (big_int.limbs) |limb| std.hash.autoHash(hasher, limb);
722 std.hash.autoHash(&hasher, int.ty);
723 std.hash.autoHash(&hasher, big_int.positive);
724 for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb);
692725 },
693726 .lazy_align, .lazy_size => |lazy_ty| {
694727 std.hash.autoHash(
695 hasher,
728 &hasher,
696729 @as(@typeInfo(Key.Int.Storage).Union.tag_type.?, int.storage),
697730 );
698 std.hash.autoHash(hasher, lazy_ty);
731 std.hash.autoHash(&hasher, lazy_ty);
699732 },
700733 }
734 return hasher.final();
701735 },
702736
703737 .float => |float| {
704 std.hash.autoHash(hasher, float.ty);
738 var hasher = std.hash.Wyhash.init(seed);
739 std.hash.autoHash(&hasher, float.ty);
705740 switch (float.storage) {
706741 inline else => |val| std.hash.autoHash(
707 hasher,
742 &hasher,
708743 @bitCast(std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(val))), val),
709744 ),
710745 }
746 return hasher.final();
711747 },
712748
713749 .ptr => |ptr| {
714 std.hash.autoHash(hasher, ptr.ty);
715 std.hash.autoHash(hasher, ptr.len);
716750 // Int-to-ptr pointers are hashed separately than decl-referencing pointers.
717751 // This is sound due to pointer provenance rules.
718 std.hash.autoHash(hasher, @as(@typeInfo(Key.Ptr.Addr).Union.tag_type.?, ptr.addr));
719 switch (ptr.addr) {
720 .decl => |decl| std.hash.autoHash(hasher, decl),
721 .mut_decl => |mut_decl| std.hash.autoHash(hasher, mut_decl),
722 .int => |int| std.hash.autoHash(hasher, int),
723 .eu_payload => |eu_payload| std.hash.autoHash(hasher, eu_payload),
724 .opt_payload => |opt_payload| std.hash.autoHash(hasher, opt_payload),
725 .comptime_field => |comptime_field| std.hash.autoHash(hasher, comptime_field),
726 .elem => |elem| std.hash.autoHash(hasher, elem),
727 .field => |field| std.hash.autoHash(hasher, field),
728 }
752 const addr: @typeInfo(Key.Ptr.Addr).Union.tag_type.? = ptr.addr;
753 const seed2 = seed + @enumToInt(addr);
754 const common = asBytes(&ptr.ty) ++ asBytes(&ptr.len);
755 return switch (ptr.addr) {
756 .decl => |x| WyhashKing.hash(seed2, common ++ asBytes(&x)),
757
758 .mut_decl => |x| WyhashKing.hash(
759 seed2,
760 asBytes(&x.decl) ++ asBytes(&x.runtime_index),
761 ),
762
763 .int, .eu_payload, .opt_payload, .comptime_field => |int| WyhashKing.hash(
764 seed2,
765 asBytes(&int),
766 ),
767
768 .elem, .field => |x| WyhashKing.hash(
769 seed2,
770 asBytes(&x.base) ++ asBytes(&x.index),
771 ),
772 };
729773 },
730774
731775 .aggregate => |aggregate| {
732 std.hash.autoHash(hasher, aggregate.ty);
776 var hasher = std.hash.Wyhash.init(seed);
777 std.hash.autoHash(&hasher, aggregate.ty);
733778 const len = ip.aggregateTypeLen(aggregate.ty);
734779 const child = switch (ip.indexToKey(aggregate.ty)) {
735780 .array_type => |array_type| array_type.child,
......@@ -741,16 +786,16 @@ pub const Key = union(enum) {
741786 if (child == .u8_type) {
742787 switch (aggregate.storage) {
743788 .bytes => |bytes| for (bytes[0..@intCast(usize, len)]) |byte| {
744 std.hash.autoHash(hasher, KeyTag.int);
745 std.hash.autoHash(hasher, byte);
789 std.hash.autoHash(&hasher, KeyTag.int);
790 std.hash.autoHash(&hasher, byte);
746791 },
747792 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem| {
748793 const elem_key = ip.indexToKey(elem);
749 std.hash.autoHash(hasher, @as(KeyTag, elem_key));
794 std.hash.autoHash(&hasher, @as(KeyTag, elem_key));
750795 switch (elem_key) {
751796 .undef => {},
752797 .int => |int| std.hash.autoHash(
753 hasher,
798 &hasher,
754799 @intCast(u8, int.storage.u64),
755800 ),
756801 else => unreachable,
......@@ -760,11 +805,11 @@ pub const Key = union(enum) {
760805 const elem_key = ip.indexToKey(elem);
761806 var remaining = len;
762807 while (remaining > 0) : (remaining -= 1) {
763 std.hash.autoHash(hasher, @as(KeyTag, elem_key));
808 std.hash.autoHash(&hasher, @as(KeyTag, elem_key));
764809 switch (elem_key) {
765810 .undef => {},
766811 .int => |int| std.hash.autoHash(
767 hasher,
812 &hasher,
768813 @intCast(u8, int.storage.u64),
769814 ),
770815 else => unreachable,
......@@ -772,47 +817,60 @@ pub const Key = union(enum) {
772817 }
773818 },
774819 }
775 return;
820 return hasher.final();
776821 }
777822
778823 switch (aggregate.storage) {
779824 .bytes => unreachable,
780825 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem|
781 std.hash.autoHash(hasher, elem),
826 std.hash.autoHash(&hasher, elem),
782827 .repeated_elem => |elem| {
783828 var remaining = len;
784 while (remaining > 0) : (remaining -= 1) std.hash.autoHash(hasher, elem);
829 while (remaining > 0) : (remaining -= 1) std.hash.autoHash(&hasher, elem);
785830 },
786831 }
832 return hasher.final();
787833 },
788834
789835 .error_set_type => |error_set_type| {
790 for (error_set_type.names) |elem| std.hash.autoHash(hasher, elem);
836 var hasher = std.hash.Wyhash.init(seed);
837 for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem);
838 return hasher.final();
791839 },
792840
793841 .anon_struct_type => |anon_struct_type| {
794 for (anon_struct_type.types) |elem| std.hash.autoHash(hasher, elem);
795 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);
796 for (anon_struct_type.names) |elem| std.hash.autoHash(hasher, elem);
842 var hasher = std.hash.Wyhash.init(seed);
843 for (anon_struct_type.types) |elem| std.hash.autoHash(&hasher, elem);
844 for (anon_struct_type.values) |elem| std.hash.autoHash(&hasher, elem);
845 for (anon_struct_type.names) |elem| std.hash.autoHash(&hasher, elem);
846 return hasher.final();
797847 },
798848
799849 .func_type => |func_type| {
800 for (func_type.param_types) |param_type| std.hash.autoHash(hasher, param_type);
801 std.hash.autoHash(hasher, func_type.return_type);
802 std.hash.autoHash(hasher, func_type.comptime_bits);
803 std.hash.autoHash(hasher, func_type.noalias_bits);
804 std.hash.autoHash(hasher, func_type.alignment);
805 std.hash.autoHash(hasher, func_type.cc);
806 std.hash.autoHash(hasher, func_type.is_var_args);
807 std.hash.autoHash(hasher, func_type.is_generic);
808 std.hash.autoHash(hasher, func_type.is_noinline);
850 var hasher = std.hash.Wyhash.init(seed);
851 for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type);
852 std.hash.autoHash(&hasher, func_type.return_type);
853 std.hash.autoHash(&hasher, func_type.comptime_bits);
854 std.hash.autoHash(&hasher, func_type.noalias_bits);
855 std.hash.autoHash(&hasher, func_type.alignment);
856 std.hash.autoHash(&hasher, func_type.cc);
857 std.hash.autoHash(&hasher, func_type.is_var_args);
858 std.hash.autoHash(&hasher, func_type.is_generic);
859 std.hash.autoHash(&hasher, func_type.is_noinline);
860 return hasher.final();
809861 },
810862
811 .memoized_decl => |memoized_decl| std.hash.autoHash(hasher, memoized_decl.val),
863 .memoized_decl => |memoized_decl| {
864 var hasher = std.hash.Wyhash.init(seed);
865 std.hash.autoHash(&hasher, memoized_decl.val);
866 return hasher.final();
867 },
812868
813869 .memoized_call => |memoized_call| {
814 std.hash.autoHash(hasher, memoized_call.func);
815 for (memoized_call.arg_values) |arg| std.hash.autoHash(hasher, arg);
870 var hasher = std.hash.Wyhash.init(seed);
871 std.hash.autoHash(&hasher, memoized_call.func);
872 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
873 return hasher.final();
816874 },
817875 }
818876 }
......@@ -1340,7 +1398,7 @@ pub const Index = enum(u32) {
13401398 type_array_big: struct { data: *Array },
13411399 type_array_small: struct { data: *Vector },
13421400 type_vector: struct { data: *Vector },
1343 type_pointer: struct { data: *Pointer },
1401 type_pointer: struct { data: *Tag.TypePointer },
13441402 type_slice: DataIsIndex,
13451403 type_optional: DataIsIndex,
13461404 type_anyframe: DataIsIndex,
......@@ -1564,44 +1622,56 @@ pub const static_keys = [_]Key{
15641622 .{ .simple_type = .type_info },
15651623
15661624 .{ .ptr_type = .{
1567 .elem_type = .u8_type,
1568 .size = .Many,
1625 .child = .u8_type,
1626 .flags = .{
1627 .size = .Many,
1628 },
15691629 } },
15701630
15711631 // manyptr_const_u8_type
15721632 .{ .ptr_type = .{
1573 .elem_type = .u8_type,
1574 .size = .Many,
1575 .is_const = true,
1633 .child = .u8_type,
1634 .flags = .{
1635 .size = .Many,
1636 .is_const = true,
1637 },
15761638 } },
15771639
15781640 // manyptr_const_u8_sentinel_0_type
15791641 .{ .ptr_type = .{
1580 .elem_type = .u8_type,
1642 .child = .u8_type,
15811643 .sentinel = .zero_u8,
1582 .size = .Many,
1583 .is_const = true,
1644 .flags = .{
1645 .size = .Many,
1646 .is_const = true,
1647 },
15841648 } },
15851649
15861650 .{ .ptr_type = .{
1587 .elem_type = .comptime_int_type,
1588 .size = .One,
1589 .is_const = true,
1651 .child = .comptime_int_type,
1652 .flags = .{
1653 .size = .One,
1654 .is_const = true,
1655 },
15901656 } },
15911657
15921658 // slice_const_u8_type
15931659 .{ .ptr_type = .{
1594 .elem_type = .u8_type,
1595 .size = .Slice,
1596 .is_const = true,
1660 .child = .u8_type,
1661 .flags = .{
1662 .size = .Slice,
1663 .is_const = true,
1664 },
15971665 } },
15981666
15991667 // slice_const_u8_sentinel_0_type
16001668 .{ .ptr_type = .{
1601 .elem_type = .u8_type,
1669 .child = .u8_type,
16021670 .sentinel = .zero_u8,
1603 .size = .Slice,
1604 .is_const = true,
1671 .flags = .{
1672 .size = .Slice,
1673 .is_const = true,
1674 },
16051675 } },
16061676
16071677 // anyerror_void_error_union_type
......@@ -1702,7 +1772,6 @@ pub const Tag = enum(u8) {
17021772 /// data is payload to Vector.
17031773 type_vector,
17041774 /// A fully explicitly specified pointer type.
1705 /// data is payload to Pointer.
17061775 type_pointer,
17071776 /// A slice type.
17081777 /// data is Index of underlying pointer type.
......@@ -1941,6 +2010,7 @@ pub const Tag = enum(u8) {
19412010 const Func = Key.Func;
19422011 const Union = Key.Union;
19432012 const MemoizedDecl = Key.MemoizedDecl;
2013 const TypePointer = Key.PtrType;
19442014
19452015 fn Payload(comptime tag: Tag) type {
19462016 return switch (tag) {
......@@ -1949,7 +2019,7 @@ pub const Tag = enum(u8) {
19492019 .type_array_big => Array,
19502020 .type_array_small => Vector,
19512021 .type_vector => Vector,
1952 .type_pointer => Pointer,
2022 .type_pointer => TypePointer,
19532023 .type_slice => unreachable,
19542024 .type_optional => unreachable,
19552025 .type_anyframe => unreachable,
......@@ -2167,32 +2237,6 @@ pub const SimpleValue = enum(u32) {
21672237 generic_poison,
21682238};
21692239
2170pub const Pointer = struct {
2171 child: Index,
2172 sentinel: Index,
2173 flags: Flags,
2174 packed_offset: PackedOffset,
2175
2176 pub const Flags = packed struct(u32) {
2177 size: Size,
2178 alignment: Alignment,
2179 is_const: bool,
2180 is_volatile: bool,
2181 is_allowzero: bool,
2182 address_space: AddressSpace,
2183 vector_index: VectorIndex,
2184 };
2185
2186 pub const PackedOffset = packed struct(u32) {
2187 host_size: u16,
2188 bit_offset: u16,
2189 };
2190
2191 pub const Size = std.builtin.Type.Pointer.Size;
2192 pub const AddressSpace = std.builtin.AddressSpace;
2193 pub const VectorIndex = Key.PtrType.VectorIndex;
2194};
2195
21962240/// Stored as a power-of-two, with one special value to indicate none.
21972241pub const Alignment = enum(u6) {
21982242 none = std.math.maxInt(u6),
......@@ -2531,39 +2575,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
25312575 } };
25322576 },
25332577
2534 .type_pointer => {
2535 const ptr_info = ip.extraData(Pointer, data);
2536 return .{ .ptr_type = .{
2537 .elem_type = ptr_info.child,
2538 .sentinel = ptr_info.sentinel,
2539 .alignment = ptr_info.flags.alignment,
2540 .size = ptr_info.flags.size,
2541 .is_const = ptr_info.flags.is_const,
2542 .is_volatile = ptr_info.flags.is_volatile,
2543 .is_allowzero = ptr_info.flags.is_allowzero,
2544 .address_space = ptr_info.flags.address_space,
2545 .vector_index = ptr_info.flags.vector_index,
2546 .host_size = ptr_info.packed_offset.host_size,
2547 .bit_offset = ptr_info.packed_offset.bit_offset,
2548 } };
2549 },
2578 .type_pointer => .{ .ptr_type = ip.extraData(Tag.TypePointer, data) },
25502579
25512580 .type_slice => {
25522581 assert(ip.items.items(.tag)[data] == .type_pointer);
2553 const ptr_info = ip.extraData(Pointer, ip.items.items(.data)[data]);
2554 return .{ .ptr_type = .{
2555 .elem_type = ptr_info.child,
2556 .sentinel = ptr_info.sentinel,
2557 .alignment = ptr_info.flags.alignment,
2558 .size = .Slice,
2559 .is_const = ptr_info.flags.is_const,
2560 .is_volatile = ptr_info.flags.is_volatile,
2561 .is_allowzero = ptr_info.flags.is_allowzero,
2562 .address_space = ptr_info.flags.address_space,
2563 .vector_index = ptr_info.flags.vector_index,
2564 .host_size = ptr_info.packed_offset.host_size,
2565 .bit_offset = ptr_info.packed_offset.bit_offset,
2566 } };
2582 var ptr_info = ip.extraData(Tag.TypePointer, ip.items.items(.data)[data]);
2583 ptr_info.flags.size = .Slice;
2584 return .{ .ptr_type = ptr_info };
25672585 },
25682586
25692587 .type_optional => .{ .opt_type = @intToEnum(Index, data) },
......@@ -3066,13 +3084,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
30663084 });
30673085 },
30683086 .ptr_type => |ptr_type| {
3069 assert(ptr_type.elem_type != .none);
3070 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.elem_type);
3087 assert(ptr_type.child != .none);
3088 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.child);
30713089
3072 if (ptr_type.size == .Slice) {
3090 if (ptr_type.flags.size == .Slice) {
30733091 _ = ip.map.pop();
30743092 var new_key = key;
3075 new_key.ptr_type.size = .Many;
3093 new_key.ptr_type.flags.size = .Many;
30763094 const ptr_type_index = try ip.get(gpa, new_key);
30773095 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
30783096 try ip.items.ensureUnusedCapacity(gpa, 1);
......@@ -3083,27 +3101,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
30833101 return @intToEnum(Index, ip.items.len - 1);
30843102 }
30853103
3086 const is_allowzero = ptr_type.is_allowzero or ptr_type.size == .C;
3104 var ptr_type_adjusted = ptr_type;
3105 if (ptr_type.flags.size == .C) ptr_type_adjusted.flags.is_allowzero = true;
30873106
30883107 ip.items.appendAssumeCapacity(.{
30893108 .tag = .type_pointer,
3090 .data = try ip.addExtra(gpa, Pointer{
3091 .child = ptr_type.elem_type,
3092 .sentinel = ptr_type.sentinel,
3093 .flags = .{
3094 .alignment = ptr_type.alignment,
3095 .is_const = ptr_type.is_const,
3096 .is_volatile = ptr_type.is_volatile,
3097 .is_allowzero = is_allowzero,
3098 .size = ptr_type.size,
3099 .address_space = ptr_type.address_space,
3100 .vector_index = ptr_type.vector_index,
3101 },
3102 .packed_offset = .{
3103 .host_size = ptr_type.host_size,
3104 .bit_offset = ptr_type.bit_offset,
3105 },
3106 }),
3109 .data = try ip.addExtra(gpa, ptr_type_adjusted),
31073110 });
31083111 },
31093112 .array_type => |array_type| {
......@@ -3379,7 +3382,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
33793382 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
33803383 switch (ptr.len) {
33813384 .none => {
3382 assert(ptr_type.size != .Slice);
3385 assert(ptr_type.flags.size != .Slice);
33833386 switch (ptr.addr) {
33843387 .decl => |decl| ip.items.appendAssumeCapacity(.{
33853388 .tag = .ptr_decl,
......@@ -3410,10 +3413,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34103413 switch (ptr.addr) {
34113414 .int => assert(ip.typeOf(base) == .usize_type),
34123415 .eu_payload => assert(ip.indexToKey(
3413 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
3416 ip.indexToKey(ip.typeOf(base)).ptr_type.child,
34143417 ) == .error_union_type),
34153418 .opt_payload => assert(ip.indexToKey(
3416 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
3419 ip.indexToKey(ip.typeOf(base)).ptr_type.child,
34173420 ) == .opt_type),
34183421 else => unreachable,
34193422 }
......@@ -3433,10 +3436,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34333436 .elem, .field => |base_index| {
34343437 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
34353438 switch (ptr.addr) {
3436 .elem => assert(base_ptr_type.size == .Many),
3439 .elem => assert(base_ptr_type.flags.size == .Many),
34373440 .field => {
3438 assert(base_ptr_type.size == .One);
3439 switch (ip.indexToKey(base_ptr_type.elem_type)) {
3441 assert(base_ptr_type.flags.size == .One);
3442 switch (ip.indexToKey(base_ptr_type.child)) {
34403443 .anon_struct_type => |anon_struct_type| {
34413444 assert(ptr.addr == .field);
34423445 assert(base_index.index < anon_struct_type.types.len);
......@@ -3451,7 +3454,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34513454 },
34523455 .ptr_type => |slice_type| {
34533456 assert(ptr.addr == .field);
3454 assert(slice_type.size == .Slice);
3457 assert(slice_type.flags.size == .Slice);
34553458 assert(base_index.index < 2);
34563459 },
34573460 else => unreachable,
......@@ -3485,12 +3488,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34853488 // TODO: change Key.Ptr for slices to reference the manyptr value
34863489 // rather than having an addr field directly. Then we can avoid
34873490 // these problematic calls to pop(), get(), and getOrPutAdapted().
3488 assert(ptr_type.size == .Slice);
3491 assert(ptr_type.flags.size == .Slice);
34893492 _ = ip.map.pop();
34903493 var new_key = key;
34913494 new_key.ptr.ty = ip.slicePtrType(ptr.ty);
34923495 new_key.ptr.len = .none;
3493 assert(ip.indexToKey(new_key.ptr.ty).ptr_type.size == .Many);
3496 assert(ip.indexToKey(new_key.ptr.ty).ptr_type.flags.size == .Many);
34943497 const ptr_index = try ip.get(gpa, new_key);
34953498 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
34963499 try ip.items.ensureUnusedCapacity(gpa, 1);
......@@ -4302,10 +4305,10 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
43024305 NullTerminatedString => @enumToInt(@field(extra, field.name)),
43034306 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),
43044307 i32 => @bitCast(u32, @field(extra, field.name)),
4305 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),
4308 Tag.TypePointer.Flags => @bitCast(u32, @field(extra, field.name)),
43064309 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
4307 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
4308 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),
4310 Tag.TypePointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
4311 Tag.TypePointer.VectorIndex => @enumToInt(@field(extra, field.name)),
43094312 Tag.Variable.Flags => @bitCast(u32, @field(extra, field.name)),
43104313 else => @compileError("bad field type: " ++ @typeName(field.type)),
43114314 });
......@@ -4370,10 +4373,10 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
43704373 NullTerminatedString => @intToEnum(NullTerminatedString, int32),
43714374 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),
43724375 i32 => @bitCast(i32, int32),
4373 Pointer.Flags => @bitCast(Pointer.Flags, int32),
4376 Tag.TypePointer.Flags => @bitCast(Tag.TypePointer.Flags, int32),
43744377 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
4375 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
4376 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),
4378 Tag.TypePointer.PackedOffset => @bitCast(Tag.TypePointer.PackedOffset, int32),
4379 Tag.TypePointer.VectorIndex => @intToEnum(Tag.TypePointer.VectorIndex, int32),
43774380 Tag.Variable.Flags => @bitCast(Tag.Variable.Flags, int32),
43784381 else => @compileError("bad field type: " ++ @typeName(field.type)),
43794382 };
......@@ -4487,7 +4490,7 @@ test "basic usage" {
44874490
44884491pub fn childType(ip: *const InternPool, i: Index) Index {
44894492 return switch (ip.indexToKey(i)) {
4490 .ptr_type => |ptr_type| ptr_type.elem_type,
4493 .ptr_type => |ptr_type| ptr_type.child,
44914494 .vector_type => |vector_type| vector_type.child,
44924495 .array_type => |array_type| array_type.child,
44934496 .opt_type, .anyframe_type => |child| child,
......@@ -4559,7 +4562,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
45594562 return ip.get(gpa, .{ .ptr = .{
45604563 .ty = new_ty,
45614564 .addr = .{ .int = .zero_usize },
4562 .len = switch (ip.indexToKey(new_ty).ptr_type.size) {
4565 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
45634566 .One, .Many, .C => .none,
45644567 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
45654568 },
......@@ -4623,7 +4626,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
46234626 .none => try ip.get(gpa, .{ .ptr = .{
46244627 .ty = new_ty,
46254628 .addr = .{ .int = .zero_usize },
4626 .len = switch (ip.indexToKey(new_ty).ptr_type.size) {
4629 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
46274630 .One, .Many, .C => .none,
46284631 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
46294632 },
......@@ -4889,7 +4892,7 @@ fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
48894892 .type_array_small => @sizeOf(Vector),
48904893 .type_array_big => @sizeOf(Array),
48914894 .type_vector => @sizeOf(Vector),
4892 .type_pointer => @sizeOf(Pointer),
4895 .type_pointer => @sizeOf(Tag.TypePointer),
48934896 .type_slice => 0,
48944897 .type_optional => 0,
48954898 .type_anyframe => 0,
......@@ -5007,6 +5010,7 @@ fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50075010 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
50085011 const values = ctx.map.values();
50095012 return values[a_index].bytes > values[b_index].bytes;
5013 //return values[a_index].count > values[b_index].count;
50105014 }
50115015 };
50125016 counts.sort(SortContext{ .map = &counts });
......@@ -5621,3 +5625,79 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
56215625 .none => unreachable, // special tag
56225626 };
56235627}
5628
5629/// I got this from King, using this temporarily until std lib hashing can be
5630/// improved to make stateless hashing performant. Currently the
5631/// implementations suffer from not special casing small lengths and not taking
5632/// advantage of comptime-known lengths, both of which this implementation
5633/// does.
5634const WyhashKing = struct {
5635 inline fn mum(pair: *[2]u64) void {
5636 const x = @as(u128, pair[0]) *% pair[1];
5637 pair[0] = @truncate(u64, x);
5638 pair[1] = @truncate(u64, x >> 64);
5639 }
5640
5641 inline fn mix(a: u64, b: u64) u64 {
5642 var pair = [_]u64{ a, b };
5643 mum(&pair);
5644 return pair[0] ^ pair[1];
5645 }
5646
5647 inline fn read(comptime I: type, in: []const u8) I {
5648 return std.mem.readIntLittle(I, in[0..@sizeOf(I)]);
5649 }
5650
5651 const secret = [_]u64{
5652 0xa0761d6478bd642f,
5653 0xe7037ed1a0b428db,
5654 0x8ebc6af09c88c6e3,
5655 0x589965cc75374cc3,
5656 };
5657
5658 fn hash(seed: u64, input: anytype) u64 {
5659 var in: []const u8 = input;
5660 var last = std.mem.zeroes([2]u64);
5661 const starting_len: u64 = input.len;
5662 var state = seed ^ mix(seed ^ secret[0], secret[1]);
5663
5664 if (in.len <= 16) {
5665 if (in.len >= 4) {
5666 const end = (in.len >> 3) << 2;
5667 last[0] = (@as(u64, read(u32, in)) << 32) | read(u32, in[end..]);
5668 last[1] = (@as(u64, read(u32, in[in.len - 4 ..])) << 32) | read(u32, in[in.len - 4 - end ..]);
5669 } else if (in.len > 0) {
5670 last[0] = (@as(u64, in[0]) << 16) | (@as(u64, in[in.len >> 1]) << 8) | in[in.len - 1];
5671 }
5672 } else {
5673 large: {
5674 if (in.len <= 48) break :large;
5675 var split = [_]u64{ state, state, state };
5676 while (true) {
5677 for (&split, 0..) |*lane, i| {
5678 const a = read(u64, in[(i * 2) * 8 ..]) ^ secret[i + 1];
5679 const b = read(u64, in[((i * 2) + 1) * 8 ..]) ^ lane.*;
5680 lane.* = mix(a, b);
5681 }
5682 in = in[48..];
5683 if (in.len > 48) continue;
5684 state = split[0] ^ (split[1] ^ split[2]);
5685 break :large;
5686 }
5687 }
5688 while (true) {
5689 if (in.len <= 16) break;
5690 state = mix(read(u64, in) ^ secret[1], read(u64, in[8..]) ^ state);
5691 in = in[16..];
5692 if (in.len <= 16) break;
5693 }
5694 last[0] = read(u64, in[in.len - 16 ..]);
5695 last[1] = read(u64, in[in.len - 8 ..]);
5696 }
5697
5698 last[0] ^= secret[1];
5699 last[1] ^= state;
5700 mum(&last);
5701 return mix(last[0] ^ secret[0] ^ starting_len, last[1] ^ secret[1]);
5702 }
5703};
src/Module.zig+38-31
......@@ -6430,8 +6430,10 @@ pub fn populateTestFunctions(
64306430 // func
64316431 try mod.intern(.{ .ptr = .{
64326432 .ty = try mod.intern(.{ .ptr_type = .{
6433 .elem_type = test_decl.ty.toIntern(),
6434 .is_const = true,
6433 .child = test_decl.ty.toIntern(),
6434 .flags = .{
6435 .is_const = true,
6436 },
64356437 } }),
64366438 .addr = .{ .decl = test_decl_index },
64376439 } }),
......@@ -6466,9 +6468,11 @@ pub fn populateTestFunctions(
64666468
64676469 {
64686470 const new_ty = try mod.ptrType(.{
6469 .elem_type = test_fn_ty.toIntern(),
6470 .is_const = true,
6471 .size = .Slice,
6471 .child = test_fn_ty.toIntern(),
6472 .flags = .{
6473 .is_const = true,
6474 .size = .Slice,
6475 },
64726476 });
64736477 const new_val = decl.val;
64746478 const new_init = try mod.intern(.{ .ptr = .{
......@@ -6681,65 +6685,68 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
66816685
66826686pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
66836687 var canon_info = info;
6684 const have_elem_layout = info.elem_type.toType().layoutIsResolved(mod);
6688 const have_elem_layout = info.child.toType().layoutIsResolved(mod);
66856689
6686 if (info.size == .C) canon_info.is_allowzero = true;
6690 if (info.flags.size == .C) canon_info.flags.is_allowzero = true;
66876691
66886692 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
66896693 // type, we change it to 0 here. If this causes an assertion trip because the
66906694 // pointee type needs to be resolved more, that needs to be done before calling
66916695 // this ptr() function.
6692 if (info.alignment.toByteUnitsOptional()) |info_align| {
6693 if (have_elem_layout and info_align == info.elem_type.toType().abiAlignment(mod)) {
6694 canon_info.alignment = .none;
6696 if (info.flags.alignment.toByteUnitsOptional()) |info_align| {
6697 if (have_elem_layout and info_align == info.child.toType().abiAlignment(mod)) {
6698 canon_info.flags.alignment = .none;
66956699 }
66966700 }
66976701
6698 switch (info.vector_index) {
6702 switch (info.flags.vector_index) {
66996703 // Canonicalize host_size. If it matches the bit size of the pointee type,
67006704 // we change it to 0 here. If this causes an assertion trip, the pointee type
67016705 // needs to be resolved before calling this ptr() function.
6702 .none => if (have_elem_layout and info.host_size != 0) {
6703 const elem_bit_size = info.elem_type.toType().bitSize(mod);
6704 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
6705 if (info.host_size * 8 == elem_bit_size) {
6706 canon_info.host_size = 0;
6706 .none => if (have_elem_layout and info.packed_offset.host_size != 0) {
6707 const elem_bit_size = info.child.toType().bitSize(mod);
6708 assert(info.packed_offset.bit_offset + elem_bit_size <= info.packed_offset.host_size * 8);
6709 if (info.packed_offset.host_size * 8 == elem_bit_size) {
6710 canon_info.packed_offset.host_size = 0;
67076711 }
67086712 },
67096713 .runtime => {},
6710 _ => assert(@enumToInt(info.vector_index) < info.host_size),
6714 _ => assert(@enumToInt(info.flags.vector_index) < info.packed_offset.host_size),
67116715 }
67126716
67136717 return (try intern(mod, .{ .ptr_type = canon_info })).toType();
67146718}
67156719
67166720pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6717 return ptrType(mod, .{ .elem_type = child_type.toIntern() });
6721 return ptrType(mod, .{ .child = child_type.toIntern() });
67186722}
67196723
67206724pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6721 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .is_const = true });
6725 return ptrType(mod, .{
6726 .child = child_type.toIntern(),
6727 .flags = .{
6728 .is_const = true,
6729 },
6730 });
67226731}
67236732
67246733pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6725 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .size = .Many, .is_const = true });
6734 return ptrType(mod, .{
6735 .child = child_type.toIntern(),
6736 .flags = .{
6737 .size = .Many,
6738 .is_const = true,
6739 },
6740 });
67266741}
67276742
67286743pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
67296744 const info = Type.ptrInfoIp(&mod.intern_pool, ptr_ty.toIntern());
67306745 return mod.ptrType(.{
6731 .elem_type = new_child.toIntern(),
6732
6746 .child = new_child.toIntern(),
67336747 .sentinel = info.sentinel,
6734 .alignment = info.alignment,
6735 .host_size = info.host_size,
6736 .bit_offset = info.bit_offset,
6737 .vector_index = info.vector_index,
6738 .size = info.size,
6739 .is_const = info.is_const,
6740 .is_volatile = info.is_volatile,
6741 .is_allowzero = info.is_allowzero,
6742 .address_space = info.address_space,
6748 .flags = info.flags,
6749 .packed_offset = info.packed_offset,
67436750 });
67446751}
67456752
src/Sema.zig+104-72
......@@ -2490,9 +2490,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24902490 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
24912491
24922492 const ptr_ty = try mod.ptrType(.{
2493 .elem_type = pointee_ty.toIntern(),
2494 .alignment = ia1.alignment,
2495 .address_space = addr_space,
2493 .child = pointee_ty.toIntern(),
2494 .flags = .{
2495 .alignment = ia1.alignment,
2496 .address_space = addr_space,
2497 },
24962498 });
24972499 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
24982500
......@@ -2519,9 +2521,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
25192521 try sema.resolveTypeLayout(pointee_ty);
25202522 }
25212523 const ptr_ty = try mod.ptrType(.{
2522 .elem_type = pointee_ty.toIntern(),
2523 .alignment = alignment,
2524 .address_space = addr_space,
2524 .child = pointee_ty.toIntern(),
2525 .flags = .{
2526 .alignment = alignment,
2527 .address_space = addr_space,
2528 },
25252529 });
25262530 try sema.maybeQueueFuncBodyAnalysis(decl_index);
25272531 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
......@@ -3771,10 +3775,12 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37713775 if (iac.is_const) try decl.intern(mod);
37723776 const final_elem_ty = decl.ty;
37733777 const final_ptr_ty = try mod.ptrType(.{
3774 .elem_type = final_elem_ty.toIntern(),
3775 .is_const = false,
3776 .alignment = iac.alignment,
3777 .address_space = target_util.defaultAddressSpace(target, .local),
3778 .child = final_elem_ty.toIntern(),
3779 .flags = .{
3780 .is_const = false,
3781 .alignment = iac.alignment,
3782 .address_space = target_util.defaultAddressSpace(target, .local),
3783 },
37783784 });
37793785
37803786 try sema.maybeQueueFuncBodyAnalysis(decl_index);
......@@ -3797,9 +3803,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37973803 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
37983804
37993805 const final_ptr_ty = try mod.ptrType(.{
3800 .elem_type = final_elem_ty.toIntern(),
3801 .alignment = ia1.alignment,
3802 .address_space = target_util.defaultAddressSpace(target, .local),
3806 .child = final_elem_ty.toIntern(),
3807 .flags = .{
3808 .alignment = ia1.alignment,
3809 .address_space = target_util.defaultAddressSpace(target, .local),
3810 },
38033811 });
38043812
38053813 if (!ia1.is_const) {
......@@ -3916,9 +3924,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
39163924 defer trash_block.instructions.deinit(gpa);
39173925
39183926 const mut_final_ptr_ty = try mod.ptrType(.{
3919 .elem_type = final_elem_ty.toIntern(),
3920 .alignment = ia1.alignment,
3921 .address_space = target_util.defaultAddressSpace(target, .local),
3927 .child = final_elem_ty.toIntern(),
3928 .flags = .{
3929 .alignment = ia1.alignment,
3930 .address_space = target_util.defaultAddressSpace(target, .local),
3931 },
39223932 });
39233933 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
39243934 const empty_trash_count = trash_block.instructions.items.len;
......@@ -12038,7 +12048,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1203812048
1203912049 const has_field = hf: {
1204012050 switch (ip.indexToKey(ty.toIntern())) {
12041 .ptr_type => |ptr_type| switch (ptr_type.size) {
12051 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1204212052 .Slice => {
1204312053 if (mem.eql(u8, field_name, "ptr")) break :hf true;
1204412054 if (mem.eql(u8, field_name, "len")) break :hf true;
......@@ -16019,9 +16029,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1601916029 );
1602016030 break :v try mod.intern(.{ .ptr = .{
1602116031 .ty = (try mod.ptrType(.{
16022 .elem_type = param_info_ty.toIntern(),
16023 .size = .Slice,
16024 .is_const = true,
16032 .child = param_info_ty.toIntern(),
16033 .flags = .{
16034 .size = .Slice,
16035 .is_const = true,
16036 },
1602516037 })).toIntern(),
1602616038 .addr = .{ .decl = new_decl },
1602716039 .len = (try mod.intValue(Type.usize, param_vals.len)).toIntern(),
......@@ -16329,9 +16341,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1632916341
1633016342 // Build our ?[]const Error value
1633116343 const slice_errors_ty = try mod.ptrType(.{
16332 .elem_type = error_field_ty.toIntern(),
16333 .size = .Slice,
16334 .is_const = true,
16344 .child = error_field_ty.toIntern(),
16345 .flags = .{
16346 .size = .Slice,
16347 .is_const = true,
16348 },
1633516349 });
1633616350 const opt_slice_errors_ty = try mod.optionalType(slice_errors_ty.toIntern());
1633716351 const errors_payload_val: InternPool.Index = if (error_field_vals) |vals| v: {
......@@ -16471,9 +16485,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1647116485 );
1647216486 break :v try mod.intern(.{ .ptr = .{
1647316487 .ty = (try mod.ptrType(.{
16474 .elem_type = enum_field_ty.toIntern(),
16475 .size = .Slice,
16476 .is_const = true,
16488 .child = enum_field_ty.toIntern(),
16489 .flags = .{
16490 .size = .Slice,
16491 .is_const = true,
16492 },
1647716493 })).toIntern(),
1647816494 .addr = .{ .decl = new_decl },
1647916495 .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),
......@@ -16614,9 +16630,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1661416630 );
1661516631 break :v try mod.intern(.{ .ptr = .{
1661616632 .ty = (try mod.ptrType(.{
16617 .elem_type = union_field_ty.toIntern(),
16618 .size = .Slice,
16619 .is_const = true,
16633 .child = union_field_ty.toIntern(),
16634 .flags = .{
16635 .size = .Slice,
16636 .is_const = true,
16637 },
1662016638 })).toIntern(),
1662116639 .addr = .{ .decl = new_decl },
1662216640 .len = (try mod.intValue(Type.usize, union_field_vals.len)).toIntern(),
......@@ -16833,9 +16851,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1683316851 );
1683416852 break :v try mod.intern(.{ .ptr = .{
1683516853 .ty = (try mod.ptrType(.{
16836 .elem_type = struct_field_ty.toIntern(),
16837 .size = .Slice,
16838 .is_const = true,
16854 .child = struct_field_ty.toIntern(),
16855 .flags = .{
16856 .size = .Slice,
16857 .is_const = true,
16858 },
1683916859 })).toIntern(),
1684016860 .addr = .{ .decl = new_decl },
1684116861 .len = (try mod.intValue(Type.usize, struct_field_vals.len)).toIntern(),
......@@ -16976,9 +16996,11 @@ fn typeInfoDecls(
1697616996 );
1697716997 return try mod.intern(.{ .ptr = .{
1697816998 .ty = (try mod.ptrType(.{
16979 .elem_type = declaration_ty.toIntern(),
16980 .size = .Slice,
16981 .is_const = true,
16999 .child = declaration_ty.toIntern(),
17000 .flags = .{
17001 .size = .Slice,
17002 .is_const = true,
17003 },
1698217004 })).toIntern(),
1698317005 .addr = .{ .decl = new_decl },
1698417006 .len = (try mod.intValue(Type.usize, decl_vals.items.len)).toIntern(),
......@@ -18047,16 +18069,20 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1804718069 }
1804818070
1804918071 const ty = try mod.ptrType(.{
18050 .elem_type = elem_ty.toIntern(),
18072 .child = elem_ty.toIntern(),
1805118073 .sentinel = sentinel,
18052 .alignment = abi_align,
18053 .address_space = address_space,
18054 .bit_offset = bit_offset,
18055 .host_size = host_size,
18056 .is_const = !inst_data.flags.is_mutable,
18057 .is_allowzero = inst_data.flags.is_allowzero,
18058 .is_volatile = inst_data.flags.is_volatile,
18059 .size = inst_data.size,
18074 .flags = .{
18075 .alignment = abi_align,
18076 .address_space = address_space,
18077 .is_const = !inst_data.flags.is_mutable,
18078 .is_allowzero = inst_data.flags.is_allowzero,
18079 .is_volatile = inst_data.flags.is_volatile,
18080 .size = inst_data.size,
18081 },
18082 .packed_offset = .{
18083 .bit_offset = bit_offset,
18084 .host_size = host_size,
18085 },
1806018086 });
1806118087 return sema.addType(ty);
1806218088}
......@@ -19209,14 +19235,16 @@ fn zirReify(
1920919235 }
1921019236
1921119237 const ty = try mod.ptrType(.{
19212 .size = ptr_size,
19213 .is_const = is_const_val.toBool(),
19214 .is_volatile = is_volatile_val.toBool(),
19215 .alignment = abi_align,
19216 .address_space = mod.toEnum(std.builtin.AddressSpace, address_space_val),
19217 .elem_type = elem_ty.toIntern(),
19218 .is_allowzero = is_allowzero_val.toBool(),
19238 .child = elem_ty.toIntern(),
1921919239 .sentinel = actual_sentinel,
19240 .flags = .{
19241 .size = ptr_size,
19242 .is_const = is_const_val.toBool(),
19243 .is_volatile = is_volatile_val.toBool(),
19244 .alignment = abi_align,
19245 .address_space = mod.toEnum(std.builtin.AddressSpace, address_space_val),
19246 .is_allowzero = is_allowzero_val.toBool(),
19247 },
1922019248 });
1922119249 return sema.addType(ty);
1922219250 },
......@@ -22714,9 +22742,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2271422742 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
2271522743 else if (new_dest_ptr_ty.ptrSize(mod) == .One) ptr: {
2271622744 var dest_manyptr_ty_key = mod.intern_pool.indexToKey(new_dest_ptr_ty.toIntern()).ptr_type;
22717 assert(dest_manyptr_ty_key.size == .One);
22718 dest_manyptr_ty_key.elem_type = dest_elem_ty.toIntern();
22719 dest_manyptr_ty_key.size = .Many;
22745 assert(dest_manyptr_ty_key.flags.size == .One);
22746 dest_manyptr_ty_key.child = dest_elem_ty.toIntern();
22747 dest_manyptr_ty_key.flags.size = .Many;
2272022748 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);
2272122749 } else new_dest_ptr;
2272222750
......@@ -22725,9 +22753,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2272522753 try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty)
2272622754 else if (new_src_ptr_ty.ptrSize(mod) == .One) ptr: {
2272722755 var src_manyptr_ty_key = mod.intern_pool.indexToKey(new_src_ptr_ty.toIntern()).ptr_type;
22728 assert(src_manyptr_ty_key.size == .One);
22729 src_manyptr_ty_key.elem_type = src_elem_ty.toIntern();
22730 src_manyptr_ty_key.size = .Many;
22756 assert(src_manyptr_ty_key.flags.size == .One);
22757 src_manyptr_ty_key.child = src_elem_ty.toIntern();
22758 src_manyptr_ty_key.flags.size = .Many;
2273122759 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);
2273222760 } else new_src_ptr;
2273322761
......@@ -24036,8 +24064,10 @@ fn panicWithMsg(
2403624064 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
2403724065 const target = mod.getTarget();
2403824066 const ptr_stack_trace_ty = try mod.ptrType(.{
24039 .elem_type = stack_trace_ty.toIntern(),
24040 .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
24067 .child = stack_trace_ty.toIntern(),
24068 .flags = .{
24069 .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
24070 },
2404124071 });
2404224072 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
2404324073 const null_stack_trace = try sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{
......@@ -29630,10 +29660,12 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo
2963029660 const decl = mod.declPtr(decl_index);
2963129661 const decl_tv = try decl.typedValue();
2963229662 const ptr_ty = try mod.ptrType(.{
29633 .elem_type = decl_tv.ty.toIntern(),
29634 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29635 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
29636 .address_space = decl.@"addrspace",
29663 .child = decl_tv.ty.toIntern(),
29664 .flags = .{
29665 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29666 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
29667 .address_space = decl.@"addrspace",
29668 },
2963729669 });
2963829670 if (analyze_fn_body) {
2963929671 try sema.maybeQueueFuncBodyAnalysis(decl_index);
......@@ -30025,10 +30057,10 @@ fn analyzeSlice(
3002530057 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
3002630058 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {
3002730059 var manyptr_ty_key = mod.intern_pool.indexToKey(slice_ty.toIntern()).ptr_type;
30028 assert(manyptr_ty_key.elem_type == array_ty.toIntern());
30029 assert(manyptr_ty_key.size == .One);
30030 manyptr_ty_key.elem_type = elem_ty.toIntern();
30031 manyptr_ty_key.size = .Many;
30060 assert(manyptr_ty_key.child == array_ty.toIntern());
30061 assert(manyptr_ty_key.flags.size == .One);
30062 manyptr_ty_key.child = elem_ty.toIntern();
30063 manyptr_ty_key.flags.size = .Many;
3003230064 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);
3003330065 } else ptr_or_slice;
3003430066
......@@ -31972,7 +32004,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3197232004 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3197332005 .int_type => false,
3197432006 .ptr_type => |ptr_type| {
31975 const child_ty = ptr_type.elem_type.toType();
32007 const child_ty = ptr_type.child.toType();
3197632008 if (child_ty.zigTypeTag(mod) == .Fn) {
3197732009 return mod.typeToFunc(child_ty).?.is_generic;
3197832010 } else {
......@@ -33917,15 +33949,15 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError
3391733949fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
3391833950 const mod = sema.mod;
3391933951 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
33920 .ptr_type => |ptr_type| switch (ptr_type.size) {
33952 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3392133953 .One, .Many, .C => ty,
3392233954 .Slice => null,
3392333955 },
3392433956 .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) {
33925 .ptr_type => |ptr_type| switch (ptr_type.size) {
33957 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3392633958 .Slice, .C => null,
3392733959 .Many, .One => {
33928 if (ptr_type.is_allowzero) return null;
33960 if (ptr_type.flags.is_allowzero) return null;
3392933961
3393033962 // optionals of zero sized types behave like bools, not pointers
3393133963 const payload_ty = opt_child.toType();
......@@ -33956,7 +33988,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3395633988 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3395733989 .int_type => return false,
3395833990 .ptr_type => |ptr_type| {
33959 const child_ty = ptr_type.elem_type.toType();
33991 const child_ty = ptr_type.child.toType();
3396033992 if (child_ty.zigTypeTag(mod) == .Fn) {
3396133993 return mod.typeToFunc(child_ty).?.is_generic;
3396233994 } else {
src/codegen.zig+2-2
......@@ -673,7 +673,7 @@ fn lowerParentPtr(
673673 mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).abiSize(mod))),
674674 ),
675675 .field => |field| {
676 const base_type = mod.intern_pool.indexToKey(mod.intern_pool.typeOf(field.base)).ptr_type.elem_type;
676 const base_type = mod.intern_pool.indexToKey(mod.intern_pool.typeOf(field.base)).ptr_type.child;
677677 return lowerParentPtr(
678678 bin_file,
679679 src_loc,
......@@ -681,7 +681,7 @@ fn lowerParentPtr(
681681 code,
682682 debug_output,
683683 reloc_info.offset(switch (mod.intern_pool.indexToKey(base_type)) {
684 .ptr_type => |ptr_type| switch (ptr_type.size) {
684 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
685685 .One, .Many, .C => unreachable,
686686 .Slice => switch (field.index) {
687687 0 => 0,
src/codegen/c.zig+6-4
......@@ -630,7 +630,7 @@ pub const DeclGen = struct {
630630 try writer.writeByte(')');
631631 }
632632 try writer.writeAll("&(");
633 if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.size == .One)
633 if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One)
634634 try writer.writeByte('*');
635635 try dg.renderParentPtr(writer, elem.base, location);
636636 try writer.print(")[{d}]", .{elem.index});
......@@ -642,7 +642,7 @@ pub const DeclGen = struct {
642642 _ = try dg.typeToIndex(base_ty, .complete);
643643 const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {
644644 .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(field.index, mod),
645 .ptr_type => |ptr_type| switch (ptr_type.size) {
645 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
646646 .One, .Many, .C => unreachable,
647647 .Slice => switch (field.index) {
648648 Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),
......@@ -6285,8 +6285,10 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
62856285 // casted to a regular pointer, otherwise an error like this occurs:
62866286 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable
62876287 const elem_ptr_ty = try mod.ptrType(.{
6288 .size = .C,
6289 .elem_type = elem_ty.ip_index,
6288 .child = elem_ty.ip_index,
6289 .flags = .{
6290 .size = .C,
6291 },
62906292 });
62916293
62926294 const index = try f.allocLocal(inst, Type.usize);
src/codegen/llvm.zig+37-27
......@@ -1577,25 +1577,27 @@ pub const Object = struct {
15771577 const ptr_info = Type.ptrInfoIp(&mod.intern_pool, ty.toIntern());
15781578
15791579 if (ptr_info.sentinel != .none or
1580 ptr_info.address_space != .generic or
1581 ptr_info.bit_offset != 0 or
1582 ptr_info.host_size != 0 or
1583 ptr_info.vector_index != .none or
1584 ptr_info.is_allowzero or
1585 ptr_info.is_const or
1586 ptr_info.is_volatile or
1587 ptr_info.size == .Many or ptr_info.size == .C or
1588 !ptr_info.elem_type.toType().hasRuntimeBitsIgnoreComptime(mod))
1580 ptr_info.flags.address_space != .generic or
1581 ptr_info.packed_offset.bit_offset != 0 or
1582 ptr_info.packed_offset.host_size != 0 or
1583 ptr_info.flags.vector_index != .none or
1584 ptr_info.flags.is_allowzero or
1585 ptr_info.flags.is_const or
1586 ptr_info.flags.is_volatile or
1587 ptr_info.flags.size == .Many or ptr_info.flags.size == .C or
1588 !ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
15891589 {
15901590 const bland_ptr_ty = try mod.ptrType(.{
1591 .elem_type = if (!ptr_info.elem_type.toType().hasRuntimeBitsIgnoreComptime(mod))
1591 .child = if (!ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
15921592 .anyopaque_type
15931593 else
1594 ptr_info.elem_type,
1595 .alignment = ptr_info.alignment,
1596 .size = switch (ptr_info.size) {
1597 .Many, .C, .One => .One,
1598 .Slice => .Slice,
1594 ptr_info.child,
1595 .flags = .{
1596 .alignment = ptr_info.flags.alignment,
1597 .size = switch (ptr_info.flags.size) {
1598 .Many, .C, .One => .One,
1599 .Slice => .Slice,
1600 },
15991601 },
16001602 });
16011603 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
......@@ -1683,7 +1685,7 @@ pub const Object = struct {
16831685 return full_di_ty;
16841686 }
16851687
1686 const elem_di_ty = try o.lowerDebugType(ptr_info.elem_type.toType(), .fwd);
1688 const elem_di_ty = try o.lowerDebugType(ptr_info.child.toType(), .fwd);
16871689 const name = try ty.nameAlloc(gpa, o.module);
16881690 defer gpa.free(name);
16891691 const ptr_di_ty = dib.createPointerType(
......@@ -5856,8 +5858,10 @@ pub const FuncGen = struct {
58565858 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
58575859 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");
58585860 const field_ptr_ty = try mod.ptrType(.{
5859 .elem_type = llvm_field.ty.toIntern(),
5860 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
5861 .child = llvm_field.ty.toIntern(),
5862 .flags = .{
5863 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
5864 },
58615865 });
58625866 if (isByRef(field_ty, mod)) {
58635867 if (canElideLoad(self, body_tail))
......@@ -6732,8 +6736,10 @@ pub const FuncGen = struct {
67326736 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
67336737 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");
67346738 const field_ptr_ty = try mod.ptrType(.{
6735 .elem_type = llvm_field.ty.toIntern(),
6736 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
6739 .child = llvm_field.ty.toIntern(),
6740 .flags = .{
6741 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
6742 },
67376743 });
67386744 return self.load(field_ptr, field_ptr_ty);
67396745 }
......@@ -9131,10 +9137,12 @@ pub const FuncGen = struct {
91319137 indices[1] = llvm_u32.constInt(llvm_i, .False);
91329138 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
91339139 const field_ptr_ty = try mod.ptrType(.{
9134 .elem_type = self.typeOf(elem).toIntern(),
9135 .alignment = InternPool.Alignment.fromNonzeroByteUnits(
9136 result_ty.structFieldAlign(i, mod),
9137 ),
9140 .child = self.typeOf(elem).toIntern(),
9141 .flags = .{
9142 .alignment = InternPool.Alignment.fromNonzeroByteUnits(
9143 result_ty.structFieldAlign(i, mod),
9144 ),
9145 },
91389146 });
91399147 try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);
91409148 }
......@@ -9160,7 +9168,7 @@ pub const FuncGen = struct {
91609168
91619169 const array_info = result_ty.arrayInfo(mod);
91629170 const elem_ptr_ty = try mod.ptrType(.{
9163 .elem_type = array_info.elem_type.toIntern(),
9171 .child = array_info.elem_type.toIntern(),
91649172 });
91659173
91669174 for (elements, 0..) |elem, i| {
......@@ -9282,8 +9290,10 @@ pub const FuncGen = struct {
92829290 const index_type = self.context.intType(32);
92839291
92849292 const field_ptr_ty = try mod.ptrType(.{
9285 .elem_type = field.ty.toIntern(),
9286 .alignment = InternPool.Alignment.fromNonzeroByteUnits(field_align),
9293 .child = field.ty.toIntern(),
9294 .flags = .{
9295 .alignment = InternPool.Alignment.fromNonzeroByteUnits(field_align),
9296 },
92879297 });
92889298 if (layout.tag_size == 0) {
92899299 const indices: [3]*llvm.Value = .{
src/type.zig+56-52
......@@ -85,7 +85,7 @@ pub const Type = struct {
8585
8686 /// Asserts the type is a pointer.
8787 pub fn ptrIsMutable(ty: Type, mod: *const Module) bool {
88 return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.is_const;
88 return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.flags.is_const;
8989 }
9090
9191 pub const ArrayInfo = struct {
......@@ -488,7 +488,7 @@ pub const Type = struct {
488488 // Pointers to zero-bit types still have a runtime address; however, pointers
489489 // to comptime-only types do not, with the exception of function pointers.
490490 if (ignore_comptime_only) return true;
491 const child_ty = ptr_type.elem_type.toType();
491 const child_ty = ptr_type.child.toType();
492492 if (child_ty.zigTypeTag(mod) == .Fn) return !mod.typeToFunc(child_ty).?.is_generic;
493493 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
494494 return !comptimeOnly(ty, mod);
......@@ -689,7 +689,7 @@ pub const Type = struct {
689689
690690 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
691691 .opt_type => ty.isPtrLikeOptional(mod),
692 .ptr_type => |ptr_type| ptr_type.size != .Slice,
692 .ptr_type => |ptr_type| ptr_type.flags.size != .Slice,
693693
694694 .simple_type => |t| switch (t) {
695695 .f16,
......@@ -823,13 +823,13 @@ pub const Type = struct {
823823 pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !u32 {
824824 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
825825 .ptr_type => |ptr_type| {
826 if (ptr_type.alignment.toByteUnitsOptional()) |a| {
826 if (ptr_type.flags.alignment.toByteUnitsOptional()) |a| {
827827 return @intCast(u32, a);
828828 } else if (opt_sema) |sema| {
829 const res = try ptr_type.elem_type.toType().abiAlignmentAdvanced(mod, .{ .sema = sema });
829 const res = try ptr_type.child.toType().abiAlignmentAdvanced(mod, .{ .sema = sema });
830830 return res.scalar;
831831 } else {
832 return (ptr_type.elem_type.toType().abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
832 return (ptr_type.child.toType().abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
833833 }
834834 },
835835 .opt_type => |child| child.toType().ptrAlignmentAdvanced(mod, opt_sema),
......@@ -839,8 +839,8 @@ pub const Type = struct {
839839
840840 pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {
841841 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
842 .ptr_type => |ptr_type| ptr_type.address_space,
843 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.address_space,
842 .ptr_type => |ptr_type| ptr_type.flags.address_space,
843 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.flags.address_space,
844844 else => unreachable,
845845 };
846846 }
......@@ -1297,7 +1297,7 @@ pub const Type = struct {
12971297 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
12981298 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
12991299 },
1300 .ptr_type => |ptr_type| switch (ptr_type.size) {
1300 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
13011301 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
13021302 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
13031303 },
......@@ -1620,7 +1620,7 @@ pub const Type = struct {
16201620
16211621 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
16221622 .int_type => |int_type| return int_type.bits,
1623 .ptr_type => |ptr_type| switch (ptr_type.size) {
1623 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
16241624 .Slice => return target.ptrBitWidth() * 2,
16251625 else => return target.ptrBitWidth(),
16261626 },
......@@ -1795,7 +1795,7 @@ pub const Type = struct {
17951795
17961796 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
17971797 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1798 .ptr_type => |ptr_info| ptr_info.size == .One,
1798 .ptr_type => |ptr_info| ptr_info.flags.size == .One,
17991799 else => false,
18001800 };
18011801 }
......@@ -1808,14 +1808,14 @@ pub const Type = struct {
18081808 /// Returns `null` if `ty` is not a pointer.
18091809 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
18101810 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1811 .ptr_type => |ptr_info| ptr_info.size,
1811 .ptr_type => |ptr_info| ptr_info.flags.size,
18121812 else => null,
18131813 };
18141814 }
18151815
18161816 pub fn isSlice(ty: Type, mod: *const Module) bool {
18171817 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1818 .ptr_type => |ptr_type| ptr_type.size == .Slice,
1818 .ptr_type => |ptr_type| ptr_type.flags.size == .Slice,
18191819 else => false,
18201820 };
18211821 }
......@@ -1826,7 +1826,7 @@ pub const Type = struct {
18261826
18271827 pub fn isConstPtr(ty: Type, mod: *const Module) bool {
18281828 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1829 .ptr_type => |ptr_type| ptr_type.is_const,
1829 .ptr_type => |ptr_type| ptr_type.flags.is_const,
18301830 else => false,
18311831 };
18321832 }
......@@ -1837,14 +1837,14 @@ pub const Type = struct {
18371837
18381838 pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {
18391839 return switch (ip.indexToKey(ty.toIntern())) {
1840 .ptr_type => |ptr_type| ptr_type.is_volatile,
1840 .ptr_type => |ptr_type| ptr_type.flags.is_volatile,
18411841 else => false,
18421842 };
18431843 }
18441844
18451845 pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {
18461846 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1847 .ptr_type => |ptr_type| ptr_type.is_allowzero,
1847 .ptr_type => |ptr_type| ptr_type.flags.is_allowzero,
18481848 .opt_type => true,
18491849 else => false,
18501850 };
......@@ -1852,21 +1852,21 @@ pub const Type = struct {
18521852
18531853 pub fn isCPtr(ty: Type, mod: *const Module) bool {
18541854 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1855 .ptr_type => |ptr_type| ptr_type.size == .C,
1855 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
18561856 else => false,
18571857 };
18581858 }
18591859
18601860 pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {
18611861 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1862 .ptr_type => |ptr_type| switch (ptr_type.size) {
1862 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
18631863 .Slice => false,
18641864 .One, .Many, .C => true,
18651865 },
18661866 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1867 .ptr_type => |p| switch (p.size) {
1867 .ptr_type => |p| switch (p.flags.size) {
18681868 .Slice, .C => false,
1869 .Many, .One => !p.is_allowzero,
1869 .Many, .One => !p.flags.is_allowzero,
18701870 },
18711871 else => false,
18721872 },
......@@ -1887,14 +1887,14 @@ pub const Type = struct {
18871887 pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
18881888 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
18891889 .opt_type => |child_type| switch (mod.intern_pool.indexToKey(child_type)) {
1890 .ptr_type => |ptr_type| switch (ptr_type.size) {
1890 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
18911891 .C => false,
1892 .Slice, .Many, .One => !ptr_type.is_allowzero,
1892 .Slice, .Many, .One => !ptr_type.flags.is_allowzero,
18931893 },
18941894 .error_set_type => true,
18951895 else => false,
18961896 },
1897 .ptr_type => |ptr_type| ptr_type.size == .C,
1897 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
18981898 else => false,
18991899 };
19001900 }
......@@ -1904,11 +1904,11 @@ pub const Type = struct {
19041904 /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
19051905 pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
19061906 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1907 .ptr_type => |ptr_type| ptr_type.size == .C,
1907 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
19081908 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1909 .ptr_type => |ptr_type| switch (ptr_type.size) {
1909 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
19101910 .Slice, .C => false,
1911 .Many, .One => !ptr_type.is_allowzero,
1911 .Many, .One => !ptr_type.flags.is_allowzero,
19121912 },
19131913 else => false,
19141914 },
......@@ -1938,9 +1938,9 @@ pub const Type = struct {
19381938 /// For anyframe->T, returns T.
19391939 pub fn elemType2(ty: Type, mod: *const Module) Type {
19401940 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1941 .ptr_type => |ptr_type| switch (ptr_type.size) {
1942 .One => ptr_type.elem_type.toType().shallowElemType(mod),
1943 .Many, .C, .Slice => ptr_type.elem_type.toType(),
1941 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1942 .One => ptr_type.child.toType().shallowElemType(mod),
1943 .Many, .C, .Slice => ptr_type.child.toType(),
19441944 },
19451945 .anyframe_type => |child| {
19461946 assert(child != .none);
......@@ -1974,7 +1974,7 @@ pub const Type = struct {
19741974 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
19751975 .opt_type => |child| child.toType(),
19761976 .ptr_type => |ptr_type| b: {
1977 assert(ptr_type.size == .C);
1977 assert(ptr_type.flags.size == .C);
19781978 break :b ty;
19791979 },
19801980 else => unreachable,
......@@ -2390,7 +2390,7 @@ pub const Type = struct {
23902390
23912391 pub fn fnReturnTypeIp(ty: Type, ip: *const InternPool) Type {
23922392 return switch (ip.indexToKey(ty.toIntern())) {
2393 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.elem_type).func_type.return_type,
2393 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.child).func_type.return_type,
23942394 .func_type => |func_type| func_type.return_type,
23952395 else => unreachable,
23962396 }.toType();
......@@ -2672,7 +2672,7 @@ pub const Type = struct {
26722672 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
26732673 .int_type => false,
26742674 .ptr_type => |ptr_type| {
2675 const child_ty = ptr_type.elem_type.toType();
2675 const child_ty = ptr_type.child.toType();
26762676 if (child_ty.zigTypeTag(mod) == .Fn) {
26772677 return false;
26782678 } else {
......@@ -3374,17 +3374,17 @@ pub const Type = struct {
33743374
33753375 pub fn fromKey(p: InternPool.Key.PtrType) Data {
33763376 return .{
3377 .pointee_type = p.elem_type.toType(),
3377 .pointee_type = p.child.toType(),
33783378 .sentinel = if (p.sentinel != .none) p.sentinel.toValue() else null,
3379 .@"align" = @intCast(u32, p.alignment.toByteUnits(0)),
3380 .@"addrspace" = p.address_space,
3381 .bit_offset = p.bit_offset,
3382 .host_size = p.host_size,
3383 .vector_index = p.vector_index,
3384 .@"allowzero" = p.is_allowzero,
3385 .mutable = !p.is_const,
3386 .@"volatile" = p.is_volatile,
3387 .size = p.size,
3379 .@"align" = @intCast(u32, p.flags.alignment.toByteUnits(0)),
3380 .@"addrspace" = p.flags.address_space,
3381 .bit_offset = p.packed_offset.bit_offset,
3382 .host_size = p.packed_offset.host_size,
3383 .vector_index = p.flags.vector_index,
3384 .@"allowzero" = p.flags.is_allowzero,
3385 .mutable = !p.flags.is_const,
3386 .@"volatile" = p.flags.is_volatile,
3387 .size = p.flags.size,
33883388 };
33893389 }
33903390 };
......@@ -3478,17 +3478,21 @@ pub const Type = struct {
34783478 }
34793479
34803480 return mod.ptrType(.{
3481 .elem_type = d.pointee_type.ip_index,
3481 .child = d.pointee_type.ip_index,
34823482 .sentinel = if (d.sentinel) |s| s.ip_index else .none,
3483 .alignment = InternPool.Alignment.fromByteUnits(d.@"align"),
3484 .host_size = d.host_size,
3485 .bit_offset = d.bit_offset,
3486 .vector_index = d.vector_index,
3487 .size = d.size,
3488 .is_const = !d.mutable,
3489 .is_volatile = d.@"volatile",
3490 .is_allowzero = d.@"allowzero",
3491 .address_space = d.@"addrspace",
3483 .flags = .{
3484 .alignment = InternPool.Alignment.fromByteUnits(d.@"align"),
3485 .vector_index = d.vector_index,
3486 .size = d.size,
3487 .is_const = !d.mutable,
3488 .is_volatile = d.@"volatile",
3489 .is_allowzero = d.@"allowzero",
3490 .address_space = d.@"addrspace",
3491 },
3492 .packed_offset = .{
3493 .host_size = d.host_size,
3494 .bit_offset = d.bit_offset,
3495 },
34923496 });
34933497 }
34943498
src/value.zig+2-2
......@@ -2080,8 +2080,8 @@ pub const Value = struct {
20802080 else => val,
20812081 };
20822082 var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type;
2083 assert(ptr_ty_key.size != .Slice);
2084 ptr_ty_key.size = .Many;
2083 assert(ptr_ty_key.flags.size != .Slice);
2084 ptr_ty_key.flags.size = .Many;
20852085 return (try mod.intern(.{ .ptr = .{
20862086 .ty = elem_ptr_ty.toIntern(),
20872087 .addr = .{ .elem = .{