mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
std.Target.maxIntAlignment: move to compiler implementation
This should not be a public API, and the x86 backend does not support the value 16.
This commit is contained in:
parent
62381011e0
commit
b7799ef322
2
lib/compiler/aro/aro/Type.zig
vendored
2
lib/compiler/aro/aro/Type.zig
vendored
@ -1116,7 +1116,7 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 {
|
||||
|
||||
.bit_int => @min(
|
||||
std.math.ceilPowerOfTwoPromote(u16, (ty.data.int.bits + 7) / 8),
|
||||
comp.target.maxIntAlignment(),
|
||||
16, // comp.target.maxIntAlignment(), please use your own logic for this value as it is implementation-defined
|
||||
),
|
||||
|
||||
.float => comp.target.c_type_alignment(.float),
|
||||
|
||||
@ -1862,97 +1862,6 @@ pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
|
||||
return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
|
||||
}
|
||||
|
||||
pub fn maxIntAlignment(target: Target) u16 {
|
||||
return switch (target.cpu.arch) {
|
||||
.avr => 1,
|
||||
.msp430 => 2,
|
||||
.xcore => 4,
|
||||
|
||||
.arm,
|
||||
.armeb,
|
||||
.thumb,
|
||||
.thumbeb,
|
||||
.hexagon,
|
||||
.mips,
|
||||
.mipsel,
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.r600,
|
||||
.amdgcn,
|
||||
.riscv32,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
.s390x,
|
||||
.lanai,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 8,
|
||||
|
||||
.x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) {
|
||||
.windows, .uefi => 8,
|
||||
else => 4,
|
||||
},
|
||||
|
||||
// For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
|
||||
// is a relevant number in three cases:
|
||||
// 1. Different machine code instruction when loading into SIMD register.
|
||||
// 2. The C ABI wants 16 for extern structs.
|
||||
// 3. 16-byte cmpxchg needs 16-byte alignment.
|
||||
// Same logic for powerpc64, mips64, sparc64.
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.sparc64,
|
||||
=> return switch (target.ofmt) {
|
||||
.c => 16,
|
||||
else => 8,
|
||||
},
|
||||
|
||||
// Even LLVMABIAlignmentOfType(i128) agrees on these targets.
|
||||
.x86_64,
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
.riscv64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
=> 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.
|
||||
.spu_2,
|
||||
.csky,
|
||||
.arc,
|
||||
.m68k,
|
||||
.tce,
|
||||
.tcele,
|
||||
.le32,
|
||||
.amdil,
|
||||
.hsail,
|
||||
.spir,
|
||||
.kalimba,
|
||||
.renderscript32,
|
||||
.spirv,
|
||||
.spirv32,
|
||||
.shave,
|
||||
.le64,
|
||||
.amdil64,
|
||||
.hsail64,
|
||||
.spir64,
|
||||
.renderscript64,
|
||||
.ve,
|
||||
.spirv64,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.loongarch64,
|
||||
.xtensa,
|
||||
=> 16,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {
|
||||
switch (abi) {
|
||||
.gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32,
|
||||
|
||||
@ -1312,10 +1312,10 @@ pub const Pool = struct {
|
||||
},
|
||||
else => {
|
||||
const target = &mod.resolved_target.result;
|
||||
const abi_align = Type.intAbiAlignment(int_info.bits, target.*);
|
||||
const abi_align = Type.intAbiAlignment(int_info.bits, target.*, false);
|
||||
const abi_align_bytes = abi_align.toByteUnits().?;
|
||||
const array_ctype = try pool.getArray(allocator, .{
|
||||
.len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes),
|
||||
.len = @divExact(Type.intAbiSize(int_info.bits, target.*, false), abi_align_bytes),
|
||||
.elem_ctype = try pool.fromIntInfo(allocator, .{
|
||||
.signedness = .unsigned,
|
||||
.bits = @intCast(abi_align_bytes * 8),
|
||||
@ -1443,7 +1443,7 @@ pub const Pool = struct {
|
||||
.name = .{ .index = .len },
|
||||
.ctype = CType.usize,
|
||||
.alignas = AlignAs.fromAbiAlignment(
|
||||
Type.intAbiAlignment(target.ptrBitWidth(), target.*),
|
||||
Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),
|
||||
),
|
||||
},
|
||||
};
|
||||
@ -1545,7 +1545,7 @@ pub const Pool = struct {
|
||||
.name = .{ .index = .len },
|
||||
.ctype = CType.usize,
|
||||
.alignas = AlignAs.fromAbiAlignment(
|
||||
Type.intAbiAlignment(target.ptrBitWidth(), target.*),
|
||||
Type.intAbiAlignment(target.ptrBitWidth(), target.*, false),
|
||||
),
|
||||
},
|
||||
};
|
||||
@ -1665,7 +1665,7 @@ pub const Pool = struct {
|
||||
.name = .{ .index = .@"error" },
|
||||
.ctype = error_set_ctype,
|
||||
.alignas = AlignAs.fromAbiAlignment(
|
||||
Type.intAbiAlignment(error_set_bits, target.*),
|
||||
Type.intAbiAlignment(error_set_bits, target.*, false),
|
||||
),
|
||||
},
|
||||
.{
|
||||
|
||||
@ -609,7 +609,7 @@ const DataLayoutBuilder = struct {
|
||||
switch (kind) {
|
||||
.integer => {
|
||||
if (self.target.ptrBitWidth() <= 16 and size >= 128) return;
|
||||
abi = @min(abi, self.target.maxIntAlignment() * 8);
|
||||
abi = @min(abi, Type.maxIntAlignment(self.target, true) * 8);
|
||||
switch (self.target.cpu.arch) {
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
|
||||
@ -383,7 +383,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
|
||||
.msvc => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
|
||||
else => {},
|
||||
}
|
||||
try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{target.maxIntAlignment()});
|
||||
try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
|
||||
Type.maxIntAlignment(target, false),
|
||||
});
|
||||
return defines;
|
||||
}
|
||||
|
||||
|
||||
119
src/type.zig
119
src/type.zig
@ -883,6 +883,7 @@ pub const Type = struct {
|
||||
strat: AbiAlignmentAdvancedStrat,
|
||||
) Module.CompileError!AbiAlignmentAdvanced {
|
||||
const target = mod.getTarget();
|
||||
const use_llvm = mod.comp.config.use_llvm;
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
const opt_sema = switch (strat) {
|
||||
@ -895,7 +896,7 @@ pub const Type = struct {
|
||||
else => switch (ip.indexToKey(ty.toIntern())) {
|
||||
.int_type => |int_type| {
|
||||
if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
|
||||
return .{ .scalar = intAbiAlignment(int_type.bits, target) };
|
||||
return .{ .scalar = intAbiAlignment(int_type.bits, target, use_llvm) };
|
||||
},
|
||||
.ptr_type, .anyframe_type => {
|
||||
return .{ .scalar = ptrAbiAlignment(target) };
|
||||
@ -941,7 +942,7 @@ pub const Type = struct {
|
||||
.error_set_type, .inferred_error_set_type => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
|
||||
return .{ .scalar = intAbiAlignment(bits, target) };
|
||||
return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
|
||||
},
|
||||
|
||||
// represents machine code; not a pointer
|
||||
@ -962,7 +963,7 @@ pub const Type = struct {
|
||||
|
||||
.usize,
|
||||
.isize,
|
||||
=> return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) },
|
||||
=> return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },
|
||||
|
||||
.export_options,
|
||||
.extern_options,
|
||||
@ -1001,7 +1002,7 @@ pub const Type = struct {
|
||||
.anyerror, .adhoc_inferred_error_set => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
|
||||
return .{ .scalar = intAbiAlignment(bits, target) };
|
||||
return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
|
||||
},
|
||||
|
||||
.void,
|
||||
@ -1216,6 +1217,7 @@ pub const Type = struct {
|
||||
strat: AbiAlignmentAdvancedStrat,
|
||||
) Module.CompileError!AbiSizeAdvanced {
|
||||
const target = mod.getTarget();
|
||||
const use_llvm = mod.comp.config.use_llvm;
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
switch (ty.toIntern()) {
|
||||
@ -1224,7 +1226,7 @@ pub const Type = struct {
|
||||
else => switch (ip.indexToKey(ty.toIntern())) {
|
||||
.int_type => |int_type| {
|
||||
if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target, use_llvm) };
|
||||
},
|
||||
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
|
||||
.Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
|
||||
@ -1286,7 +1288,7 @@ pub const Type = struct {
|
||||
.error_set_type, .inferred_error_set_type => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
|
||||
},
|
||||
|
||||
.error_union_type => |error_union_type| {
|
||||
@ -1384,7 +1386,7 @@ pub const Type = struct {
|
||||
.anyerror, .adhoc_inferred_error_set => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
|
||||
},
|
||||
|
||||
.prefetch_options => unreachable, // missing call to resolveTypeFields
|
||||
@ -1533,17 +1535,112 @@ pub const Type = struct {
|
||||
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 intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 {
|
||||
return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
|
||||
}
|
||||
|
||||
pub fn intAbiAlignment(bits: u16, target: Target) Alignment {
|
||||
pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {
|
||||
return Alignment.fromByteUnits(@min(
|
||||
std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
|
||||
target.maxIntAlignment(),
|
||||
maxIntAlignment(target, use_llvm),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {
|
||||
return switch (target.cpu.arch) {
|
||||
.avr => 1,
|
||||
.msp430 => 2,
|
||||
.xcore => 4,
|
||||
|
||||
.arm,
|
||||
.armeb,
|
||||
.thumb,
|
||||
.thumbeb,
|
||||
.hexagon,
|
||||
.mips,
|
||||
.mipsel,
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.r600,
|
||||
.amdgcn,
|
||||
.riscv32,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
.s390x,
|
||||
.lanai,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 8,
|
||||
|
||||
.x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) {
|
||||
.windows, .uefi => 8,
|
||||
else => 4,
|
||||
},
|
||||
|
||||
// For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
|
||||
// is a relevant number in three cases:
|
||||
// 1. Different machine code instruction when loading into SIMD register.
|
||||
// 2. The C ABI wants 16 for extern structs.
|
||||
// 3. 16-byte cmpxchg needs 16-byte alignment.
|
||||
// Same logic for powerpc64, mips64, sparc64.
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.sparc64,
|
||||
=> switch (target.ofmt) {
|
||||
.c => 16,
|
||||
else => 8,
|
||||
},
|
||||
|
||||
.x86_64 => switch (target_util.zigBackend(target, use_llvm)) {
|
||||
.stage2_x86_64 => 8,
|
||||
else => 16,
|
||||
},
|
||||
|
||||
// Even LLVMABIAlignmentOfType(i128) agrees on these targets.
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
.riscv64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
=> 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.
|
||||
.spu_2,
|
||||
.csky,
|
||||
.arc,
|
||||
.m68k,
|
||||
.tce,
|
||||
.tcele,
|
||||
.le32,
|
||||
.amdil,
|
||||
.hsail,
|
||||
.spir,
|
||||
.kalimba,
|
||||
.renderscript32,
|
||||
.spirv,
|
||||
.spirv32,
|
||||
.shave,
|
||||
.le64,
|
||||
.amdil64,
|
||||
.hsail64,
|
||||
.spir64,
|
||||
.renderscript64,
|
||||
.ve,
|
||||
.spirv64,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.loongarch64,
|
||||
.xtensa,
|
||||
=> 16,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn bitSize(ty: Type, mod: *Module) u64 {
|
||||
return bitSizeAdvanced(ty, mod, null) catch unreachable;
|
||||
}
|
||||
|
||||
@ -184,6 +184,33 @@ test "alignment and size of structs with 128-bit fields" {
|
||||
},
|
||||
},
|
||||
|
||||
.x86_64 => switch (builtin.zig_backend) {
|
||||
.stage2_x86_64 => .{
|
||||
.a_align = 8,
|
||||
.a_size = 16,
|
||||
|
||||
.b_align = 16,
|
||||
.b_size = 32,
|
||||
|
||||
.u128_align = 8,
|
||||
.u128_size = 16,
|
||||
.u129_align = 8,
|
||||
.u129_size = 24,
|
||||
},
|
||||
else => .{
|
||||
.a_align = 16,
|
||||
.a_size = 16,
|
||||
|
||||
.b_align = 16,
|
||||
.b_size = 32,
|
||||
|
||||
.u128_align = 16,
|
||||
.u128_size = 16,
|
||||
.u129_align = 16,
|
||||
.u129_size = 32,
|
||||
},
|
||||
},
|
||||
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
@ -192,7 +219,6 @@ test "alignment and size of structs with 128-bit fields" {
|
||||
.bpfeb,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.x86_64,
|
||||
=> .{
|
||||
.a_align = 16,
|
||||
.a_size = 16,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user