wcc: str -> 24B {ptr,len,cap}, 3-reg ABI -- parity with []u8 (both stages)
A ww `str` becomes a 24-byte {ptr,len,cap} value, identical in layout to
[]u8 -- the enabling prerequisite for the Phase 2 `str == []u8` collapse.
Both stages, atomically:
- ty_str 16->24B; str value flows 3-reg AX/BX/CX (was 2-reg); str literals
emit cap (=len).
- str in a tagged union grows to a 32B slot, using the AX/DX/CX/R8 4th-word
path already used by 32B slice-variant unions -- str-variant is now
structurally identical.
- tuple (scalar,str) return: 4-reg AX/DX/CX/R8 + 32B receive, extending the
existing type-keyed return (no sret).
- str == []u8 for index and .ptr/.len/.cap, kind-gated where size-based
dispatch collided at 24B; cstage and wwstage mirror exactly.
- table-driven runtime coverage: test/wcc/928_str_abi_run.c.
Cannot be split (rule 10/11): a 24B str and a 16B str cannot coexist across
the two compiler stages without breaking byte-identity, so the size change
and every dependent ABI/codegen site land in one atomic commit, both stages.
Known follow-ups (zero corpus impact, tracked): str-literal global .cap
static-init; >16B struct by-value (pre-existing); tagged-union
match-scrutinee stage divergence (pre-existing).
This commit is contained in:
@@ -222,11 +222,11 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
stkcursor += 3;
|
||||
};};
|
||||
} else { if (isstrtype(c, p.lhs)) {
|
||||
if (idx + 2 <= 6) {
|
||||
// #60: route str-param slot width through the
|
||||
// primtypesize SSoT so #1's ty_str bump propagates
|
||||
// here (parent #43 covered the reg-fill site only
|
||||
// inside cgexpr).
|
||||
if (idx + 3 <= 6) {
|
||||
// str IS []u8: 3-word param (ptr,len,cap), same as
|
||||
// the slice arm above (#1/Phase 3). #60: route slot
|
||||
// width through the primtypesize SSoT so #1's ty_str
|
||||
// bump propagates here.
|
||||
let off: i32 = localadd(c, nm, primtypesize("str"): i32, p.lhs);
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
@@ -240,11 +240,14 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
emitoff((off + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
emitline(", ");
|
||||
emitoff((off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
} else { if (idx < 6) {
|
||||
// Partial-fit stitch — mirrors tagged at lines
|
||||
// 440-469. Only idx=5 hits this (nw=2,
|
||||
// regs_left=1): ptr lands in R9, len at
|
||||
// +16+stkcursor*8(BP).
|
||||
// Partial-fit stitch — mirrors the slice arm above.
|
||||
// #60: same SSoT routing as the regs-fit arm above.
|
||||
let off: i32 = localadd(c, nm, primtypesize("str"): i32, p.lhs);
|
||||
let regs_left: i32 = 6 - idx;
|
||||
@@ -258,7 +261,7 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
idx += 1;
|
||||
w += 1;
|
||||
};
|
||||
for (w < 2) {
|
||||
for (w < 3) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((16 + stkcursor*8): i64);
|
||||
emitline("(BP), AX\n");
|
||||
@@ -270,7 +273,7 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
};
|
||||
} else {
|
||||
localaddstack(c, nm, p.lhs, 16 + stkcursor*8);
|
||||
stkcursor += 2;
|
||||
stkcursor += 3;
|
||||
};};
|
||||
} else { let stsz: i32 = structparamsize(c, p.lhs);
|
||||
if (stsz > 0) {
|
||||
|
||||
Reference in New Issue
Block a user