wcc: cgen N_CALL "len" TY_ARRAY/TY_SLICE/TY_STR intercept (#131)
wwstage cgenexpr cgcall now intercepts the N_IDENT-callee `len` like cstage cgen.c:4283-4297 — TY_ARRAY folds to MOVQ $alen,AX at compile time, TY_SLICE/TY_STR + N_IDENT loads the .len slot from local header, fallback to cgexpr. Rule-9 Hare-fidelity (Hare/Rust/Go compile-time-fold len(fixedarray)) + rule-10 align wwstage UP to cstage. Byte-id-neutral at master (bootstrap has no current len(fixedarray) call-form uses); prereq for fold-3 decimal.ha port (`len(d.digits)` at decimal.ha:66/ 77/86/124).
This commit is contained in:
@@ -17714,6 +17714,52 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// `len(x)` Hare builtin — mirror cmd/w6c/cgen.c:4283-4297.
|
||||
// Required for byte-id when compiler-imported lib code uses
|
||||
// len(fixedarray) (e.g. lib/strconv/decimal.ha's `len(d.digits)`
|
||||
// over the [800]u8 field). Without this intercept wwstage falls
|
||||
// through to a regular CALL len(SB) while cstage folds to
|
||||
// `MOVQ $alen, AX` — rule-10 byte-id break (#131).
|
||||
//
|
||||
// Argument-type-driven branches:
|
||||
// TY_SLICE / TY_STR (+ N_IDENT operand) → load .len at BP+off+8.
|
||||
// TY_ARRAY → fold `MOVQ $alen, AX`.
|
||||
// else → evaluate operand (cstage's pseudo-.len fallback —
|
||||
// unlikely to fire on Hare-shaped sources).
|
||||
if (streq(callee.str, "len")) {
|
||||
if (n.list != nil) {
|
||||
let a: *node = n.list;
|
||||
let at: *tinfo = a.type_: *tinfo;
|
||||
let u: *tinfo = at;
|
||||
for (u != nil && u.kind == tykind.TY_NAMED) {
|
||||
u = u.under;
|
||||
};
|
||||
if (u != nil) {
|
||||
if ((u.kind == tykind.TY_SLICE
|
||||
|| u.kind == tykind.TY_STR)
|
||||
&& a.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, a.str);
|
||||
if (lc != nil) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + 8): i64);
|
||||
emitline("(BP), AX\n");
|
||||
return;
|
||||
};
|
||||
};
|
||||
if (u.kind == tykind.TY_ARRAY) {
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(u.alen: i64);
|
||||
emitline(", AX\n");
|
||||
return;
|
||||
};
|
||||
};
|
||||
// Fallback: evaluate the argument and let AX carry
|
||||
// whatever the value-load shape yields. Mirrors
|
||||
// cstage's `cgexpr(c, a, locals)` fallthrough.
|
||||
cgexpr(c, a);
|
||||
return;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user