diff --git a/selfhost/cmd/wcc/cgenstmt.ww b/selfhost/cmd/wcc/cgenstmt.ww index 6cac2f74..34b01c40 100644 --- a/selfhost/cmd/wcc/cgenstmt.ww +++ b/selfhost/cmd/wcc/cgenstmt.ww @@ -864,6 +864,26 @@ fn cglet(c: *cgen, n: *node) void = { }; }; }; + // 16B tuple init from a function call: SysV returns a + // 16-byte aggregate across the integer cursor (AX, DX). Spill + // BOTH eightbytes over the integer registers — an f64 element + // also rides its eightbyte in AX/DX here and is re-read from + // X0/XMM at field-read time, so no SSE cursor is needed (the + // f64 read is already byte-id). Mirror of cstage cgen.c:6652. + // Without this branch a 16B tuple receive (any element mix, + // incl. all-integer) fell to the generic single-word store + // below and dropped word1 — silent loss of t.1 (#102). + if (rettupleof(c, rhs) != nil && sz == 16) { + cgexpr(c, rhs); + emitline("\tMOVQ\tAX, "); + emitoff(off: i64); + emitline("(BP)\n"); + emitline("\tMOVQ\tDX, "); + emitoff((off + 8): i64); + emitline("(BP)\n"); + c.lastwasreturn = 0; + return; + }; // Array literal init: `let xs: [N]T = [a, b, c];` (or [_]T). // Walk elements in declaration order, store each at off + i*esz // using the right width for the element type. Trailing `...`