mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
x86_64: fix c abi of f32 struct field followed by padding
Closes #31864
This commit is contained in:
@@ -181632,9 +181632,11 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
|
|||||||
else => break,
|
else => break,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
var part_sizes: u64 = 0;
|
var parts_size: u64 = 0;
|
||||||
for (parts) |part| part_sizes += part.abiSize(zcu);
|
for (parts) |part| parts_size += part.abiSize(zcu);
|
||||||
if (part_sizes == ty.abiSize(zcu)) return parts;
|
const abi_size = ty.abiSize(zcu);
|
||||||
|
if (abi_size == parts_size) return parts;
|
||||||
|
if (classes[classes.len - 1] == .float and abi_size > parts_size and abi_size <= parts_size + 4) return parts;
|
||||||
};
|
};
|
||||||
return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) });
|
return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,21 +300,26 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
|
|||||||
for (result, 0..) |class, i| switch (class) {
|
for (result, 0..) |class, i| switch (class) {
|
||||||
.memory => return Class.stack,
|
.memory => return Class.stack,
|
||||||
.x87up => if (i == 0 or result[i - 1] != .x87) return Class.stack,
|
.x87up => if (i == 0 or result[i - 1] != .x87) return Class.stack,
|
||||||
else => continue,
|
else => {},
|
||||||
};
|
};
|
||||||
// "If the size of the aggregate exceeds two eightbytes and the first eight-
|
// "If the size of the aggregate exceeds two eightbytes and the first eight-
|
||||||
// byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument
|
// byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument
|
||||||
// is passed in memory."
|
// is passed in memory."
|
||||||
if (ty_size > 16 and (result[0] != .sse or
|
if (ty_size > 16 and (result[0] != .sse or
|
||||||
std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack;
|
std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack;
|
||||||
|
|
||||||
// "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
|
// "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
|
||||||
for (&result, 0..) |*item, i| {
|
for (&result, 0..) |*class, i| switch (class.*) {
|
||||||
if (item.* == .sseup) switch (result[i - 1]) {
|
.sseup => switch (result[i - 1]) {
|
||||||
.sse, .sseup => continue,
|
.sse, .sseup => {},
|
||||||
else => item.* = .sse,
|
else => class.* = .sse,
|
||||||
};
|
},
|
||||||
}
|
.float => if (i + 1 < result.len) switch (result[i + 1]) {
|
||||||
|
.none => {},
|
||||||
|
else => class.* = .float_combine,
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
.array => {
|
.array => {
|
||||||
|
|||||||
@@ -2948,7 +2948,6 @@ void run_c_tests(void) {
|
|||||||
#if !defined(__riscv)
|
#if !defined(__riscv)
|
||||||
#if !defined(__s390x__)
|
#if !defined(__s390x__)
|
||||||
#if !defined(__i386__)
|
#if !defined(__i386__)
|
||||||
#if !defined(__x86_64__)
|
|
||||||
{
|
{
|
||||||
struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8();
|
struct Struct_f32a8_f32a8 s = zig_ret_struct_f32a8_f32a8();
|
||||||
assert_or_panic(s.a == 1.25f);
|
assert_or_panic(s.a == 1.25f);
|
||||||
@@ -2962,7 +2961,6 @@ void run_c_tests(void) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !(defined(__arm__) && defined(__SOFTFP__))
|
#if !(defined(__arm__) && defined(__SOFTFP__))
|
||||||
#if !defined(__loongarch__) && !defined(__mips64__)
|
#if !defined(__loongarch__) && !defined(__mips64__)
|
||||||
|
|||||||
+7
-16
@@ -554,22 +554,14 @@ const Struct_f32a8_f32a8 = extern struct {
|
|||||||
b: f32 align(8),
|
b: f32 align(8),
|
||||||
};
|
};
|
||||||
|
|
||||||
comptime {
|
export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 {
|
||||||
skip: {
|
return .{ .a = 1.25, .b = 2.75 };
|
||||||
if (builtin.zig_backend == .stage2_x86_64) break :skip;
|
}
|
||||||
|
|
||||||
_ = struct {
|
export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void {
|
||||||
export fn zig_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8 {
|
expect(s.a == 3.125) catch @panic("test failure");
|
||||||
return .{ .a = 1.25, .b = 2.75 };
|
expect(s.b == 4.375) catch @panic("test failure");
|
||||||
}
|
expect(f == 5.5) catch @panic("test failure");
|
||||||
|
|
||||||
export fn zig_struct_f32a8_f32a8(s: Struct_f32a8_f32a8, f: f32) void {
|
|
||||||
expect(s.a == 3.125) catch @panic("test failure");
|
|
||||||
expect(s.b == 4.375) catch @panic("test failure");
|
|
||||||
expect(f == 5.5) catch @panic("test failure");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8;
|
extern fn c_ret_struct_f32a8_f32a8() Struct_f32a8_f32a8;
|
||||||
@@ -584,7 +576,6 @@ test "C ABI struct f32 align(8), f32 align(8)" {
|
|||||||
if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
|
if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
|
||||||
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
|
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
|
||||||
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
|
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
|
||||||
if (builtin.cpu.arch == .x86_64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const s = c_ret_struct_f32a8_f32a8();
|
const s = c_ret_struct_f32a8_f32a8();
|
||||||
try expect(s.a == 6.625);
|
try expect(s.a == 6.625);
|
||||||
|
|||||||
Reference in New Issue
Block a user