cgen: address-of fn name emits LEAQ via mafn (#180)
Pre-fix the N_UN TK_AMP arm fell through silently when the operand
was an N_IDENT naming a top-level function — the let/def cascade
had no TY_FN branch, so the store at the assign site picked up
whatever AX held from prior code (commonly a stale arg register).
A subsequent (*f)(...) jumped through that junk and segfaulted.
Cstage: cmd/w6c/cgen.c N_UN TK_AMP IDENT adds a TY_FN arm before
the let/def cascade, mirror of the read-arm at line 2330 — same
mafn(opnd->str, c->cur_mod) shape. Wwstage twin in selfhost/cmd/
wcc/cgenexpr.ww cgun TK_AMP IDENT uses the analogous predicate
fnretlookup(c, nm) != nil + emitfnname(c, nm, c.curmod), matching
the cstage emit on byte-id. Both stages must land together per
rule-10 (cstage-only breaks 990-997 byte-id gates).
Combined.ww regenerated for selfhost/cmd/{w6c,wwdump}/main.combined
.ww per #110 freshness gate.
Probe: test/wcc/764_amp_fn_ident.c, 6 rows table-driven —
minimal / branched-callee / alias-chain / fn-with-args / fn-tuple
-return / cross-module. Rows 1-5 gate both stages (run + .s LEAQ
check + cs.s == ww.s byte-id); row 6 cross-module is cstage-only
because wwstage bails asserttyped on `&mod.fn` (sibling project
#184, filed). Per drew option (b) the probe exercises the address
-of without (*f)(7) — deref-call runtime coverage stays with
project #181's probe once the wwstage asserttyped bail on
N_CALL(*f) is lifted.
Phase 1 cross-mod verdict = FINE for cstage (LEAQ emits via the
already-present N_DOT TK_AMP branch at cgen.c:2477-2493); WWSTAGE
fails asserttyped on the same shape → project #184.
This commit is contained in:
@@ -2435,8 +2435,23 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
Node *opnd = n->lhs;
|
||||
if (opnd && opnd->kind == N_IDENT) {
|
||||
int off = localfind(locals, opnd->str);
|
||||
Type *ot = opnd->type;
|
||||
Type *ou = (ot && ot->kind == TY_NAMED)
|
||||
? ot->under : ot;
|
||||
if (off != 0) {
|
||||
ins2(c, A_LEAQ, amem(D_BP, off), areg(D_AX));
|
||||
} else if (ou && ou->kind == TY_FN) {
|
||||
/* #180: address-of a top-level fn name.
|
||||
* Twin of the N_IDENT TY_FN read-arm at
|
||||
* line 2330 (mafn with c->cur_mod hint).
|
||||
* Previously this fell through silently —
|
||||
* the AX-store at the assign site picked
|
||||
* up whatever AX held from prior code, so
|
||||
* `let f = &add1; (*f)(7)` jumped through
|
||||
* stale AX. */
|
||||
ins2(c, A_LEAQ,
|
||||
mafn(c, opnd->str, c->cur_mod),
|
||||
areg(D_AX));
|
||||
} else if (let_islet(opnd->str)
|
||||
|| def_isstructdef(opnd->str)
|
||||
|| def_isarraydef(opnd->str)
|
||||
|
||||
Reference in New Issue
Block a user