wcc,ww: bare-module fn mangles bare, not an imported same-leaf (M4 E2, #84)
A package-less primary's bare fn (module="") whose leaf collided with an imported module's same-leaf exported fn was mis-mangled to the imported qualified name (a user `fn run` emitted as `test.run`), producing a dead-duplicate symbol the linker silently shadowed -- a #263-class silent miscompile, gate-blind and symmetric across both stages. cgen now registers bare-module fns and resolves a bare-ident reference to its own bare leaf: mod_lookup_for_fn prefers the bare entry when the call carries no module hint and skips bare entries when it does, so the moduled-caller path stays byte-identical. The moduled `main` entry carve-out is an orthogonal rule (the linker entry is force-bared) and is retained. Prereq for the @test user-`run` coexist (#80). The bare non-fn (let/def/type) sibling is the same class but hint-less; deferred as #85, noted at the retained skip.
This commit is contained in:
@@ -598,12 +598,15 @@ fn cgfn(c: *cgen, fn_: *syntax.node) void = {
|
||||
if ((frame & 15) != 0) { frame = (frame + 15) & ~15; };
|
||||
|
||||
// Emit the TEXT label via emitfnname so the def site picks up the
|
||||
// same skip rule (FFI / `main` / empty-module) and the same module
|
||||
// hint (this fn's own module) that the call sites use. M1 #32: the
|
||||
// ROOT-unit main (imported==0) is the bare `_start` entry — emit it
|
||||
// bare directly, mirroring collectmods' skip; without this its
|
||||
// fn_.nmod hint would fall through modlookupforfn's first-leaf match
|
||||
// onto an IMPORTED package's now-registered `pkg.main`.
|
||||
// same module hint (this fn's own module) the call sites use. M1 #32:
|
||||
// the ROOT-unit main (imported==0) is the bare `_start` entry — emit
|
||||
// it bare directly, mirroring collectmods' skip. Irreducibly name-
|
||||
// based: a `package main` primary's decls are MODULED "main" (the
|
||||
// package clause sets curmod; cmd/ww/main.c:394), so main is NOT a
|
||||
// bare-module decl — dropping this carve-out mangles it to `main.main`
|
||||
// (undefined `main`). #84's bare-module handling is the orthogonal
|
||||
// axis (a package-LESS `//ww:module-reset` fn, nmod empty), resolved
|
||||
// in modlookupforfn, NOT here.
|
||||
emitline("TEXT ");
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0) {
|
||||
emitbytes(fn_.str.ptr, fn_.str.len: u64);
|
||||
|
||||
Reference in New Issue
Block a user