wwstage cgdot lacked a TY_FN branch for module-qualified N_DOT
rvalues. `let p = mod1.ping` fell through to the MOVQ/LEAQ-narrow
fallback, loading 8 prologue bytes from the fn's first instruction
instead of taking its address. Cstage cgdot already handled this
case (wired during #9, f1440bf).
Mirror cstage: gate on fnretlookup(c, fld) before the localloadop
fallback; emit `LEAQ <module>.<name>(SB), AX` via emitfnname with
the hint from lhs.str.
Extend 706_fnlabel_mangle: pos.ww now stores mod1.ping/mod2.ping
into local fn-pointer slots and dispatches through them in addition
to the existing direct calls. Expected exit 56 → 112. Regression
shape: without the new branch, MOVQ leaf(SB) loads the prologue
bytes; indirect call jumps into garbage → SIGSEGV.
ww2 == ww3 == ww4 byte-identical at the new emit.
18 lines
656 B
Plaintext
18 lines
656 B
Plaintext
// Two modules each `export fn ping` and each define a private
|
|
// `helper` with the same leaf. Together with mod2 they pin all four
|
|
// label-emit sites #9 touches:
|
|
// - CALL N_DOT : main calls mod1.ping / mod2.ping
|
|
// - CALL N_IDENT : ping bare-calls helper inside its own module
|
|
// - LEAQ N_IDENT : fpi takes `helper` by value, then calls it
|
|
// - LEAQ N_DOT : main does `let p = mod1.ping` then `p()`
|
|
// (pos.ww — wired via #12 wwstage cgdot fix)
|
|
|
|
fn helper() i32 = { return 11i32; };
|
|
|
|
fn fpi() i32 = {
|
|
let h: fn() i32 = helper;
|
|
return h();
|
|
};
|
|
|
|
export fn ping() i32 = { return 3i32 + helper() + fpi(); };
|