w6c: sret-wire the chained-leaf call store (o.a.b = wide())
The chained value-struct walker's N_CALL arm handled only <=24B register returns; an sret-class rhs fell to the scalar tail and stored ONE word (the sret dest pointer) into the leaf -- silent truncation in BOTH stages, byteid-blind. Point the callee's hidden RDI at the BP-relative leaf slot (the single-dot #234 arm verbatim); a ptr-root/global chain joins the #234-tail loud-stop family.
This commit is contained in:
@@ -6768,6 +6768,29 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* #234: over-cap sret STORE into a chained
|
||||||
|
* value-struct leaf — `o.a.b = wide();`
|
||||||
|
* (cg_sret_retsize > 0: a >24B struct OR an
|
||||||
|
* over-cap tuple). Point the callee's hidden
|
||||||
|
* RDI dest at the leaf slot so it writes the
|
||||||
|
* WHOLE value there; pre-#234 this fell to
|
||||||
|
* the scalar tail and stored ONE word (the
|
||||||
|
* sret dest pointer). cg_sret_dest_off is
|
||||||
|
* BP-relative ONLY, so a ptr-root/global
|
||||||
|
* chain needs the runtime RDI-pointer dest
|
||||||
|
* variant deferred to #234-tail and HARD-
|
||||||
|
* STOPS loud (rule 7). */
|
||||||
|
if (n->rhs && n->rhs->kind == N_CALL
|
||||||
|
&& cg_sret_retsize(leaf_type) > 0) {
|
||||||
|
if (via_cx)
|
||||||
|
fatal("#234-tail: over-cap tuple "
|
||||||
|
"sret store to chained "
|
||||||
|
"ptr/global dest unsupported");
|
||||||
|
cg_sret_dest_off = base_disp + total_off;
|
||||||
|
cgexpr(c, n->rhs, locals);
|
||||||
|
cg_sret_dest_off = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* TY_STRUCT terminal in the chained-DOT walker:
|
/* TY_STRUCT terminal in the chained-DOT walker:
|
||||||
* three rhs shapes — mirror of the single-dot
|
* three rhs shapes — mirror of the single-dot
|
||||||
* branch.
|
* branch.
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package wwfixture;
|
package wwfixture;
|
||||||
|
|
||||||
def protocolversion: i32 = 1;
|
def protocolversion: i32 = 1;
|
||||||
def corpuscount: i32 = 1745;
|
def corpuscount: i32 = 1746;
|
||||||
def errorcount: i32 = 346;
|
def errorcount: i32 = 346;
|
||||||
def compilecount: i32 = 21;
|
def compilecount: i32 = 21;
|
||||||
def runcount: i32 = 209;
|
def runcount: i32 = 209;
|
||||||
def runexitcount: i32 = 1169;
|
def runexitcount: i32 = 1170;
|
||||||
def nativecount: i32 = 3490;
|
def nativecount: i32 = 3492;
|
||||||
def corpushash: str = "472974a00552c6b3f5db1fc6b0c1ed128d7554e134880196c833f11f99370f21";
|
def corpushash: str = "6afbab274e0c6d1479a2f0cb6e575b14f5e4ffd25a9cb8a3701307db97d3c489";
|
||||||
|
|
||||||
type directive = enum i32 {
|
type directive = enum i32 {
|
||||||
ERROR = 0,
|
ERROR = 0,
|
||||||
|
|||||||
@@ -12052,6 +12052,31 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
|||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
// #234: over-cap sret STORE into a chained
|
||||||
|
// value-struct leaf — `o.a.b = wide();`
|
||||||
|
// (sretretsize > 0: a >24B struct OR an
|
||||||
|
// over-cap tuple). Point the callee's hidden
|
||||||
|
// RDI dest at the leaf slot so it writes the
|
||||||
|
// WHOLE value there; pre-#234 this fell to
|
||||||
|
// the scalar tail and stored ONE word (the
|
||||||
|
// sret dest pointer). c.sretdestoff is
|
||||||
|
// BP-relative ONLY, so a ptr-root/global
|
||||||
|
// chain needs the runtime RDI-pointer dest
|
||||||
|
// variant deferred to #234-tail and HARD-
|
||||||
|
// STOPS loud (rule 7).
|
||||||
|
if (n.rhs != nil
|
||||||
|
&& n.rhs.kind == syntax.nkind.N_CALL
|
||||||
|
&& sretretsizetn(c, leaftype) > 0) {
|
||||||
|
if (viacx) {
|
||||||
|
let m234: str = "#234-tail: over-cap tuple sret store to chained ptr/global dest unsupported\n";
|
||||||
|
os.write(2, m234.ptr, m234.len: u64);
|
||||||
|
os.exit(1);
|
||||||
|
};
|
||||||
|
c.sretdestoff = rootoff + totaloff;
|
||||||
|
cgexpr(c, n.rhs);
|
||||||
|
c.sretdestoff = 0;
|
||||||
|
return;
|
||||||
|
};
|
||||||
// TY_STRUCT terminal: three rhs shapes:
|
// TY_STRUCT terminal: three rhs shapes:
|
||||||
// - N_IDENT: word-copy from the rhs local slot
|
// - N_IDENT: word-copy from the rhs local slot
|
||||||
// (cgexpr is skipped — no whole-struct register
|
// (cgexpr is skipped — no whole-struct register
|
||||||
|
|||||||
29
test/wcc/data/r234_chain_leaf_sret/case.ww
Normal file
29
test/wcc/data/r234_chain_leaf_sret/case.ww
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//ww:run-exit 0
|
||||||
|
// #234 chained-leaf arm: `o.a.b = f()` with a >24B sret-class return
|
||||||
|
// routes the callee's hidden RDI at the leaf slot. Pre-fix both stages
|
||||||
|
// fell to the scalar tail and stored ONE word (the sret dest pointer).
|
||||||
|
package main;
|
||||||
|
type big = struct { x: i64, y: i64, z: i64, w: i64 };
|
||||||
|
type mid = struct { pad: i64, b: big };
|
||||||
|
type outer = struct { a: mid };
|
||||||
|
|
||||||
|
fn f() big = {
|
||||||
|
let r: big;
|
||||||
|
r.x = 11;
|
||||||
|
r.y = 22;
|
||||||
|
r.z = 33;
|
||||||
|
r.w = 44;
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
export fn main() i32 = {
|
||||||
|
let o: outer;
|
||||||
|
o.a.pad = 7;
|
||||||
|
o.a.b = f();
|
||||||
|
if (o.a.pad != 7) { return 1; };
|
||||||
|
if (o.a.b.x != 11) { return 2; };
|
||||||
|
if (o.a.b.y != 22) { return 3; };
|
||||||
|
if (o.a.b.z != 33) { return 4; };
|
||||||
|
if (o.a.b.w != 44) { return 5; };
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user