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:
2026-05-12 02:10:10 +09:00
parent 4085742853
commit 2f385cec00
9 changed files with 173 additions and 99 deletions

View File

@@ -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);