diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-10-27 21:15:22 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-27 21:15:22 -0400 |
| commit | 1d1c7ae5de3e981099522a8610764a6595b1b7a1 (patch) | |
| tree | b879cc51fd26ff9d0c12e5b7a05026639968bfdd /src | |
| parent | d03c47bf85b17f7727d2f1fe5bd497b311c9eba7 (diff) | |
| parent | 4ecc384f99e5f4c5a320714484866fb48699245f (diff) | |
| download | zig-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.zig | 4 | ||||
| -rw-r--r-- | src/type.zig | 503 |
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, + }, + ); + } }; |
