aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-10-27 21:15:22 -0400
committerGitHub <noreply@github.com>2022-10-27 21:15:22 -0400
commit1d1c7ae5de3e981099522a8610764a6595b1b7a1 (patch)
treeb879cc51fd26ff9d0c12e5b7a05026639968bfdd /src
parentd03c47bf85b17f7727d2f1fe5bd497b311c9eba7 (diff)
parent4ecc384f99e5f4c5a320714484866fb48699245f (diff)
downloadzig-1d1c7ae5de3e981099522a8610764a6595b1b7a1.tar.gz
zig-1d1c7ae5de3e981099522a8610764a6595b1b7a1.zip
Merge pull request #13257 from topolarity/ctype-fixes
stage 2: Update `CType` size/alignment
Diffstat (limited to 'src')
-rw-r--r--src/codegen/llvm.zig4
-rw-r--r--src/type.zig503
2 files changed, 416 insertions, 91 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 938770629f..1c2d65246f 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -10730,8 +10730,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 => target.longDoubleIs(f80) and backendSupportsF80(target),
- .f128 => target.longDoubleIs(f128) and backendSupportsF128(target),
+ .f80 => (CType.longdouble.sizeInBits(target) == 80) and backendSupportsF80(target),
+ .f128 => (CType.longdouble.sizeInBits(target) == 128) and backendSupportsF128(target),
else => true,
};
}
diff --git a/src/type.zig b/src/type.zig
index a2f0bb9e8f..8f2cd7c54d 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -2892,41 +2892,24 @@ pub const Type = extern union {
.anyframe_T,
=> return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
- .c_short => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.short.sizeInBits(target), 8) },
- .c_ushort => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ushort.sizeInBits(target), 8) },
- .c_int => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.int.sizeInBits(target), 8) },
- .c_uint => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.uint.sizeInBits(target), 8) },
- .c_long => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.long.sizeInBits(target), 8) },
- .c_ulong => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ulong.sizeInBits(target), 8) },
- .c_longlong => switch (target.cpu.arch) {
- .i386 => switch (target.os.tag) {
- .windows, .uefi => return AbiAlignmentAdvanced{ .scalar = 8 },
- else => return AbiAlignmentAdvanced{ .scalar = 4 },
- },
- else => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },
- },
- .c_ulonglong => switch (target.cpu.arch) {
- .i386 => switch (target.os.tag) {
- .windows, .uefi => return AbiAlignmentAdvanced{ .scalar = 8 },
- else => return AbiAlignmentAdvanced{ .scalar = 4 },
- },
- else => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ulonglong.sizeInBits(target), 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) },
.f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
- .f32 => return AbiAlignmentAdvanced{ .scalar = 4 },
- .f64 => switch (target.cpu.arch) {
- .i386 => switch (target.os.tag) {
- .windows, .uefi => return AbiAlignmentAdvanced{ .scalar = 8 },
- else => return AbiAlignmentAdvanced{ .scalar = 4 },
- },
+ .f32 => return AbiAlignmentAdvanced{ .scalar = CType.float.alignment(target) },
+ .f64 => switch (CType.double.sizeInBits(target)) {
+ 64 => return AbiAlignmentAdvanced{ .scalar = CType.double.alignment(target) },
else => return AbiAlignmentAdvanced{ .scalar = 8 },
},
- .f128 => return AbiAlignmentAdvanced{ .scalar = 16 },
-
- .f80 => switch (target.cpu.arch) {
- .i386 => return AbiAlignmentAdvanced{ .scalar = 4 },
- .x86_64 => return AbiAlignmentAdvanced{ .scalar = 16 },
+ .f80 => switch (CType.longdouble.sizeInBits(target)) {
+ 80 => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
else => {
var payload: Payload.Bits = .{
.base = .{ .tag = .int_unsigned },
@@ -2936,17 +2919,7 @@ pub const Type = extern union {
return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, target) };
},
},
- .c_longdouble => switch (CType.longdouble.sizeInBits(target)) {
- 16 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f16, target) },
- 32 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f32, target) },
- 64 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f64, target) },
- 80 => if (target.cpu.arch == .i386 and target.isMinGW())
- return AbiAlignmentAdvanced{ .scalar = 4 }
- else
- return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f80, target) },
- 128 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f128, target) },
- else => unreachable,
- },
+ .f128 => return AbiAlignmentAdvanced{ .scalar = 16 },
// TODO revisit this when we have the concept of the error tag type
.anyerror_void_error_union,
@@ -3411,16 +3384,8 @@ pub const Type = extern union {
.f32 => return AbiSizeAdvanced{ .scalar = 4 },
.f64 => return AbiSizeAdvanced{ .scalar = 8 },
.f128 => return AbiSizeAdvanced{ .scalar = 16 },
-
- .f80 => switch (target.cpu.arch) {
- .i386 => switch (target.os.tag) {
- .windows => switch (target.abi) {
- .msvc => return AbiSizeAdvanced{ .scalar = 16 },
- else => return AbiSizeAdvanced{ .scalar = 12 },
- },
- else => return AbiSizeAdvanced{ .scalar = 12 },
- },
- .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
+ .f80 => switch (CType.longdouble.sizeInBits(target)) {
+ 80 => return AbiSizeAdvanced{ .scalar = std.mem.alignForward(10, CType.longdouble.alignment(target)) },
else => {
var payload: Payload.Bits = .{
.base = .{ .tag = .int_unsigned },
@@ -6654,45 +6619,80 @@ pub const CType = enum {
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,
- .long, .ulong => return 32,
- .longlong, .ulonglong, .longdouble => return 64,
+ .float, .long, .ulong => return 32,
+ .longlong, .ulonglong, .double, .longdouble => return 64,
},
.avr => switch (self) {
.short, .ushort, .int, .uint => return 16,
- .long, .ulong, .longdouble => return 32,
+ .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 => return 32,
+ .int, .uint, .float => return 32,
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
- .longlong, .ulonglong => return 64,
+ .longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.i386 => switch (target.abi) {
.android => return 64,
else => return 80,
},
- .x86_64 => 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,
- .mips64,
- .mips64el,
.sparc,
.sparc64,
.sparcel,
- .powerpc,
- .powerpcle,
- .powerpc64,
- .powerpc64le,
.wasm32,
.wasm64,
=> return 128,
@@ -6716,23 +6716,78 @@ pub const CType = enum {
.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, .longdouble => return 32,
+ .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 => return 32,
+ .int, .uint, .float => return 32,
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
- .longlong, .ulonglong => return 64,
+ .longlong, .ulonglong, .double => return 64,
.longdouble => switch (target.cpu.arch) {
.i386 => switch (target.abi) {
.android => return 64,
else => return 80,
},
- .x86_64 => 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,
@@ -6743,10 +6798,6 @@ pub const CType = enum {
.sparc,
.sparc64,
.sparcel,
- .powerpc,
- .powerpcle,
- .powerpc64,
- .powerpc64le,
.wasm32,
.wasm64,
=> return 128,
@@ -6756,37 +6807,77 @@ pub const CType = enum {
},
},
- .windows, .uefi => switch (self) {
- .short, .ushort => return 16,
- .int, .uint, .long, .ulong => return 32,
- .longlong, .ulonglong => return 64,
- .longdouble => switch (target.cpu.arch) {
- .i386 => switch (target.abi) {
- .gnu => return 80,
+ .windows, .uefi => switch (target.cpu.arch) {
+ .i386 => 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 (target.abi) {
- .gnu => return 80,
+ },
+ .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 => 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 => return 32,
- .long, .ulong, .longlong, .ulonglong => return 64,
+ .int, .uint, .float => return 32,
+ .long, .ulong => switch (target.cpu.arch) {
+ .i386, .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) {
- .i386, .x86_64 => return 80,
+ .i386 => 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 => return 32,
- .long, .ulong, .longlong, .ulonglong => return 64,
+ .int, .uint, .float => return 32,
+ .long, .ulong, .longlong, .ulonglong, .double => return 64,
.longdouble => return 128,
},
@@ -6797,8 +6888,6 @@ pub const CType = enum {
.rtems,
.nacl,
.aix,
- .cuda,
- .nvcl,
.ps4,
.ps5,
.elfiamcu,
@@ -6814,4 +6903,240 @@ pub const CType = enum {
=> @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,
+ },
+ .i386 => 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,
+ .i386,
+ .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,
+ },
+ .i386 => 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,
+ .i386,
+ .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,
+ },
+ );
+ }
};