ww: cgen trap batch (def-str field, chained-ptr write, scalar+str tuple ABI)

This commit is contained in:
2026-05-11 20:49:21 +09:00
parent 2ac15e4e99
commit c5f30f2fce
14 changed files with 1629 additions and 67 deletions

View File

@@ -39,6 +39,54 @@ fn scanlocals(c: *cgen, n: *node) i32 = {
total += sz;
};
};
// Multi-let from a tuple-returning call: each binding's size
// comes from its annotated type (l.lhs) when present, else from
// the rhs call's return-tuple element type. Marking via
// scanseenmark also dedupes the recursive descent into n.list
// so each child isn't counted again at the default 8B.
if (n.kind == N_MLET) {
let p0t: *node = nil;
let p1t: *node = nil;
if (n.rhs != nil) {
if (n.rhs.kind == N_CALL) {
let callee: *node = n.rhs.lhs;
if (callee != nil) {
let cnm: str;
cnm.ptr = nil; cnm.len = 0;
if (callee.kind == N_IDENT) { cnm = callee.str; };
if (callee.kind == N_DOT) { cnm = callee.str; };
if (cnm.len > 0) {
let rt: *node = fnretlookup(c, cnm);
if (rt != nil) {
if (rt.kind == N_TTUPLE) {
p0t = rt.list;
if (p0t != nil) { p1t = p0t.next; };
};
};
};
};
};
};
let l: *node = n.list;
let pt: *node = p0t;
let bidx: i32 = 0;
for (l != nil) {
if (!scanseenmark(c, l.str)) {
let t: *node = l.lhs;
if (t == nil) {
if (bidx == 0) { t = p0t; };
if (bidx == 1) { t = p1t; };
};
let sz: i32 = 8;
if (t != nil) { sz = slotsize(c, t); };
if (sz < 8) { sz = 8; };
if ((sz & 7) != 0) { sz = (sz + 7) & ~7; };
total += sz;
};
l = l.next;
bidx += 1;
};
};
// Match-arm binding (`case let v: T => ...`) gets a slot too.
// Crucially we do NOT dedup these against c.locals: C cgen
// handles a match as an expression with a by-value locals copy,