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...@@ -285,17 +285,16 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8
285285
286 // "If one of the classes is MEMORY, the whole argument is passed in memory"286 // "If one of the classes is MEMORY, the whole argument is passed in memory"
287 // "If X87UP is not preceded by X87, the whole argument is passed in memory."287 // "If X87UP is not preceded by X87, the whole argument is passed in memory."
288 var found_sseup = false;288 for (result, 0..) |class, i| switch (class) {
289 for (result, 0..) |item, i| switch (item) {
290 .memory => return memory_class,289 .memory => return memory_class,
291 .x87up => if (i == 0 or result[i - 1] != .x87) return memory_class,290 .x87up => if (i == 0 or result[i - 1] != .x87) return memory_class,
292 .sseup => found_sseup = true,
293 else => continue,291 else => continue,
294 };292 };
295 // "If the size of the aggregate exceeds two eightbytes and the first eight-293 // "If the size of the aggregate exceeds two eightbytes and the first eight-
296 // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument294 // byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole argument
297 // is passed in memory."295 // 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
300 // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."299 // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
301 for (&result, 0..) |*item, i| {300 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) {...@@ -5478,17 +5478,35 @@ f80_extra_struct c_f80_extra_struct(f80_extra_struct a) {
5478#endif5478#endif
54795479
5480#ifndef ZIG_NO_F1285480#ifndef ZIG_NO_F128
5481__float128 zig_f128(__float128 a);
5481__float128 c_f128(__float128 a) {5482__float128 c_f128(__float128 a) {
5482 assert_or_panic((double)a == 12.34);5483 assert_or_panic((double)a == 12.34);
5484 assert_or_panic(zig_f128(12) == 34);
5483 return 56.78;5485 return 56.78;
5484}5486}
5485typedef struct {5487typedef struct {
5486 __float128 a;5488 __float128 a;
5487} f128_struct;5489} f128_struct;
5490f128_struct zig_f128_struct(f128_struct a);
5488f128_struct c_f128_struct(f128_struct a) {5491f128_struct c_f128_struct(f128_struct a) {
5489 assert_or_panic((double)a.a == 12.34);5492 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);
5490 return (f128_struct){56.78};5495 return (f128_struct){56.78};
5491}5496}
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}
5492#endif5510#endif
54935511
5494void __attribute__((stdcall)) stdcall_scalars(char a, short b, int c, float d, double e) {5512void __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 {...@@ -136,7 +136,7 @@ export fn zig_f64(x: f64) void {
136 expect(x == 56.78) catch @panic("test failure: zig_f64");136 expect(x == 56.78) catch @panic("test failure: zig_f64");
137}137}
138export fn zig_longdouble(x: c_longdouble) void {138export fn zig_longdouble(x: c_longdouble) void {
139 if (!builtin.cpu.arch.isWasm()) return; // waiting for #1481139 if (!builtin.target.isWasm()) return; // waiting for #1481
140 expect(x == 12.34) catch @panic("test failure: zig_longdouble");140 expect(x == 12.34) catch @panic("test failure: zig_longdouble");
141}141}
142142
...@@ -1671,7 +1671,7 @@ test "bool simd vector" {...@@ -1671,7 +1671,7 @@ test "bool simd vector" {
1671 }1671 }
16721672
1673 {1673 {
1674 if (builtin.target.cpu.arch != .wasm32) c_vector_256_bool(.{1674 if (!builtin.target.isWasm()) c_vector_256_bool(.{
1675 false,1675 false,
1676 true,1676 true,
1677 true,1677 true,
...@@ -2189,7 +2189,7 @@ test "bool simd vector" {...@@ -2189,7 +2189,7 @@ test "bool simd vector" {
2189 try expect(vec[255] == false);2189 try expect(vec[255] == false);
2190 }2190 }
2191 {2191 {
2192 if (builtin.target.cpu.arch != .wasm32) c_vector_512_bool(.{2192 if (!builtin.target.isWasm()) c_vector_512_bool(.{
2193 true,2193 true,
2194 true,2194 true,
2195 true,2195 true,
...@@ -5614,23 +5614,64 @@ test "f80 extra struct" {...@@ -5614,23 +5614,64 @@ test "f80 extra struct" {
5614 try expect(a.b == 24);5614 try expect(a.b == 24);
5615}5615}
56165616
5617extern fn c_f128(f128) f128;5617comptime {
5618test "f128 bare" {5618 skip: {
5619 if (!have_f128) return error.SkipZigTest;5619 if (builtin.target.isWasm()) break :skip;
56205620
5621 const a = c_f128(12.34);5621 _ = struct {
5622 try expect(@as(f64, @floatCast(a)) == 56.78);5622 export fn zig_f128(x: f128) f128 {
5623}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 {5630 const a = c_f128(12.34);
5626 a: f128,5631 try expect(@as(f64, @floatCast(a)) == 56.78);
5627};5632 }
5628extern fn c_f128_struct(f128_struct) f128_struct;
5629test "f128 struct" {
5630 if (!have_f128) return error.SkipZigTest;
56315633
5632 const a = c_f128_struct(.{ .a = 12.34 });5634 const f128_struct = extern struct {
5633 try expect(@as(f64, @floatCast(a.a)) == 56.78);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 }
5634}5675}
56355676
5636// The stdcall attribute on C functions is ignored when compiled on non-x865677// The stdcall attribute on C functions is ignored when compiled on non-x86