cgen: materialize and store all eightbytes of an aggregate unwrap success (#12)
A struct/array success variant in an (S|e)! / r? unwrap dropped eightbytes on BOTH stages (byte-id blind). Two layers: (L1) the unwrap success shuffle (cgtrytaggedshift) matched no arm for a struct/array success and fell to a bare MOVQ DX,AX, materializing only w0 — widen the existing nested-TAGGED shift's gate to admit TY_STRUCT/TY_ARRAY (the in-cap union packs the payload as raw GP words past the tag, so that shift is exact); (L2) the aggregate store arms gated on rhs.kind==N_CALL and stored one word for an unwrap rhs — relax to also admit N_TRYUNW/N_TRYPROP at the three silent store shapes (arr[i]=, single-dot field, indexed-field), reusing the materialise scratch path (now #10-correct). Rule-7 LOUD-STOP for a float-bearing success variant (an SSE eightbyte cannot ride the GP {AX,DX,CX} shift, #165). The four already-loud unwrap consumers (let-receive #7, call-arg #271, assign-existing #49, resolver-field #24) stay loud; global/chained single-dot field (#16) and the sub-8-tail-through-unwrap union-maker frame clobber (#15) are separate follow-ups. Value-asserting pin, reddens under each stage's independent revert.
This commit is contained in:
@@ -3013,6 +3013,42 @@ fn aggargfloatstop(n: *syntax.node) bool = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// tinfoaggfloat — does an aggregate tinfo carry ANY float leaf
|
||||
// (recursively through struct fields / array element / tuple
|
||||
// positionals)? The #12 producer (cgtrytaggedshift) loud-stops a
|
||||
// float-bearing aggregate success variant: the union return places a
|
||||
// float eightbyte in the SSE class (X0/X1) which the GP {AX,DX,CX}
|
||||
// payload shuffle cannot reach (mirror #11/#165). Conservative — ANY
|
||||
// float, not a per-eightbyte SSE classify like structfloatclass — a
|
||||
// loud-stop only needs to refuse, not transport. Mirrors cstage
|
||||
// agg_has_float (cmd/w6c/cgen.c).
|
||||
fn tinfoaggfloat(t: *syntax.tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let u: *syntax.tinfo = tichase(t);
|
||||
if (u == nil) { return false; };
|
||||
if (syntax.typeisfloat(u)) { return true; };
|
||||
if (u.kind == syntax.tykind.TY_STRUCT) {
|
||||
let fi: *syntax.tfield = u.fields;
|
||||
for (fi != nil) {
|
||||
if (tinfoaggfloat(fi.type_)) { return true; };
|
||||
fi = fi.tnext;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
if (u.kind == syntax.tykind.TY_ARRAY) {
|
||||
return tinfoaggfloat(u.sub);
|
||||
};
|
||||
if (u.kind == syntax.tykind.TY_TUPLE) {
|
||||
let pe: *syntax.ttupleelem = u.tupleelems;
|
||||
for (pe != nil) {
|
||||
if (tinfoaggfloat(pe.type_)) { return true; };
|
||||
pe = pe.tnext;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// structfloatclass — SysV per-eightbyte classification for the #165
|
||||
// float-bearing-struct param case (param twin of #171's struct return;
|
||||
// classifies per-eightbyte, not #163's per-element). Returns 0 when the
|
||||
|
||||
Reference in New Issue
Block a user