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) {...@@ -249,35 +249,47 @@ pub const Key = union(enum) {
249 }249 }
250 };250 };
251251
252 pub const PtrType = struct {252 /// Extern layout so it can be hashed with `std.mem.asBytes`.
253 elem_type: Index,253 pub const PtrType = extern struct {
254 child: Index,
254 sentinel: Index = .none,255 sentinel: Index = .none,
255 /// `none` indicates the ABI alignment of the pointee_type. In this256 flags: Flags = .{},
256 /// case, this field *must* be set to `none`, otherwise the257 packed_offset: PackedOffset = .{ .bit_offset = 0, .host_size = 0 },
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,
275258
276 pub const VectorIndex = enum(u16) {259 pub const VectorIndex = enum(u16) {
277 none = std.math.maxInt(u16),260 none = std.math.maxInt(u16),
278 runtime = std.math.maxInt(u16) - 1,261 runtime = std.math.maxInt(u16) - 1,
279 _,262 _,
280 };263 };
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;
281 };293 };
282294
283 pub const ArrayType = struct {295 pub const ArrayType = struct {
...@@ -635,17 +647,13 @@ pub const Key = union(enum) {...@@ -635,17 +647,13 @@ pub const Key = union(enum) {
635 }647 }
636648
637 pub fn hash64(key: Key, ip: *const InternPool) u64 {649 pub fn hash64(key: Key, ip: *const InternPool) u64 {
638 var hasher = std.hash.Wyhash.init(0);650 const asBytes = std.mem.asBytes;
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 {
644 const KeyTag = @typeInfo(Key).Union.tag_type.?;651 const KeyTag = @typeInfo(Key).Union.tag_type.?;
645 std.hash.autoHash(hasher, @as(KeyTag, key));652 const seed = @enumToInt(@as(KeyTag, key));
646 switch (key) {653 switch (key) {
654 .ptr_type => |x| return WyhashKing.hash(seed, asBytes(&x)),
655
647 inline .int_type,656 inline .int_type,
648 .ptr_type,
649 .array_type,657 .array_type,
650 .vector_type,658 .vector_type,
651 .opt_type,659 .opt_type,
...@@ -663,73 +671,110 @@ pub const Key = union(enum) {...@@ -663,73 +671,110 @@ pub const Key = union(enum) {
663 .enum_literal,671 .enum_literal,
664 .enum_tag,672 .enum_tag,
665 .inferred_error_set_type,673 .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),680 .runtime_value => |runtime_value| {
669 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),681 var hasher = std.hash.Wyhash.init(seed);
670 .enum_type => |enum_type| std.hash.autoHash(hasher, enum_type.decl),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 },
673 .extern_func => |extern_func| {701 .extern_func => |extern_func| {
674 std.hash.autoHash(hasher, extern_func.ty);702 var hasher = std.hash.Wyhash.init(seed);
675 std.hash.autoHash(hasher, extern_func.decl);703 std.hash.autoHash(&hasher, extern_func.ty);
704 std.hash.autoHash(&hasher, extern_func.decl);
705 return hasher.final();
676 },706 },
677 .func => |func| {707 .func => |func| {
678 std.hash.autoHash(hasher, func.ty);708 var hasher = std.hash.Wyhash.init(seed);
679 std.hash.autoHash(hasher, func.index);709 std.hash.autoHash(&hasher, func.ty);
710 std.hash.autoHash(&hasher, func.index);
711 return hasher.final();
680 },712 },
681713
682 .int => |int| {714 .int => |int| {
715 var hasher = std.hash.Wyhash.init(seed);
683 // Canonicalize all integers by converting them to BigIntConst.716 // Canonicalize all integers by converting them to BigIntConst.
684 switch (int.storage) {717 switch (int.storage) {
685 .u64, .i64, .big_int => {718 .u64, .i64, .big_int => {
686 var buffer: Key.Int.Storage.BigIntSpace = undefined;719 var buffer: Key.Int.Storage.BigIntSpace = undefined;
687 const big_int = int.storage.toBigInt(&buffer);720 const big_int = int.storage.toBigInt(&buffer);
688721
689 std.hash.autoHash(hasher, int.ty);722 std.hash.autoHash(&hasher, int.ty);
690 std.hash.autoHash(hasher, big_int.positive);723 std.hash.autoHash(&hasher, big_int.positive);
691 for (big_int.limbs) |limb| std.hash.autoHash(hasher, limb);724 for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb);
692 },725 },
693 .lazy_align, .lazy_size => |lazy_ty| {726 .lazy_align, .lazy_size => |lazy_ty| {
694 std.hash.autoHash(727 std.hash.autoHash(
695 hasher,728 &hasher,
696 @as(@typeInfo(Key.Int.Storage).Union.tag_type.?, int.storage),729 @as(@typeInfo(Key.Int.Storage).Union.tag_type.?, int.storage),
697 );730 );
698 std.hash.autoHash(hasher, lazy_ty);731 std.hash.autoHash(&hasher, lazy_ty);
699 },732 },
700 }733 }
734 return hasher.final();
701 },735 },
702736
703 .float => |float| {737 .float => |float| {
704 std.hash.autoHash(hasher, float.ty);738 var hasher = std.hash.Wyhash.init(seed);
739 std.hash.autoHash(&hasher, float.ty);
705 switch (float.storage) {740 switch (float.storage) {
706 inline else => |val| std.hash.autoHash(741 inline else => |val| std.hash.autoHash(
707 hasher,742 &hasher,
708 @bitCast(std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(val))), val),743 @bitCast(std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(val))), val),
709 ),744 ),
710 }745 }
746 return hasher.final();
711 },747 },
712748
713 .ptr => |ptr| {749 .ptr => |ptr| {
714 std.hash.autoHash(hasher, ptr.ty);
715 std.hash.autoHash(hasher, ptr.len);
716 // Int-to-ptr pointers are hashed separately than decl-referencing pointers.750 // Int-to-ptr pointers are hashed separately than decl-referencing pointers.
717 // This is sound due to pointer provenance rules.751 // This is sound due to pointer provenance rules.
718 std.hash.autoHash(hasher, @as(@typeInfo(Key.Ptr.Addr).Union.tag_type.?, ptr.addr));752 const addr: @typeInfo(Key.Ptr.Addr).Union.tag_type.? = ptr.addr;
719 switch (ptr.addr) {753 const seed2 = seed + @enumToInt(addr);
720 .decl => |decl| std.hash.autoHash(hasher, decl),754 const common = asBytes(&ptr.ty) ++ asBytes(&ptr.len);
721 .mut_decl => |mut_decl| std.hash.autoHash(hasher, mut_decl),755 return switch (ptr.addr) {
722 .int => |int| std.hash.autoHash(hasher, int),756 .decl => |x| WyhashKing.hash(seed2, common ++ asBytes(&x)),
723 .eu_payload => |eu_payload| std.hash.autoHash(hasher, eu_payload),757
724 .opt_payload => |opt_payload| std.hash.autoHash(hasher, opt_payload),758 .mut_decl => |x| WyhashKing.hash(
725 .comptime_field => |comptime_field| std.hash.autoHash(hasher, comptime_field),759 seed2,
726 .elem => |elem| std.hash.autoHash(hasher, elem),760 asBytes(&x.decl) ++ asBytes(&x.runtime_index),
727 .field => |field| std.hash.autoHash(hasher, field),761 ),
728 }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 };
729 },773 },
730774
731 .aggregate => |aggregate| {775 .aggregate => |aggregate| {
732 std.hash.autoHash(hasher, aggregate.ty);776 var hasher = std.hash.Wyhash.init(seed);
777 std.hash.autoHash(&hasher, aggregate.ty);
733 const len = ip.aggregateTypeLen(aggregate.ty);778 const len = ip.aggregateTypeLen(aggregate.ty);
734 const child = switch (ip.indexToKey(aggregate.ty)) {779 const child = switch (ip.indexToKey(aggregate.ty)) {
735 .array_type => |array_type| array_type.child,780 .array_type => |array_type| array_type.child,
...@@ -741,16 +786,16 @@ pub const Key = union(enum) {...@@ -741,16 +786,16 @@ pub const Key = union(enum) {
741 if (child == .u8_type) {786 if (child == .u8_type) {
742 switch (aggregate.storage) {787 switch (aggregate.storage) {
743 .bytes => |bytes| for (bytes[0..@intCast(usize, len)]) |byte| {788 .bytes => |bytes| for (bytes[0..@intCast(usize, len)]) |byte| {
744 std.hash.autoHash(hasher, KeyTag.int);789 std.hash.autoHash(&hasher, KeyTag.int);
745 std.hash.autoHash(hasher, byte);790 std.hash.autoHash(&hasher, byte);
746 },791 },
747 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem| {792 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem| {
748 const elem_key = ip.indexToKey(elem);793 const elem_key = ip.indexToKey(elem);
749 std.hash.autoHash(hasher, @as(KeyTag, elem_key));794 std.hash.autoHash(&hasher, @as(KeyTag, elem_key));
750 switch (elem_key) {795 switch (elem_key) {
751 .undef => {},796 .undef => {},
752 .int => |int| std.hash.autoHash(797 .int => |int| std.hash.autoHash(
753 hasher,798 &hasher,
754 @intCast(u8, int.storage.u64),799 @intCast(u8, int.storage.u64),
755 ),800 ),
756 else => unreachable,801 else => unreachable,
...@@ -760,11 +805,11 @@ pub const Key = union(enum) {...@@ -760,11 +805,11 @@ pub const Key = union(enum) {
760 const elem_key = ip.indexToKey(elem);805 const elem_key = ip.indexToKey(elem);
761 var remaining = len;806 var remaining = len;
762 while (remaining > 0) : (remaining -= 1) {807 while (remaining > 0) : (remaining -= 1) {
763 std.hash.autoHash(hasher, @as(KeyTag, elem_key));808 std.hash.autoHash(&hasher, @as(KeyTag, elem_key));
764 switch (elem_key) {809 switch (elem_key) {
765 .undef => {},810 .undef => {},
766 .int => |int| std.hash.autoHash(811 .int => |int| std.hash.autoHash(
767 hasher,812 &hasher,
768 @intCast(u8, int.storage.u64),813 @intCast(u8, int.storage.u64),
769 ),814 ),
770 else => unreachable,815 else => unreachable,
...@@ -772,47 +817,60 @@ pub const Key = union(enum) {...@@ -772,47 +817,60 @@ pub const Key = union(enum) {
772 }817 }
773 },818 },
774 }819 }
775 return;820 return hasher.final();
776 }821 }
777822
778 switch (aggregate.storage) {823 switch (aggregate.storage) {
779 .bytes => unreachable,824 .bytes => unreachable,
780 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem|825 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem|
781 std.hash.autoHash(hasher, elem),826 std.hash.autoHash(&hasher, elem),
782 .repeated_elem => |elem| {827 .repeated_elem => |elem| {
783 var remaining = len;828 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);
785 },830 },
786 }831 }
832 return hasher.final();
787 },833 },
788834
789 .error_set_type => |error_set_type| {835 .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();
791 },839 },
792840
793 .anon_struct_type => |anon_struct_type| {841 .anon_struct_type => |anon_struct_type| {
794 for (anon_struct_type.types) |elem| std.hash.autoHash(hasher, elem);842 var hasher = std.hash.Wyhash.init(seed);
795 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);843 for (anon_struct_type.types) |elem| std.hash.autoHash(&hasher, elem);
796 for (anon_struct_type.names) |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();
797 },847 },
798848
799 .func_type => |func_type| {849 .func_type => |func_type| {
800 for (func_type.param_types) |param_type| std.hash.autoHash(hasher, param_type);850 var hasher = std.hash.Wyhash.init(seed);
801 std.hash.autoHash(hasher, func_type.return_type);851 for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type);
802 std.hash.autoHash(hasher, func_type.comptime_bits);852 std.hash.autoHash(&hasher, func_type.return_type);
803 std.hash.autoHash(hasher, func_type.noalias_bits);853 std.hash.autoHash(&hasher, func_type.comptime_bits);
804 std.hash.autoHash(hasher, func_type.alignment);854 std.hash.autoHash(&hasher, func_type.noalias_bits);
805 std.hash.autoHash(hasher, func_type.cc);855 std.hash.autoHash(&hasher, func_type.alignment);
806 std.hash.autoHash(hasher, func_type.is_var_args);856 std.hash.autoHash(&hasher, func_type.cc);
807 std.hash.autoHash(hasher, func_type.is_generic);857 std.hash.autoHash(&hasher, func_type.is_var_args);
808 std.hash.autoHash(hasher, func_type.is_noinline);858 std.hash.autoHash(&hasher, func_type.is_generic);
859 std.hash.autoHash(&hasher, func_type.is_noinline);
860 return hasher.final();
809 },861 },
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
813 .memoized_call => |memoized_call| {869 .memoized_call => |memoized_call| {
814 std.hash.autoHash(hasher, memoized_call.func);870 var hasher = std.hash.Wyhash.init(seed);
815 for (memoized_call.arg_values) |arg| std.hash.autoHash(hasher, arg);871 std.hash.autoHash(&hasher, memoized_call.func);
872 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
873 return hasher.final();
816 },874 },
817 }875 }
818 }876 }
...@@ -1340,7 +1398,7 @@ pub const Index = enum(u32) {...@@ -1340,7 +1398,7 @@ pub const Index = enum(u32) {
1340 type_array_big: struct { data: *Array },1398 type_array_big: struct { data: *Array },
1341 type_array_small: struct { data: *Vector },1399 type_array_small: struct { data: *Vector },
1342 type_vector: struct { data: *Vector },1400 type_vector: struct { data: *Vector },
1343 type_pointer: struct { data: *Pointer },1401 type_pointer: struct { data: *Tag.TypePointer },
1344 type_slice: DataIsIndex,1402 type_slice: DataIsIndex,
1345 type_optional: DataIsIndex,1403 type_optional: DataIsIndex,
1346 type_anyframe: DataIsIndex,1404 type_anyframe: DataIsIndex,
...@@ -1564,44 +1622,56 @@ pub const static_keys = [_]Key{...@@ -1564,44 +1622,56 @@ pub const static_keys = [_]Key{
1564 .{ .simple_type = .type_info },1622 .{ .simple_type = .type_info },
15651623
1566 .{ .ptr_type = .{1624 .{ .ptr_type = .{
1567 .elem_type = .u8_type,1625 .child = .u8_type,
1568 .size = .Many,1626 .flags = .{
1627 .size = .Many,
1628 },
1569 } },1629 } },
15701630
1571 // manyptr_const_u8_type1631 // manyptr_const_u8_type
1572 .{ .ptr_type = .{1632 .{ .ptr_type = .{
1573 .elem_type = .u8_type,1633 .child = .u8_type,
1574 .size = .Many,1634 .flags = .{
1575 .is_const = true,1635 .size = .Many,
1636 .is_const = true,
1637 },
1576 } },1638 } },
15771639
1578 // manyptr_const_u8_sentinel_0_type1640 // manyptr_const_u8_sentinel_0_type
1579 .{ .ptr_type = .{1641 .{ .ptr_type = .{
1580 .elem_type = .u8_type,1642 .child = .u8_type,
1581 .sentinel = .zero_u8,1643 .sentinel = .zero_u8,
1582 .size = .Many,1644 .flags = .{
1583 .is_const = true,1645 .size = .Many,
1646 .is_const = true,
1647 },
1584 } },1648 } },
15851649
1586 .{ .ptr_type = .{1650 .{ .ptr_type = .{
1587 .elem_type = .comptime_int_type,1651 .child = .comptime_int_type,
1588 .size = .One,1652 .flags = .{
1589 .is_const = true,1653 .size = .One,
1654 .is_const = true,
1655 },
1590 } },1656 } },
15911657
1592 // slice_const_u8_type1658 // slice_const_u8_type
1593 .{ .ptr_type = .{1659 .{ .ptr_type = .{
1594 .elem_type = .u8_type,1660 .child = .u8_type,
1595 .size = .Slice,1661 .flags = .{
1596 .is_const = true,1662 .size = .Slice,
1663 .is_const = true,
1664 },
1597 } },1665 } },
15981666
1599 // slice_const_u8_sentinel_0_type1667 // slice_const_u8_sentinel_0_type
1600 .{ .ptr_type = .{1668 .{ .ptr_type = .{
1601 .elem_type = .u8_type,1669 .child = .u8_type,
1602 .sentinel = .zero_u8,1670 .sentinel = .zero_u8,
1603 .size = .Slice,1671 .flags = .{
1604 .is_const = true,1672 .size = .Slice,
1673 .is_const = true,
1674 },
1605 } },1675 } },
16061676
1607 // anyerror_void_error_union_type1677 // anyerror_void_error_union_type
...@@ -1702,7 +1772,6 @@ pub const Tag = enum(u8) {...@@ -1702,7 +1772,6 @@ pub const Tag = enum(u8) {
1702 /// data is payload to Vector.1772 /// data is payload to Vector.
1703 type_vector,1773 type_vector,
1704 /// A fully explicitly specified pointer type.1774 /// A fully explicitly specified pointer type.
1705 /// data is payload to Pointer.
1706 type_pointer,1775 type_pointer,
1707 /// A slice type.1776 /// A slice type.
1708 /// data is Index of underlying pointer type.1777 /// data is Index of underlying pointer type.
...@@ -1941,6 +2010,7 @@ pub const Tag = enum(u8) {...@@ -1941,6 +2010,7 @@ pub const Tag = enum(u8) {
1941 const Func = Key.Func;2010 const Func = Key.Func;
1942 const Union = Key.Union;2011 const Union = Key.Union;
1943 const MemoizedDecl = Key.MemoizedDecl;2012 const MemoizedDecl = Key.MemoizedDecl;
2013 const TypePointer = Key.PtrType;
19442014
1945 fn Payload(comptime tag: Tag) type {2015 fn Payload(comptime tag: Tag) type {
1946 return switch (tag) {2016 return switch (tag) {
...@@ -1949,7 +2019,7 @@ pub const Tag = enum(u8) {...@@ -1949,7 +2019,7 @@ pub const Tag = enum(u8) {
1949 .type_array_big => Array,2019 .type_array_big => Array,
1950 .type_array_small => Vector,2020 .type_array_small => Vector,
1951 .type_vector => Vector,2021 .type_vector => Vector,
1952 .type_pointer => Pointer,2022 .type_pointer => TypePointer,
1953 .type_slice => unreachable,2023 .type_slice => unreachable,
1954 .type_optional => unreachable,2024 .type_optional => unreachable,
1955 .type_anyframe => unreachable,2025 .type_anyframe => unreachable,
...@@ -2167,32 +2237,6 @@ pub const SimpleValue = enum(u32) {...@@ -2167,32 +2237,6 @@ pub const SimpleValue = enum(u32) {
2167 generic_poison,2237 generic_poison,
2168};2238};
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
2196/// Stored as a power-of-two, with one special value to indicate none.2240/// Stored as a power-of-two, with one special value to indicate none.
2197pub const Alignment = enum(u6) {2241pub const Alignment = enum(u6) {
2198 none = std.math.maxInt(u6),2242 none = std.math.maxInt(u6),
...@@ -2531,39 +2575,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2531,39 +2575,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2531 } };2575 } };
2532 },2576 },
25332577
2534 .type_pointer => {2578 .type_pointer => .{ .ptr_type = ip.extraData(Tag.TypePointer, data) },
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 },
25502579
2551 .type_slice => {2580 .type_slice => {
2552 assert(ip.items.items(.tag)[data] == .type_pointer);2581 assert(ip.items.items(.tag)[data] == .type_pointer);
2553 const ptr_info = ip.extraData(Pointer, ip.items.items(.data)[data]);2582 var ptr_info = ip.extraData(Tag.TypePointer, ip.items.items(.data)[data]);
2554 return .{ .ptr_type = .{2583 ptr_info.flags.size = .Slice;
2555 .elem_type = ptr_info.child,2584 return .{ .ptr_type = ptr_info };
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 } };
2567 },2585 },
25682586
2569 .type_optional => .{ .opt_type = @intToEnum(Index, data) },2587 .type_optional => .{ .opt_type = @intToEnum(Index, data) },
...@@ -3066,13 +3084,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3066,13 +3084,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3066 });3084 });
3067 },3085 },
3068 .ptr_type => |ptr_type| {3086 .ptr_type => |ptr_type| {
3069 assert(ptr_type.elem_type != .none);3087 assert(ptr_type.child != .none);
3070 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.elem_type);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) {
3073 _ = ip.map.pop();3091 _ = ip.map.pop();
3074 var new_key = key;3092 var new_key = key;
3075 new_key.ptr_type.size = .Many;3093 new_key.ptr_type.flags.size = .Many;
3076 const ptr_type_index = try ip.get(gpa, new_key);3094 const ptr_type_index = try ip.get(gpa, new_key);
3077 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);3095 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3078 try ip.items.ensureUnusedCapacity(gpa, 1);3096 try ip.items.ensureUnusedCapacity(gpa, 1);
...@@ -3083,27 +3101,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3083,27 +3101,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3083 return @intToEnum(Index, ip.items.len - 1);3101 return @intToEnum(Index, ip.items.len - 1);
3084 }3102 }
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
3088 ip.items.appendAssumeCapacity(.{3107 ip.items.appendAssumeCapacity(.{
3089 .tag = .type_pointer,3108 .tag = .type_pointer,
3090 .data = try ip.addExtra(gpa, Pointer{3109 .data = try ip.addExtra(gpa, ptr_type_adjusted),
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 }),
3107 });3110 });
3108 },3111 },
3109 .array_type => |array_type| {3112 .array_type => |array_type| {
...@@ -3379,7 +3382,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3379,7 +3382,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3379 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;3382 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
3380 switch (ptr.len) {3383 switch (ptr.len) {
3381 .none => {3384 .none => {
3382 assert(ptr_type.size != .Slice);3385 assert(ptr_type.flags.size != .Slice);
3383 switch (ptr.addr) {3386 switch (ptr.addr) {
3384 .decl => |decl| ip.items.appendAssumeCapacity(.{3387 .decl => |decl| ip.items.appendAssumeCapacity(.{
3385 .tag = .ptr_decl,3388 .tag = .ptr_decl,
...@@ -3410,10 +3413,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3410,10 +3413,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3410 switch (ptr.addr) {3413 switch (ptr.addr) {
3411 .int => assert(ip.typeOf(base) == .usize_type),3414 .int => assert(ip.typeOf(base) == .usize_type),
3412 .eu_payload => assert(ip.indexToKey(3415 .eu_payload => assert(ip.indexToKey(
3413 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,3416 ip.indexToKey(ip.typeOf(base)).ptr_type.child,
3414 ) == .error_union_type),3417 ) == .error_union_type),
3415 .opt_payload => assert(ip.indexToKey(3418 .opt_payload => assert(ip.indexToKey(
3416 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,3419 ip.indexToKey(ip.typeOf(base)).ptr_type.child,
3417 ) == .opt_type),3420 ) == .opt_type),
3418 else => unreachable,3421 else => unreachable,
3419 }3422 }
...@@ -3433,10 +3436,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3433,10 +3436,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3433 .elem, .field => |base_index| {3436 .elem, .field => |base_index| {
3434 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;3437 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
3435 switch (ptr.addr) {3438 switch (ptr.addr) {
3436 .elem => assert(base_ptr_type.size == .Many),3439 .elem => assert(base_ptr_type.flags.size == .Many),
3437 .field => {3440 .field => {
3438 assert(base_ptr_type.size == .One);3441 assert(base_ptr_type.flags.size == .One);
3439 switch (ip.indexToKey(base_ptr_type.elem_type)) {3442 switch (ip.indexToKey(base_ptr_type.child)) {
3440 .anon_struct_type => |anon_struct_type| {3443 .anon_struct_type => |anon_struct_type| {
3441 assert(ptr.addr == .field);3444 assert(ptr.addr == .field);
3442 assert(base_index.index < anon_struct_type.types.len);3445 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 {...@@ -3451,7 +3454,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3451 },3454 },
3452 .ptr_type => |slice_type| {3455 .ptr_type => |slice_type| {
3453 assert(ptr.addr == .field);3456 assert(ptr.addr == .field);
3454 assert(slice_type.size == .Slice);3457 assert(slice_type.flags.size == .Slice);
3455 assert(base_index.index < 2);3458 assert(base_index.index < 2);
3456 },3459 },
3457 else => unreachable,3460 else => unreachable,
...@@ -3485,12 +3488,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3485,12 +3488,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3485 // TODO: change Key.Ptr for slices to reference the manyptr value3488 // TODO: change Key.Ptr for slices to reference the manyptr value
3486 // rather than having an addr field directly. Then we can avoid3489 // rather than having an addr field directly. Then we can avoid
3487 // these problematic calls to pop(), get(), and getOrPutAdapted().3490 // these problematic calls to pop(), get(), and getOrPutAdapted().
3488 assert(ptr_type.size == .Slice);3491 assert(ptr_type.flags.size == .Slice);
3489 _ = ip.map.pop();3492 _ = ip.map.pop();
3490 var new_key = key;3493 var new_key = key;
3491 new_key.ptr.ty = ip.slicePtrType(ptr.ty);3494 new_key.ptr.ty = ip.slicePtrType(ptr.ty);
3492 new_key.ptr.len = .none;3495 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);
3494 const ptr_index = try ip.get(gpa, new_key);3497 const ptr_index = try ip.get(gpa, new_key);
3495 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);3498 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3496 try ip.items.ensureUnusedCapacity(gpa, 1);3499 try ip.items.ensureUnusedCapacity(gpa, 1);
...@@ -4302,10 +4305,10 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -4302,10 +4305,10 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
4302 NullTerminatedString => @enumToInt(@field(extra, field.name)),4305 NullTerminatedString => @enumToInt(@field(extra, field.name)),
4303 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),4306 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),
4304 i32 => @bitCast(u32, @field(extra, field.name)),4307 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)),
4306 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),4309 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
4307 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),4310 Tag.TypePointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
4308 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),4311 Tag.TypePointer.VectorIndex => @enumToInt(@field(extra, field.name)),
4309 Tag.Variable.Flags => @bitCast(u32, @field(extra, field.name)),4312 Tag.Variable.Flags => @bitCast(u32, @field(extra, field.name)),
4310 else => @compileError("bad field type: " ++ @typeName(field.type)),4313 else => @compileError("bad field type: " ++ @typeName(field.type)),
4311 });4314 });
...@@ -4370,10 +4373,10 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct...@@ -4370,10 +4373,10 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
4370 NullTerminatedString => @intToEnum(NullTerminatedString, int32),4373 NullTerminatedString => @intToEnum(NullTerminatedString, int32),
4371 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),4374 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),
4372 i32 => @bitCast(i32, int32),4375 i32 => @bitCast(i32, int32),
4373 Pointer.Flags => @bitCast(Pointer.Flags, int32),4376 Tag.TypePointer.Flags => @bitCast(Tag.TypePointer.Flags, int32),
4374 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),4377 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
4375 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),4378 Tag.TypePointer.PackedOffset => @bitCast(Tag.TypePointer.PackedOffset, int32),
4376 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),4379 Tag.TypePointer.VectorIndex => @intToEnum(Tag.TypePointer.VectorIndex, int32),
4377 Tag.Variable.Flags => @bitCast(Tag.Variable.Flags, int32),4380 Tag.Variable.Flags => @bitCast(Tag.Variable.Flags, int32),
4378 else => @compileError("bad field type: " ++ @typeName(field.type)),4381 else => @compileError("bad field type: " ++ @typeName(field.type)),
4379 };4382 };
...@@ -4487,7 +4490,7 @@ test "basic usage" {...@@ -4487,7 +4490,7 @@ test "basic usage" {
44874490
4488pub fn childType(ip: *const InternPool, i: Index) Index {4491pub fn childType(ip: *const InternPool, i: Index) Index {
4489 return switch (ip.indexToKey(i)) {4492 return switch (ip.indexToKey(i)) {
4490 .ptr_type => |ptr_type| ptr_type.elem_type,4493 .ptr_type => |ptr_type| ptr_type.child,
4491 .vector_type => |vector_type| vector_type.child,4494 .vector_type => |vector_type| vector_type.child,
4492 .array_type => |array_type| array_type.child,4495 .array_type => |array_type| array_type.child,
4493 .opt_type, .anyframe_type => |child| child,4496 .opt_type, .anyframe_type => |child| child,
...@@ -4559,7 +4562,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -4559,7 +4562,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
4559 return ip.get(gpa, .{ .ptr = .{4562 return ip.get(gpa, .{ .ptr = .{
4560 .ty = new_ty,4563 .ty = new_ty,
4561 .addr = .{ .int = .zero_usize },4564 .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) {
4563 .One, .Many, .C => .none,4566 .One, .Many, .C => .none,
4564 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),4567 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4565 },4568 },
...@@ -4623,7 +4626,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -4623,7 +4626,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
4623 .none => try ip.get(gpa, .{ .ptr = .{4626 .none => try ip.get(gpa, .{ .ptr = .{
4624 .ty = new_ty,4627 .ty = new_ty,
4625 .addr = .{ .int = .zero_usize },4628 .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) {
4627 .One, .Many, .C => .none,4630 .One, .Many, .C => .none,
4628 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),4631 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4629 },4632 },
...@@ -4889,7 +4892,7 @@ fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -4889,7 +4892,7 @@ fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
4889 .type_array_small => @sizeOf(Vector),4892 .type_array_small => @sizeOf(Vector),
4890 .type_array_big => @sizeOf(Array),4893 .type_array_big => @sizeOf(Array),
4891 .type_vector => @sizeOf(Vector),4894 .type_vector => @sizeOf(Vector),
4892 .type_pointer => @sizeOf(Pointer),4895 .type_pointer => @sizeOf(Tag.TypePointer),
4893 .type_slice => 0,4896 .type_slice => 0,
4894 .type_optional => 0,4897 .type_optional => 0,
4895 .type_anyframe => 0,4898 .type_anyframe => 0,
...@@ -5007,6 +5010,7 @@ fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5007,6 +5010,7 @@ fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5007 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {5010 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
5008 const values = ctx.map.values();5011 const values = ctx.map.values();
5009 return values[a_index].bytes > values[b_index].bytes;5012 return values[a_index].bytes > values[b_index].bytes;
5013 //return values[a_index].count > values[b_index].count;
5010 }5014 }
5011 };5015 };
5012 counts.sort(SortContext{ .map = &counts });5016 counts.sort(SortContext{ .map = &counts });
...@@ -5621,3 +5625,79 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5621,3 +5625,79 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5621 .none => unreachable, // special tag5625 .none => unreachable, // special tag
5622 };5626 };
5623}5627}
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(...@@ -6430,8 +6430,10 @@ pub fn populateTestFunctions(
6430 // func6430 // func
6431 try mod.intern(.{ .ptr = .{6431 try mod.intern(.{ .ptr = .{
6432 .ty = try mod.intern(.{ .ptr_type = .{6432 .ty = try mod.intern(.{ .ptr_type = .{
6433 .elem_type = test_decl.ty.toIntern(),6433 .child = test_decl.ty.toIntern(),
6434 .is_const = true,6434 .flags = .{
6435 .is_const = true,
6436 },
6435 } }),6437 } }),
6436 .addr = .{ .decl = test_decl_index },6438 .addr = .{ .decl = test_decl_index },
6437 } }),6439 } }),
...@@ -6466,9 +6468,11 @@ pub fn populateTestFunctions(...@@ -6466,9 +6468,11 @@ pub fn populateTestFunctions(
64666468
6467 {6469 {
6468 const new_ty = try mod.ptrType(.{6470 const new_ty = try mod.ptrType(.{
6469 .elem_type = test_fn_ty.toIntern(),6471 .child = test_fn_ty.toIntern(),
6470 .is_const = true,6472 .flags = .{
6471 .size = .Slice,6473 .is_const = true,
6474 .size = .Slice,
6475 },
6472 });6476 });
6473 const new_val = decl.val;6477 const new_val = decl.val;
6474 const new_init = try mod.intern(.{ .ptr = .{6478 const new_init = try mod.intern(.{ .ptr = .{
...@@ -6681,65 +6685,68 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!...@@ -6681,65 +6685,68 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
66816685
6682pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {6686pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
6683 var canon_info = info;6687 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
6688 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee6692 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
6689 // type, we change it to 0 here. If this causes an assertion trip because the6693 // type, we change it to 0 here. If this causes an assertion trip because the
6690 // pointee type needs to be resolved more, that needs to be done before calling6694 // pointee type needs to be resolved more, that needs to be done before calling
6691 // this ptr() function.6695 // this ptr() function.
6692 if (info.alignment.toByteUnitsOptional()) |info_align| {6696 if (info.flags.alignment.toByteUnitsOptional()) |info_align| {
6693 if (have_elem_layout and info_align == info.elem_type.toType().abiAlignment(mod)) {6697 if (have_elem_layout and info_align == info.child.toType().abiAlignment(mod)) {
6694 canon_info.alignment = .none;6698 canon_info.flags.alignment = .none;
6695 }6699 }
6696 }6700 }
66976701
6698 switch (info.vector_index) {6702 switch (info.flags.vector_index) {
6699 // Canonicalize host_size. If it matches the bit size of the pointee type,6703 // Canonicalize host_size. If it matches the bit size of the pointee type,
6700 // we change it to 0 here. If this causes an assertion trip, the pointee type6704 // we change it to 0 here. If this causes an assertion trip, the pointee type
6701 // needs to be resolved before calling this ptr() function.6705 // needs to be resolved before calling this ptr() function.
6702 .none => if (have_elem_layout and info.host_size != 0) {6706 .none => if (have_elem_layout and info.packed_offset.host_size != 0) {
6703 const elem_bit_size = info.elem_type.toType().bitSize(mod);6707 const elem_bit_size = info.child.toType().bitSize(mod);
6704 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);6708 assert(info.packed_offset.bit_offset + elem_bit_size <= info.packed_offset.host_size * 8);
6705 if (info.host_size * 8 == elem_bit_size) {6709 if (info.packed_offset.host_size * 8 == elem_bit_size) {
6706 canon_info.host_size = 0;6710 canon_info.packed_offset.host_size = 0;
6707 }6711 }
6708 },6712 },
6709 .runtime => {},6713 .runtime => {},
6710 _ => assert(@enumToInt(info.vector_index) < info.host_size),6714 _ => assert(@enumToInt(info.flags.vector_index) < info.packed_offset.host_size),
6711 }6715 }
67126716
6713 return (try intern(mod, .{ .ptr_type = canon_info })).toType();6717 return (try intern(mod, .{ .ptr_type = canon_info })).toType();
6714}6718}
67156719
6716pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {6720pub 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() });
6718}6722}
67196723
6720pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {6724pub 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 });
6722}6731}
67236732
6724pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {6733pub 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 });
6726}6741}
67276742
6728pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {6743pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
6729 const info = Type.ptrInfoIp(&mod.intern_pool, ptr_ty.toIntern());6744 const info = Type.ptrInfoIp(&mod.intern_pool, ptr_ty.toIntern());
6730 return mod.ptrType(.{6745 return mod.ptrType(.{
6731 .elem_type = new_child.toIntern(),6746 .child = new_child.toIntern(),
6732
6733 .sentinel = info.sentinel,6747 .sentinel = info.sentinel,
6734 .alignment = info.alignment,6748 .flags = info.flags,
6735 .host_size = info.host_size,6749 .packed_offset = info.packed_offset,
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,
6743 });6750 });
6744}6751}
67456752
src/Sema.zig+104-72
...@@ -2490,9 +2490,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -2490,9 +2490,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2490 const operand = try trash_block.addBitCast(pointee_ty, .void_value);2490 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
24912491
2492 const ptr_ty = try mod.ptrType(.{2492 const ptr_ty = try mod.ptrType(.{
2493 .elem_type = pointee_ty.toIntern(),2493 .child = pointee_ty.toIntern(),
2494 .alignment = ia1.alignment,2494 .flags = .{
2495 .address_space = addr_space,2495 .alignment = ia1.alignment,
2496 .address_space = addr_space,
2497 },
2496 });2498 });
2497 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);2499 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...@@ -2519,9 +2521,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2519 try sema.resolveTypeLayout(pointee_ty);2521 try sema.resolveTypeLayout(pointee_ty);
2520 }2522 }
2521 const ptr_ty = try mod.ptrType(.{2523 const ptr_ty = try mod.ptrType(.{
2522 .elem_type = pointee_ty.toIntern(),2524 .child = pointee_ty.toIntern(),
2523 .alignment = alignment,2525 .flags = .{
2524 .address_space = addr_space,2526 .alignment = alignment,
2527 .address_space = addr_space,
2528 },
2525 });2529 });
2526 try sema.maybeQueueFuncBodyAnalysis(decl_index);2530 try sema.maybeQueueFuncBodyAnalysis(decl_index);
2527 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{2531 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
...@@ -3771,10 +3775,12 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3771,10 +3775,12 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3771 if (iac.is_const) try decl.intern(mod);3775 if (iac.is_const) try decl.intern(mod);
3772 const final_elem_ty = decl.ty;3776 const final_elem_ty = decl.ty;
3773 const final_ptr_ty = try mod.ptrType(.{3777 const final_ptr_ty = try mod.ptrType(.{
3774 .elem_type = final_elem_ty.toIntern(),3778 .child = final_elem_ty.toIntern(),
3775 .is_const = false,3779 .flags = .{
3776 .alignment = iac.alignment,3780 .is_const = false,
3777 .address_space = target_util.defaultAddressSpace(target, .local),3781 .alignment = iac.alignment,
3782 .address_space = target_util.defaultAddressSpace(target, .local),
3783 },
3778 });3784 });
37793785
3780 try sema.maybeQueueFuncBodyAnalysis(decl_index);3786 try sema.maybeQueueFuncBodyAnalysis(decl_index);
...@@ -3797,9 +3803,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3797,9 +3803,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3797 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);3803 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
37983804
3799 const final_ptr_ty = try mod.ptrType(.{3805 const final_ptr_ty = try mod.ptrType(.{
3800 .elem_type = final_elem_ty.toIntern(),3806 .child = final_elem_ty.toIntern(),
3801 .alignment = ia1.alignment,3807 .flags = .{
3802 .address_space = target_util.defaultAddressSpace(target, .local),3808 .alignment = ia1.alignment,
3809 .address_space = target_util.defaultAddressSpace(target, .local),
3810 },
3803 });3811 });
38043812
3805 if (!ia1.is_const) {3813 if (!ia1.is_const) {
...@@ -3916,9 +3924,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3916,9 +3924,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3916 defer trash_block.instructions.deinit(gpa);3924 defer trash_block.instructions.deinit(gpa);
39173925
3918 const mut_final_ptr_ty = try mod.ptrType(.{3926 const mut_final_ptr_ty = try mod.ptrType(.{
3919 .elem_type = final_elem_ty.toIntern(),3927 .child = final_elem_ty.toIntern(),
3920 .alignment = ia1.alignment,3928 .flags = .{
3921 .address_space = target_util.defaultAddressSpace(target, .local),3929 .alignment = ia1.alignment,
3930 .address_space = target_util.defaultAddressSpace(target, .local),
3931 },
3922 });3932 });
3923 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);3933 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
3924 const empty_trash_count = trash_block.instructions.items.len;3934 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...@@ -12038,7 +12048,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1203812048
12039 const has_field = hf: {12049 const has_field = hf: {
12040 switch (ip.indexToKey(ty.toIntern())) {12050 switch (ip.indexToKey(ty.toIntern())) {
12041 .ptr_type => |ptr_type| switch (ptr_type.size) {12051 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
12042 .Slice => {12052 .Slice => {
12043 if (mem.eql(u8, field_name, "ptr")) break :hf true;12053 if (mem.eql(u8, field_name, "ptr")) break :hf true;
12044 if (mem.eql(u8, field_name, "len")) break :hf true;12054 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...@@ -16019,9 +16029,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16019 );16029 );
16020 break :v try mod.intern(.{ .ptr = .{16030 break :v try mod.intern(.{ .ptr = .{
16021 .ty = (try mod.ptrType(.{16031 .ty = (try mod.ptrType(.{
16022 .elem_type = param_info_ty.toIntern(),16032 .child = param_info_ty.toIntern(),
16023 .size = .Slice,16033 .flags = .{
16024 .is_const = true,16034 .size = .Slice,
16035 .is_const = true,
16036 },
16025 })).toIntern(),16037 })).toIntern(),
16026 .addr = .{ .decl = new_decl },16038 .addr = .{ .decl = new_decl },
16027 .len = (try mod.intValue(Type.usize, param_vals.len)).toIntern(),16039 .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...@@ -16329,9 +16341,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1632916341
16330 // Build our ?[]const Error value16342 // Build our ?[]const Error value
16331 const slice_errors_ty = try mod.ptrType(.{16343 const slice_errors_ty = try mod.ptrType(.{
16332 .elem_type = error_field_ty.toIntern(),16344 .child = error_field_ty.toIntern(),
16333 .size = .Slice,16345 .flags = .{
16334 .is_const = true,16346 .size = .Slice,
16347 .is_const = true,
16348 },
16335 });16349 });
16336 const opt_slice_errors_ty = try mod.optionalType(slice_errors_ty.toIntern());16350 const opt_slice_errors_ty = try mod.optionalType(slice_errors_ty.toIntern());
16337 const errors_payload_val: InternPool.Index = if (error_field_vals) |vals| v: {16351 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...@@ -16471,9 +16485,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16471 );16485 );
16472 break :v try mod.intern(.{ .ptr = .{16486 break :v try mod.intern(.{ .ptr = .{
16473 .ty = (try mod.ptrType(.{16487 .ty = (try mod.ptrType(.{
16474 .elem_type = enum_field_ty.toIntern(),16488 .child = enum_field_ty.toIntern(),
16475 .size = .Slice,16489 .flags = .{
16476 .is_const = true,16490 .size = .Slice,
16491 .is_const = true,
16492 },
16477 })).toIntern(),16493 })).toIntern(),
16478 .addr = .{ .decl = new_decl },16494 .addr = .{ .decl = new_decl },
16479 .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),16495 .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...@@ -16614,9 +16630,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16614 );16630 );
16615 break :v try mod.intern(.{ .ptr = .{16631 break :v try mod.intern(.{ .ptr = .{
16616 .ty = (try mod.ptrType(.{16632 .ty = (try mod.ptrType(.{
16617 .elem_type = union_field_ty.toIntern(),16633 .child = union_field_ty.toIntern(),
16618 .size = .Slice,16634 .flags = .{
16619 .is_const = true,16635 .size = .Slice,
16636 .is_const = true,
16637 },
16620 })).toIntern(),16638 })).toIntern(),
16621 .addr = .{ .decl = new_decl },16639 .addr = .{ .decl = new_decl },
16622 .len = (try mod.intValue(Type.usize, union_field_vals.len)).toIntern(),16640 .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...@@ -16833,9 +16851,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16833 );16851 );
16834 break :v try mod.intern(.{ .ptr = .{16852 break :v try mod.intern(.{ .ptr = .{
16835 .ty = (try mod.ptrType(.{16853 .ty = (try mod.ptrType(.{
16836 .elem_type = struct_field_ty.toIntern(),16854 .child = struct_field_ty.toIntern(),
16837 .size = .Slice,16855 .flags = .{
16838 .is_const = true,16856 .size = .Slice,
16857 .is_const = true,
16858 },
16839 })).toIntern(),16859 })).toIntern(),
16840 .addr = .{ .decl = new_decl },16860 .addr = .{ .decl = new_decl },
16841 .len = (try mod.intValue(Type.usize, struct_field_vals.len)).toIntern(),16861 .len = (try mod.intValue(Type.usize, struct_field_vals.len)).toIntern(),
...@@ -16976,9 +16996,11 @@ fn typeInfoDecls(...@@ -16976,9 +16996,11 @@ fn typeInfoDecls(
16976 );16996 );
16977 return try mod.intern(.{ .ptr = .{16997 return try mod.intern(.{ .ptr = .{
16978 .ty = (try mod.ptrType(.{16998 .ty = (try mod.ptrType(.{
16979 .elem_type = declaration_ty.toIntern(),16999 .child = declaration_ty.toIntern(),
16980 .size = .Slice,17000 .flags = .{
16981 .is_const = true,17001 .size = .Slice,
17002 .is_const = true,
17003 },
16982 })).toIntern(),17004 })).toIntern(),
16983 .addr = .{ .decl = new_decl },17005 .addr = .{ .decl = new_decl },
16984 .len = (try mod.intValue(Type.usize, decl_vals.items.len)).toIntern(),17006 .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...@@ -18047,16 +18069,20 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18047 }18069 }
1804818070
18049 const ty = try mod.ptrType(.{18071 const ty = try mod.ptrType(.{
18050 .elem_type = elem_ty.toIntern(),18072 .child = elem_ty.toIntern(),
18051 .sentinel = sentinel,18073 .sentinel = sentinel,
18052 .alignment = abi_align,18074 .flags = .{
18053 .address_space = address_space,18075 .alignment = abi_align,
18054 .bit_offset = bit_offset,18076 .address_space = address_space,
18055 .host_size = host_size,18077 .is_const = !inst_data.flags.is_mutable,
18056 .is_const = !inst_data.flags.is_mutable,18078 .is_allowzero = inst_data.flags.is_allowzero,
18057 .is_allowzero = inst_data.flags.is_allowzero,18079 .is_volatile = inst_data.flags.is_volatile,
18058 .is_volatile = inst_data.flags.is_volatile,18080 .size = inst_data.size,
18059 .size = inst_data.size,18081 },
18082 .packed_offset = .{
18083 .bit_offset = bit_offset,
18084 .host_size = host_size,
18085 },
18060 });18086 });
18061 return sema.addType(ty);18087 return sema.addType(ty);
18062}18088}
...@@ -19209,14 +19235,16 @@ fn zirReify(...@@ -19209,14 +19235,16 @@ fn zirReify(
19209 }19235 }
1921019236
19211 const ty = try mod.ptrType(.{19237 const ty = try mod.ptrType(.{
19212 .size = ptr_size,19238 .child = elem_ty.toIntern(),
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(),
19219 .sentinel = actual_sentinel,19239 .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 },
19220 });19248 });
19221 return sema.addType(ty);19249 return sema.addType(ty);
19222 },19250 },
...@@ -22714,9 +22742,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22714,9 +22742,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22714 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)22742 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
22715 else if (new_dest_ptr_ty.ptrSize(mod) == .One) ptr: {22743 else if (new_dest_ptr_ty.ptrSize(mod) == .One) ptr: {
22716 var dest_manyptr_ty_key = mod.intern_pool.indexToKey(new_dest_ptr_ty.toIntern()).ptr_type;22744 var dest_manyptr_ty_key = mod.intern_pool.indexToKey(new_dest_ptr_ty.toIntern()).ptr_type;
22717 assert(dest_manyptr_ty_key.size == .One);22745 assert(dest_manyptr_ty_key.flags.size == .One);
22718 dest_manyptr_ty_key.elem_type = dest_elem_ty.toIntern();22746 dest_manyptr_ty_key.child = dest_elem_ty.toIntern();
22719 dest_manyptr_ty_key.size = .Many;22747 dest_manyptr_ty_key.flags.size = .Many;
22720 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);22748 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);
22721 } else new_dest_ptr;22749 } else new_dest_ptr;
2272222750
...@@ -22725,9 +22753,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22725,9 +22753,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22725 try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty)22753 try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty)
22726 else if (new_src_ptr_ty.ptrSize(mod) == .One) ptr: {22754 else if (new_src_ptr_ty.ptrSize(mod) == .One) ptr: {
22727 var src_manyptr_ty_key = mod.intern_pool.indexToKey(new_src_ptr_ty.toIntern()).ptr_type;22755 var src_manyptr_ty_key = mod.intern_pool.indexToKey(new_src_ptr_ty.toIntern()).ptr_type;
22728 assert(src_manyptr_ty_key.size == .One);22756 assert(src_manyptr_ty_key.flags.size == .One);
22729 src_manyptr_ty_key.elem_type = src_elem_ty.toIntern();22757 src_manyptr_ty_key.child = src_elem_ty.toIntern();
22730 src_manyptr_ty_key.size = .Many;22758 src_manyptr_ty_key.flags.size = .Many;
22731 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);22759 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);
22732 } else new_src_ptr;22760 } else new_src_ptr;
2273322761
...@@ -24036,8 +24064,10 @@ fn panicWithMsg(...@@ -24036,8 +24064,10 @@ fn panicWithMsg(
24036 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);24064 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
24037 const target = mod.getTarget();24065 const target = mod.getTarget();
24038 const ptr_stack_trace_ty = try mod.ptrType(.{24066 const ptr_stack_trace_ty = try mod.ptrType(.{
24039 .elem_type = stack_trace_ty.toIntern(),24067 .child = stack_trace_ty.toIntern(),
24040 .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic24068 .flags = .{
24069 .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
24070 },
24041 });24071 });
24042 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());24072 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
24043 const null_stack_trace = try sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{24073 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...@@ -29630,10 +29660,12 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo
29630 const decl = mod.declPtr(decl_index);29660 const decl = mod.declPtr(decl_index);
29631 const decl_tv = try decl.typedValue();29661 const decl_tv = try decl.typedValue();
29632 const ptr_ty = try mod.ptrType(.{29662 const ptr_ty = try mod.ptrType(.{
29633 .elem_type = decl_tv.ty.toIntern(),29663 .child = decl_tv.ty.toIntern(),
29634 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),29664 .flags = .{
29635 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,29665 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29636 .address_space = decl.@"addrspace",29666 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
29667 .address_space = decl.@"addrspace",
29668 },
29637 });29669 });
29638 if (analyze_fn_body) {29670 if (analyze_fn_body) {
29639 try sema.maybeQueueFuncBodyAnalysis(decl_index);29671 try sema.maybeQueueFuncBodyAnalysis(decl_index);
...@@ -30025,10 +30057,10 @@ fn analyzeSlice(...@@ -30025,10 +30057,10 @@ fn analyzeSlice(
30025 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)30057 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
30026 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {30058 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {
30027 var manyptr_ty_key = mod.intern_pool.indexToKey(slice_ty.toIntern()).ptr_type;30059 var manyptr_ty_key = mod.intern_pool.indexToKey(slice_ty.toIntern()).ptr_type;
30028 assert(manyptr_ty_key.elem_type == array_ty.toIntern());30060 assert(manyptr_ty_key.child == array_ty.toIntern());
30029 assert(manyptr_ty_key.size == .One);30061 assert(manyptr_ty_key.flags.size == .One);
30030 manyptr_ty_key.elem_type = elem_ty.toIntern();30062 manyptr_ty_key.child = elem_ty.toIntern();
30031 manyptr_ty_key.size = .Many;30063 manyptr_ty_key.flags.size = .Many;
30032 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);30064 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);
30033 } else ptr_or_slice;30065 } else ptr_or_slice;
3003430066
...@@ -31972,7 +32004,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31972,7 +32004,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31972 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {32004 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
31973 .int_type => false,32005 .int_type => false,
31974 .ptr_type => |ptr_type| {32006 .ptr_type => |ptr_type| {
31975 const child_ty = ptr_type.elem_type.toType();32007 const child_ty = ptr_type.child.toType();
31976 if (child_ty.zigTypeTag(mod) == .Fn) {32008 if (child_ty.zigTypeTag(mod) == .Fn) {
31977 return mod.typeToFunc(child_ty).?.is_generic;32009 return mod.typeToFunc(child_ty).?.is_generic;
31978 } else {32010 } else {
...@@ -33917,15 +33949,15 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError...@@ -33917,15 +33949,15 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError
33917fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {33949fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
33918 const mod = sema.mod;33950 const mod = sema.mod;
33919 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {33951 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) {
33921 .One, .Many, .C => ty,33953 .One, .Many, .C => ty,
33922 .Slice => null,33954 .Slice => null,
33923 },33955 },
33924 .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) {33956 .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) {
33926 .Slice, .C => null,33958 .Slice, .C => null,
33927 .Many, .One => {33959 .Many, .One => {
33928 if (ptr_type.is_allowzero) return null;33960 if (ptr_type.flags.is_allowzero) return null;
3392933961
33930 // optionals of zero sized types behave like bools, not pointers33962 // optionals of zero sized types behave like bools, not pointers
33931 const payload_ty = opt_child.toType();33963 const payload_ty = opt_child.toType();
...@@ -33956,7 +33988,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33956,7 +33988,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33956 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {33988 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
33957 .int_type => return false,33989 .int_type => return false,
33958 .ptr_type => |ptr_type| {33990 .ptr_type => |ptr_type| {
33959 const child_ty = ptr_type.elem_type.toType();33991 const child_ty = ptr_type.child.toType();
33960 if (child_ty.zigTypeTag(mod) == .Fn) {33992 if (child_ty.zigTypeTag(mod) == .Fn) {
33961 return mod.typeToFunc(child_ty).?.is_generic;33993 return mod.typeToFunc(child_ty).?.is_generic;
33962 } else {33994 } else {
src/codegen.zig+2-2
...@@ -673,7 +673,7 @@ fn lowerParentPtr(...@@ -673,7 +673,7 @@ fn lowerParentPtr(
673 mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).abiSize(mod))),673 mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).abiSize(mod))),
674 ),674 ),
675 .field => |field| {675 .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;
677 return lowerParentPtr(677 return lowerParentPtr(
678 bin_file,678 bin_file,
679 src_loc,679 src_loc,
...@@ -681,7 +681,7 @@ fn lowerParentPtr(...@@ -681,7 +681,7 @@ fn lowerParentPtr(
681 code,681 code,
682 debug_output,682 debug_output,
683 reloc_info.offset(switch (mod.intern_pool.indexToKey(base_type)) {683 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) {
685 .One, .Many, .C => unreachable,685 .One, .Many, .C => unreachable,
686 .Slice => switch (field.index) {686 .Slice => switch (field.index) {
687 0 => 0,687 0 => 0,
src/codegen/c.zig+6-4
...@@ -630,7 +630,7 @@ pub const DeclGen = struct {...@@ -630,7 +630,7 @@ pub const DeclGen = struct {
630 try writer.writeByte(')');630 try writer.writeByte(')');
631 }631 }
632 try writer.writeAll("&(");632 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)
634 try writer.writeByte('*');634 try writer.writeByte('*');
635 try dg.renderParentPtr(writer, elem.base, location);635 try dg.renderParentPtr(writer, elem.base, location);
636 try writer.print(")[{d}]", .{elem.index});636 try writer.print(")[{d}]", .{elem.index});
...@@ -642,7 +642,7 @@ pub const DeclGen = struct {...@@ -642,7 +642,7 @@ pub const DeclGen = struct {
642 _ = try dg.typeToIndex(base_ty, .complete);642 _ = try dg.typeToIndex(base_ty, .complete);
643 const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {643 const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {
644 .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(field.index, mod),644 .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) {
646 .One, .Many, .C => unreachable,646 .One, .Many, .C => unreachable,
647 .Slice => switch (field.index) {647 .Slice => switch (field.index) {
648 Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),648 Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),
...@@ -6285,8 +6285,10 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -6285,8 +6285,10 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6285 // casted to a regular pointer, otherwise an error like this occurs:6285 // casted to a regular pointer, otherwise an error like this occurs:
6286 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable6286 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable
6287 const elem_ptr_ty = try mod.ptrType(.{6287 const elem_ptr_ty = try mod.ptrType(.{
6288 .size = .C,6288 .child = elem_ty.ip_index,
6289 .elem_type = elem_ty.ip_index,6289 .flags = .{
6290 .size = .C,
6291 },
6290 });6292 });
62916293
6292 const index = try f.allocLocal(inst, Type.usize);6294 const index = try f.allocLocal(inst, Type.usize);
src/codegen/llvm.zig+37-27
...@@ -1577,25 +1577,27 @@ pub const Object = struct {...@@ -1577,25 +1577,27 @@ pub const Object = struct {
1577 const ptr_info = Type.ptrInfoIp(&mod.intern_pool, ty.toIntern());1577 const ptr_info = Type.ptrInfoIp(&mod.intern_pool, ty.toIntern());
15781578
1579 if (ptr_info.sentinel != .none or1579 if (ptr_info.sentinel != .none or
1580 ptr_info.address_space != .generic or1580 ptr_info.flags.address_space != .generic or
1581 ptr_info.bit_offset != 0 or1581 ptr_info.packed_offset.bit_offset != 0 or
1582 ptr_info.host_size != 0 or1582 ptr_info.packed_offset.host_size != 0 or
1583 ptr_info.vector_index != .none or1583 ptr_info.flags.vector_index != .none or
1584 ptr_info.is_allowzero or1584 ptr_info.flags.is_allowzero or
1585 ptr_info.is_const or1585 ptr_info.flags.is_const or
1586 ptr_info.is_volatile or1586 ptr_info.flags.is_volatile or
1587 ptr_info.size == .Many or ptr_info.size == .C or1587 ptr_info.flags.size == .Many or ptr_info.flags.size == .C or
1588 !ptr_info.elem_type.toType().hasRuntimeBitsIgnoreComptime(mod))1588 !ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
1589 {1589 {
1590 const bland_ptr_ty = try mod.ptrType(.{1590 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))
1592 .anyopaque_type1592 .anyopaque_type
1593 else1593 else
1594 ptr_info.elem_type,1594 ptr_info.child,
1595 .alignment = ptr_info.alignment,1595 .flags = .{
1596 .size = switch (ptr_info.size) {1596 .alignment = ptr_info.flags.alignment,
1597 .Many, .C, .One => .One,1597 .size = switch (ptr_info.flags.size) {
1598 .Slice => .Slice,1598 .Many, .C, .One => .One,
1599 .Slice => .Slice,
1600 },
1599 },1601 },
1600 });1602 });
1601 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);1603 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
...@@ -1683,7 +1685,7 @@ pub const Object = struct {...@@ -1683,7 +1685,7 @@ pub const Object = struct {
1683 return full_di_ty;1685 return full_di_ty;
1684 }1686 }
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);
1687 const name = try ty.nameAlloc(gpa, o.module);1689 const name = try ty.nameAlloc(gpa, o.module);
1688 defer gpa.free(name);1690 defer gpa.free(name);
1689 const ptr_di_ty = dib.createPointerType(1691 const ptr_di_ty = dib.createPointerType(
...@@ -5856,8 +5858,10 @@ pub const FuncGen = struct {...@@ -5856,8 +5858,10 @@ pub const FuncGen = struct {
5856 const struct_llvm_ty = try self.dg.lowerType(struct_ty);5858 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
5857 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");5859 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");
5858 const field_ptr_ty = try mod.ptrType(.{5860 const field_ptr_ty = try mod.ptrType(.{
5859 .elem_type = llvm_field.ty.toIntern(),5861 .child = llvm_field.ty.toIntern(),
5860 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),5862 .flags = .{
5863 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
5864 },
5861 });5865 });
5862 if (isByRef(field_ty, mod)) {5866 if (isByRef(field_ty, mod)) {
5863 if (canElideLoad(self, body_tail))5867 if (canElideLoad(self, body_tail))
...@@ -6732,8 +6736,10 @@ pub const FuncGen = struct {...@@ -6732,8 +6736,10 @@ pub const FuncGen = struct {
6732 const struct_llvm_ty = try self.dg.lowerType(struct_ty);6736 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6733 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");6737 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");
6734 const field_ptr_ty = try mod.ptrType(.{6738 const field_ptr_ty = try mod.ptrType(.{
6735 .elem_type = llvm_field.ty.toIntern(),6739 .child = llvm_field.ty.toIntern(),
6736 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),6740 .flags = .{
6741 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
6742 },
6737 });6743 });
6738 return self.load(field_ptr, field_ptr_ty);6744 return self.load(field_ptr, field_ptr_ty);
6739 }6745 }
...@@ -9131,10 +9137,12 @@ pub const FuncGen = struct {...@@ -9131,10 +9137,12 @@ pub const FuncGen = struct {
9131 indices[1] = llvm_u32.constInt(llvm_i, .False);9137 indices[1] = llvm_u32.constInt(llvm_i, .False);
9132 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");9138 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
9133 const field_ptr_ty = try mod.ptrType(.{9139 const field_ptr_ty = try mod.ptrType(.{
9134 .elem_type = self.typeOf(elem).toIntern(),9140 .child = self.typeOf(elem).toIntern(),
9135 .alignment = InternPool.Alignment.fromNonzeroByteUnits(9141 .flags = .{
9136 result_ty.structFieldAlign(i, mod),9142 .alignment = InternPool.Alignment.fromNonzeroByteUnits(
9137 ),9143 result_ty.structFieldAlign(i, mod),
9144 ),
9145 },
9138 });9146 });
9139 try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);9147 try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);
9140 }9148 }
...@@ -9160,7 +9168,7 @@ pub const FuncGen = struct {...@@ -9160,7 +9168,7 @@ pub const FuncGen = struct {
91609168
9161 const array_info = result_ty.arrayInfo(mod);9169 const array_info = result_ty.arrayInfo(mod);
9162 const elem_ptr_ty = try mod.ptrType(.{9170 const elem_ptr_ty = try mod.ptrType(.{
9163 .elem_type = array_info.elem_type.toIntern(),9171 .child = array_info.elem_type.toIntern(),
9164 });9172 });
91659173
9166 for (elements, 0..) |elem, i| {9174 for (elements, 0..) |elem, i| {
...@@ -9282,8 +9290,10 @@ pub const FuncGen = struct {...@@ -9282,8 +9290,10 @@ pub const FuncGen = struct {
9282 const index_type = self.context.intType(32);9290 const index_type = self.context.intType(32);
92839291
9284 const field_ptr_ty = try mod.ptrType(.{9292 const field_ptr_ty = try mod.ptrType(.{
9285 .elem_type = field.ty.toIntern(),9293 .child = field.ty.toIntern(),
9286 .alignment = InternPool.Alignment.fromNonzeroByteUnits(field_align),9294 .flags = .{
9295 .alignment = InternPool.Alignment.fromNonzeroByteUnits(field_align),
9296 },
9287 });9297 });
9288 if (layout.tag_size == 0) {9298 if (layout.tag_size == 0) {
9289 const indices: [3]*llvm.Value = .{9299 const indices: [3]*llvm.Value = .{
src/type.zig+56-52
...@@ -85,7 +85,7 @@ pub const Type = struct {...@@ -85,7 +85,7 @@ pub const Type = struct {
8585
86 /// Asserts the type is a pointer.86 /// Asserts the type is a pointer.
87 pub fn ptrIsMutable(ty: Type, mod: *const Module) bool {87 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;
89 }89 }
9090
91 pub const ArrayInfo = struct {91 pub const ArrayInfo = struct {
...@@ -488,7 +488,7 @@ pub const Type = struct {...@@ -488,7 +488,7 @@ pub const Type = struct {
488 // Pointers to zero-bit types still have a runtime address; however, pointers488 // Pointers to zero-bit types still have a runtime address; however, pointers
489 // to comptime-only types do not, with the exception of function pointers.489 // to comptime-only types do not, with the exception of function pointers.
490 if (ignore_comptime_only) return true;490 if (ignore_comptime_only) return true;
491 const child_ty = ptr_type.elem_type.toType();491 const child_ty = ptr_type.child.toType();
492 if (child_ty.zigTypeTag(mod) == .Fn) return !mod.typeToFunc(child_ty).?.is_generic;492 if (child_ty.zigTypeTag(mod) == .Fn) return !mod.typeToFunc(child_ty).?.is_generic;
493 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));493 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
494 return !comptimeOnly(ty, mod);494 return !comptimeOnly(ty, mod);
...@@ -689,7 +689,7 @@ pub const Type = struct {...@@ -689,7 +689,7 @@ pub const Type = struct {
689689
690 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),690 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
691 .opt_type => ty.isPtrLikeOptional(mod),691 .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
694 .simple_type => |t| switch (t) {694 .simple_type => |t| switch (t) {
695 .f16,695 .f16,
...@@ -823,13 +823,13 @@ pub const Type = struct {...@@ -823,13 +823,13 @@ pub const Type = struct {
823 pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !u32 {823 pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !u32 {
824 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {824 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
825 .ptr_type => |ptr_type| {825 .ptr_type => |ptr_type| {
826 if (ptr_type.alignment.toByteUnitsOptional()) |a| {826 if (ptr_type.flags.alignment.toByteUnitsOptional()) |a| {
827 return @intCast(u32, a);827 return @intCast(u32, a);
828 } else if (opt_sema) |sema| {828 } 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 });
830 return res.scalar;830 return res.scalar;
831 } else {831 } 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;
833 }833 }
834 },834 },
835 .opt_type => |child| child.toType().ptrAlignmentAdvanced(mod, opt_sema),835 .opt_type => |child| child.toType().ptrAlignmentAdvanced(mod, opt_sema),
...@@ -839,8 +839,8 @@ pub const Type = struct {...@@ -839,8 +839,8 @@ pub const Type = struct {
839839
840 pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {840 pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {
841 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {841 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
842 .ptr_type => |ptr_type| 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.address_space,843 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.flags.address_space,
844 else => unreachable,844 else => unreachable,
845 };845 };
846 }846 }
...@@ -1297,7 +1297,7 @@ pub const Type = struct {...@@ -1297,7 +1297,7 @@ pub const Type = struct {
1297 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };1297 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1298 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };1298 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
1299 },1299 },
1300 .ptr_type => |ptr_type| switch (ptr_type.size) {1300 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1301 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },1301 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
1302 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },1302 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1303 },1303 },
...@@ -1620,7 +1620,7 @@ pub const Type = struct {...@@ -1620,7 +1620,7 @@ pub const Type = struct {
16201620
1621 switch (mod.intern_pool.indexToKey(ty.toIntern())) {1621 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1622 .int_type => |int_type| return int_type.bits,1622 .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) {
1624 .Slice => return target.ptrBitWidth() * 2,1624 .Slice => return target.ptrBitWidth() * 2,
1625 else => return target.ptrBitWidth(),1625 else => return target.ptrBitWidth(),
1626 },1626 },
...@@ -1795,7 +1795,7 @@ pub const Type = struct {...@@ -1795,7 +1795,7 @@ pub const Type = struct {
17951795
1796 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {1796 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
1797 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1797 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,
1799 else => false,1799 else => false,
1800 };1800 };
1801 }1801 }
...@@ -1808,14 +1808,14 @@ pub const Type = struct {...@@ -1808,14 +1808,14 @@ pub const Type = struct {
1808 /// Returns `null` if `ty` is not a pointer.1808 /// Returns `null` if `ty` is not a pointer.
1809 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {1809 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
1810 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1810 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,
1812 else => null,1812 else => null,
1813 };1813 };
1814 }1814 }
18151815
1816 pub fn isSlice(ty: Type, mod: *const Module) bool {1816 pub fn isSlice(ty: Type, mod: *const Module) bool {
1817 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1817 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,
1819 else => false,1819 else => false,
1820 };1820 };
1821 }1821 }
...@@ -1826,7 +1826,7 @@ pub const Type = struct {...@@ -1826,7 +1826,7 @@ pub const Type = struct {
18261826
1827 pub fn isConstPtr(ty: Type, mod: *const Module) bool {1827 pub fn isConstPtr(ty: Type, mod: *const Module) bool {
1828 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1828 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,
1830 else => false,1830 else => false,
1831 };1831 };
1832 }1832 }
...@@ -1837,14 +1837,14 @@ pub const Type = struct {...@@ -1837,14 +1837,14 @@ pub const Type = struct {
18371837
1838 pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {1838 pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {
1839 return switch (ip.indexToKey(ty.toIntern())) {1839 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,
1841 else => false,1841 else => false,
1842 };1842 };
1843 }1843 }
18441844
1845 pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {1845 pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {
1846 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1846 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,
1848 .opt_type => true,1848 .opt_type => true,
1849 else => false,1849 else => false,
1850 };1850 };
...@@ -1852,21 +1852,21 @@ pub const Type = struct {...@@ -1852,21 +1852,21 @@ pub const Type = struct {
18521852
1853 pub fn isCPtr(ty: Type, mod: *const Module) bool {1853 pub fn isCPtr(ty: Type, mod: *const Module) bool {
1854 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1854 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,
1856 else => false,1856 else => false,
1857 };1857 };
1858 }1858 }
18591859
1860 pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {1860 pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {
1861 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1861 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) {
1863 .Slice => false,1863 .Slice => false,
1864 .One, .Many, .C => true,1864 .One, .Many, .C => true,
1865 },1865 },
1866 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {1866 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1867 .ptr_type => |p| switch (p.size) {1867 .ptr_type => |p| switch (p.flags.size) {
1868 .Slice, .C => false,1868 .Slice, .C => false,
1869 .Many, .One => !p.is_allowzero,1869 .Many, .One => !p.flags.is_allowzero,
1870 },1870 },
1871 else => false,1871 else => false,
1872 },1872 },
...@@ -1887,14 +1887,14 @@ pub const Type = struct {...@@ -1887,14 +1887,14 @@ pub const Type = struct {
1887 pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {1887 pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
1888 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1888 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1889 .opt_type => |child_type| switch (mod.intern_pool.indexToKey(child_type)) {1889 .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) {
1891 .C => false,1891 .C => false,
1892 .Slice, .Many, .One => !ptr_type.is_allowzero,1892 .Slice, .Many, .One => !ptr_type.flags.is_allowzero,
1893 },1893 },
1894 .error_set_type => true,1894 .error_set_type => true,
1895 else => false,1895 else => false,
1896 },1896 },
1897 .ptr_type => |ptr_type| ptr_type.size == .C,1897 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1898 else => false,1898 else => false,
1899 };1899 };
1900 }1900 }
...@@ -1904,11 +1904,11 @@ pub const Type = struct {...@@ -1904,11 +1904,11 @@ pub const Type = struct {
1904 /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.1904 /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
1905 pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {1905 pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
1906 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1906 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,
1908 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {1908 .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) {
1910 .Slice, .C => false,1910 .Slice, .C => false,
1911 .Many, .One => !ptr_type.is_allowzero,1911 .Many, .One => !ptr_type.flags.is_allowzero,
1912 },1912 },
1913 else => false,1913 else => false,
1914 },1914 },
...@@ -1938,9 +1938,9 @@ pub const Type = struct {...@@ -1938,9 +1938,9 @@ pub const Type = struct {
1938 /// For anyframe->T, returns T.1938 /// For anyframe->T, returns T.
1939 pub fn elemType2(ty: Type, mod: *const Module) Type {1939 pub fn elemType2(ty: Type, mod: *const Module) Type {
1940 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1940 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1941 .ptr_type => |ptr_type| switch (ptr_type.size) {1941 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1942 .One => ptr_type.elem_type.toType().shallowElemType(mod),1942 .One => ptr_type.child.toType().shallowElemType(mod),
1943 .Many, .C, .Slice => ptr_type.elem_type.toType(),1943 .Many, .C, .Slice => ptr_type.child.toType(),
1944 },1944 },
1945 .anyframe_type => |child| {1945 .anyframe_type => |child| {
1946 assert(child != .none);1946 assert(child != .none);
...@@ -1974,7 +1974,7 @@ pub const Type = struct {...@@ -1974,7 +1974,7 @@ pub const Type = struct {
1974 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {1974 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1975 .opt_type => |child| child.toType(),1975 .opt_type => |child| child.toType(),
1976 .ptr_type => |ptr_type| b: {1976 .ptr_type => |ptr_type| b: {
1977 assert(ptr_type.size == .C);1977 assert(ptr_type.flags.size == .C);
1978 break :b ty;1978 break :b ty;
1979 },1979 },
1980 else => unreachable,1980 else => unreachable,
...@@ -2390,7 +2390,7 @@ pub const Type = struct {...@@ -2390,7 +2390,7 @@ pub const Type = struct {
23902390
2391 pub fn fnReturnTypeIp(ty: Type, ip: *const InternPool) Type {2391 pub fn fnReturnTypeIp(ty: Type, ip: *const InternPool) Type {
2392 return switch (ip.indexToKey(ty.toIntern())) {2392 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,
2394 .func_type => |func_type| func_type.return_type,2394 .func_type => |func_type| func_type.return_type,
2395 else => unreachable,2395 else => unreachable,
2396 }.toType();2396 }.toType();
...@@ -2672,7 +2672,7 @@ pub const Type = struct {...@@ -2672,7 +2672,7 @@ pub const Type = struct {
2672 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {2672 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2673 .int_type => false,2673 .int_type => false,
2674 .ptr_type => |ptr_type| {2674 .ptr_type => |ptr_type| {
2675 const child_ty = ptr_type.elem_type.toType();2675 const child_ty = ptr_type.child.toType();
2676 if (child_ty.zigTypeTag(mod) == .Fn) {2676 if (child_ty.zigTypeTag(mod) == .Fn) {
2677 return false;2677 return false;
2678 } else {2678 } else {
...@@ -3374,17 +3374,17 @@ pub const Type = struct {...@@ -3374,17 +3374,17 @@ pub const Type = struct {
33743374
3375 pub fn fromKey(p: InternPool.Key.PtrType) Data {3375 pub fn fromKey(p: InternPool.Key.PtrType) Data {
3376 return .{3376 return .{
3377 .pointee_type = p.elem_type.toType(),3377 .pointee_type = p.child.toType(),
3378 .sentinel = if (p.sentinel != .none) p.sentinel.toValue() else null,3378 .sentinel = if (p.sentinel != .none) p.sentinel.toValue() else null,
3379 .@"align" = @intCast(u32, p.alignment.toByteUnits(0)),3379 .@"align" = @intCast(u32, p.flags.alignment.toByteUnits(0)),
3380 .@"addrspace" = p.address_space,3380 .@"addrspace" = p.flags.address_space,
3381 .bit_offset = p.bit_offset,3381 .bit_offset = p.packed_offset.bit_offset,
3382 .host_size = p.host_size,3382 .host_size = p.packed_offset.host_size,
3383 .vector_index = p.vector_index,3383 .vector_index = p.flags.vector_index,
3384 .@"allowzero" = p.is_allowzero,3384 .@"allowzero" = p.flags.is_allowzero,
3385 .mutable = !p.is_const,3385 .mutable = !p.flags.is_const,
3386 .@"volatile" = p.is_volatile,3386 .@"volatile" = p.flags.is_volatile,
3387 .size = p.size,3387 .size = p.flags.size,
3388 };3388 };
3389 }3389 }
3390 };3390 };
...@@ -3478,17 +3478,21 @@ pub const Type = struct {...@@ -3478,17 +3478,21 @@ pub const Type = struct {
3478 }3478 }
34793479
3480 return mod.ptrType(.{3480 return mod.ptrType(.{
3481 .elem_type = d.pointee_type.ip_index,3481 .child = d.pointee_type.ip_index,
3482 .sentinel = if (d.sentinel) |s| s.ip_index else .none,3482 .sentinel = if (d.sentinel) |s| s.ip_index else .none,
3483 .alignment = InternPool.Alignment.fromByteUnits(d.@"align"),3483 .flags = .{
3484 .host_size = d.host_size,3484 .alignment = InternPool.Alignment.fromByteUnits(d.@"align"),
3485 .bit_offset = d.bit_offset,3485 .vector_index = d.vector_index,
3486 .vector_index = d.vector_index,3486 .size = d.size,
3487 .size = d.size,3487 .is_const = !d.mutable,
3488 .is_const = !d.mutable,3488 .is_volatile = d.@"volatile",
3489 .is_volatile = d.@"volatile",3489 .is_allowzero = d.@"allowzero",
3490 .is_allowzero = d.@"allowzero",3490 .address_space = d.@"addrspace",
3491 .address_space = d.@"addrspace",3491 },
3492 .packed_offset = .{
3493 .host_size = d.host_size,
3494 .bit_offset = d.bit_offset,
3495 },
3492 });3496 });
3493 }3497 }
34943498
src/value.zig+2-2
...@@ -2080,8 +2080,8 @@ pub const Value = struct {...@@ -2080,8 +2080,8 @@ pub const Value = struct {
2080 else => val,2080 else => val,
2081 };2081 };
2082 var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type;2082 var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type;
2083 assert(ptr_ty_key.size != .Slice);2083 assert(ptr_ty_key.flags.size != .Slice);
2084 ptr_ty_key.size = .Many;2084 ptr_ty_key.flags.size = .Many;
2085 return (try mod.intern(.{ .ptr = .{2085 return (try mod.intern(.{ .ptr = .{
2086 .ty = elem_ptr_ty.toIntern(),2086 .ty = elem_ptr_ty.toIntern(),
2087 .addr = .{ .elem = .{2087 .addr = .{ .elem = .{