| ... | ... | @@ -674,11 +674,12 @@ pub const DataLayout = struct { |
| 674 | 674 | }, |
| 675 | 675 | } else first[first.len..]; |
| 676 | 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); |
| 678 | | const pref_align: Alignment = if (field_it.next()) |pref_align| |
| 679 | | .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) |
| 680 | | else |
| 681 | | abi_align; |
| 677 | const abi_align: Alignment = .fromByteUnits( |
| 678 | @divExact(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable, 8), |
| 679 | ); |
| 680 | const pref_align: Alignment = if (field_it.next()) |pref_align| .fromByteUnits( |
| 681 | @divExact(std.fmt.parseInt(u64, pref_align, 10) catch unreachable, 8), |
| 682 | ) else abi_align; |
| 682 | 683 | const index_bit_width = if (field_it.next()) |index_bit_width| |
| 683 | 684 | std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable |
| 684 | 685 | else |
| ... | ... | @@ -708,11 +709,12 @@ pub const DataLayout = struct { |
| 708 | 709 | } |
| 709 | 710 | var field_it = std.mem.splitScalar(u8, spec[1..], ':'); |
| 710 | 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 pref_align: Alignment = if (field_it.next()) |pref_align| |
| 713 | | .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) |
| 714 | | else |
| 715 | | abi_align; |
| 712 | const abi_align: Alignment = .fromByteUnits( |
| 713 | @divExact(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable, 8), |
| 714 | ); |
| 715 | const pref_align: Alignment = if (field_it.next()) |pref_align| .fromByteUnits( |
| 716 | @divExact(std.fmt.parseInt(u64, pref_align, 10) catch unreachable, 8), |
| 717 | ) else abi_align; |
| 716 | 718 | assert(field_it.peek() == null); |
| 717 | 719 | const specs = switch (kind) { |
| 718 | 720 | else => unreachable, |
| ... | ... | @@ -720,7 +722,10 @@ pub const DataLayout = struct { |
| 720 | 722 | 'f' => &float_specs, |
| 721 | 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 | 730 | 'n' => { |
| 726 | 731 | var field_it = std.mem.splitScalar(u8, spec[1..], ':'); |
| ... | ... | @@ -784,45 +789,52 @@ pub const DataLayout = struct { |
| 784 | 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 | 793 | const specs = data_layout.int_specs.keys(); |
| 789 | 794 | return specs[ |
| 790 | 795 | @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct { |
| 791 | | fn order(ctx: PrimitiveSpec.BitWidth, spec: PrimitiveSpec) std.math.Order { |
| 792 | | return std.math.order(ctx, spec.bit_width); |
| 796 | fn order(ctx: Type.Size, spec: PrimitiveSpec) std.math.Order { |
| 797 | return std.math.order(ctx.fixed, spec.bit_width); |
| 793 | 798 | } |
| 794 | 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 | 805 | if (data_layout.float_specs.getEntry(.{ |
| 800 | | .bit_width = bit_width, |
| 806 | .bit_width = fixed_bit_width, |
| 801 | 807 | .abi_align = .default, |
| 802 | 808 | .pref_align = .default, |
| 803 | 809 | })) |entry| return entry.key_ptr.*; |
| 804 | 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( |
| 811 | | data_layout: *const DataLayout, |
| 812 | | bit_width: PrimitiveSpec.BitWidth, |
| 813 | | store_size: Type.Size, |
| 814 | | ) PrimitiveSpec { |
| 815 | | if (data_layout.float_specs.getEntry(.{ |
| 816 | | .bit_width = bit_width, |
| 820 | pub fn getVectorSpec(data_layout: *const DataLayout, bit_width: Type.Size) PrimitiveSpec { |
| 821 | const known_min_bit_width: PrimitiveSpec.BitWidth = @intCast(switch (bit_width) { |
| 822 | .fixed, .scalable => |known_min| known_min, |
| 823 | }); |
| 824 | if (data_layout.vector_specs.getEntry(.{ |
| 825 | .bit_width = known_min_bit_width, |
| 817 | 826 | .abi_align = .default, |
| 818 | 827 | .pref_align = .default, |
| 819 | 828 | })) |entry| return entry.key_ptr.*; |
| 820 | | const default_align: Alignment = .fromByteUnits( |
| 821 | | std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, switch (store_size) { |
| 822 | | .fixed, .scalable => |known_min| known_min, |
| 823 | | }), |
| 824 | | ); |
| 825 | | return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; |
| 829 | const default_align: Alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| 830 | PrimitiveSpec.BitWidth, |
| 831 | std.mem.alignForward(PrimitiveSpec.BitWidth, known_min_bit_width, 8), |
| 832 | )); |
| 833 | return .{ |
| 834 | .bit_width = known_min_bit_width, |
| 835 | .abi_align = default_align, |
| 836 | .pref_align = default_align, |
| 837 | }; |
| 826 | 838 | } |
| 827 | 839 | |
| 828 | 840 | pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec { |
| ... | ... | @@ -1699,6 +1711,22 @@ pub const Type = enum(u32) { |
| 1699 | 1711 | .pointer => .{ |
| 1700 | 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 | 1744 | }; |
| 1717 | 1745 | }, |
| 1718 | 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 | 1748 | return switch (kind) { |
| 1721 | 1749 | .abi => spec.abi_align, |
| 1722 | 1750 | .pref => spec.pref_align, |
| ... | ... | @@ -1725,7 +1753,7 @@ pub const Type = enum(u32) { |
| 1725 | 1753 | .x86_amx => return comptime .fromByteUnits(64), |
| 1726 | 1754 | }, |
| 1727 | 1755 | .integer => { |
| 1728 | | const spec = builder.data_layout.getIntegerSpec(@intCast(item.data)); |
| 1756 | const spec = builder.data_layout.getIntegerSpec(.{ .fixed = item.data }); |
| 1729 | 1757 | return switch (kind) { |
| 1730 | 1758 | .abi => spec.abi_align, |
| 1731 | 1759 | .pref => spec.pref_align, |
| ... | ... | @@ -1738,6 +1766,13 @@ pub const Type = enum(u32) { |
| 1738 | 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 | }; |