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 {...@@ -1116,7 +1116,7 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 {
11161116
1117 .bit_int => @min(1117 .bit_int => @min(
1118 std.math.ceilPowerOfTwoPromote(u16, (ty.data.int.bits + 7) / 8),1118 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
1120 ),1120 ),
11211121
1122 .float => comp.target.c_type_alignment(.float),1122 .float => comp.target.c_type_alignment(.float),
lib/std/Target.zig-91
...@@ -1862,97 +1862,6 @@ pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {...@@ -1862,97 +1862,6 @@ pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1862 return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);1862 return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
1863}1863}
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
1956pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {1865pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {
1957 switch (abi) {1866 switch (abi) {
1958 .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32,1867 .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32,
src/codegen/c/Type.zig+5-5
...@@ -1312,10 +1312,10 @@ pub const Pool = struct {...@@ -1312,10 +1312,10 @@ pub const Pool = struct {
1312 },1312 },
1313 else => {1313 else => {
1314 const target = &mod.resolved_target.result;1314 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);
1316 const abi_align_bytes = abi_align.toByteUnits().?;1316 const abi_align_bytes = abi_align.toByteUnits().?;
1317 const array_ctype = try pool.getArray(allocator, .{1317 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),
1319 .elem_ctype = try pool.fromIntInfo(allocator, .{1319 .elem_ctype = try pool.fromIntInfo(allocator, .{
1320 .signedness = .unsigned,1320 .signedness = .unsigned,
1321 .bits = @intCast(abi_align_bytes * 8),1321 .bits = @intCast(abi_align_bytes * 8),
...@@ -1443,7 +1443,7 @@ pub const Pool = struct {...@@ -1443,7 +1443,7 @@ pub const Pool = struct {
1443 .name = .{ .index = .len },1443 .name = .{ .index = .len },
1444 .ctype = CType.usize,1444 .ctype = CType.usize,
1445 .alignas = AlignAs.fromAbiAlignment(1445 .alignas = AlignAs.fromAbiAlignment(
1446 Type.intAbiAlignment(target.ptrBitWidth(), target.*),1446 Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),
1447 ),1447 ),
1448 },1448 },
1449 };1449 };
...@@ -1545,7 +1545,7 @@ pub const Pool = struct {...@@ -1545,7 +1545,7 @@ pub const Pool = struct {
1545 .name = .{ .index = .len },1545 .name = .{ .index = .len },
1546 .ctype = CType.usize,1546 .ctype = CType.usize,
1547 .alignas = AlignAs.fromAbiAlignment(1547 .alignas = AlignAs.fromAbiAlignment(
1548 Type.intAbiAlignment(target.ptrBitWidth(), target.*),1548 Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),
1549 ),1549 ),
1550 },1550 },
1551 };1551 };
...@@ -1665,7 +1665,7 @@ pub const Pool = struct {...@@ -1665,7 +1665,7 @@ pub const Pool = struct {
1665 .name = .{ .index = .@"error" },1665 .name = .{ .index = .@"error" },
1666 .ctype = error_set_ctype,1666 .ctype = error_set_ctype,
1667 .alignas = AlignAs.fromAbiAlignment(1667 .alignas = AlignAs.fromAbiAlignment(
1668 Type.intAbiAlignment(error_set_bits, target.*),1668 Type.intAbiAlignment(error_set_bits, target.*, false),
1669 ),1669 ),
1670 },1670 },
1671 .{1671 .{
src/codegen/llvm.zig+1-1
...@@ -609,7 +609,7 @@ const DataLayoutBuilder = struct {...@@ -609,7 +609,7 @@ const DataLayoutBuilder = struct {
609 switch (kind) {609 switch (kind) {
610 .integer => {610 .integer => {
611 if (self.target.ptrBitWidth() <= 16 and size >= 128) return;611 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);
613 switch (self.target.cpu.arch) {613 switch (self.target.cpu.arch) {
614 .aarch64,614 .aarch64,
615 .aarch64_be,615 .aarch64_be,
src/link/C.zig+3-1
...@@ -383,7 +383,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {...@@ -383,7 +383,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
383 .msvc => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),383 .msvc => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
384 else => {},384 else => {},
385 }385 }
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 });
387 return defines;389 return defines;
388}390}
389391
src/type.zig+108-11
...@@ -883,6 +883,7 @@ pub const Type = struct {...@@ -883,6 +883,7 @@ pub const Type = struct {
883 strat: AbiAlignmentAdvancedStrat,883 strat: AbiAlignmentAdvancedStrat,
884 ) Module.CompileError!AbiAlignmentAdvanced {884 ) Module.CompileError!AbiAlignmentAdvanced {
885 const target = mod.getTarget();885 const target = mod.getTarget();
886 const use_llvm = mod.comp.config.use_llvm;
886 const ip = &mod.intern_pool;887 const ip = &mod.intern_pool;
887888
888 const opt_sema = switch (strat) {889 const opt_sema = switch (strat) {
...@@ -895,7 +896,7 @@ pub const Type = struct {...@@ -895,7 +896,7 @@ pub const Type = struct {
895 else => switch (ip.indexToKey(ty.toIntern())) {896 else => switch (ip.indexToKey(ty.toIntern())) {
896 .int_type => |int_type| {897 .int_type => |int_type| {
897 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };898 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) };
899 },900 },
900 .ptr_type, .anyframe_type => {901 .ptr_type, .anyframe_type => {
901 return .{ .scalar = ptrAbiAlignment(target) };902 return .{ .scalar = ptrAbiAlignment(target) };
...@@ -941,7 +942,7 @@ pub const Type = struct {...@@ -941,7 +942,7 @@ pub const Type = struct {
941 .error_set_type, .inferred_error_set_type => {942 .error_set_type, .inferred_error_set_type => {
942 const bits = mod.errorSetBits();943 const bits = mod.errorSetBits();
943 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };944 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
944 return .{ .scalar = intAbiAlignment(bits, target) };945 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
945 },946 },
946947
947 // represents machine code; not a pointer948 // represents machine code; not a pointer
...@@ -962,7 +963,7 @@ pub const Type = struct {...@@ -962,7 +963,7 @@ pub const Type = struct {
962963
963 .usize,964 .usize,
964 .isize,965 .isize,
965 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) },966 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },
966967
967 .export_options,968 .export_options,
968 .extern_options,969 .extern_options,
...@@ -1001,7 +1002,7 @@ pub const Type = struct {...@@ -1001,7 +1002,7 @@ pub const Type = struct {
1001 .anyerror, .adhoc_inferred_error_set => {1002 .anyerror, .adhoc_inferred_error_set => {
1002 const bits = mod.errorSetBits();1003 const bits = mod.errorSetBits();
1003 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };1004 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
1004 return .{ .scalar = intAbiAlignment(bits, target) };1005 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
1005 },1006 },
10061007
1007 .void,1008 .void,
...@@ -1216,6 +1217,7 @@ pub const Type = struct {...@@ -1216,6 +1217,7 @@ pub const Type = struct {
1216 strat: AbiAlignmentAdvancedStrat,1217 strat: AbiAlignmentAdvancedStrat,
1217 ) Module.CompileError!AbiSizeAdvanced {1218 ) Module.CompileError!AbiSizeAdvanced {
1218 const target = mod.getTarget();1219 const target = mod.getTarget();
1220 const use_llvm = mod.comp.config.use_llvm;
1219 const ip = &mod.intern_pool;1221 const ip = &mod.intern_pool;
12201222
1221 switch (ty.toIntern()) {1223 switch (ty.toIntern()) {
...@@ -1224,7 +1226,7 @@ pub const Type = struct {...@@ -1224,7 +1226,7 @@ pub const Type = struct {
1224 else => switch (ip.indexToKey(ty.toIntern())) {1226 else => switch (ip.indexToKey(ty.toIntern())) {
1225 .int_type => |int_type| {1227 .int_type => |int_type| {
1226 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };1228 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) };
1228 },1230 },
1229 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {1231 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1230 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },1232 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
...@@ -1286,7 +1288,7 @@ pub const Type = struct {...@@ -1286,7 +1288,7 @@ pub const Type = struct {
1286 .error_set_type, .inferred_error_set_type => {1288 .error_set_type, .inferred_error_set_type => {
1287 const bits = mod.errorSetBits();1289 const bits = mod.errorSetBits();
1288 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };1290 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1289 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };1291 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
1290 },1292 },
12911293
1292 .error_union_type => |error_union_type| {1294 .error_union_type => |error_union_type| {
...@@ -1384,7 +1386,7 @@ pub const Type = struct {...@@ -1384,7 +1386,7 @@ pub const Type = struct {
1384 .anyerror, .adhoc_inferred_error_set => {1386 .anyerror, .adhoc_inferred_error_set => {
1385 const bits = mod.errorSetBits();1387 const bits = mod.errorSetBits();
1386 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };1388 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1387 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };1389 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
1388 },1390 },
13891391
1390 .prefetch_options => unreachable, // missing call to resolveTypeFields1392 .prefetch_options => unreachable, // missing call to resolveTypeFields
...@@ -1533,17 +1535,112 @@ pub const Type = struct {...@@ -1533,17 +1535,112 @@ pub const Type = struct {
1533 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));1535 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
1534 }1536 }
15351537
1536 pub fn intAbiSize(bits: u16, target: Target) u64 {1538 pub fn intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 {
1537 return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));1539 return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
1538 }1540 }
15391541
1540 pub fn intAbiAlignment(bits: u16, target: Target) Alignment {1542 pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {
1541 return Alignment.fromByteUnits(@min(1543 return Alignment.fromByteUnits(@min(
1542 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),1544 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
1543 target.maxIntAlignment(),1545 maxIntAlignment(target, use_llvm),
1544 ));1546 ));
1545 }1547 }
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
1547 pub fn bitSize(ty: Type, mod: *Module) u64 {1644 pub fn bitSize(ty: Type, mod: *Module) u64 {
1548 return bitSizeAdvanced(ty, mod, null) catch unreachable;1645 return bitSizeAdvanced(ty, mod, null) catch unreachable;
1549 }1646 }
test/behavior/align.zig+27-1
...@@ -184,6 +184,33 @@ test "alignment and size of structs with 128-bit fields" {...@@ -184,6 +184,33 @@ test "alignment and size of structs with 128-bit fields" {
184 },184 },
185 },185 },
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
187 .aarch64,214 .aarch64,
188 .aarch64_be,215 .aarch64_be,
189 .aarch64_32,216 .aarch64_32,
...@@ -192,7 +219,6 @@ test "alignment and size of structs with 128-bit fields" {...@@ -192,7 +219,6 @@ test "alignment and size of structs with 128-bit fields" {
192 .bpfeb,219 .bpfeb,
193 .nvptx,220 .nvptx,
194 .nvptx64,221 .nvptx64,
195 .x86_64,
196 => .{222 => .{
197 .a_align = 16,223 .a_align = 16,
198 .a_size = 16,224 .a_size = 16,