authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-06 10:14:34+02:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-11 05:22:00-04:00
loged9aa8f259d452cb344064ee412fc5af18877d55
treebc25fc044efda559430e3ea7d715936b179b37cf
parent0132be7bf3fd02cfb8c31ffdeaddae918a76b295

compiler: Move int size/alignment functions to std.Target and std.zig.target.

This allows using them in e.g. compiler-rt.

5 files changed, 108 insertions(+), 109 deletions(-)

lib/std/Target.zig+62
...@@ -3273,6 +3273,68 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {...@@ -3273,6 +3273,68 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {
3273 );3273 );
3274}3274}
32753275
3276pub fn cMaxIntAlignment(target: std.Target) u16 {
3277 return switch (target.cpu.arch) {
3278 .avr => 1,
3279
3280 .msp430 => 2,
3281
3282 .xcore,
3283 .propeller,
3284 => 4,
3285
3286 .amdgcn,
3287 .arm,
3288 .armeb,
3289 .thumb,
3290 .thumbeb,
3291 .lanai,
3292 .hexagon,
3293 .mips,
3294 .mipsel,
3295 .powerpc,
3296 .powerpcle,
3297 .riscv32,
3298 .s390x,
3299 => 8,
3300
3301 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
3302 .aarch64,
3303 .aarch64_be,
3304 .bpfel,
3305 .bpfeb,
3306 .mips64,
3307 .mips64el,
3308 .nvptx,
3309 .nvptx64,
3310 .powerpc64,
3311 .powerpc64le,
3312 .riscv64,
3313 .sparc,
3314 .sparc64,
3315 .wasm32,
3316 .wasm64,
3317 .x86,
3318 .x86_64,
3319 => 16,
3320
3321 // Below this comment are unverified but based on the fact that C requires
3322 // int128_t to be 16 bytes aligned, it's a safe default.
3323 .arc,
3324 .csky,
3325 .kalimba,
3326 .loongarch32,
3327 .loongarch64,
3328 .m68k,
3329 .spirv,
3330 .spirv32,
3331 .spirv64,
3332 .ve,
3333 .xtensa,
3334 => 16,
3335 };
3336}
3337
3276pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention {3338pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention {
3277 return switch (target.cpu.arch) {3339 return switch (target.cpu.arch) {
3278 .x86_64 => switch (target.os.tag) {3340 .x86_64 => switch (target.os.tag) {
lib/std/zig/target.zig+32
...@@ -352,6 +352,38 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {...@@ -352,6 +352,38 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
352 }352 }
353}353}
354354
355pub fn intByteSize(target: std.Target, bits: u16) u19 {
356 return std.mem.alignForward(u19, @intCast((@as(u17, bits) + 7) / 8), intAlignment(target, bits));
357}
358
359pub fn intAlignment(target: std.Target, bits: u16) u16 {
360 return switch (target.cpu.arch) {
361 .x86 => switch (bits) {
362 0 => 0,
363 1...8 => 1,
364 9...16 => 2,
365 17...32 => 4,
366 33...64 => switch (target.os.tag) {
367 .uefi, .windows => 8,
368 else => 4,
369 },
370 else => 16,
371 },
372 .x86_64 => switch (bits) {
373 0 => 0,
374 1...8 => 1,
375 9...16 => 2,
376 17...32 => 4,
377 33...64 => 8,
378 else => 16,
379 },
380 else => return @min(
381 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
382 target.cMaxIntAlignment(),
383 ),
384 };
385}
386
355const std = @import("std");387const std = @import("std");
356const assert = std.debug.assert;388const assert = std.debug.assert;
357const Allocator = std.mem.Allocator;389const Allocator = std.mem.Allocator;
src/Type.zig+7-101
...@@ -968,7 +968,7 @@ pub fn abiAlignmentInner(...@@ -968,7 +968,7 @@ pub fn abiAlignmentInner(
968 else => switch (ip.indexToKey(ty.toIntern())) {968 else => switch (ip.indexToKey(ty.toIntern())) {
969 .int_type => |int_type| {969 .int_type => |int_type| {
970 if (int_type.bits == 0) return .{ .scalar = .@"1" };970 if (int_type.bits == 0) return .{ .scalar = .@"1" };
971 return .{ .scalar = intAbiAlignment(int_type.bits, target) };971 return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)) };
972 },972 },
973 .ptr_type, .anyframe_type => {973 .ptr_type, .anyframe_type => {
974 return .{ .scalar = ptrAbiAlignment(target) };974 return .{ .scalar = ptrAbiAlignment(target) };
...@@ -1021,7 +1021,7 @@ pub fn abiAlignmentInner(...@@ -1021,7 +1021,7 @@ pub fn abiAlignmentInner(
1021 .error_set_type, .inferred_error_set_type => {1021 .error_set_type, .inferred_error_set_type => {
1022 const bits = zcu.errorSetBits();1022 const bits = zcu.errorSetBits();
1023 if (bits == 0) return .{ .scalar = .@"1" };1023 if (bits == 0) return .{ .scalar = .@"1" };
1024 return .{ .scalar = intAbiAlignment(bits, target) };1024 return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) };
1025 },1025 },
10261026
1027 // represents machine code; not a pointer1027 // represents machine code; not a pointer
...@@ -1034,7 +1034,7 @@ pub fn abiAlignmentInner(...@@ -1034,7 +1034,7 @@ pub fn abiAlignmentInner(
10341034
1035 .usize,1035 .usize,
1036 .isize,1036 .isize,
1037 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) },1037 => return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())) },
10381038
1039 .c_char => return .{ .scalar = cTypeAlign(target, .char) },1039 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
1040 .c_short => return .{ .scalar = cTypeAlign(target, .short) },1040 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
...@@ -1065,7 +1065,7 @@ pub fn abiAlignmentInner(...@@ -1065,7 +1065,7 @@ pub fn abiAlignmentInner(
1065 .anyerror, .adhoc_inferred_error_set => {1065 .anyerror, .adhoc_inferred_error_set => {
1066 const bits = zcu.errorSetBits();1066 const bits = zcu.errorSetBits();
1067 if (bits == 0) return .{ .scalar = .@"1" };1067 if (bits == 0) return .{ .scalar = .@"1" };
1068 return .{ .scalar = intAbiAlignment(bits, target) };1068 return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) };
1069 },1069 },
10701070
1071 .void,1071 .void,
...@@ -1297,7 +1297,7 @@ pub fn abiSizeInner(...@@ -1297,7 +1297,7 @@ pub fn abiSizeInner(
1297 else => switch (ip.indexToKey(ty.toIntern())) {1297 else => switch (ip.indexToKey(ty.toIntern())) {
1298 .int_type => |int_type| {1298 .int_type => |int_type| {
1299 if (int_type.bits == 0) return .{ .scalar = 0 };1299 if (int_type.bits == 0) return .{ .scalar = 0 };
1300 return .{ .scalar = intAbiSize(int_type.bits, target) };1300 return .{ .scalar = std.zig.target.intByteSize(target, int_type.bits) };
1301 },1301 },
1302 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {1302 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1303 .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },1303 .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
...@@ -1359,7 +1359,7 @@ pub fn abiSizeInner(...@@ -1359,7 +1359,7 @@ pub fn abiSizeInner(
1359 .error_set_type, .inferred_error_set_type => {1359 .error_set_type, .inferred_error_set_type => {
1360 const bits = zcu.errorSetBits();1360 const bits = zcu.errorSetBits();
1361 if (bits == 0) return .{ .scalar = 0 };1361 if (bits == 0) return .{ .scalar = 0 };
1362 return .{ .scalar = intAbiSize(bits, target) };1362 return .{ .scalar = std.zig.target.intByteSize(target, bits) };
1363 },1363 },
13641364
1365 .error_union_type => |error_union_type| {1365 .error_union_type => |error_union_type| {
...@@ -1452,7 +1452,7 @@ pub fn abiSizeInner(...@@ -1452,7 +1452,7 @@ pub fn abiSizeInner(
1452 .anyerror, .adhoc_inferred_error_set => {1452 .anyerror, .adhoc_inferred_error_set => {
1453 const bits = zcu.errorSetBits();1453 const bits = zcu.errorSetBits();
1454 if (bits == 0) return .{ .scalar = 0 };1454 if (bits == 0) return .{ .scalar = 0 };
1455 return .{ .scalar = intAbiSize(bits, target) };1455 return .{ .scalar = std.zig.target.intByteSize(target, bits) };
1456 },1456 },
14571457
1458 .noreturn => unreachable,1458 .noreturn => unreachable,
...@@ -1606,100 +1606,6 @@ pub fn ptrAbiAlignment(target: Target) Alignment {...@@ -1606,100 +1606,6 @@ pub fn ptrAbiAlignment(target: Target) Alignment {
1606 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));1606 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
1607}1607}
16081608
1609pub fn intAbiSize(bits: u16, target: Target) u64 {
1610 return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
1611}
1612
1613pub fn intAbiAlignment(bits: u16, target: Target) Alignment {
1614 return switch (target.cpu.arch) {
1615 .x86 => switch (bits) {
1616 0 => .none,
1617 1...8 => .@"1",
1618 9...16 => .@"2",
1619 17...32 => .@"4",
1620 33...64 => switch (target.os.tag) {
1621 .uefi, .windows => .@"8",
1622 else => .@"4",
1623 },
1624 else => .@"16",
1625 },
1626 .x86_64 => switch (bits) {
1627 0 => .none,
1628 1...8 => .@"1",
1629 9...16 => .@"2",
1630 17...32 => .@"4",
1631 33...64 => .@"8",
1632 else => .@"16",
1633 },
1634 else => return Alignment.fromByteUnits(@min(
1635 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
1636 maxIntAlignment(target),
1637 )),
1638 };
1639}
1640
1641pub fn maxIntAlignment(target: std.Target) u16 {
1642 return switch (target.cpu.arch) {
1643 .avr => 1,
1644
1645 .msp430 => 2,
1646
1647 .xcore,
1648 .propeller,
1649 => 4,
1650
1651 .amdgcn,
1652 .arm,
1653 .armeb,
1654 .thumb,
1655 .thumbeb,
1656 .lanai,
1657 .hexagon,
1658 .mips,
1659 .mipsel,
1660 .powerpc,
1661 .powerpcle,
1662 .riscv32,
1663 .s390x,
1664 => 8,
1665
1666 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1667 .aarch64,
1668 .aarch64_be,
1669 .bpfel,
1670 .bpfeb,
1671 .mips64,
1672 .mips64el,
1673 .nvptx,
1674 .nvptx64,
1675 .powerpc64,
1676 .powerpc64le,
1677 .riscv64,
1678 .sparc,
1679 .sparc64,
1680 .wasm32,
1681 .wasm64,
1682 .x86,
1683 .x86_64,
1684 => 16,
1685
1686 // Below this comment are unverified but based on the fact that C requires
1687 // int128_t to be 16 bytes aligned, it's a safe default.
1688 .arc,
1689 .csky,
1690 .kalimba,
1691 .loongarch32,
1692 .loongarch64,
1693 .m68k,
1694 .spirv,
1695 .spirv32,
1696 .spirv64,
1697 .ve,
1698 .xtensa,
1699 => 16,
1700 };
1701}
1702
1703pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {1609pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {
1704 return bitSizeInner(ty, .normal, zcu, {}) catch unreachable;1610 return bitSizeInner(ty, .normal, zcu, {}) catch unreachable;
1705}1611}
src/codegen/c/Type.zig+6-7
...@@ -1319,10 +1319,9 @@ pub const Pool = struct {...@@ -1319,10 +1319,9 @@ pub const Pool = struct {
1319 },1319 },
1320 else => {1320 else => {
1321 const target = &mod.resolved_target.result;1321 const target = &mod.resolved_target.result;
1322 const abi_align = Type.intAbiAlignment(int_info.bits, target.*);1322 const abi_align_bytes = std.zig.target.intAlignment(target.*, int_info.bits);
1323 const abi_align_bytes = abi_align.toByteUnits().?;
1324 const array_ctype = try pool.getArray(allocator, .{1323 const array_ctype = try pool.getArray(allocator, .{
1325 .len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes),1324 .len = @divExact(std.zig.target.intByteSize(target.*, int_info.bits), abi_align_bytes),
1326 .elem_ctype = try pool.fromIntInfo(allocator, .{1325 .elem_ctype = try pool.fromIntInfo(allocator, .{
1327 .signedness = .unsigned,1326 .signedness = .unsigned,
1328 .bits = @intCast(abi_align_bytes * 8),1327 .bits = @intCast(abi_align_bytes * 8),
...@@ -1333,7 +1332,7 @@ pub const Pool = struct {...@@ -1333,7 +1332,7 @@ pub const Pool = struct {
1333 .{1332 .{
1334 .name = .{ .index = .array },1333 .name = .{ .index = .array },
1335 .ctype = array_ctype,1334 .ctype = array_ctype,
1336 .alignas = AlignAs.fromAbiAlignment(abi_align),1335 .alignas = AlignAs.fromAbiAlignment(.fromByteUnits(abi_align_bytes)),
1337 },1336 },
1338 };1337 };
1339 return pool.fromFields(allocator, .@"struct", &fields, kind);1338 return pool.fromFields(allocator, .@"struct", &fields, kind);
...@@ -1437,7 +1436,7 @@ pub const Pool = struct {...@@ -1437,7 +1436,7 @@ pub const Pool = struct {
1437 .name = .{ .index = .len },1436 .name = .{ .index = .len },
1438 .ctype = .usize,1437 .ctype = .usize,
1439 .alignas = AlignAs.fromAbiAlignment(1438 .alignas = AlignAs.fromAbiAlignment(
1440 Type.intAbiAlignment(target.ptrBitWidth(), target.*),1439 .fromByteUnits(std.zig.target.intAlignment(target.*, target.ptrBitWidth())),
1441 ),1440 ),
1442 },1441 },
1443 };1442 };
...@@ -1937,7 +1936,7 @@ pub const Pool = struct {...@@ -1937,7 +1936,7 @@ pub const Pool = struct {
1937 .name = .{ .index = .len },1936 .name = .{ .index = .len },
1938 .ctype = .usize,1937 .ctype = .usize,
1939 .alignas = AlignAs.fromAbiAlignment(1938 .alignas = AlignAs.fromAbiAlignment(
1940 Type.intAbiAlignment(target.ptrBitWidth(), target.*),1939 .fromByteUnits(std.zig.target.intAlignment(target.*, target.ptrBitWidth())),
1941 ),1940 ),
1942 },1941 },
1943 };1942 };
...@@ -2057,7 +2056,7 @@ pub const Pool = struct {...@@ -2057,7 +2056,7 @@ pub const Pool = struct {
2057 .name = .{ .index = .@"error" },2056 .name = .{ .index = .@"error" },
2058 .ctype = error_set_ctype,2057 .ctype = error_set_ctype,
2059 .alignas = AlignAs.fromAbiAlignment(2058 .alignas = AlignAs.fromAbiAlignment(
2060 Type.intAbiAlignment(error_set_bits, target.*),2059 .fromByteUnits(std.zig.target.intAlignment(target.*, error_set_bits)),
2061 ),2060 ),
2062 },2061 },
2063 .{2062 .{
src/link/C.zig+1-1
...@@ -396,7 +396,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {...@@ -396,7 +396,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
396 else => {},396 else => {},
397 }397 }
398 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{398 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
399 Type.maxIntAlignment(target),399 target.cMaxIntAlignment(),
400 });400 });
401 return defines;401 return defines;
402}402}