diff --git a/lib/std/Target.zig b/lib/std/Target.zig index ea7be17697..e445ab42e6 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3273,6 +3273,68 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { ); } +pub fn cMaxIntAlignment(target: std.Target) u16 { + return switch (target.cpu.arch) { + .avr => 1, + + .msp430 => 2, + + .xcore, + .propeller, + => 4, + + .amdgcn, + .arm, + .armeb, + .thumb, + .thumbeb, + .lanai, + .hexagon, + .mips, + .mipsel, + .powerpc, + .powerpcle, + .riscv32, + .s390x, + => 8, + + // Even LLVMABIAlignmentOfType(i128) agrees on these targets. + .aarch64, + .aarch64_be, + .bpfel, + .bpfeb, + .mips64, + .mips64el, + .nvptx, + .nvptx64, + .powerpc64, + .powerpc64le, + .riscv64, + .sparc, + .sparc64, + .wasm32, + .wasm64, + .x86, + .x86_64, + => 16, + + // Below this comment are unverified but based on the fact that C requires + // int128_t to be 16 bytes aligned, it's a safe default. + .arc, + .csky, + .kalimba, + .loongarch32, + .loongarch64, + .m68k, + .spirv, + .spirv32, + .spirv64, + .ve, + .xtensa, + => 16, + }; +} + pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { return switch (target.cpu.arch) { .x86_64 => switch (target.os.tag) { diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 2574f26d18..4b20c132a6 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -352,6 +352,38 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool { } } +pub fn intByteSize(target: std.Target, bits: u16) u19 { + return std.mem.alignForward(u19, @intCast((@as(u17, bits) + 7) / 8), intAlignment(target, bits)); +} + +pub fn intAlignment(target: std.Target, bits: u16) u16 { + return switch (target.cpu.arch) { + .x86 => switch (bits) { + 0 => 0, + 1...8 => 1, + 9...16 => 2, + 17...32 => 4, + 33...64 => switch (target.os.tag) { + .uefi, .windows => 8, + else => 4, + }, + else => 16, + }, + .x86_64 => switch (bits) { + 0 => 0, + 1...8 => 1, + 9...16 => 2, + 17...32 => 4, + 33...64 => 8, + else => 16, + }, + else => return @min( + std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), + target.cMaxIntAlignment(), + ), + }; +} + const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; diff --git a/src/Type.zig b/src/Type.zig index dfa77f3383..a789edefe1 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -968,7 +968,7 @@ pub fn abiAlignmentInner( else => switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| { if (int_type.bits == 0) return .{ .scalar = .@"1" }; - return .{ .scalar = intAbiAlignment(int_type.bits, target) }; + return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)) }; }, .ptr_type, .anyframe_type => { return .{ .scalar = ptrAbiAlignment(target) }; @@ -1021,7 +1021,7 @@ pub fn abiAlignmentInner( .error_set_type, .inferred_error_set_type => { const bits = zcu.errorSetBits(); if (bits == 0) return .{ .scalar = .@"1" }; - return .{ .scalar = intAbiAlignment(bits, target) }; + return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) }; }, // represents machine code; not a pointer @@ -1034,7 +1034,7 @@ pub fn abiAlignmentInner( .usize, .isize, - => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) }, + => return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())) }, .c_char => return .{ .scalar = cTypeAlign(target, .char) }, .c_short => return .{ .scalar = cTypeAlign(target, .short) }, @@ -1065,7 +1065,7 @@ pub fn abiAlignmentInner( .anyerror, .adhoc_inferred_error_set => { const bits = zcu.errorSetBits(); if (bits == 0) return .{ .scalar = .@"1" }; - return .{ .scalar = intAbiAlignment(bits, target) }; + return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) }; }, .void, @@ -1297,7 +1297,7 @@ pub fn abiSizeInner( else => switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| { if (int_type.bits == 0) return .{ .scalar = 0 }; - return .{ .scalar = intAbiSize(int_type.bits, target) }; + return .{ .scalar = std.zig.target.intByteSize(target, int_type.bits) }; }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, @@ -1359,7 +1359,7 @@ pub fn abiSizeInner( .error_set_type, .inferred_error_set_type => { const bits = zcu.errorSetBits(); if (bits == 0) return .{ .scalar = 0 }; - return .{ .scalar = intAbiSize(bits, target) }; + return .{ .scalar = std.zig.target.intByteSize(target, bits) }; }, .error_union_type => |error_union_type| { @@ -1452,7 +1452,7 @@ pub fn abiSizeInner( .anyerror, .adhoc_inferred_error_set => { const bits = zcu.errorSetBits(); if (bits == 0) return .{ .scalar = 0 }; - return .{ .scalar = intAbiSize(bits, target) }; + return .{ .scalar = std.zig.target.intByteSize(target, bits) }; }, .noreturn => unreachable, @@ -1606,100 +1606,6 @@ pub fn ptrAbiAlignment(target: Target) Alignment { return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); } -pub fn intAbiSize(bits: u16, target: Target) u64 { - return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); -} - -pub fn intAbiAlignment(bits: u16, target: Target) Alignment { - return switch (target.cpu.arch) { - .x86 => switch (bits) { - 0 => .none, - 1...8 => .@"1", - 9...16 => .@"2", - 17...32 => .@"4", - 33...64 => switch (target.os.tag) { - .uefi, .windows => .@"8", - else => .@"4", - }, - else => .@"16", - }, - .x86_64 => switch (bits) { - 0 => .none, - 1...8 => .@"1", - 9...16 => .@"2", - 17...32 => .@"4", - 33...64 => .@"8", - else => .@"16", - }, - else => return Alignment.fromByteUnits(@min( - std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), - maxIntAlignment(target), - )), - }; -} - -pub fn maxIntAlignment(target: std.Target) u16 { - return switch (target.cpu.arch) { - .avr => 1, - - .msp430 => 2, - - .xcore, - .propeller, - => 4, - - .amdgcn, - .arm, - .armeb, - .thumb, - .thumbeb, - .lanai, - .hexagon, - .mips, - .mipsel, - .powerpc, - .powerpcle, - .riscv32, - .s390x, - => 8, - - // Even LLVMABIAlignmentOfType(i128) agrees on these targets. - .aarch64, - .aarch64_be, - .bpfel, - .bpfeb, - .mips64, - .mips64el, - .nvptx, - .nvptx64, - .powerpc64, - .powerpc64le, - .riscv64, - .sparc, - .sparc64, - .wasm32, - .wasm64, - .x86, - .x86_64, - => 16, - - // Below this comment are unverified but based on the fact that C requires - // int128_t to be 16 bytes aligned, it's a safe default. - .arc, - .csky, - .kalimba, - .loongarch32, - .loongarch64, - .m68k, - .spirv, - .spirv32, - .spirv64, - .ve, - .xtensa, - => 16, - }; -} - pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { return bitSizeInner(ty, .normal, zcu, {}) catch unreachable; } diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index db7455ebb0..0b3066f9bd 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -1319,10 +1319,9 @@ pub const Pool = struct { }, else => { const target = &mod.resolved_target.result; - const abi_align = Type.intAbiAlignment(int_info.bits, target.*); - const abi_align_bytes = abi_align.toByteUnits().?; + const abi_align_bytes = std.zig.target.intAlignment(target.*, int_info.bits); const array_ctype = try pool.getArray(allocator, .{ - .len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes), + .len = @divExact(std.zig.target.intByteSize(target.*, int_info.bits), abi_align_bytes), .elem_ctype = try pool.fromIntInfo(allocator, .{ .signedness = .unsigned, .bits = @intCast(abi_align_bytes * 8), @@ -1333,7 +1332,7 @@ pub const Pool = struct { .{ .name = .{ .index = .array }, .ctype = array_ctype, - .alignas = AlignAs.fromAbiAlignment(abi_align), + .alignas = AlignAs.fromAbiAlignment(.fromByteUnits(abi_align_bytes)), }, }; return pool.fromFields(allocator, .@"struct", &fields, kind); @@ -1437,7 +1436,7 @@ pub const Pool = struct { .name = .{ .index = .len }, .ctype = .usize, .alignas = AlignAs.fromAbiAlignment( - Type.intAbiAlignment(target.ptrBitWidth(), target.*), + .fromByteUnits(std.zig.target.intAlignment(target.*, target.ptrBitWidth())), ), }, }; @@ -1937,7 +1936,7 @@ pub const Pool = struct { .name = .{ .index = .len }, .ctype = .usize, .alignas = AlignAs.fromAbiAlignment( - Type.intAbiAlignment(target.ptrBitWidth(), target.*), + .fromByteUnits(std.zig.target.intAlignment(target.*, target.ptrBitWidth())), ), }, }; @@ -2057,7 +2056,7 @@ pub const Pool = struct { .name = .{ .index = .@"error" }, .ctype = error_set_ctype, .alignas = AlignAs.fromAbiAlignment( - Type.intAbiAlignment(error_set_bits, target.*), + .fromByteUnits(std.zig.target.intAlignment(target.*, error_set_bits)), ), }, .{ diff --git a/src/link/C.zig b/src/link/C.zig index 8a43845639..0689faaae1 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -396,7 +396,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { else => {}, } try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{ - Type.maxIntAlignment(target), + target.cMaxIntAlignment(), }); return defines; }