authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-29 17:40:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-08 19:37:29-07:00
logb7799ef322103c8e449c45494c29fb4a8c9867df
treef1f1a5fe4c52a7ce335a6e1ae75e939bcb07c86d
parent62381011e0dd692ec6bb30d14e0d5e2f6ec4d5d5

std.Target.maxIntAlignment: move to compiler implementation

This should not be a public API, and the x86 backend does not support the value 16.

7 files changed, 145 insertions(+), 111 deletions(-)

lib/compiler/aro/aro/Type.zig+1-1
......@@ -1116,7 +1116,7 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 {
11161116
11171117 .bit_int => @min(
11181118 std.math.ceilPowerOfTwoPromote(u16, (ty.data.int.bits + 7) / 8),
1119 comp.target.maxIntAlignment(),
1119 16, // comp.target.maxIntAlignment(), please use your own logic for this value as it is implementation-defined
11201120 ),
11211121
11221122 .float => comp.target.c_type_alignment(.float),
lib/std/Target.zig-91
......@@ -1862,97 +1862,6 @@ pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
18621862 return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
18631863}
18641864
1865pub fn maxIntAlignment(target: Target) u16 {
1866 return switch (target.cpu.arch) {
1867 .avr => 1,
1868 .msp430 => 2,
1869 .xcore => 4,
1870
1871 .arm,
1872 .armeb,
1873 .thumb,
1874 .thumbeb,
1875 .hexagon,
1876 .mips,
1877 .mipsel,
1878 .powerpc,
1879 .powerpcle,
1880 .r600,
1881 .amdgcn,
1882 .riscv32,
1883 .sparc,
1884 .sparcel,
1885 .s390x,
1886 .lanai,
1887 .wasm32,
1888 .wasm64,
1889 => 8,
1890
1891 .x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) {
1892 .windows, .uefi => 8,
1893 else => 4,
1894 },
1895
1896 // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
1897 // is a relevant number in three cases:
1898 // 1. Different machine code instruction when loading into SIMD register.
1899 // 2. The C ABI wants 16 for extern structs.
1900 // 3. 16-byte cmpxchg needs 16-byte alignment.
1901 // Same logic for powerpc64, mips64, sparc64.
1902 .powerpc64,
1903 .powerpc64le,
1904 .mips64,
1905 .mips64el,
1906 .sparc64,
1907 => return switch (target.ofmt) {
1908 .c => 16,
1909 else => 8,
1910 },
1911
1912 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1913 .x86_64,
1914 .aarch64,
1915 .aarch64_be,
1916 .aarch64_32,
1917 .riscv64,
1918 .bpfel,
1919 .bpfeb,
1920 .nvptx,
1921 .nvptx64,
1922 => 16,
1923
1924 // Below this comment are unverified but based on the fact that C requires
1925 // int128_t to be 16 bytes aligned, it's a safe default.
1926 .spu_2,
1927 .csky,
1928 .arc,
1929 .m68k,
1930 .tce,
1931 .tcele,
1932 .le32,
1933 .amdil,
1934 .hsail,
1935 .spir,
1936 .kalimba,
1937 .renderscript32,
1938 .spirv,
1939 .spirv32,
1940 .shave,
1941 .le64,
1942 .amdil64,
1943 .hsail64,
1944 .spir64,
1945 .renderscript64,
1946 .ve,
1947 .spirv64,
1948 .dxil,
1949 .loongarch32,
1950 .loongarch64,
1951 .xtensa,
1952 => 16,
1953 };
1954}
1955
19561865pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {
19571866 switch (abi) {
19581867 .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32,
src/codegen/c/Type.zig+5-5
......@@ -1312,10 +1312,10 @@ pub const Pool = struct {
13121312 },
13131313 else => {
13141314 const target = &mod.resolved_target.result;
1315 const abi_align = Type.intAbiAlignment(int_info.bits, target.*);
1315 const abi_align = Type.intAbiAlignment(int_info.bits, target.*, false);
13161316 const abi_align_bytes = abi_align.toByteUnits().?;
13171317 const array_ctype = try pool.getArray(allocator, .{
1318 .len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes),
1318 .len = @divExact(Type.intAbiSize(int_info.bits, target.*, false), abi_align_bytes),
13191319 .elem_ctype = try pool.fromIntInfo(allocator, .{
13201320 .signedness = .unsigned,
13211321 .bits = @intCast(abi_align_bytes * 8),
......@@ -1443,7 +1443,7 @@ pub const Pool = struct {
14431443 .name = .{ .index = .len },
14441444 .ctype = CType.usize,
14451445 .alignas = AlignAs.fromAbiAlignment(
1446 Type.intAbiAlignment(target.ptrBitWidth(), target.*),
1446 Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),
14471447 ),
14481448 },
14491449 };
......@@ -1545,7 +1545,7 @@ pub const Pool = struct {
15451545 .name = .{ .index = .len },
15461546 .ctype = CType.usize,
15471547 .alignas = AlignAs.fromAbiAlignment(
1548 Type.intAbiAlignment(target.ptrBitWidth(), target.*),
1548 Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),
15491549 ),
15501550 },
15511551 };
......@@ -1665,7 +1665,7 @@ pub const Pool = struct {
16651665 .name = .{ .index = .@"error" },
16661666 .ctype = error_set_ctype,
16671667 .alignas = AlignAs.fromAbiAlignment(
1668 Type.intAbiAlignment(error_set_bits, target.*),
1668 Type.intAbiAlignment(error_set_bits, target.*, false),
16691669 ),
16701670 },
16711671 .{
src/codegen/llvm.zig+1-1
......@@ -609,7 +609,7 @@ const DataLayoutBuilder = struct {
609609 switch (kind) {
610610 .integer => {
611611 if (self.target.ptrBitWidth() <= 16 and size >= 128) return;
612 abi = @min(abi, self.target.maxIntAlignment() * 8);
612 abi = @min(abi, Type.maxIntAlignment(self.target, true) * 8);
613613 switch (self.target.cpu.arch) {
614614 .aarch64,
615615 .aarch64_be,
src/link/C.zig+3-1
......@@ -383,7 +383,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
383383 .msvc => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
384384 else => {},
385385 }
386 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{target.maxIntAlignment()});
386 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
387 Type.maxIntAlignment(target, false),
388 });
387389 return defines;
388390}
389391
src/type.zig+108-11
......@@ -883,6 +883,7 @@ pub const Type = struct {
883883 strat: AbiAlignmentAdvancedStrat,
884884 ) Module.CompileError!AbiAlignmentAdvanced {
885885 const target = mod.getTarget();
886 const use_llvm = mod.comp.config.use_llvm;
886887 const ip = &mod.intern_pool;
887888
888889 const opt_sema = switch (strat) {
......@@ -895,7 +896,7 @@ pub const Type = struct {
895896 else => switch (ip.indexToKey(ty.toIntern())) {
896897 .int_type => |int_type| {
897898 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
898 return .{ .scalar = intAbiAlignment(int_type.bits, target) };
899 return .{ .scalar = intAbiAlignment(int_type.bits, target, use_llvm) };
899900 },
900901 .ptr_type, .anyframe_type => {
901902 return .{ .scalar = ptrAbiAlignment(target) };
......@@ -941,7 +942,7 @@ pub const Type = struct {
941942 .error_set_type, .inferred_error_set_type => {
942943 const bits = mod.errorSetBits();
943944 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
944 return .{ .scalar = intAbiAlignment(bits, target) };
945 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
945946 },
946947
947948 // represents machine code; not a pointer
......@@ -962,7 +963,7 @@ pub const Type = struct {
962963
963964 .usize,
964965 .isize,
965 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) },
966 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },
966967
967968 .export_options,
968969 .extern_options,
......@@ -1001,7 +1002,7 @@ pub const Type = struct {
10011002 .anyerror, .adhoc_inferred_error_set => {
10021003 const bits = mod.errorSetBits();
10031004 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
1004 return .{ .scalar = intAbiAlignment(bits, target) };
1005 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
10051006 },
10061007
10071008 .void,
......@@ -1216,6 +1217,7 @@ pub const Type = struct {
12161217 strat: AbiAlignmentAdvancedStrat,
12171218 ) Module.CompileError!AbiSizeAdvanced {
12181219 const target = mod.getTarget();
1220 const use_llvm = mod.comp.config.use_llvm;
12191221 const ip = &mod.intern_pool;
12201222
12211223 switch (ty.toIntern()) {
......@@ -1224,7 +1226,7 @@ pub const Type = struct {
12241226 else => switch (ip.indexToKey(ty.toIntern())) {
12251227 .int_type => |int_type| {
12261228 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1227 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
1229 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target, use_llvm) };
12281230 },
12291231 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
12301232 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
......@@ -1286,7 +1288,7 @@ pub const Type = struct {
12861288 .error_set_type, .inferred_error_set_type => {
12871289 const bits = mod.errorSetBits();
12881290 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1289 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1291 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
12901292 },
12911293
12921294 .error_union_type => |error_union_type| {
......@@ -1384,7 +1386,7 @@ pub const Type = struct {
13841386 .anyerror, .adhoc_inferred_error_set => {
13851387 const bits = mod.errorSetBits();
13861388 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1387 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1389 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
13881390 },
13891391
13901392 .prefetch_options => unreachable, // missing call to resolveTypeFields
......@@ -1533,17 +1535,112 @@ pub const Type = struct {
15331535 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
15341536 }
15351537
1536 pub fn intAbiSize(bits: u16, target: Target) u64 {
1537 return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
1538 pub fn intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 {
1539 return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
15381540 }
15391541
1540 pub fn intAbiAlignment(bits: u16, target: Target) Alignment {
1542 pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {
15411543 return Alignment.fromByteUnits(@min(
15421544 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
1543 target.maxIntAlignment(),
1545 maxIntAlignment(target, use_llvm),
15441546 ));
15451547 }
15461548
1549 pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {
1550 return switch (target.cpu.arch) {
1551 .avr => 1,
1552 .msp430 => 2,
1553 .xcore => 4,
1554
1555 .arm,
1556 .armeb,
1557 .thumb,
1558 .thumbeb,
1559 .hexagon,
1560 .mips,
1561 .mipsel,
1562 .powerpc,
1563 .powerpcle,
1564 .r600,
1565 .amdgcn,
1566 .riscv32,
1567 .sparc,
1568 .sparcel,
1569 .s390x,
1570 .lanai,
1571 .wasm32,
1572 .wasm64,
1573 => 8,
1574
1575 .x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) {
1576 .windows, .uefi => 8,
1577 else => 4,
1578 },
1579
1580 // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
1581 // is a relevant number in three cases:
1582 // 1. Different machine code instruction when loading into SIMD register.
1583 // 2. The C ABI wants 16 for extern structs.
1584 // 3. 16-byte cmpxchg needs 16-byte alignment.
1585 // Same logic for powerpc64, mips64, sparc64.
1586 .powerpc64,
1587 .powerpc64le,
1588 .mips64,
1589 .mips64el,
1590 .sparc64,
1591 => switch (target.ofmt) {
1592 .c => 16,
1593 else => 8,
1594 },
1595
1596 .x86_64 => switch (target_util.zigBackend(target, use_llvm)) {
1597 .stage2_x86_64 => 8,
1598 else => 16,
1599 },
1600
1601 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1602 .aarch64,
1603 .aarch64_be,
1604 .aarch64_32,
1605 .riscv64,
1606 .bpfel,
1607 .bpfeb,
1608 .nvptx,
1609 .nvptx64,
1610 => 16,
1611
1612 // Below this comment are unverified but based on the fact that C requires
1613 // int128_t to be 16 bytes aligned, it's a safe default.
1614 .spu_2,
1615 .csky,
1616 .arc,
1617 .m68k,
1618 .tce,
1619 .tcele,
1620 .le32,
1621 .amdil,
1622 .hsail,
1623 .spir,
1624 .kalimba,
1625 .renderscript32,
1626 .spirv,
1627 .spirv32,
1628 .shave,
1629 .le64,
1630 .amdil64,
1631 .hsail64,
1632 .spir64,
1633 .renderscript64,
1634 .ve,
1635 .spirv64,
1636 .dxil,
1637 .loongarch32,
1638 .loongarch64,
1639 .xtensa,
1640 => 16,
1641 };
1642 }
1643
15471644 pub fn bitSize(ty: Type, mod: *Module) u64 {
15481645 return bitSizeAdvanced(ty, mod, null) catch unreachable;
15491646 }
test/behavior/align.zig+27-1
......@@ -184,6 +184,33 @@ test "alignment and size of structs with 128-bit fields" {
184184 },
185185 },
186186
187 .x86_64 => switch (builtin.zig_backend) {
188 .stage2_x86_64 => .{
189 .a_align = 8,
190 .a_size = 16,
191
192 .b_align = 16,
193 .b_size = 32,
194
195 .u128_align = 8,
196 .u128_size = 16,
197 .u129_align = 8,
198 .u129_size = 24,
199 },
200 else => .{
201 .a_align = 16,
202 .a_size = 16,
203
204 .b_align = 16,
205 .b_size = 32,
206
207 .u128_align = 16,
208 .u128_size = 16,
209 .u129_align = 16,
210 .u129_size = 32,
211 },
212 },
213
187214 .aarch64,
188215 .aarch64_be,
189216 .aarch64_32,
......@@ -192,7 +219,6 @@ test "alignment and size of structs with 128-bit fields" {
192219 .bpfeb,
193220 .nvptx,
194221 .nvptx64,
195 .x86_64,
196222 => .{
197223 .a_align = 16,
198224 .a_size = 16,