authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-26 02:34:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-11-27 05:05:59+01:00
loga1827d597723aff6236001bd0bb74a6b0bab9ce7
tree8ac972914895e88893673c9a2b58af529163dc9c
parent51bb2b3d2d2361eb73ee659a12c32e101b98dd96

x86_64: fix abi of a struct that partially fits in registers

Closes #26035

3 files changed, 78 insertions(+), 54 deletions(-)

src/codegen/x86_64/CodeGen.zig+6
......@@ -181159,6 +181159,9 @@ fn resolveCallingConventionValues(
181159181159 else => unreachable,
181160181160 }
181161181161
181162 const save_param_gpr_index = param_gpr_index;
181163 const save_param_sse_index = param_gpr_index;
181164
181162181165 var arg_mcv: [4]MCValue = undefined;
181163181166 var arg_mcv_len: u32 = 0;
181164181167
......@@ -181258,6 +181261,9 @@ fn resolveCallingConventionValues(
181258181261 continue;
181259181262 }
181260181263
181264 param_gpr_index = save_param_gpr_index;
181265 param_sse_index = save_param_sse_index;
181266
181261181267 const param_align = ty.abiAlignment(zcu).max(.@"8");
181262181268 result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
181263181269 result.stack_align = result.stack_align.max(param_align);
test/c_abi/cfuncs.c+36-27
......@@ -212,55 +212,64 @@ struct Struct_u64_u64 {
212212
213213struct Struct_u64_u64 zig_ret_struct_u64_u64(void);
214214
215void zig_struct_u64_u64_0(struct Struct_u64_u64);
216void zig_struct_u64_u64_1(size_t, struct Struct_u64_u64);
217void zig_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64);
218void zig_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64);
219void zig_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64);
220void zig_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64);
221void zig_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64);
222void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64);
223void zig_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64);
215void zig_struct_u64_u64_0(struct Struct_u64_u64, size_t);
216void zig_struct_u64_u64_1(size_t, struct Struct_u64_u64, size_t);
217void zig_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64, size_t);
218void zig_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64, size_t);
219void zig_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
220void zig_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
221void zig_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
222void zig_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
223void zig_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64, size_t);
224224
225225struct Struct_u64_u64 c_ret_struct_u64_u64(void) {
226226 return (struct Struct_u64_u64){ 21, 22 };
227227}
228228
229void c_struct_u64_u64_0(struct Struct_u64_u64 s) {
229void c_struct_u64_u64_0(struct Struct_u64_u64 s, size_t i) {
230230 assert_or_panic(s.a == 23);
231231 assert_or_panic(s.b == 24);
232 assert_or_panic(i == 1);
232233}
233void c_struct_u64_u64_1(size_t, struct Struct_u64_u64 s) {
234void c_struct_u64_u64_1(size_t a0, struct Struct_u64_u64 s, size_t i) {
234235 assert_or_panic(s.a == 25);
235236 assert_or_panic(s.b == 26);
237 assert_or_panic(i == 2);
236238}
237void c_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64 s) {
239void c_struct_u64_u64_2(size_t, size_t, struct Struct_u64_u64 s, size_t i) {
238240 assert_or_panic(s.a == 27);
239241 assert_or_panic(s.b == 28);
242 assert_or_panic(i == 3);
240243}
241void c_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64 s) {
244void c_struct_u64_u64_3(size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
242245 assert_or_panic(s.a == 29);
243246 assert_or_panic(s.b == 30);
247 assert_or_panic(i == 4);
244248}
245void c_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) {
249void c_struct_u64_u64_4(size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
246250 assert_or_panic(s.a == 31);
247251 assert_or_panic(s.b == 32);
252 assert_or_panic(i == 5);
248253}
249void c_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) {
254void c_struct_u64_u64_5(size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
250255 assert_or_panic(s.a == 33);
251256 assert_or_panic(s.b == 34);
257 assert_or_panic(i == 6);
252258}
253void c_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) {
259void c_struct_u64_u64_6(size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
254260 assert_or_panic(s.a == 35);
255261 assert_or_panic(s.b == 36);
262 assert_or_panic(i == 7);
256263}
257void c_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) {
264void c_struct_u64_u64_7(size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
258265 assert_or_panic(s.a == 37);
259266 assert_or_panic(s.b == 38);
267 assert_or_panic(i == 8);
260268}
261void c_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s) {
269void c_struct_u64_u64_8(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, struct Struct_u64_u64 s, size_t i) {
262270 assert_or_panic(s.a == 39);
263271 assert_or_panic(s.b == 40);
272 assert_or_panic(i == 9);
264273}
265274
266275struct Struct_f32 {
......@@ -2737,15 +2746,15 @@ void run_c_tests(void) {
27372746 struct Struct_u64_u64 s = zig_ret_struct_u64_u64();
27382747 assert_or_panic(s.a == 1);
27392748 assert_or_panic(s.b == 2);
2740 zig_struct_u64_u64_0((struct Struct_u64_u64){ .a = 3, .b = 4 });
2741 zig_struct_u64_u64_1(0, (struct Struct_u64_u64){ .a = 5, .b = 6 });
2742 zig_struct_u64_u64_2(0, 1, (struct Struct_u64_u64){ .a = 7, .b = 8 });
2743 zig_struct_u64_u64_3(0, 1, 2, (struct Struct_u64_u64){ .a = 9, .b = 10 });
2744 zig_struct_u64_u64_4(0, 1, 2, 3, (struct Struct_u64_u64){ .a = 11, .b = 12 });
2745 zig_struct_u64_u64_5(0, 1, 2, 3, 4, (struct Struct_u64_u64){ .a = 13, .b = 14 });
2746 zig_struct_u64_u64_6(0, 1, 2, 3, 4, 5, (struct Struct_u64_u64){ .a = 15, .b = 16 });
2747 zig_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, (struct Struct_u64_u64){ .a = 17, .b = 18 });
2748 zig_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 });
2749 zig_struct_u64_u64_0((struct Struct_u64_u64){ .a = 3, .b = 4 }, 1);
2750 zig_struct_u64_u64_1(0, (struct Struct_u64_u64){ .a = 5, .b = 6 }, 2);
2751 zig_struct_u64_u64_2(0, 1, (struct Struct_u64_u64){ .a = 7, .b = 8 }, 3);
2752 zig_struct_u64_u64_3(0, 1, 2, (struct Struct_u64_u64){ .a = 9, .b = 10 }, 4);
2753 zig_struct_u64_u64_4(0, 1, 2, 3, (struct Struct_u64_u64){ .a = 11, .b = 12 }, 5);
2754 zig_struct_u64_u64_5(0, 1, 2, 3, 4, (struct Struct_u64_u64){ .a = 13, .b = 14 }, 6);
2755 zig_struct_u64_u64_6(0, 1, 2, 3, 4, 5, (struct Struct_u64_u64){ .a = 15, .b = 16 }, 7);
2756 zig_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, (struct Struct_u64_u64){ .a = 17, .b = 18 }, 8);
2757 zig_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 }, 9);
27492758 }
27502759
27512760#if !defined(ZIG_RISCV64)
test/c_abi/main.zig+36-27
......@@ -278,54 +278,63 @@ export fn zig_ret_struct_u64_u64() Struct_u64_u64 {
278278 return .{ .a = 1, .b = 2 };
279279}
280280
281export fn zig_struct_u64_u64_0(s: Struct_u64_u64) void {
281export fn zig_struct_u64_u64_0(s: Struct_u64_u64, i: usize) void {
282282 expect(s.a == 3) catch @panic("test failure");
283283 expect(s.b == 4) catch @panic("test failure");
284 expect(i == 1) catch @panic("test failure");
284285}
285export fn zig_struct_u64_u64_1(_: usize, s: Struct_u64_u64) void {
286export fn zig_struct_u64_u64_1(_: usize, s: Struct_u64_u64, i: usize) void {
286287 expect(s.a == 5) catch @panic("test failure");
287288 expect(s.b == 6) catch @panic("test failure");
289 expect(i == 2) catch @panic("test failure");
288290}
289export fn zig_struct_u64_u64_2(_: usize, _: usize, s: Struct_u64_u64) void {
291export fn zig_struct_u64_u64_2(_: usize, _: usize, s: Struct_u64_u64, i: usize) void {
290292 expect(s.a == 7) catch @panic("test failure");
291293 expect(s.b == 8) catch @panic("test failure");
294 expect(i == 3) catch @panic("test failure");
292295}
293export fn zig_struct_u64_u64_3(_: usize, _: usize, _: usize, s: Struct_u64_u64) void {
296export fn zig_struct_u64_u64_3(_: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
294297 expect(s.a == 9) catch @panic("test failure");
295298 expect(s.b == 10) catch @panic("test failure");
299 expect(i == 4) catch @panic("test failure");
296300}
297export fn zig_struct_u64_u64_4(_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
301export fn zig_struct_u64_u64_4(_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
298302 expect(s.a == 11) catch @panic("test failure");
299303 expect(s.b == 12) catch @panic("test failure");
304 expect(i == 5) catch @panic("test failure");
300305}
301export fn zig_struct_u64_u64_5(_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
306export fn zig_struct_u64_u64_5(_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
302307 expect(s.a == 13) catch @panic("test failure");
303308 expect(s.b == 14) catch @panic("test failure");
309 expect(i == 6) catch @panic("test failure");
304310}
305export fn zig_struct_u64_u64_6(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
311export fn zig_struct_u64_u64_6(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
306312 expect(s.a == 15) catch @panic("test failure");
307313 expect(s.b == 16) catch @panic("test failure");
314 expect(i == 7) catch @panic("test failure");
308315}
309export fn zig_struct_u64_u64_7(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
316export fn zig_struct_u64_u64_7(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
310317 expect(s.a == 17) catch @panic("test failure");
311318 expect(s.b == 18) catch @panic("test failure");
319 expect(i == 8) catch @panic("test failure");
312320}
313export fn zig_struct_u64_u64_8(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
321export fn zig_struct_u64_u64_8(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64, i: usize) void {
314322 expect(s.a == 19) catch @panic("test failure");
315323 expect(s.b == 20) catch @panic("test failure");
324 expect(i == 9) catch @panic("test failure");
316325}
317326
318327extern fn c_ret_struct_u64_u64() Struct_u64_u64;
319328
320extern fn c_struct_u64_u64_0(Struct_u64_u64) void;
321extern fn c_struct_u64_u64_1(usize, Struct_u64_u64) void;
322extern fn c_struct_u64_u64_2(usize, usize, Struct_u64_u64) void;
323extern fn c_struct_u64_u64_3(usize, usize, usize, Struct_u64_u64) void;
324extern fn c_struct_u64_u64_4(usize, usize, usize, usize, Struct_u64_u64) void;
325extern fn c_struct_u64_u64_5(usize, usize, usize, usize, usize, Struct_u64_u64) void;
326extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u64_u64) void;
327extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64) void;
328extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64) void;
329extern fn c_struct_u64_u64_0(Struct_u64_u64, usize) void;
330extern fn c_struct_u64_u64_1(usize, Struct_u64_u64, usize) void;
331extern fn c_struct_u64_u64_2(usize, usize, Struct_u64_u64, usize) void;
332extern fn c_struct_u64_u64_3(usize, usize, usize, Struct_u64_u64, usize) void;
333extern fn c_struct_u64_u64_4(usize, usize, usize, usize, Struct_u64_u64, usize) void;
334extern fn c_struct_u64_u64_5(usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
335extern fn c_struct_u64_u64_6(usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
336extern fn c_struct_u64_u64_7(usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
337extern fn c_struct_u64_u64_8(usize, usize, usize, usize, usize, usize, usize, usize, Struct_u64_u64, usize) void;
329338
330339test "C ABI struct u64 u64" {
331340 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
......@@ -336,15 +345,15 @@ test "C ABI struct u64 u64" {
336345 const s = c_ret_struct_u64_u64();
337346 try expect(s.a == 21);
338347 try expect(s.b == 22);
339 c_struct_u64_u64_0(.{ .a = 23, .b = 24 });
340 c_struct_u64_u64_1(0, .{ .a = 25, .b = 26 });
341 c_struct_u64_u64_2(0, 1, .{ .a = 27, .b = 28 });
342 c_struct_u64_u64_3(0, 1, 2, .{ .a = 29, .b = 30 });
343 c_struct_u64_u64_4(0, 1, 2, 3, .{ .a = 31, .b = 32 });
344 c_struct_u64_u64_5(0, 1, 2, 3, 4, .{ .a = 33, .b = 34 });
345 c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36 });
346 c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38 });
347 c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40 });
348 c_struct_u64_u64_0(.{ .a = 23, .b = 24 }, 1);
349 c_struct_u64_u64_1(0, .{ .a = 25, .b = 26 }, 2);
350 c_struct_u64_u64_2(0, 1, .{ .a = 27, .b = 28 }, 3);
351 c_struct_u64_u64_3(0, 1, 2, .{ .a = 29, .b = 30 }, 4);
352 c_struct_u64_u64_4(0, 1, 2, 3, .{ .a = 31, .b = 32 }, 5);
353 c_struct_u64_u64_5(0, 1, 2, 3, 4, .{ .a = 33, .b = 34 }, 6);
354 c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36 }, 7);
355 c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38 }, 8);
356 c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40 }, 9);
348357}
349358
350359const Struct_f32 = extern struct {