selfhost+cstage+test: graduate deflookup mod-qualified same-module-first (#11)
cstage Sdef walk #2 N_DOT branch used c->cur_mod where n->lhs->str is the correct module hint. Sister of #4c wwstage graduation; same shape as the TY_FN branch which already uses mafn(c, n->str, n->lhs->str). cmd/w6c/cgen.c: add sdef_mod_match_hint(s, hint); walk #2 routes hint first then head-pick fallback, matching #4a/#28/#31/#34 *mod variant pattern. selfhost: add deflookuprhsmod(c, name, mod); cgdot N_DOT mod-qualified str-def value-load routes through it. Rule-10 symmetric stages: both stages now share the lhs.str polarity (was: both used cur_mod / cur-module hint). 747_def_modqual_modshadow: table-driven sentinel — gamma calls alpha.MSG with beta.MSG (same-leaf-name) at head of c.defs/sdefs. want_imm "$38," (alpha strlit len), bad_imm "$27," (beta strlit len), plus cs-vs-ws byte-id. Reverting cstage walk #2 to head-pick → fails $38 on cstage + diverges cs-vs-ws; reverting wwstage cgdot to plain deflookuprhs → fails $38 on wwstage. make test 121/121; ww2==ww3==ww4 byte-id holds.
This commit is contained in:
@@ -548,6 +548,20 @@ sdef_mod_match(Cg *c, Sdef *s)
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
|
||||
/* Explicit-hint variant for `mod.NAME` N_DOT mod-qualified Sdef walks
|
||||
* (sister of wwstage deflookuprhsmod). Walk #2 needs n->lhs->str — a
|
||||
* cross-module qualifier from a third module won't match c->cur_mod
|
||||
* and would fall back to head-pick, possibly inlining the wrong-module
|
||||
* strlit when both source modules export the same-leaf str def. */
|
||||
static int
|
||||
sdef_mod_match_hint(Sdef *s, const char *hint)
|
||||
{
|
||||
const char *a = s->mod;
|
||||
if (a == hint) return 1;
|
||||
if (a == NULL || hint == NULL) return 0;
|
||||
return strcmp(a, hint) == 0;
|
||||
}
|
||||
|
||||
/* Interned string literals — emitted as DATA directives after all
|
||||
* function bodies, so the linker lays them out alongside .text. */
|
||||
typedef struct Strlit Strlit;
|
||||
@@ -5317,14 +5331,36 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
mafn(c, n->str, n->lhs->str), areg(D_AX));
|
||||
break;
|
||||
}
|
||||
for (Sdef *s = sdefs; s; s = s->next) {
|
||||
if (strcmp(s->name, n->str) != 0) continue;
|
||||
const char *lab = intern_strlit(c, s->bytes,
|
||||
s->len);
|
||||
ins2(c, A_LEAQ, asym(lab), areg(D_AX));
|
||||
ins2(c, A_MOVQ, aimm((long long)s->len),
|
||||
areg(D_BX));
|
||||
goto dot_done;
|
||||
{
|
||||
/* Same-module-first walk using n->lhs->str as
|
||||
* the explicit module hint (sister of wwstage
|
||||
* deflookuprhsmod). The TY_FN branch above
|
||||
* already uses n->lhs->str via mafn for the
|
||||
* cross-module qualifier disambiguation; this
|
||||
* walk mirrors that polarity so `alpha.MSG`
|
||||
* from a third module beats a head-of-sdefs
|
||||
* beta.MSG collision (#11, sister of #4c). */
|
||||
Sdef *s;
|
||||
for (s = sdefs; s; s = s->next) {
|
||||
if (strcmp(s->name, n->str) != 0)
|
||||
continue;
|
||||
if (sdef_mod_match_hint(s, n->lhs->str))
|
||||
break;
|
||||
}
|
||||
if (s == NULL) {
|
||||
for (s = sdefs; s; s = s->next)
|
||||
if (strcmp(s->name, n->str) == 0)
|
||||
break;
|
||||
}
|
||||
if (s != NULL) {
|
||||
const char *lab = intern_strlit(c,
|
||||
s->bytes, s->len);
|
||||
ins2(c, A_LEAQ, asym(lab), areg(D_AX));
|
||||
ins2(c, A_MOVQ,
|
||||
aimm((long long)s->len),
|
||||
areg(D_BX));
|
||||
goto dot_done;
|
||||
}
|
||||
}
|
||||
/* Same gating as the bare-ident catch-all: lets route
|
||||
* through localloadop (their slot can be the target of
|
||||
|
||||
Reference in New Issue
Block a user