Commit e4e1c21e1f

Evan Haas <evan@lagerdata.com>
2022-10-07 00:29:10
i386 ABI: Fix some sizes and alignments
This makes the following changes for i386: long long and unsigned long long have 4 byte alignment on non-Windows f64 (double) has 4-byte alignment on non-Windows long double is 80 bits and has 4 byte alignment on mingw long double on android is 64 bits, not 80: https://www.uclibc.org/docs/psABI-i386.pdf Fixes #12453 Fixes #12987
1 parent c8da03a
Changed files (3)
lib/std/target.zig
@@ -1761,7 +1761,7 @@ pub const Target = struct {
     }
 
     pub inline fn longDoubleIs(target: Target, comptime F: type) bool {
-        if (target.abi == .msvc) {
+        if (target.abi == .msvc or (target.abi == .android and target.cpu.arch == .i386)) {
             return F == f64;
         }
         return switch (F) {
src/type.zig
@@ -2892,12 +2892,30 @@ pub const Type = extern union {
             .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 => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },
-            .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ulonglong.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) },
+            },
 
             .f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
             .f32 => return AbiAlignmentAdvanced{ .scalar = 4 },
-            .f64 => return AbiAlignmentAdvanced{ .scalar = 8 },
+            .f64 => switch (target.cpu.arch) {
+                .i386 => switch (target.os.tag) {
+                    .windows, .uefi => return AbiAlignmentAdvanced{ .scalar = 8 },
+                    else => return AbiAlignmentAdvanced{ .scalar = 4 },
+                },
+                else => return AbiAlignmentAdvanced{ .scalar = 8 },
+            },
             .f128 => return AbiAlignmentAdvanced{ .scalar = 16 },
 
             .f80 => switch (target.cpu.arch) {
@@ -2916,7 +2934,10 @@ pub const Type = extern union {
                 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 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f80, 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,
             },
@@ -6637,7 +6658,11 @@ pub const CType = enum {
                     .long, .ulong => return target.cpu.arch.ptrBitWidth(),
                     .longlong, .ulonglong => 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,
 
                         .riscv64,
                         .aarch64,
@@ -6687,7 +6712,11 @@ pub const CType = enum {
                     .long, .ulong => return target.cpu.arch.ptrBitWidth(),
                     .longlong, .ulonglong => 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,
 
                         .riscv64,
                         .aarch64,
@@ -6715,7 +6744,18 @@ pub const CType = enum {
             .windows, .uefi => switch (self) {
                 .short, .ushort => return 16,
                 .int, .uint, .long, .ulong => return 32,
-                .longlong, .ulonglong, .longdouble => return 64,
+                .longlong, .ulonglong => return 64,
+                .longdouble => switch (target.cpu.arch) {
+                    .i386 => switch (target.abi) {
+                        .gnu => return 80,
+                        else => return 64,
+                    },
+                    .x86_64 => switch (target.abi) {
+                        .gnu => return 80,
+                        else => return 64,
+                    },
+                    else => return 64,
+                },
             },
 
             .macos, .ios, .tvos, .watchos => switch (self) {
test/standalone.zig
@@ -53,6 +53,9 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
     if (builtin.cpu.arch.isAARCH64() and builtin.zig_backend == .stage2_llvm) {
         cases.addBuildFile("test/c_abi/build.zig", .{});
     }
+    if (builtin.cpu.arch == .i386 and builtin.zig_backend == .stage2_llvm) {
+        cases.addBuildFile("test/c_abi/build.zig", .{});
+    }
     // C ABI tests only pass for the Wasm target when using stage2
     cases.addBuildFile("test/c_abi/build_wasm.zig", .{
         .requires_stage2 = true,