Commit b7799ef322
Changed files (7)
lib/compiler/aro/aro/Type.zig
@@ -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),
lib/std/Target.zig
@@ -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,
src/codegen/c/Type.zig
@@ -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),
),
},
.{
src/codegen/llvm.zig
@@ -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,
src/link/C.zig
@@ -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;
}
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;
}
test/behavior/align.zig
@@ -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,