| ... | @@ -674,11 +674,12 @@ pub const DataLayout = struct { | ... | @@ -674,11 +674,12 @@ pub const DataLayout = struct { |
| 674 | }, | 674 | }, |
| 675 | } else first[first.len..]; | 675 | } else first[first.len..]; |
| 676 | const bit_width = std.fmt.parseInt(PointerSpec.BitWidth, field_it.next().?, 10) catch unreachable; | 676 | const bit_width = std.fmt.parseInt(PointerSpec.BitWidth, field_it.next().?, 10) catch unreachable; |
| 677 | const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable); | 677 | const abi_align: Alignment = .fromByteUnits( |
| 678 | const pref_align: Alignment = if (field_it.next()) |pref_align| | 678 | @divExact(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable, 8), |
| 679 | .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) | 679 | ); |
| 680 | else | 680 | const pref_align: Alignment = if (field_it.next()) |pref_align| .fromByteUnits( |
| 681 | abi_align; | 681 | @divExact(std.fmt.parseInt(u64, pref_align, 10) catch unreachable, 8), |
| | 682 | ) else abi_align; |
| 682 | const index_bit_width = if (field_it.next()) |index_bit_width| | 683 | const index_bit_width = if (field_it.next()) |index_bit_width| |
| 683 | std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable | 684 | std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable |
| 684 | else | 685 | else |
| ... | @@ -708,11 +709,12 @@ pub const DataLayout = struct { | ... | @@ -708,11 +709,12 @@ pub const DataLayout = struct { |
| 708 | } | 709 | } |
| 709 | var field_it = std.mem.splitScalar(u8, spec[1..], ':'); | 710 | var field_it = std.mem.splitScalar(u8, spec[1..], ':'); |
| 710 | const bit_width = std.fmt.parseInt(PrimitiveSpec.BitWidth, field_it.first(), 10) catch unreachable; | 711 | const bit_width = std.fmt.parseInt(PrimitiveSpec.BitWidth, field_it.first(), 10) catch unreachable; |
| 711 | const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable); | 712 | const abi_align: Alignment = .fromByteUnits( |
| 712 | const pref_align: Alignment = if (field_it.next()) |pref_align| | 713 | @divExact(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable, 8), |
| 713 | .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) | 714 | ); |
| 714 | else | 715 | const pref_align: Alignment = if (field_it.next()) |pref_align| .fromByteUnits( |
| 715 | abi_align; | 716 | @divExact(std.fmt.parseInt(u64, pref_align, 10) catch unreachable, 8), |
| | 717 | ) else abi_align; |
| 716 | assert(field_it.peek() == null); | 718 | assert(field_it.peek() == null); |
| 717 | const specs = switch (kind) { | 719 | const specs = switch (kind) { |
| 718 | else => unreachable, | 720 | else => unreachable, |
| ... | @@ -720,7 +722,10 @@ pub const DataLayout = struct { | ... | @@ -720,7 +722,10 @@ pub const DataLayout = struct { |
| 720 | 'f' => &float_specs, | 722 | 'f' => &float_specs, |
| 721 | 'v' => &vector_specs, | 723 | 'v' => &vector_specs, |
| 722 | }; | 724 | }; |
| 723 | try specs.put(gpa, .{ .bit_width = bit_width, .abi_align = abi_align, .pref_align = pref_align }, {}); | 725 | const primitive_spec: PrimitiveSpec = |
| | 726 | .{ .bit_width = bit_width, .abi_align = abi_align, .pref_align = pref_align }; |
| | 727 | const gop = try specs.getOrPut(gpa, primitive_spec); |
| | 728 | gop.key_ptr.* = primitive_spec; |
| 724 | }, | 729 | }, |
| 725 | 'n' => { | 730 | 'n' => { |
| 726 | var field_it = std.mem.splitScalar(u8, spec[1..], ':'); | 731 | var field_it = std.mem.splitScalar(u8, spec[1..], ':'); |
| ... | @@ -784,45 +789,52 @@ pub const DataLayout = struct { | ... | @@ -784,45 +789,52 @@ pub const DataLayout = struct { |
| 784 | data_layout.pointer_specs.deinit(gpa); | 789 | data_layout.pointer_specs.deinit(gpa); |
| 785 | } | 790 | } |
| 786 | | 791 | |
| 787 | pub fn getIntegerSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec { | 792 | pub fn getIntegerSpec(data_layout: *const DataLayout, bit_width: Type.Size) PrimitiveSpec { |
| 788 | const specs = data_layout.int_specs.keys(); | 793 | const specs = data_layout.int_specs.keys(); |
| 789 | return specs[ | 794 | return specs[ |
| 790 | @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct { | 795 | @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct { |
| 791 | fn order(ctx: PrimitiveSpec.BitWidth, spec: PrimitiveSpec) std.math.Order { | 796 | fn order(ctx: Type.Size, spec: PrimitiveSpec) std.math.Order { |
| 792 | return std.math.order(ctx, spec.bit_width); | 797 | return std.math.order(ctx.fixed, spec.bit_width); |
| 793 | } | 798 | } |
| 794 | }.order), specs.len - 1) | 799 | }.order), specs.len - 1) |
| 795 | ]; | 800 | ]; |
| 796 | } | 801 | } |
| 797 | | 802 | |
| 798 | pub fn getFloatSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec { | 803 | pub fn getFloatSpec(data_layout: *const DataLayout, bit_width: Type.Size) PrimitiveSpec { |
| | 804 | const fixed_bit_width: PrimitiveSpec.BitWidth = @intCast(bit_width.fixed); |
| 799 | if (data_layout.float_specs.getEntry(.{ | 805 | if (data_layout.float_specs.getEntry(.{ |
| 800 | .bit_width = bit_width, | 806 | .bit_width = fixed_bit_width, |
| 801 | .abi_align = .default, | 807 | .abi_align = .default, |
| 802 | .pref_align = .default, | 808 | .pref_align = .default, |
| 803 | })) |entry| return entry.key_ptr.*; | 809 | })) |entry| return entry.key_ptr.*; |
| 804 | const default_align: Alignment = .fromByteUnits( | 810 | const default_align: Alignment = .fromByteUnits( |
| 805 | std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, bit_width / 8), | 811 | std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, @divExact(fixed_bit_width, 8)), |
| 806 | ); | 812 | ); |
| 807 | return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; | 813 | return .{ |
| | 814 | .bit_width = fixed_bit_width, |
| | 815 | .abi_align = default_align, |
| | 816 | .pref_align = default_align, |
| | 817 | }; |
| 808 | } | 818 | } |
| 809 | | 819 | |
| 810 | pub fn getVectorSpec( | 820 | pub fn getVectorSpec(data_layout: *const DataLayout, bit_width: Type.Size) PrimitiveSpec { |
| 811 | data_layout: *const DataLayout, | 821 | const known_min_bit_width: PrimitiveSpec.BitWidth = @intCast(switch (bit_width) { |
| 812 | bit_width: PrimitiveSpec.BitWidth, | 822 | .fixed, .scalable => |known_min| known_min, |
| 813 | store_size: Type.Size, | 823 | }); |
| 814 | ) PrimitiveSpec { | 824 | if (data_layout.vector_specs.getEntry(.{ |
| 815 | if (data_layout.float_specs.getEntry(.{ | 825 | .bit_width = known_min_bit_width, |
| 816 | .bit_width = bit_width, | | |
| 817 | .abi_align = .default, | 826 | .abi_align = .default, |
| 818 | .pref_align = .default, | 827 | .pref_align = .default, |
| 819 | })) |entry| return entry.key_ptr.*; | 828 | })) |entry| return entry.key_ptr.*; |
| 820 | const default_align: Alignment = .fromByteUnits( | 829 | const default_align: Alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| 821 | std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, switch (store_size) { | 830 | PrimitiveSpec.BitWidth, |
| 822 | .fixed, .scalable => |known_min| known_min, | 831 | std.mem.alignForward(PrimitiveSpec.BitWidth, known_min_bit_width, 8), |
| 823 | }), | 832 | )); |
| 824 | ); | 833 | return .{ |
| 825 | return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; | 834 | .bit_width = known_min_bit_width, |
| | 835 | .abi_align = default_align, |
| | 836 | .pref_align = default_align, |
| | 837 | }; |
| 826 | } | 838 | } |
| 827 | | 839 | |
| 828 | pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec { | 840 | pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec { |
| ... | @@ -1699,6 +1711,22 @@ pub const Type = enum(u32) { | ... | @@ -1699,6 +1711,22 @@ pub const Type = enum(u32) { |
| 1699 | .pointer => .{ | 1711 | .pointer => .{ |
| 1700 | .fixed = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width, | 1712 | .fixed = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width, |
| 1701 | }, | 1713 | }, |
| | 1714 | .vector, .scalable_vector => { |
| | 1715 | const extra = builder.typeExtraData(Type.Vector, item.data); |
| | 1716 | const min_bits = extra.len * extra.child.bits(builder).fixed; |
| | 1717 | return switch (item.tag) { |
| | 1718 | else => unreachable, |
| | 1719 | .vector => .{ .fixed = min_bits }, |
| | 1720 | .scalable_vector => .{ .scalable = min_bits }, |
| | 1721 | }; |
| | 1722 | }, |
| | 1723 | }; |
| | 1724 | } |
| | 1725 | |
| | 1726 | pub fn storeSize(ty: Type, builder: *const Builder) Size { |
| | 1727 | return switch (ty.bits(builder)) { |
| | 1728 | .fixed => |fixed| .{ .fixed = @divCeil(fixed, 8) }, |
| | 1729 | .scalable => |known_min| .{ .scalable = @divCeil(known_min, 8) }, |
| 1702 | }; | 1730 | }; |
| 1703 | } | 1731 | } |
| 1704 | | 1732 | |
| ... | @@ -1716,7 +1744,7 @@ pub const Type = enum(u32) { | ... | @@ -1716,7 +1744,7 @@ pub const Type = enum(u32) { |
| 1716 | }; | 1744 | }; |
| 1717 | }, | 1745 | }, |
| 1718 | .half, .bfloat, .float, .double, .ppc_fp128, .fp128, .x86_fp80 => { | 1746 | .half, .bfloat, .float, .double, .ppc_fp128, .fp128, .x86_fp80 => { |
| 1719 | const spec = builder.data_layout.getFloatSpec(@intCast(ty.bits(builder).fixed)); | 1747 | const spec = builder.data_layout.getFloatSpec(ty.bits(builder)); |
| 1720 | return switch (kind) { | 1748 | return switch (kind) { |
| 1721 | .abi => spec.abi_align, | 1749 | .abi => spec.abi_align, |
| 1722 | .pref => spec.pref_align, | 1750 | .pref => spec.pref_align, |
| ... | @@ -1725,7 +1753,7 @@ pub const Type = enum(u32) { | ... | @@ -1725,7 +1753,7 @@ pub const Type = enum(u32) { |
| 1725 | .x86_amx => return comptime .fromByteUnits(64), | 1753 | .x86_amx => return comptime .fromByteUnits(64), |
| 1726 | }, | 1754 | }, |
| 1727 | .integer => { | 1755 | .integer => { |
| 1728 | const spec = builder.data_layout.getIntegerSpec(@intCast(item.data)); | 1756 | const spec = builder.data_layout.getIntegerSpec(.{ .fixed = item.data }); |
| 1729 | return switch (kind) { | 1757 | return switch (kind) { |
| 1730 | .abi => spec.abi_align, | 1758 | .abi => spec.abi_align, |
| 1731 | .pref => spec.pref_align, | 1759 | .pref => spec.pref_align, |
| ... | @@ -1738,6 +1766,13 @@ pub const Type = enum(u32) { | ... | @@ -1738,6 +1766,13 @@ pub const Type = enum(u32) { |
| 1738 | .pref => spec.flags.pref_align, | 1766 | .pref => spec.flags.pref_align, |
| 1739 | }; | 1767 | }; |
| 1740 | }, | 1768 | }, |
| | 1769 | .vector, .scalable_vector => { |
| | 1770 | const spec = builder.data_layout.getVectorSpec(ty.bits(builder)); |
| | 1771 | return switch (kind) { |
| | 1772 | .abi => spec.abi_align, |
| | 1773 | .pref => spec.pref_align, |
| | 1774 | }; |
| | 1775 | }, |
| 1741 | } | 1776 | } |
| 1742 | } | 1777 | } |
| 1743 | }; | 1778 | }; |