move compiler's CType logic to std.Target

This API only depends on std.Target and is extremely useful in build
scripts when populating configure files.
This commit is contained in:
Andrew Kelley 2023-01-31 14:56:35 -07:00
parent 90e48d4b34
commit 2f5892671e
5 changed files with 601 additions and 590 deletions

View File

@ -1880,6 +1880,559 @@ pub const Target = struct {
=> 16,
};
}
pub const CType = enum {
short,
ushort,
int,
uint,
long,
ulong,
longlong,
ulonglong,
float,
double,
longdouble,
};
pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
return switch (c_type) {
.short,
.ushort,
.int,
.uint,
.long,
.ulong,
.longlong,
.ulonglong,
=> @divExact(c_type_bit_size(t, c_type), 8),
.float => 4,
.double => 8,
.longdouble => switch (c_type_bit_size(t, c_type)) {
16 => 2,
32 => 4,
64 => 8,
80 => @intCast(u16, mem.alignForward(10, c_type_alignment(t, .longdouble))),
128 => 16,
else => unreachable,
},
};
}
pub fn c_type_bit_size(target: Target, c_type: CType) u16 {
switch (target.os.tag) {
.freestanding, .other => switch (target.cpu.arch) {
.msp430 => switch (c_type) {
.short, .ushort, .int, .uint => return 16,
.float, .long, .ulong => return 32,
.longlong, .ulonglong, .double, .longdouble => return 64,
},
.avr => switch (c_type) {
.short, .ushort, .int, .uint => return 16,
.long, .ulong, .float, .double, .longdouble => return 32,
.longlong, .ulonglong => return 64,
},
.tce, .tcele => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
.float, .double, .longdouble => return 32,
},
.mips64, .mips64el => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => return 128,
},
.x86_64 => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
.gnux32, .muslx32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => return 80,
},
else => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.x86 => switch (target.abi) {
.android => return 64,
else => return 80,
},
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
=> switch (target.abi) {
.musl,
.musleabi,
.musleabihf,
.muslx32,
=> return 64,
else => return 128,
},
.riscv32,
.riscv64,
.aarch64,
.aarch64_be,
.aarch64_32,
.s390x,
.sparc,
.sparc64,
.sparcel,
.wasm32,
.wasm64,
=> return 128,
else => return 64,
},
},
},
.linux,
.freebsd,
.netbsd,
.dragonfly,
.openbsd,
.wasi,
.emscripten,
.plan9,
.solaris,
.haiku,
.ananas,
.fuchsia,
.minix,
=> switch (target.cpu.arch) {
.msp430 => switch (c_type) {
.short, .ushort, .int, .uint => return 16,
.long, .ulong, .float => return 32,
.longlong, .ulonglong, .double, .longdouble => return 64,
},
.avr => switch (c_type) {
.short, .ushort, .int, .uint => return 16,
.long, .ulong, .float, .double, .longdouble => return 32,
.longlong, .ulonglong => return 64,
},
.tce, .tcele => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
.float, .double, .longdouble => return 32,
},
.mips64, .mips64el => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => if (target.os.tag == .freebsd) return 64 else return 128,
},
.x86_64 => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
.gnux32, .muslx32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => return 80,
},
else => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.x86 => switch (target.abi) {
.android => return 64,
else => return 80,
},
.powerpc,
.powerpcle,
=> switch (target.abi) {
.musl,
.musleabi,
.musleabihf,
.muslx32,
=> return 64,
else => switch (target.os.tag) {
.freebsd, .netbsd, .openbsd => return 64,
else => return 128,
},
},
.powerpc64,
.powerpc64le,
=> switch (target.abi) {
.musl,
.musleabi,
.musleabihf,
.muslx32,
=> return 64,
else => switch (target.os.tag) {
.freebsd, .openbsd => return 64,
else => return 128,
},
},
.riscv32,
.riscv64,
.aarch64,
.aarch64_be,
.aarch64_32,
.s390x,
.mips64,
.mips64el,
.sparc,
.sparc64,
.sparcel,
.wasm32,
.wasm64,
=> return 128,
else => return 64,
},
},
},
.windows, .uefi => switch (target.cpu.arch) {
.x86 => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 80,
else => return 64,
},
},
.x86_64 => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
.cygnus => return 64,
else => return 32,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 80,
else => return 64,
},
},
else => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => return 64,
},
},
.macos, .ios, .tvos, .watchos => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.cpu.arch) {
.x86, .arm, .aarch64_32 => return 32,
.x86_64 => switch (target.abi) {
.gnux32, .muslx32 => return 32,
else => return 64,
},
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.x86 => switch (target.abi) {
.android => return 64,
else => return 80,
},
.x86_64 => return 80,
else => return 64,
},
},
.nvcl, .cuda => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.cpu.arch) {
.nvptx => return 32,
.nvptx64 => return 64,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => return 64,
},
.amdhsa, .amdpal => switch (c_type) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong, .longlong, .ulonglong, .double => return 64,
.longdouble => return 128,
},
.cloudabi,
.kfreebsd,
.lv2,
.zos,
.rtems,
.nacl,
.aix,
.ps4,
.ps5,
.elfiamcu,
.mesa3d,
.contiki,
.hermit,
.hurd,
.opencl,
.glsl450,
.vulkan,
.driverkit,
.shadermodel,
=> @panic("TODO specify the C integer and float type sizes for this OS"),
}
}
pub fn c_type_alignment(target: Target, c_type: CType) u16 {
// Overrides for unusual alignments
switch (target.cpu.arch) {
.avr => switch (c_type) {
.short, .ushort => return 2,
else => return 1,
},
.x86 => switch (target.os.tag) {
.windows, .uefi => switch (c_type) {
.longlong, .ulonglong, .double => return 8,
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 4,
else => return 8,
},
else => {},
},
else => {},
},
else => {},
}
// Next-power-of-two-aligned, up to a maximum.
return @min(
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
switch (target.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.netbsd => switch (target.abi) {
.gnueabi,
.gnueabihf,
.eabi,
.eabihf,
.android,
.musleabi,
.musleabihf,
=> 8,
else => @as(u16, 4),
},
.ios, .tvos, .watchos => 4,
else => 8,
},
.msp430,
.avr,
=> 2,
.arc,
.csky,
.x86,
.xcore,
.dxil,
.loongarch32,
.tce,
.tcele,
.le32,
.amdil,
.hsail,
.spir,
.spirv32,
.kalimba,
.shave,
.renderscript32,
.ve,
.spu_2,
=> 4,
.aarch64_32,
.amdgcn,
.amdil64,
.bpfel,
.bpfeb,
.hexagon,
.hsail64,
.loongarch64,
.m68k,
.mips,
.mipsel,
.sparc,
.sparcel,
.sparc64,
.lanai,
.le64,
.nvptx,
.nvptx64,
.r600,
.s390x,
.spir64,
.spirv64,
.renderscript64,
=> 8,
.aarch64,
.aarch64_be,
.mips64,
.mips64el,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.riscv32,
.riscv64,
.x86_64,
.wasm32,
.wasm64,
=> 16,
},
);
}
pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
// Overrides for unusual alignments
switch (target.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.netbsd => switch (target.abi) {
.gnueabi,
.gnueabihf,
.eabi,
.eabihf,
.android,
.musleabi,
.musleabihf,
=> {},
else => switch (c_type) {
.longdouble => return 4,
else => {},
},
},
.ios, .tvos, .watchos => switch (c_type) {
.longdouble => return 4,
else => {},
},
else => {},
},
.arc => switch (c_type) {
.longdouble => return 4,
else => {},
},
.avr => switch (c_type) {
.int, .uint, .long, .ulong, .float, .longdouble => return 1,
.short, .ushort => return 2,
.double => return 4,
.longlong, .ulonglong => return 8,
},
.x86 => switch (target.os.tag) {
.windows, .uefi => switch (c_type) {
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 4,
else => return 8,
},
else => {},
},
else => switch (c_type) {
.longdouble => return 4,
else => {},
},
},
else => {},
}
// Next-power-of-two-aligned, up to a maximum.
return @min(
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
switch (target.cpu.arch) {
.msp430 => @as(u16, 2),
.csky,
.xcore,
.dxil,
.loongarch32,
.tce,
.tcele,
.le32,
.amdil,
.hsail,
.spir,
.spirv32,
.kalimba,
.shave,
.renderscript32,
.ve,
.spu_2,
=> 4,
.arc,
.arm,
.armeb,
.avr,
.thumb,
.thumbeb,
.aarch64_32,
.amdgcn,
.amdil64,
.bpfel,
.bpfeb,
.hexagon,
.hsail64,
.x86,
.loongarch64,
.m68k,
.mips,
.mipsel,
.sparc,
.sparcel,
.sparc64,
.lanai,
.le64,
.nvptx,
.nvptx64,
.r600,
.s390x,
.spir64,
.spirv64,
.renderscript64,
=> 8,
.aarch64,
.aarch64_be,
.mips64,
.mips64el,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.riscv32,
.riscv64,
.x86_64,
.wasm32,
.wasm64,
=> 16,
},
);
}
};
test {

View File

@ -26076,7 +26076,7 @@ fn coerceVarArgParam(
.Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
.Float => float: {
const target = sema.mod.getTarget();
const double_bits = @import("type.zig").CType.sizeInBits(.double, target);
const double_bits = target.c_type_bit_size(.double);
const inst_bits = uncasted_ty.floatBits(sema.mod.getTarget());
if (inst_bits >= double_bits) break :float inst;
switch (double_bits) {

View File

@ -16,7 +16,6 @@ const trace = @import("../tracy.zig").trace;
const LazySrcLoc = Module.LazySrcLoc;
const Air = @import("../Air.zig");
const Liveness = @import("../Liveness.zig");
const CType = @import("../type.zig").CType;
const target_util = @import("../target.zig");
const libcFloatPrefix = target_util.libcFloatPrefix;

View File

@ -19,7 +19,6 @@ const Liveness = @import("../Liveness.zig");
const Value = @import("../value.zig").Value;
const Type = @import("../type.zig").Type;
const LazySrcLoc = Module.LazySrcLoc;
const CType = @import("../type.zig").CType;
const x86_64_abi = @import("../arch/x86_64/abi.zig");
const wasm_c_abi = @import("../arch/wasm/abi.zig");
const aarch64_c_abi = @import("../arch/aarch64/abi.zig");
@ -11043,8 +11042,8 @@ fn backendSupportsF128(target: std.Target) bool {
fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {
return switch (scalar_ty.tag()) {
.f16 => backendSupportsF16(target),
.f80 => (CType.longdouble.sizeInBits(target) == 80) and backendSupportsF80(target),
.f128 => (CType.longdouble.sizeInBits(target) == 128) and backendSupportsF128(target),
.f80 => (target.c_type_bit_size(.longdouble) == 80) and backendSupportsF80(target),
.f128 => (target.c_type_bit_size(.longdouble) == 128) and backendSupportsF128(target),
else => true,
};
}

View File

@ -2937,24 +2937,24 @@ pub const Type = extern union {
.anyframe_T,
=> return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
.c_short => return AbiAlignmentAdvanced{ .scalar = CType.short.alignment(target) },
.c_ushort => return AbiAlignmentAdvanced{ .scalar = CType.ushort.alignment(target) },
.c_int => return AbiAlignmentAdvanced{ .scalar = CType.int.alignment(target) },
.c_uint => return AbiAlignmentAdvanced{ .scalar = CType.uint.alignment(target) },
.c_long => return AbiAlignmentAdvanced{ .scalar = CType.long.alignment(target) },
.c_ulong => return AbiAlignmentAdvanced{ .scalar = CType.ulong.alignment(target) },
.c_longlong => return AbiAlignmentAdvanced{ .scalar = CType.longlong.alignment(target) },
.c_ulonglong => return AbiAlignmentAdvanced{ .scalar = CType.ulonglong.alignment(target) },
.c_longdouble => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
.c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) },
.c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) },
.c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) },
.c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) },
.c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) },
.c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) },
.c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) },
.c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) },
.c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
.f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
.f32 => return AbiAlignmentAdvanced{ .scalar = CType.float.alignment(target) },
.f64 => switch (CType.double.sizeInBits(target)) {
64 => return AbiAlignmentAdvanced{ .scalar = CType.double.alignment(target) },
.f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) },
.f64 => switch (target.c_type_bit_size(.double)) {
64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) },
else => return AbiAlignmentAdvanced{ .scalar = 8 },
},
.f80 => switch (CType.longdouble.sizeInBits(target)) {
80 => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
.f80 => switch (target.c_type_bit_size(.longdouble)) {
80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
else => {
var payload: Payload.Bits = .{
.base = .{ .tag = .int_unsigned },
@ -2964,8 +2964,8 @@ pub const Type = extern union {
return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, target) };
},
},
.f128 => switch (CType.longdouble.sizeInBits(target)) {
128 => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
.f128 => switch (target.c_type_bit_size(.longdouble)) {
128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
else => return AbiAlignmentAdvanced{ .scalar = 16 },
},
@ -3434,21 +3434,22 @@ pub const Type = extern union {
else => return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
},
.c_short => return AbiSizeAdvanced{ .scalar = @divExact(CType.short.sizeInBits(target), 8) },
.c_ushort => return AbiSizeAdvanced{ .scalar = @divExact(CType.ushort.sizeInBits(target), 8) },
.c_int => return AbiSizeAdvanced{ .scalar = @divExact(CType.int.sizeInBits(target), 8) },
.c_uint => return AbiSizeAdvanced{ .scalar = @divExact(CType.uint.sizeInBits(target), 8) },
.c_long => return AbiSizeAdvanced{ .scalar = @divExact(CType.long.sizeInBits(target), 8) },
.c_ulong => return AbiSizeAdvanced{ .scalar = @divExact(CType.ulong.sizeInBits(target), 8) },
.c_longlong => return AbiSizeAdvanced{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },
.c_ulonglong => return AbiSizeAdvanced{ .scalar = @divExact(CType.ulonglong.sizeInBits(target), 8) },
.c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
.c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
.c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
.c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
.c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
.c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
.c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
.c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
.c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
.f16 => return AbiSizeAdvanced{ .scalar = 2 },
.f32 => return AbiSizeAdvanced{ .scalar = 4 },
.f64 => return AbiSizeAdvanced{ .scalar = 8 },
.f128 => return AbiSizeAdvanced{ .scalar = 16 },
.f80 => switch (CType.longdouble.sizeInBits(target)) {
80 => return AbiSizeAdvanced{ .scalar = std.mem.alignForward(10, CType.longdouble.alignment(target)) },
.f80 => switch (target.c_type_bit_size(.longdouble)) {
80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
else => {
var payload: Payload.Bits = .{
.base = .{ .tag = .int_unsigned },
@ -3458,14 +3459,6 @@ pub const Type = extern union {
return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, target) };
},
},
.c_longdouble => switch (CType.longdouble.sizeInBits(target)) {
16 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f16, target) },
32 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f32, target) },
64 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f64, target) },
80 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f80, target) },
128 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f128, target) },
else => unreachable,
},
// TODO revisit this when we have the concept of the error tag type
.anyerror_void_error_union,
@ -3748,15 +3741,15 @@ pub const Type = extern union {
.manyptr_const_u8_sentinel_0,
=> return target.cpu.arch.ptrBitWidth(),
.c_short => return CType.short.sizeInBits(target),
.c_ushort => return CType.ushort.sizeInBits(target),
.c_int => return CType.int.sizeInBits(target),
.c_uint => return CType.uint.sizeInBits(target),
.c_long => return CType.long.sizeInBits(target),
.c_ulong => return CType.ulong.sizeInBits(target),
.c_longlong => return CType.longlong.sizeInBits(target),
.c_ulonglong => return CType.ulonglong.sizeInBits(target),
.c_longdouble => return CType.longdouble.sizeInBits(target),
.c_short => return target.c_type_bit_size(.short),
.c_ushort => return target.c_type_bit_size(.ushort),
.c_int => return target.c_type_bit_size(.int),
.c_uint => return target.c_type_bit_size(.uint),
.c_long => return target.c_type_bit_size(.long),
.c_ulong => return target.c_type_bit_size(.ulong),
.c_longlong => return target.c_type_bit_size(.longlong),
.c_ulonglong => return target.c_type_bit_size(.ulonglong),
.c_longdouble => return target.c_type_bit_size(.longdouble),
.error_set,
.error_set_single,
@ -4631,14 +4624,14 @@ pub const Type = extern union {
.i128 => return .{ .signedness = .signed, .bits = 128 },
.usize => return .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
.isize => return .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
.c_short => return .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },
.c_ushort => return .{ .signedness = .unsigned, .bits = CType.ushort.sizeInBits(target) },
.c_int => return .{ .signedness = .signed, .bits = CType.int.sizeInBits(target) },
.c_uint => return .{ .signedness = .unsigned, .bits = CType.uint.sizeInBits(target) },
.c_long => return .{ .signedness = .signed, .bits = CType.long.sizeInBits(target) },
.c_ulong => return .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
.c_longlong => return .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
.c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
.c_short => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
.c_ushort => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
.c_int => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
.c_uint => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.uint) },
.c_long => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.long) },
.c_ulong => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulong) },
.c_longlong => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.longlong) },
.c_ulonglong => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
.enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,
.enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty,
@ -4724,7 +4717,7 @@ pub const Type = extern union {
.f64 => 64,
.f80 => 80,
.f128, .comptime_float => 128,
.c_longdouble => CType.longdouble.sizeInBits(target),
.c_longdouble => target.c_type_bit_size(.longdouble),
else => unreachable,
};
@ -6689,536 +6682,3 @@ pub const Type = extern union {
/// to packed struct layout to find out all the places in the codebase you need to edit!
pub const packed_struct_layout_version = 2;
};
pub const CType = enum {
short,
ushort,
int,
uint,
long,
ulong,
longlong,
ulonglong,
longdouble,
// We don't have a `c_float`/`c_double` type in Zig, but these
// are useful for querying target-correct alignment and checking
// whether C's double is f64 or f32
float,
double,
pub fn sizeInBits(self: CType, target: Target) u16 {
switch (target.os.tag) {
.freestanding, .other => switch (target.cpu.arch) {
.msp430 => switch (self) {
.short, .ushort, .int, .uint => return 16,
.float, .long, .ulong => return 32,
.longlong, .ulonglong, .double, .longdouble => return 64,
},
.avr => switch (self) {
.short, .ushort, .int, .uint => return 16,
.long, .ulong, .float, .double, .longdouble => return 32,
.longlong, .ulonglong => return 64,
},
.tce, .tcele => switch (self) {
.short, .ushort => return 16,
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
.float, .double, .longdouble => return 32,
},
.mips64, .mips64el => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => return 128,
},
.x86_64 => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
.gnux32, .muslx32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => return 80,
},
else => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.x86 => switch (target.abi) {
.android => return 64,
else => return 80,
},
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
=> switch (target.abi) {
.musl,
.musleabi,
.musleabihf,
.muslx32,
=> return 64,
else => return 128,
},
.riscv32,
.riscv64,
.aarch64,
.aarch64_be,
.aarch64_32,
.s390x,
.sparc,
.sparc64,
.sparcel,
.wasm32,
.wasm64,
=> return 128,
else => return 64,
},
},
},
.linux,
.freebsd,
.netbsd,
.dragonfly,
.openbsd,
.wasi,
.emscripten,
.plan9,
.solaris,
.haiku,
.ananas,
.fuchsia,
.minix,
=> switch (target.cpu.arch) {
.msp430 => switch (self) {
.short, .ushort, .int, .uint => return 16,
.long, .ulong, .float => return 32,
.longlong, .ulonglong, .double, .longdouble => return 64,
},
.avr => switch (self) {
.short, .ushort, .int, .uint => return 16,
.long, .ulong, .float, .double, .longdouble => return 32,
.longlong, .ulonglong => return 64,
},
.tce, .tcele => switch (self) {
.short, .ushort => return 16,
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
.float, .double, .longdouble => return 32,
},
.mips64, .mips64el => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => if (target.os.tag == .freebsd) return 64 else return 128,
},
.x86_64 => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
.gnux32, .muslx32 => return 32,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => return 80,
},
else => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.x86 => switch (target.abi) {
.android => return 64,
else => return 80,
},
.powerpc,
.powerpcle,
=> switch (target.abi) {
.musl,
.musleabi,
.musleabihf,
.muslx32,
=> return 64,
else => switch (target.os.tag) {
.freebsd, .netbsd, .openbsd => return 64,
else => return 128,
},
},
.powerpc64,
.powerpc64le,
=> switch (target.abi) {
.musl,
.musleabi,
.musleabihf,
.muslx32,
=> return 64,
else => switch (target.os.tag) {
.freebsd, .openbsd => return 64,
else => return 128,
},
},
.riscv32,
.riscv64,
.aarch64,
.aarch64_be,
.aarch64_32,
.s390x,
.mips64,
.mips64el,
.sparc,
.sparc64,
.sparcel,
.wasm32,
.wasm64,
=> return 128,
else => return 64,
},
},
},
.windows, .uefi => switch (target.cpu.arch) {
.x86 => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 80,
else => return 64,
},
},
.x86_64 => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.abi) {
.cygnus => return 64,
else => return 32,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 80,
else => return 64,
},
},
else => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => return 32,
.longlong, .ulonglong, .double => return 64,
.longdouble => return 64,
},
},
.macos, .ios, .tvos, .watchos => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.cpu.arch) {
.x86, .arm, .aarch64_32 => return 32,
.x86_64 => switch (target.abi) {
.gnux32, .muslx32 => return 32,
else => return 64,
},
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.x86 => switch (target.abi) {
.android => return 64,
else => return 80,
},
.x86_64 => return 80,
else => return 64,
},
},
.nvcl, .cuda => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong => switch (target.cpu.arch) {
.nvptx => return 32,
.nvptx64 => return 64,
else => return 64,
},
.longlong, .ulonglong, .double => return 64,
.longdouble => return 64,
},
.amdhsa, .amdpal => switch (self) {
.short, .ushort => return 16,
.int, .uint, .float => return 32,
.long, .ulong, .longlong, .ulonglong, .double => return 64,
.longdouble => return 128,
},
.cloudabi,
.kfreebsd,
.lv2,
.zos,
.rtems,
.nacl,
.aix,
.ps4,
.ps5,
.elfiamcu,
.mesa3d,
.contiki,
.hermit,
.hurd,
.opencl,
.glsl450,
.vulkan,
.driverkit,
.shadermodel,
=> @panic("TODO specify the C integer and float type sizes for this OS"),
}
}
pub fn alignment(self: CType, target: Target) u16 {
// Overrides for unusual alignments
switch (target.cpu.arch) {
.avr => switch (self) {
.short, .ushort => return 2,
else => return 1,
},
.x86 => switch (target.os.tag) {
.windows, .uefi => switch (self) {
.longlong, .ulonglong, .double => return 8,
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 4,
else => return 8,
},
else => {},
},
else => {},
},
else => {},
}
// Next-power-of-two-aligned, up to a maximum.
return @min(
std.math.ceilPowerOfTwoAssert(u16, (self.sizeInBits(target) + 7) / 8),
switch (target.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.netbsd => switch (target.abi) {
.gnueabi,
.gnueabihf,
.eabi,
.eabihf,
.android,
.musleabi,
.musleabihf,
=> 8,
else => @as(u16, 4),
},
.ios, .tvos, .watchos => 4,
else => 8,
},
.msp430,
.avr,
=> 2,
.arc,
.csky,
.x86,
.xcore,
.dxil,
.loongarch32,
.tce,
.tcele,
.le32,
.amdil,
.hsail,
.spir,
.spirv32,
.kalimba,
.shave,
.renderscript32,
.ve,
.spu_2,
=> 4,
.aarch64_32,
.amdgcn,
.amdil64,
.bpfel,
.bpfeb,
.hexagon,
.hsail64,
.loongarch64,
.m68k,
.mips,
.mipsel,
.sparc,
.sparcel,
.sparc64,
.lanai,
.le64,
.nvptx,
.nvptx64,
.r600,
.s390x,
.spir64,
.spirv64,
.renderscript64,
=> 8,
.aarch64,
.aarch64_be,
.mips64,
.mips64el,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.riscv32,
.riscv64,
.x86_64,
.wasm32,
.wasm64,
=> 16,
},
);
}
pub fn preferredAlignment(self: CType, target: Target) u16 {
// Overrides for unusual alignments
switch (target.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.netbsd => switch (target.abi) {
.gnueabi,
.gnueabihf,
.eabi,
.eabihf,
.android,
.musleabi,
.musleabihf,
=> {},
else => switch (self) {
.longdouble => return 4,
else => {},
},
},
.ios, .tvos, .watchos => switch (self) {
.longdouble => return 4,
else => {},
},
else => {},
},
.arc => switch (self) {
.longdouble => return 4,
else => {},
},
.avr => switch (self) {
.int, .uint, .long, .ulong, .float, .longdouble => return 1,
.short, .ushort => return 2,
.double => return 4,
.longlong, .ulonglong => return 8,
},
.x86 => switch (target.os.tag) {
.windows, .uefi => switch (self) {
.longdouble => switch (target.abi) {
.gnu, .gnuilp32, .cygnus => return 4,
else => return 8,
},
else => {},
},
else => switch (self) {
.longdouble => return 4,
else => {},
},
},
else => {},
}
// Next-power-of-two-aligned, up to a maximum.
return @min(
std.math.ceilPowerOfTwoAssert(u16, (self.sizeInBits(target) + 7) / 8),
switch (target.cpu.arch) {
.msp430 => @as(u16, 2),
.csky,
.xcore,
.dxil,
.loongarch32,
.tce,
.tcele,
.le32,
.amdil,
.hsail,
.spir,
.spirv32,
.kalimba,
.shave,
.renderscript32,
.ve,
.spu_2,
=> 4,
.arc,
.arm,
.armeb,
.avr,
.thumb,
.thumbeb,
.aarch64_32,
.amdgcn,
.amdil64,
.bpfel,
.bpfeb,
.hexagon,
.hsail64,
.x86,
.loongarch64,
.m68k,
.mips,
.mipsel,
.sparc,
.sparcel,
.sparc64,
.lanai,
.le64,
.nvptx,
.nvptx64,
.r600,
.s390x,
.spir64,
.spirv64,
.renderscript64,
=> 8,
.aarch64,
.aarch64_be,
.mips64,
.mips64el,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.riscv32,
.riscv64,
.x86_64,
.wasm32,
.wasm64,
=> 16,
},
);
}
};