Strlit labels were emitted as `_S_<n>` from a global counter with no
per-unit prefix (cgen.c intern_strlit + wwstage internstrlit twin).
Under separate compilation two str-bearing packages both emit `_S_0`..
-> w6l link collision.
Prefix the label with the owning package PATH (`<module>._S_<n>`,
matching mklabel's spelling). The prefix is c->cur_mod, set per-fn by
cgfn and now per-decl by let_pre_intern (save/restore so the later
emit passes, which read cur_mod for fn-ptr relocs, are unaffected).
Pure function of the module path — NOT a build-nonce — so the
self-host fixed-point holds across ww2/ww3/ww4. Both stages, symmetric.
Transparent rename on the live combined path: the label is interned
once and shared by every reference, so ref and def move in lockstep.
cs==ww byte-id holds; the w6c/wwdump combined.ww embed wcc/cgen.ww and
are regenerated.
746_strdef_inline: the strdef-inline sentinel pinned the bare
`LEAQ\t_S_` shape; update to the module-prefixed form (alpha._S_ for
the in-module def, beta._S_ for the use-site-interned cross-module
inline).
989_m3sep_run: add the #49 LINK leg. The str sub-fixture (sleaf+smid)
was keystone-only — never linked — precisely because the global
counter made both emit `_S_0`. With the prefix, compile both `-c`
separately, link (w6l) + run (sroot reads a distinguishing byte through
each string's .ptr, so a collided label would corrupt the exit), both
stages + cs==ww final exe.
Class A silent miscompile. wwstage cgenexpr.ww cgident's bare-ident
deflookup→true branch and cgdot's module-qualified leaf branch
emitted `MOVQ <mod>.<name>(SB), AX` for a `def MSG: str = "..."`
value reference — a load from a SB symbol that emit_data never
writes. Str defs are not laid out at SB; they live as interned
strlits the .ptr/.len fold (post-#4c) and value-load consume.
Cstage already strlit-inlines via Sdef walks #1 (case N_IDENT
non-local) and #2 (case N_DOT untyped-lhs); wwstage now matches
the (LEAQ _S_<n>(SB), MOVQ $<len>, BX) emit shape per rule 10.
Surfaced by reviewer-def during #4c R3 while attempting option (B)
for the cstage Sdef walks #1/#2 prefer-pass — both walks'
cs-vs-ws byte-id sentinel rows could not pass while wwstage
emitted the bogus DATAW shape. Filed as #12 and deferred until
the wwstage emit shape was fixed. Unblocks #11 + #13 (cstage
prefer-pass graduations).
Latent: no in-tree corpus referenced a str def as a value (only
as .ptr/.len via cgdot field-fold) prior to lib/strings c3 —
same corpus-coverage-blind shape as the #4a-#4e graduations.
746_strdef_inline pins both sites with 2 rows: bare ident +
mod-qualified. Each row asserts `LEAQ _S_` + `MOVQ $<strlit_len>,`
inside the caller TEXT before RET, anti-checks the pre-fix
`<mod>.<name>(SB)` symbol-load, and cs-vs-ws byte-id per row.
120/120 ok. ww2 == ww3 == ww4 byte-id holds.