w6c+w6c_ww: size-keyed @tagscr — one tagged scratch per slot size (fix #44)

A fn mixing two tagged slot sizes smaller-first (regex compile(): 56B
append-element widen then 64B sret return) hit the #15/#26c rule-7
grow-fatal — the single shared per-fn @tagscr is first-use-sized and
its pinned offset can't grow. Key the scratch by slot size instead:
@tagscr<sz>, one first-use-allocated slot per distinct size, all three
sites (widen-store via_outer, widen-push, N_INDEX tagged-element
assign) funnelled through cg_tagscr_slot / tagscradd in both stages.
Single-size fns emit byte-identical asm to pre-fix (control row pinned
+ hand-cmp'd vs master w6c). 736's tagscr_size_grow_fatal fixture
pinned the now-unreachable fatal; converted to a byte-id succ row.
Runtime rows live in 926_tagscr_sizes_run.
This commit is contained in:
2026-06-04 04:34:54 +09:00
parent 8999b59ab0
commit c2308a11c7
9 changed files with 483 additions and 176 deletions

View File

@@ -647,6 +647,39 @@ fn localadd(c: *cgen, name: str, sz: i32, tnode: *node) i32 = {
return localalloc(c, name, sz, tnode);
};
// tagscradd — the ONLY alloc path for the per-fn tagged scratch (#44).
// "@tagscr<sz>" keys localadd's @-prefix name-dedup by slot size, so a
// fn mixing two tagged slot sizes smaller-first (regex compile(): 56B
// append-element widen then 64B sret return) no longer trips the
// #15/#26c grow-fatal — each distinct size pins its own first-use
// slot, in source order in BOTH stages (byte-id). Mirrors cstage
// cg_tagscr_slot (cmd/w6c/cgen.c).
fn tagscradd(c: *cgen, sz: i32) i32 = {
let buf: [32]u8;
let pre: str = "@tagscr";
let i: i32 = 0;
for (i < pre.len) {
buf[i] = pre[i];
i += 1;
};
let ns: str = strconv.i64tos(sz: i64, strconv.base.DEC);
let n: i32 = ns.len;
let k: i32 = 0;
for (k < n) { buf[i + k] = ns.ptr[k]; k += 1; };
let total: i32 = i + n;
let p: []u8 = alloc([], (total: u64) + 1u64)!;
let j: i32 = 0;
for (j < total) {
p[j] = buf[j];
j += 1;
};
p[total] = 0u8;
let name: str;
name.ptr = p.ptr;
name.len = total;
return localadd(c, name, sz, nil);
};
fn localfindnode(c: *cgen, name: str) *local = {
let l: *local = c.locals;
for (l != nil) {