cgen: loop/yield/defer fixed-max buffers raw-ptr → []T (#9)
Phase 0 #9. cgen struct fields loopendbuf/loopcontbuf/yieldbuf/ deferbuf change from `*str`/`**node` over-allocated arena chunks to `[]str`/`[]*node` slices. The 4 alloc sites in cgeninit drop the byte-count form (`LOOP_MAX*24u64`, `DEFER_MAX*8u64`) for element-count (`LOOP_MAX: u64`, `DEFER_MAX: u64`). 10 caller sites in cgenstmt.ww/cgenexpr.ww use `[i]` indexing which works identically for slice-shaped struct fields. Two-line let-then-assign idiom for the 4 inits is a real checker limitation: alloc's element-deferred `[]u8` → `[]T` retype only fires in let-init (checkletassign N_TSLICE LHS), and cglet's alloc-slice writeback shortcut (cgenstmt.ww:577) only fires in let-init too. Direct `c.field = alloc([], N)!` would silently emit a scalar alloc with a junk slice header. Filed #49 for the checker enhancement; the let-then-assign is Hare-idiomatic in the meantime. Verified 132/132 + 995_self_rebuild byte-identity.
This commit is contained in:
@@ -21544,12 +21544,12 @@ type cgen = struct {
|
|||||||
// before walking the body.
|
// before walking the body.
|
||||||
fnret: *node, // declared return type of current fn (or nil)
|
fnret: *node, // declared return type of current fn (or nil)
|
||||||
looptop: i32,
|
looptop: i32,
|
||||||
loopendbuf: *str, // stack of end labels for break
|
loopendbuf: []str, // stack of end labels for break
|
||||||
loopcontbuf: *str, // stack of cont labels for continue
|
loopcontbuf: []str, // stack of cont labels for continue
|
||||||
yieldtop: i32,
|
yieldtop: i32,
|
||||||
yieldbuf: *str, // stack of match end labels for yield
|
yieldbuf: []str, // stack of match end labels for yield
|
||||||
defertop: i32,
|
defertop: i32,
|
||||||
deferbuf: **node, // stack of deferred exprs (LIFO at return)
|
deferbuf: []*node, // stack of deferred exprs (LIFO at return)
|
||||||
// Variadic-call gather state. cgcall bumps this on each gather
|
// Variadic-call gather state. cgcall bumps this on each gather
|
||||||
// emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per
|
// emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per
|
||||||
// callsite; mirrors cstage's mklabel("vararg_d/sl") freshness
|
// callsite; mirrors cstage's mklabel("vararg_d/sl") freshness
|
||||||
@@ -21609,16 +21609,16 @@ fn cgeninit(c: *cgen, a: *arena) void = {
|
|||||||
// persist across cgfn calls within one file. cgfile resets them
|
// persist across cgfn calls within one file. cgfile resets them
|
||||||
// at the start of each compilation unit.
|
// at the start of each compilation unit.
|
||||||
c.looptop = 0;
|
c.looptop = 0;
|
||||||
// #35: per-slot stride is sizeof(str); the bare 16 is the str=16
|
let loopendbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
// width and undershoots under str=24, so indices past (LOOP_MAX*16)/24
|
c.loopendbuf = loopendbuf;
|
||||||
// = 10 would spill into the next amalloc. Bumped to 24/slot; +8/slot
|
let loopcontbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
// over-alloc under str=16 is harmless under the bump arena.
|
c.loopcontbuf = loopcontbuf;
|
||||||
c.loopendbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
|
||||||
c.loopcontbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
|
||||||
c.yieldtop = 0;
|
c.yieldtop = 0;
|
||||||
c.yieldbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
let yieldbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
|
c.yieldbuf = yieldbuf;
|
||||||
c.defertop = 0;
|
c.defertop = 0;
|
||||||
c.deferbuf = amalloc(a, (DEFER_MAX: u64) * 8u64): **node;
|
let deferbuf: []*node = alloc([], DEFER_MAX: u64)!;
|
||||||
|
c.deferbuf = deferbuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
// localalloc — append a slot for `name` without dedup. Used for
|
// localalloc — append a slot for `name` without dedup. Used for
|
||||||
|
|||||||
@@ -469,12 +469,12 @@ type cgen = struct {
|
|||||||
// before walking the body.
|
// before walking the body.
|
||||||
fnret: *node, // declared return type of current fn (or nil)
|
fnret: *node, // declared return type of current fn (or nil)
|
||||||
looptop: i32,
|
looptop: i32,
|
||||||
loopendbuf: *str, // stack of end labels for break
|
loopendbuf: []str, // stack of end labels for break
|
||||||
loopcontbuf: *str, // stack of cont labels for continue
|
loopcontbuf: []str, // stack of cont labels for continue
|
||||||
yieldtop: i32,
|
yieldtop: i32,
|
||||||
yieldbuf: *str, // stack of match end labels for yield
|
yieldbuf: []str, // stack of match end labels for yield
|
||||||
defertop: i32,
|
defertop: i32,
|
||||||
deferbuf: **node, // stack of deferred exprs (LIFO at return)
|
deferbuf: []*node, // stack of deferred exprs (LIFO at return)
|
||||||
// Variadic-call gather state. cgcall bumps this on each gather
|
// Variadic-call gather state. cgcall bumps this on each gather
|
||||||
// emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per
|
// emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per
|
||||||
// callsite; mirrors cstage's mklabel("vararg_d/sl") freshness
|
// callsite; mirrors cstage's mklabel("vararg_d/sl") freshness
|
||||||
@@ -534,16 +534,16 @@ fn cgeninit(c: *cgen, a: *arena) void = {
|
|||||||
// persist across cgfn calls within one file. cgfile resets them
|
// persist across cgfn calls within one file. cgfile resets them
|
||||||
// at the start of each compilation unit.
|
// at the start of each compilation unit.
|
||||||
c.looptop = 0;
|
c.looptop = 0;
|
||||||
// #35: per-slot stride is sizeof(str); the bare 16 is the str=16
|
let loopendbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
// width and undershoots under str=24, so indices past (LOOP_MAX*16)/24
|
c.loopendbuf = loopendbuf;
|
||||||
// = 10 would spill into the next amalloc. Bumped to 24/slot; +8/slot
|
let loopcontbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
// over-alloc under str=16 is harmless under the bump arena.
|
c.loopcontbuf = loopcontbuf;
|
||||||
c.loopendbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
|
||||||
c.loopcontbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
|
||||||
c.yieldtop = 0;
|
c.yieldtop = 0;
|
||||||
c.yieldbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
let yieldbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
|
c.yieldbuf = yieldbuf;
|
||||||
c.defertop = 0;
|
c.defertop = 0;
|
||||||
c.deferbuf = amalloc(a, (DEFER_MAX: u64) * 8u64): **node;
|
let deferbuf: []*node = alloc([], DEFER_MAX: u64)!;
|
||||||
|
c.deferbuf = deferbuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
// localalloc — append a slot for `name` without dedup. Used for
|
// localalloc — append a slot for `name` without dedup. Used for
|
||||||
|
|||||||
@@ -21544,12 +21544,12 @@ type cgen = struct {
|
|||||||
// before walking the body.
|
// before walking the body.
|
||||||
fnret: *node, // declared return type of current fn (or nil)
|
fnret: *node, // declared return type of current fn (or nil)
|
||||||
looptop: i32,
|
looptop: i32,
|
||||||
loopendbuf: *str, // stack of end labels for break
|
loopendbuf: []str, // stack of end labels for break
|
||||||
loopcontbuf: *str, // stack of cont labels for continue
|
loopcontbuf: []str, // stack of cont labels for continue
|
||||||
yieldtop: i32,
|
yieldtop: i32,
|
||||||
yieldbuf: *str, // stack of match end labels for yield
|
yieldbuf: []str, // stack of match end labels for yield
|
||||||
defertop: i32,
|
defertop: i32,
|
||||||
deferbuf: **node, // stack of deferred exprs (LIFO at return)
|
deferbuf: []*node, // stack of deferred exprs (LIFO at return)
|
||||||
// Variadic-call gather state. cgcall bumps this on each gather
|
// Variadic-call gather state. cgcall bumps this on each gather
|
||||||
// emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per
|
// emit and uses it to mint `@vararg_d_N` / `@vararg_sl_N` per
|
||||||
// callsite; mirrors cstage's mklabel("vararg_d/sl") freshness
|
// callsite; mirrors cstage's mklabel("vararg_d/sl") freshness
|
||||||
@@ -21609,16 +21609,16 @@ fn cgeninit(c: *cgen, a: *arena) void = {
|
|||||||
// persist across cgfn calls within one file. cgfile resets them
|
// persist across cgfn calls within one file. cgfile resets them
|
||||||
// at the start of each compilation unit.
|
// at the start of each compilation unit.
|
||||||
c.looptop = 0;
|
c.looptop = 0;
|
||||||
// #35: per-slot stride is sizeof(str); the bare 16 is the str=16
|
let loopendbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
// width and undershoots under str=24, so indices past (LOOP_MAX*16)/24
|
c.loopendbuf = loopendbuf;
|
||||||
// = 10 would spill into the next amalloc. Bumped to 24/slot; +8/slot
|
let loopcontbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
// over-alloc under str=16 is harmless under the bump arena.
|
c.loopcontbuf = loopcontbuf;
|
||||||
c.loopendbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
|
||||||
c.loopcontbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
|
||||||
c.yieldtop = 0;
|
c.yieldtop = 0;
|
||||||
c.yieldbuf = amalloc(a, (LOOP_MAX: u64) * 24u64): *str;
|
let yieldbuf: []str = alloc([], LOOP_MAX: u64)!;
|
||||||
|
c.yieldbuf = yieldbuf;
|
||||||
c.defertop = 0;
|
c.defertop = 0;
|
||||||
c.deferbuf = amalloc(a, (DEFER_MAX: u64) * 8u64): **node;
|
let deferbuf: []*node = alloc([], DEFER_MAX: u64)!;
|
||||||
|
c.deferbuf = deferbuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
// localalloc — append a slot for `name` without dedup. Used for
|
// localalloc — append a slot for `name` without dedup. Used for
|
||||||
|
|||||||
Reference in New Issue
Block a user