aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-04-29 17:40:49 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-05-08 19:37:29 -0700
commitb7799ef322103c8e449c45494c29fb4a8c9867df (patch)
treef1f1a5fe4c52a7ce335a6e1ae75e939bcb07c86d /src/type.zig
parent62381011e0dd692ec6bb30d14e0d5e2f6ec4d5d5 (diff)
downloadzig-b7799ef322103c8e449c45494c29fb4a8c9867df.tar.gz
zig-b7799ef322103c8e449c45494c29fb4a8c9867df.zip
std.Target.maxIntAlignment: move to compiler implementation
This should not be a public API, and the x86 backend does not support the value 16.
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig119
1 files changed, 108 insertions, 11 deletions
diff --git a/src/type.zig b/src/type.zig
index 5fc6e962c4..9fe95f99f7 100644
--- a/src/type.zig
+++ b/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;
}