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:
@@ -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) {
|
||||
|
||||
@@ -5679,13 +5679,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// scratch slot via cgwidentaggedstore (handles struct /
|
||||
// str / scalar / subset / nullable variants uniformly),
|
||||
// then compute &arr[i] and byte-copy. The scratch
|
||||
// (@tagscr) is reused across all tagged-arr stores in
|
||||
// the function; first-use sizes the slot (#15/#26c).
|
||||
// (@tagscr<sz>) is reused across all same-size tagged-arr
|
||||
// stores in the function; first-use sizes the slot
|
||||
// (#15/#26c, size-keyed by #44).
|
||||
if (elemtn != nil) {
|
||||
if (istaggedtype(c, elemtn)) {
|
||||
let slot_sz: i32 = slotsize(c, elemtn);
|
||||
let scroff: i32 = localadd(c, "@tagscr",
|
||||
slot_sz, nil);
|
||||
let scroff: i32 = tagscradd(c, slot_sz);
|
||||
// Pre-zero scratch (matches push helper).
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let zz: i32 = 0;
|
||||
|
||||
@@ -206,7 +206,7 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node) i32 = {
|
||||
let pname: str = rhsstructpayload(c, arg);
|
||||
if (pname.len > 0) {
|
||||
let ptype: *node = param.lhs;
|
||||
let scroff: i32 = localadd(c, "@tagscr", widensz, nil);
|
||||
let scroff: i32 = tagscradd(c, widensz);
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let zz: i32 = 0;
|
||||
for (zz < widensz) {
|
||||
@@ -2831,11 +2831,10 @@ fn cgwidentaggedstore(c: *cgen, dst: *tinfo, src: *node,
|
||||
emitline(", ");
|
||||
emitoff(bspill: i64);
|
||||
emitline("(BP)\n");
|
||||
// Shared scratch sized at first use per #15/#26c. A sibling
|
||||
// site (cgreturn, pushargsrev, cgindex) hitting @tagscr later
|
||||
// with a larger size fatals (rule 7) — pinned offset can't
|
||||
// grow in place.
|
||||
let scr: i32 = localadd(c, "@tagscr", slot_sz, nil);
|
||||
// Shared per-size scratch sized at first use (#15/#26c, size-keyed
|
||||
// by #44): sibling sites (cgreturn, pushargsrev, cgindex) hitting
|
||||
// the same slot size reuse the slot; a different size pins its own.
|
||||
let scr: i32 = tagscradd(c, slot_sz);
|
||||
emitline("\tXORQ\tAX, AX\n");
|
||||
let z: i32 = 0;
|
||||
for (z < slot_sz) {
|
||||
|
||||
Reference in New Issue
Block a user