authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-05-01 23:39:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-08 19:37:29-07:00
log08cecc1c7e453042123f8ec6a240a49cbf3b165a
tree41782f843f057d6727e272f9cf08235a4676b7d3
parente9efed9ed117c1b6f5fc138999d82e0dbb1f13bf

x86_64: fix C abi of incomplete sse register


3 files changed, 79 insertions(+), 21 deletions(-)

src/arch/x86_64/abi.zig+3-4
......@@ -285,17 +285,16 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8
285285
286286 // "If one of the classes is MEMORY, the whole argument is passed in memory"
287287 // "If X87UP is not preceded by X87, the whole argument is passed in memory."
288 var found_sseup = false;
289 for (result, 0..) |item, i| switch (item) {
288 for (result, 0..) |class, i| switch (class) {
290289 .memory => return memory_class,
291290 .x87up => if (i == 0 or result[i - 1] != .x87) return memory_class,
292 .sseup => found_sseup = true,
293291 else => continue,
294292 };
295293 // "If the size of the aggregate exceeds two eightbytes and the first eight-
296294 // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument
297295 // is passed in memory."
298 if (ty_size > 16 and (result[0] != .sse or !found_sseup)) return memory_class;
296 if (ty_size > 16 and (result[0] != .sse or
297 std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return memory_class;
299298
300299 // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
301300 for (&result, 0..) |*item, i| {
test/c_abi/cfuncs.c+18
......@@ -5478,17 +5478,35 @@ f80_extra_struct c_f80_extra_struct(f80_extra_struct a) {
54785478#endif
54795479
54805480#ifndef ZIG_NO_F128
5481__float128 zig_f128(__float128 a);
54815482__float128 c_f128(__float128 a) {
54825483 assert_or_panic((double)a == 12.34);
5484 assert_or_panic(zig_f128(12) == 34);
54835485 return 56.78;
54845486}
54855487typedef struct {
54865488 __float128 a;
54875489} f128_struct;
5490f128_struct zig_f128_struct(f128_struct a);
54885491f128_struct c_f128_struct(f128_struct a) {
54895492 assert_or_panic((double)a.a == 12.34);
5493 f128_struct b = zig_f128_struct((f128_struct){12345});
5494 assert_or_panic(b.a == 98765);
54905495 return (f128_struct){56.78};
54915496}
5497
5498typedef struct {
5499 __float128 a, b;
5500} f128_f128_struct;
5501f128_f128_struct zig_f128_f128_struct(f128_f128_struct a);
5502f128_f128_struct c_f128_f128_struct(f128_f128_struct a) {
5503 assert_or_panic((double)a.a == 12.34);
5504 assert_or_panic((double)a.b == 87.65);
5505 f128_f128_struct b = zig_f128_f128_struct((f128_f128_struct){13, 57});
5506 assert_or_panic((double)b.a == 24);
5507 assert_or_panic((double)b.b == 68);
5508 return (f128_f128_struct){56.78, 43.21};
5509}
54925510#endif
54935511
54945512void __attribute__((stdcall)) stdcall_scalars(char a, short b, int c, float d, double e) {
test/c_abi/main.zig+58-17
......@@ -136,7 +136,7 @@ export fn zig_f64(x: f64) void {
136136 expect(x == 56.78) catch @panic("test failure: zig_f64");
137137}
138138export fn zig_longdouble(x: c_longdouble) void {
139 if (!builtin.cpu.arch.isWasm()) return; // waiting for #1481
139 if (!builtin.target.isWasm()) return; // waiting for #1481
140140 expect(x == 12.34) catch @panic("test failure: zig_longdouble");
141141}
142142
......@@ -1671,7 +1671,7 @@ test "bool simd vector" {
16711671 }
16721672
16731673 {
1674 if (builtin.target.cpu.arch != .wasm32) c_vector_256_bool(.{
1674 if (!builtin.target.isWasm()) c_vector_256_bool(.{
16751675 false,
16761676 true,
16771677 true,
......@@ -2189,7 +2189,7 @@ test "bool simd vector" {
21892189 try expect(vec[255] == false);
21902190 }
21912191 {
2192 if (builtin.target.cpu.arch != .wasm32) c_vector_512_bool(.{
2192 if (!builtin.target.isWasm()) c_vector_512_bool(.{
21932193 true,
21942194 true,
21952195 true,
......@@ -5614,23 +5614,64 @@ test "f80 extra struct" {
56145614 try expect(a.b == 24);
56155615}
56165616
5617extern fn c_f128(f128) f128;
5618test "f128 bare" {
5619 if (!have_f128) return error.SkipZigTest;
5617comptime {
5618 skip: {
5619 if (builtin.target.isWasm()) break :skip;
56205620
5621 const a = c_f128(12.34);
5622 try expect(@as(f64, @floatCast(a)) == 56.78);
5623}
5621 _ = struct {
5622 export fn zig_f128(x: f128) f128 {
5623 expect(x == 12) catch @panic("test failure");
5624 return 34;
5625 }
5626 extern fn c_f128(f128) f128;
5627 test "f128 bare" {
5628 if (!have_f128) return error.SkipZigTest;
56245629
5625const f128_struct = extern struct {
5626 a: f128,
5627};
5628extern fn c_f128_struct(f128_struct) f128_struct;
5629test "f128 struct" {
5630 if (!have_f128) return error.SkipZigTest;
5630 const a = c_f128(12.34);
5631 try expect(@as(f64, @floatCast(a)) == 56.78);
5632 }
56315633
5632 const a = c_f128_struct(.{ .a = 12.34 });
5633 try expect(@as(f64, @floatCast(a.a)) == 56.78);
5634 const f128_struct = extern struct {
5635 a: f128,
5636 };
5637 export fn zig_f128_struct(a: f128_struct) f128_struct {
5638 expect(a.a == 12345) catch @panic("test failure");
5639 return .{ .a = 98765 };
5640 }
5641 extern fn c_f128_struct(f128_struct) f128_struct;
5642 test "f128 struct" {
5643 if (!have_f128) return error.SkipZigTest;
5644
5645 const a = c_f128_struct(.{ .a = 12.34 });
5646 try expect(@as(f64, @floatCast(a.a)) == 56.78);
5647
5648 const b = c_f128_f128_struct(.{ .a = 12.34, .b = 87.65 });
5649 try expect(@as(f64, @floatCast(b.a)) == 56.78);
5650 try expect(@as(f64, @floatCast(b.b)) == 43.21);
5651 }
5652
5653 const f128_f128_struct = extern struct {
5654 a: f128,
5655 b: f128,
5656 };
5657 export fn zig_f128_f128_struct(a: f128_f128_struct) f128_f128_struct {
5658 expect(a.a == 13) catch @panic("test failure");
5659 expect(a.b == 57) catch @panic("test failure");
5660 return .{ .a = 24, .b = 68 };
5661 }
5662 extern fn c_f128_f128_struct(f128_f128_struct) f128_f128_struct;
5663 test "f128 f128 struct" {
5664 if (!have_f128) return error.SkipZigTest;
5665
5666 const a = c_f128_struct(.{ .a = 12.34 });
5667 try expect(@as(f64, @floatCast(a.a)) == 56.78);
5668
5669 const b = c_f128_f128_struct(.{ .a = 12.34, .b = 87.65 });
5670 try expect(@as(f64, @floatCast(b.a)) == 56.78);
5671 try expect(@as(f64, @floatCast(b.b)) == 43.21);
5672 }
5673 };
5674 }
56345675}
56355676
56365677// The stdcall attribute on C functions is ignored when compiled on non-x86