ascii: graduate digitval to (i32 | void); selfhost tagged ABI follow-on
ascii.digitval returns (i32 | void) instead of an i32 -1 sentinel.
Two callers updated to match-on the result (lib/ww/lex/lex.ww escape
parse, selfhost/test/smoke.ww probe 6).
`!` would have been more idiomatic at both call sites — both have
verified isxdigit beforehand — but the selfhost parser doesn't yet
recognize postfix `!`/`?`, so using them in bootstrap-bound code
breaks the 993/995 byte-identity gates. Match is fine for now.
Selfhost cgen follow-on for the 8-byte-rounded tagged-union ABI
(landed in 1e2f55a for the C side):
- cgenutil.slotsize: tagged size = 8 (tag) + max(payload), padded to
8-byte multiple. Was hardcoded 24.
- cgendecl prologue: spill size/8 arg registers, not always 3.
- cgenstmt cglet tagged-call path: spill the CX value-word only when
the slot is >16 bytes.
All three were emitting 3-register patterns appropriate to (T | str)
sized unions and overflowing the new 16-byte (i32 | void) slots.
This commit is contained in:
@@ -128,27 +128,21 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
if (p.kind == N_PARAM) {
|
||||
let nm: str = p.str;
|
||||
if (istaggedtype(p.lhs)) {
|
||||
// tagged-union param: passed in 3 regs (tag, v0, v1),
|
||||
// 24-byte slot.
|
||||
let off: i32 = localadd(c, nm, 24, p.lhs);
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
emitline(", ");
|
||||
emitoff(off: i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
emitline(", ");
|
||||
emitoff((off + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
emitline(", ");
|
||||
emitoff((off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
// tagged-union param: spill size/8 registers
|
||||
// (tag + value words). Slot sized to match.
|
||||
let slot: i32 = slotsize(c, p.lhs);
|
||||
let off: i32 = localadd(c, nm, slot, p.lhs);
|
||||
let nw: i32 = slot / 8;
|
||||
let w: i32 = 0;
|
||||
for (w < nw) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(argregname(idx));
|
||||
emitline(", ");
|
||||
emitoff((off + w*8): i64);
|
||||
emitline("(BP)\n");
|
||||
idx += 1;
|
||||
w += 1;
|
||||
};
|
||||
} else { if (isslicetype(c, p.lhs)) {
|
||||
// slice param: 3 regs (ptr, len, cap), 24-byte slot.
|
||||
let off: i32 = localadd(c, nm, 24, p.lhs);
|
||||
|
||||
@@ -184,15 +184,19 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
};
|
||||
cgexpr(c, rhs);
|
||||
if (rhsreturnstagged) {
|
||||
// Spill size/8 registers (tag + value words).
|
||||
// Slots smaller than 24 don't carry a CX word.
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(off: i64);
|
||||
emitline("(BP)\n");
|
||||
emitline("\tMOVQ\tDX, ");
|
||||
emitoff((off + 8): i64);
|
||||
emitline("(BP)\n");
|
||||
emitline("\tMOVQ\tCX, ");
|
||||
emitoff((off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
if (sz > 16) {
|
||||
emitline("\tMOVQ\tCX, ");
|
||||
emitoff((off + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
c.lastwasreturn = 0;
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -702,7 +702,21 @@ fn slotsize(c: *cgen, typn: *node) i32 = {
|
||||
};
|
||||
return total;
|
||||
};
|
||||
if (k == N_TTAGGED){ return 24; };
|
||||
if (k == N_TTAGGED){
|
||||
// Slot = 8 (tag) + max(variant payload sizes), rounded up
|
||||
// to an 8-byte multiple so the reg-passing ABI (size/8
|
||||
// words) doesn't drop the last value register. Mirrors C
|
||||
// cgen's resolve_type for N_TTAGGED.
|
||||
let v: *node = typn.list;
|
||||
let maxsz: i32 = 0;
|
||||
for (v != nil) {
|
||||
let sz: i32 = slotsize(c, v);
|
||||
if (sz > maxsz) { maxsz = sz; };
|
||||
v = v.next;
|
||||
};
|
||||
let pad: i32 = (maxsz + 7) & ~7;
|
||||
return 8 + pad;
|
||||
};
|
||||
if (k == N_TNAME) {
|
||||
let nm: str = typn.str;
|
||||
if (streq(nm, "str")) { return 16; };
|
||||
|
||||
Reference in New Issue
Block a user