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:
@@ -85,11 +85,14 @@ static const struct row rows[] = {
|
||||
"export fn main() i32 = { return 0; };\n",
|
||||
"\tMOVZBQ\t(AX), AX\n",
|
||||
"" },
|
||||
/* Write: `obj.arr[i] = v` where arr: [N](i64|str) — 24B tagged.
|
||||
/* Write: `obj.arr[i] = v` where arr: [N](i64|str) — tagged element.
|
||||
* Post-fix wwstage: cgassign N_DOT arm sets elemtn → tagged-store
|
||||
* path → IMULQ $24 + byte-copy from scratch. Scanlocals N_DOT arm
|
||||
* pre-reserves @tagscr in the frame. Pre-fix: scalar `MOVQ AX,
|
||||
* (BX)` over the 24B slot. */
|
||||
* path → IMULQ (stride) + byte-copy from scratch. Scanlocals N_DOT
|
||||
* arm pre-reserves @tagscr in the frame. Pre-fix: scalar `MOVQ AX,
|
||||
* (BX)` over the slot.
|
||||
* #1/Phase 3: str IS []u8 (24B), so the (i64|str) slot is
|
||||
* 8(tag)+24(str payload)=32B — stride is $32, not the 16B-world
|
||||
* $24. Byte-identical across stages. */
|
||||
{ "dotbase_array_tagged_write",
|
||||
"type T = (i64 | str);\n"
|
||||
"type S = struct{ pad: i64, arr: [4]T };\n"
|
||||
@@ -98,7 +101,7 @@ static const struct row rows[] = {
|
||||
" s.arr[i] = 42i64;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = { return 0; };\n",
|
||||
"\tMOVQ\t$24, CX\n",
|
||||
"\tMOVQ\t$32, CX\n",
|
||||
"" },
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user