ww: cgen trap batch (def-str field, chained-ptr write, scalar+str tuple ABI)
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user