w6c+wwstage: qualify cross-module value-global by defining module (#1)
A bare cross-module value-global load mis-qualified its symbol: cgen mangled it with curmod via a non-preferring leaf lookup, so an exported `let v` in module aa emitted both its DATA storage AND its bare-load as main.v, colliding with main's private v. aa.getv() returned 99, not 7. Functions were already correct (they thread a cur_mod hint via mafn / emitfnname); value-globals did not. Both stages emitted IDENTICAL wrong asm, so the byte-id gate was blind to it; combined.ww (frontend) is clean -- the bug is purely in cgen. This is the cgen residual of #55 (#1 cgen value-global module-qualifier). Fix, symmetric in cmd/w6c/cgen.c + selfhost/cmd/wcc/{cgen,cgenexpr}.ww: reference-site mangle uses the resolved module (curmod-prefer for bare idents); definition/DATA-site mangle uses the decl's own module (d->module / d.nmod) -- threaded per-site the way fns already do, via mahint / emitsymnamehint. The fn-mangle path is left byte-for-byte untouched. Deviation from the signed-off spec (ratified by rob-pike after this finding): the spec prescribed reusing the fn lookup (mod_mangle_fn / modlookupforfn), but its first-match fallback mis-fires for value- globals -- mod_collect export-skips exported non-fn decls (cgen.c:1059) to keep their bare-name data ABI, so an exported leaf is absent from the module map and the fallback grabs another module's same-leaf private global. The value path therefore uses a distinct exact-(name,module)-or- bare lookup (mod_lookup_value / modlookupvalue): mangle only on an exact match, else stay bare. Byte-id-neutral on all existing single-owner code; exported globals stay bare (ABI preserved), private stay module-qualified. Honest boundary (rule 7): if two modules BOTH export the same value leaf, both stay bare and the linker sees a duplicate symbol -- a correct, loud, link-time ABI clash (like C), NOT a silent miscompile; left to the linker, not papered over with a cgen heuristic. Test: test/wcc/795_xmod_valglobal_run.c -- runtime (the exported global read returns its own value, not the colliding private one) + cs==ww byte-id, across i32-let / def-const / f64-let. Sibling to the checker test 794_xmod_ident_prefer, which deliberately omitted byte-id because this cgen bug diverged the asm independently.
This commit is contained in:
10
Makefile
10
Makefile
@@ -341,6 +341,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
|
||||
$(BIN)/test_xmod_variant_match \
|
||||
$(BIN)/test_spread_variant_match \
|
||||
$(BIN)/test_xmod_ident_prefer \
|
||||
$(BIN)/test_xmod_valglobal_run \
|
||||
$(BIN)/test_widen_pad_zero_run \
|
||||
$(BIN)/test_named_ptr_alias_variant_widen \
|
||||
$(BIN)/test_single_field_struct_zeroinit \
|
||||
@@ -811,6 +812,15 @@ $(BIN)/test_xmod_ident_prefer: test/wcc/794_xmod_ident_prefer.c \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
# #1 (cgen residual of #55): cross-module bare value-global load must
|
||||
# mangle reference-site by resolved module / definition-site by the
|
||||
# decl's own module — runtime + cs==ww byte-id. Self-contained single-
|
||||
# file multi-package probe (953 model).
|
||||
$(BIN)/test_xmod_valglobal_run: test/wcc/795_xmod_valglobal_run.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww $(BIN)/w6a $(BIN)/w6l \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
# #15: widening a bare *vtable into a NAMED-alias variant (`stream` =
|
||||
# *vtable) of `(file | stream)` must compute the right tag, not default
|
||||
# to tag 0. Both-stage byte-id + runtime, plus a degenerate-ambiguity
|
||||
|
||||
Reference in New Issue
Block a user