| author | |
| committer | |
| log | 08cecc1c7e453042123f8ec6a240a49cbf3b165a |
| tree | 41782f843f057d6727e272f9cf08235a4676b7d3 |
| parent | e9efed9ed117c1b6f5fc138999d82e0dbb1f13bf |
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 |
| 285 | 285 | ||
| 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 argument | 294 | // 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; | ||
| 299 | 298 | ||
| 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 | #endif | 5478 | #endif |
| 5479 | 5479 | ||
| 5480 | #ifndef ZIG_NO_F128 | 5480 | #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 | } |
| 5485 | typedef struct { | 5487 | typedef struct { |
| 5486 | __float128 a; | 5488 | __float128 a; |
| 5487 | } f128_struct; | 5489 | } f128_struct; |
| 5490 | f128_struct zig_f128_struct(f128_struct a); | ||
| 5488 | f128_struct c_f128_struct(f128_struct a) { | 5491 | f128_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 | |||
| 5498 | typedef struct { | ||
| 5499 | __float128 a, b; | ||
| 5500 | } f128_f128_struct; | ||
| 5501 | f128_f128_struct zig_f128_f128_struct(f128_f128_struct a); | ||
| 5502 | f128_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 | #endif | 5510 | #endif |
| 5493 | 5511 | ||
| 5494 | void __attribute__((stdcall)) stdcall_scalars(char a, short b, int c, float d, double e) { | 5512 | void __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 | } |
| 138 | export fn zig_longdouble(x: c_longdouble) void { | 138 | export 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 |
| 140 | expect(x == 12.34) catch @panic("test failure: zig_longdouble"); | 140 | expect(x == 12.34) catch @panic("test failure: zig_longdouble"); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| ... | @@ -1671,7 +1671,7 @@ test "bool simd vector" { | ... | @@ -1671,7 +1671,7 @@ test "bool simd vector" { |
| 1671 | } | 1671 | } |
| 1672 | 1672 | ||
| 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 | } |
| 5616 | 5616 | ||
| 5617 | extern fn c_f128(f128) f128; | 5617 | comptime { |
| 5618 | test "f128 bare" { | 5618 | skip: { |
| 5619 | if (!have_f128) return error.SkipZigTest; | 5619 | if (builtin.target.isWasm()) break :skip; |
| 5620 | 5620 | ||
| 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; | ||
| 5624 | 5629 | ||
| 5625 | const 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 | } |
| 5628 | extern fn c_f128_struct(f128_struct) f128_struct; | ||
| 5629 | test "f128 struct" { | ||
| 5630 | if (!have_f128) return error.SkipZigTest; | ||
| 5631 | 5633 | ||
| 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 | } |
| 5635 | 5676 | ||
| 5636 | // The stdcall attribute on C functions is ignored when compiled on non-x86 | 5677 | // The stdcall attribute on C functions is ignored when compiled on non-x86 |