w6c+wwstage: receive over-cap tuple sret returns at the call site (#10 Fold B)
Fold A made the CALLEE emit an over-capacity tuple return (> 4 GP or > 2
SSE eightbytes) via sret, but every receive site stayed loud-stopped, so
such a fn was not yet usefully callable. Fold B wires the call/receive end
by aligning every receive gate UP to the shared cg_sret_retsize() /
callsretsize() > 0 predicate (never a kind), per Rob's (B) ruling:
- single-var-let `let t = f();` cstage gate generalised from
TY_STRUCT&&>24 to cg_sret_retsize(lt)>0; the let's slot IS the
sret dest, the callee writes the whole tuple there, t.0/t.1 read
by offset. wwstage already keyed callsretsize (verified).
- N_ASSIGN-ident `t = f();` same generalisation; global arm
kept TY_STRUCT-only (a tuple-global has no sret-to-symbol path in
either stage). wwstage grows a tuple-local arm (rettupleof gates
it apart from the >24B-struct recv, which keeps its own path).
- destructure `let (a,b) = f();` and `a,b = f();` — the genuinely
new wiring: the callee sret's into the @sretscr discard slot, then
a copy-out loop moves each element to its binding at the SAME
packed offset the SEND wrote (foff += element size), each at its
natural width (#169); a `_` binding skips its store but advances
foff. Both stages, byte-identical.
- return-forward `return f();` cstage forward gate generalised
to the predicate, reusing cg_sret_forward verbatim. wwstage
already keyed sretretsize (verified).
The escape boundary stays loud: arg-pass `g(f())` fatals identically in
both stages (tuple arg exceeds return-cursor ABI capacity).
Test 799 is the runtime net Fold A deferred (byte-id is blind to a
SEND/RECEIVE layout mismatch): the bytes.cut-shaped ([]u8,[]u8) round-trip
over destructure / single-var-let / reassign / return-forward, each both
RUN under cstage and asserted cs==ww byte-identical. Tests 945 (row F)
and 956 (f64x3) flip from asserting the old over-cap loud-stop to
asserting the now-working sret round-trip. combined.ww amalgams (w6c +
wwdump embed the wcc cgen) regenerated. Unblocks #4 bytes.cut/rcut.
This commit is contained in:
@@ -11,8 +11,9 @@
|
||||
* float to @tupfscr as it walks (X0 is clobbered by later elements) and
|
||||
* reloads X0/X1 by SSE index after the integer pops; every receive site
|
||||
* (single-var 16B/32B, destructure, reassign) reads the float from its
|
||||
* SSE-cursor reg. SSE caps at 2 (X0,X1) — (f64,f64,f64) loud-stops at
|
||||
* compile (f64x3_loudstop row asserts the compiler ERRORS, both stages).
|
||||
* SSE-cursor reg. SSE caps at 2 (X0,X1) — (f64,f64,f64) is over-cap, so
|
||||
* it returns via sret (#10 Fold A SEND + Fold B destructure RECEIVE); the
|
||||
* f64x3_recv row asserts that round-trip works in both stages.
|
||||
*
|
||||
* #105 (original): a tuple-from-call receive corrupts the f64 word when
|
||||
* the callee is BRANCHED. Covers ALL THREE receive forms, which share the
|
||||
@@ -355,13 +356,12 @@ static const struct row rows[] = {
|
||||
"\tif (t.0.len != 5) { return 2; };\n"
|
||||
"\treturn 0;\n"
|
||||
"};\n", 0 },
|
||||
/* #164 LOUD-STOP — three f64 = 0 GP / 3 SSE exceeds the SSE return
|
||||
* cap (X0,X1 only). Must FAIL TO COMPILE in BOTH stages (rule-7:
|
||||
* surface, never silently collide). Master has no SSE cap and
|
||||
* miscompiles (build succeeds), so want_compile_fail discriminates:
|
||||
* pre-fix the build succeeds (test fails), post-fix both stages
|
||||
* error (test passes). */
|
||||
{ "f64x3_loudstop",
|
||||
/* #10 OVER-CAP RECV — three f64 = 0 GP / 3 SSE exceeds the SSE return
|
||||
* cap (X0,X1 only). #164 loud-stopped this at the SEND; #10 Fold A
|
||||
* sret's it (callee stores X0/X1 → @sretarg at foff 0/8/16) and Fold B
|
||||
* destructures it (each element MOVSD'd out of @sretscr into its
|
||||
* binding), so it is now a working round-trip in BOTH stages. */
|
||||
{ "f64x3_recv",
|
||||
"package main;\n"
|
||||
"fn tri(a: f64, b: f64, c: f64) (f64, f64, f64) = {\n"
|
||||
"\treturn (a, b, c);\n"
|
||||
@@ -372,7 +372,7 @@ static const struct row rows[] = {
|
||||
"\tif (y != 2.0) { return 2; };\n"
|
||||
"\tif (z != 3.0) { return 3; };\n"
|
||||
"\treturn 0;\n"
|
||||
"};\n", 0, 0, 1 },
|
||||
"};\n", 0, 0, 0 },
|
||||
/* CONTROL — all-integer branched 2-tuple. The integer-cursor MOVQ
|
||||
* path is untouched by the fix (e0/e1 not float), so this is correct
|
||||
* pre- and post-fix and byte-id both ways. a=5, b=7 -> 12. */
|
||||
|
||||
Reference in New Issue
Block a user