w6c: global *struct base field store loads the pointer from g(SB)

cstage dereferenced 0(BP) for the base — a SEGV on every store
through a module-global struct pointer; wwstage was already correct
(the inverse-set member). Mirror ww's global-pointer load. New
989_globptrfield_run pins cs==ww both stages. Task #47.
This commit is contained in:
2026-06-12 22:48:37 +09:00
parent e09a8c1775
commit 77747061c6
3 changed files with 179 additions and 1 deletions

View File

@@ -5368,7 +5368,27 @@ cgexpr(Cg *c, Node *n, Local *locals)
}
/* now store AX into target */
if (via_ptr) {
ins2(c, A_MOVQ, amem(D_BP, boff), areg(D_BX));
if (boff == 0 && let_islet(base->str)) {
/* #47 (inverse): a GLOBAL *struct
* base. The pointer VALUE lives at
* gp(SB), not a BP slot — load it
* from the symbol. Pre-fix MOVQ
* (BP),BX derefed saved BP → SEGV.
* Mirrors the already-correct wwstage
* global-base load; cs==ww. (Other
* via_ptr field arms keep the latent
* BP-deref — inverse siblings #60/#61,
* ken-triage.) */
ins1(c, A_PUSHQ, areg(D_AX));
ins2(c, A_LEAQ,
masym(c, base->str), areg(D_BX));
ins2(c, A_MOVQ, amem(D_BX, 0),
areg(D_BX));
ins1(c, A_POPQ, areg(D_AX));
} else {
ins2(c, A_MOVQ,
amem(D_BP, boff), areg(D_BX));
}
ins2(c, store_op, areg(D_AX), amem(D_BX, foff));
} else if (is_global) {
ins2(c, A_LEAQ, masym(c, base->str), areg(D_BX));