w6c+wwstage: array return-by-value via the struct-return ABI (#267 fold-2)
Wire TY_ARRAY into the existing struct-return gates so arrays ride the same reg-class (<=24B in AX:DX:CX) / sret-class (>24B) path the struct return ABI already emits byte-identically. No new ABI machinery. Both stages, uniform gate-widen: - cg_sret_retsize / sretretsize: +TY_ARRAY (natural size sub.size*len, the type table) -> auto-enables sret send/recv + the >24B sret N_IDENT word-copy + return-forward, all keyed on the shared sret SSoT. - cgreturn <=24B reg-send: +TY_ARRAY (N_IDENT scratch word-copy -> AX/DX/CX). reg-class return-forward rides the default cgexpr passthrough. - let-init / assign <=24B recv: +TY_ARRAY (AX/DX/CX sized stores). struct_float_class stays struct-only: pure-int element arrays only; no pure-float-array-return consumer exists today. 949 +11 rows: reg-class 8/16/24B + sret-class 32B, [N]u32 and [N]u8, at let-init/assign/return-forward, full-member readback, + a struct- return regression control. All cstage-run + cs==ww byte-id.
This commit is contained in:
@@ -311,6 +311,11 @@ cg_sret_retsize(Type *rt)
|
||||
if (rt == NULL) return 0;
|
||||
if (rt->kind == TY_STRUCT)
|
||||
return (int)rt->size <= 24 ? 0 : (int)rt->size;
|
||||
/* #267: arrays ride the struct-return ABI — same ≤24 reg / >24 sret
|
||||
* split. Pure-int element arrays only; no float-array-return
|
||||
* consumer exists, so struct_float_class stays struct-only. */
|
||||
if (rt->kind == TY_ARRAY)
|
||||
return (int)rt->size <= 24 ? 0 : (int)rt->size;
|
||||
if (rt->kind == TY_TUPLE) {
|
||||
int gptotal = 0, ssecount = 0, f32;
|
||||
for (Tparam *p = rt->params; p; p = p->next) {
|
||||
@@ -5453,7 +5458,7 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
* the receive side of #4's cgreturn (calls + literals).
|
||||
* Sizes >24B and non-{0,1,2,4}-byte tails fall through
|
||||
* to the existing scalar path. */
|
||||
if (lu && lu->kind == TY_STRUCT
|
||||
if (lu && (lu->kind == TY_STRUCT || lu->kind == TY_ARRAY)
|
||||
&& (int)lu->size <= 24) {
|
||||
int off = localfind(locals, n->lhs->str);
|
||||
if (off != 0) {
|
||||
@@ -8620,7 +8625,8 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
}
|
||||
}
|
||||
if (n->rhs && n->rhs->kind == N_CALL && lu
|
||||
&& lu->kind == TY_STRUCT && sz <= 24
|
||||
&& (lu->kind == TY_STRUCT || lu->kind == TY_ARRAY)
|
||||
&& sz <= 24
|
||||
&& (sz % 8 == 0 || sz % 8 == 1
|
||||
|| sz % 8 == 2 || sz % 8 == 4)) {
|
||||
cgexpr(c, n->rhs, *locals);
|
||||
@@ -9171,7 +9177,7 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
ins0(c, A_RET);
|
||||
break;
|
||||
}
|
||||
if (rt && rt->kind == TY_STRUCT
|
||||
if (rt && (rt->kind == TY_STRUCT || rt->kind == TY_ARRAY)
|
||||
&& (int)rt->size > 24
|
||||
&& (n->lhs->kind == N_IDENT
|
||||
|| n->lhs->kind == N_STRUCTLIT)) {
|
||||
@@ -9182,9 +9188,12 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
* narrow field (e.g. bool@32 in a 33B struct
|
||||
* padded to 40B) widened to an 8B MOVQ at the
|
||||
* loop tail — diverged from wwstage's MOVB
|
||||
* tail. Task #33, Class A. */
|
||||
* tail. Task #33, Class A. An array (#267) has no
|
||||
* fields; its natural size IS rt->size. */
|
||||
int sz = 0;
|
||||
for (Tfield *fl = rt->fields; fl; fl = fl->next) {
|
||||
if (rt->kind == TY_ARRAY) {
|
||||
sz = (int)rt->size;
|
||||
} else for (Tfield *fl = rt->fields; fl; fl = fl->next) {
|
||||
int end = (int)fl->offset + (int)(fl->type
|
||||
? fl->type->size : 8);
|
||||
if (end > sz) sz = end;
|
||||
@@ -9260,7 +9269,8 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
* for the same rationale. The ≤24B register-return
|
||||
* ABI uses the same TY_STRUCT gate. */
|
||||
Type *rt = type_chase_named(cg_ret_type);
|
||||
if (rt && rt->kind == TY_STRUCT && rt->size <= 24
|
||||
if (rt && (rt->kind == TY_STRUCT || rt->kind == TY_ARRAY)
|
||||
&& rt->size <= 24
|
||||
&& (n->lhs->kind == N_IDENT
|
||||
|| n->lhs->kind == N_STRUCTLIT)) {
|
||||
int sz = (int)rt->size;
|
||||
|
||||
Reference in New Issue
Block a user