w6c,ww: mangle an imported package's fn main under separate compilation (M4 E3, #99)
The bare-`main` carve-out (which keeps the link entry's main unmangled) keyed on `leaf == "main" && imported == 0`. Under the combined path a dependency's body folds in with imported==1, so only the root's main stayed bare. Under separate compilation each package is its own unit and a dependency's body carries a path-mangling module-reset but imported==0 (#57) — so an imported `fn main` matched the carve-out, emitted a bare `TEXT main`, and collided with the root entry (`w6l: duplicate symbol main`). The combined path was unaffected, so this only surfaced under sep. Gate the carve-out with sep_isdep = (wwiout != NULL): the producer emits a .wwi output only for dependency units, never for the root/link-entry unit (root stripped, #69), symmetric on both stages. Only the root unit's main now stays bare; an imported package's main mangles on its import path (e.g. aa.bb.main). Both stages. Gate: test/wcc/989_depmain_sep.c (table-driven, dotted + single-component shapes, both stages; asserts the mangled dep main + a single bare root main + cs==ww byte-id; combined path stays neutral).
This commit is contained in:
@@ -41326,8 +41326,11 @@ fn cgfn(c: *cgen, fn_: *syntax.node) void = {
|
||||
// (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.
|
||||
// #99: gate on sepisdep — under sep a dep unit's main is imported==0
|
||||
// (path-carrying `//ww:module-reset`, #57); only the root/link-entry
|
||||
// unit (wwiout==nil, #69) keeps the bare label.
|
||||
emitline("TEXT ");
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0) {
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0 && c.sepisdep == 0) {
|
||||
emitbytes(fn_.str.ptr, fn_.str.len: u64);
|
||||
} else {
|
||||
emitfnname(c, fn_.str, fn_.nmod);
|
||||
@@ -41932,6 +41935,14 @@ type cgen = struct {
|
||||
// must survive to the post-loop emitletdataw/emitdefconstants pass,
|
||||
// like strlits/ffis. Symmetric with cstage Cg.sep_mode.
|
||||
sepmode: i32,
|
||||
// #99: this unit is a sep DEPENDENCY, not the root/link-entry unit.
|
||||
// Set from `wwiout != nil` in main — the producer passes -I (.wwi
|
||||
// output) to DEP units only; the root's .wwi is stripped (#69), so
|
||||
// wwiout==nil <=> root/link-entry unit. Gates the bare-`main` carve-
|
||||
// out: a dep's `fn main` mangles on its path like any decl; only the
|
||||
// root entry stays bare. Like sepmode, NOT reset by cgeninit (per-fn).
|
||||
// Symmetric with cstage Cg.sep_isdep.
|
||||
sepisdep: i32,
|
||||
};
|
||||
|
||||
// Top-level mutable `let` registry. Mirrors cmd/w6c/cgen.c LetVar.
|
||||
@@ -45263,7 +45274,12 @@ fn collectmods(c: *cgen, file: *syntax.node) void = {
|
||||
// label). M1 #32: only ROOT main (imported==0) stays bare;
|
||||
// an IMPORTED `fn main` mangles on its path. Mirrors
|
||||
// cstage cgen.c mod_collect.
|
||||
if (!syntax.streq(d.str, "main") || d.imported != 0) {
|
||||
// #99: under sep a dep unit's main is imported==0 too (its
|
||||
// body is composed with a path-carrying `//ww:module-reset`,
|
||||
// #57), so imported==0 no longer means "root unit" per-unit.
|
||||
// sepisdep (wwiout==nil <=> root/link-entry unit, #69)
|
||||
// re-mangles a dep's main; only the root's stays bare.
|
||||
if (!syntax.streq(d.str, "main") || d.imported != 0 || c.sepisdep != 0) {
|
||||
let m: *modent = alloc(modent{mname=d.str, nmod=d.nmod, omod=d.nmod, mnext=c.mods})!;
|
||||
c.mods = m;
|
||||
};
|
||||
@@ -46339,6 +46355,10 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
let cg: cgen;
|
||||
cgeninit(&cg);
|
||||
cg.sepmode = sepmode;
|
||||
// #99: wwiout != nil <=> this is a sep DEP unit (the producer passes
|
||||
// -I to deps only; the root's .wwi is stripped per #69). Gates the
|
||||
// bare-`main` carve-out so only the root/link-entry main stays bare.
|
||||
if (wwiout != nil) { cg.sepisdep = 1i32; };
|
||||
cgfile(&cg, f);
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -195,6 +195,10 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
let cg: cgen;
|
||||
cgeninit(&cg);
|
||||
cg.sepmode = sepmode;
|
||||
// #99: wwiout != nil <=> this is a sep DEP unit (the producer passes
|
||||
// -I to deps only; the root's .wwi is stripped per #69). Gates the
|
||||
// bare-`main` carve-out so only the root/link-entry main stays bare.
|
||||
if (wwiout != nil) { cg.sepisdep = 1i32; };
|
||||
cgfile(&cg, f);
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -544,6 +544,14 @@ type cgen = struct {
|
||||
// must survive to the post-loop emitletdataw/emitdefconstants pass,
|
||||
// like strlits/ffis. Symmetric with cstage Cg.sep_mode.
|
||||
sepmode: i32,
|
||||
// #99: this unit is a sep DEPENDENCY, not the root/link-entry unit.
|
||||
// Set from `wwiout != nil` in main — the producer passes -I (.wwi
|
||||
// output) to DEP units only; the root's .wwi is stripped (#69), so
|
||||
// wwiout==nil <=> root/link-entry unit. Gates the bare-`main` carve-
|
||||
// out: a dep's `fn main` mangles on its path like any decl; only the
|
||||
// root entry stays bare. Like sepmode, NOT reset by cgeninit (per-fn).
|
||||
// Symmetric with cstage Cg.sep_isdep.
|
||||
sepisdep: i32,
|
||||
};
|
||||
|
||||
// Top-level mutable `let` registry. Mirrors cmd/w6c/cgen.c LetVar.
|
||||
@@ -3875,7 +3883,12 @@ fn collectmods(c: *cgen, file: *syntax.node) void = {
|
||||
// label). M1 #32: only ROOT main (imported==0) stays bare;
|
||||
// an IMPORTED `fn main` mangles on its path. Mirrors
|
||||
// cstage cgen.c mod_collect.
|
||||
if (!syntax.streq(d.str, "main") || d.imported != 0) {
|
||||
// #99: under sep a dep unit's main is imported==0 too (its
|
||||
// body is composed with a path-carrying `//ww:module-reset`,
|
||||
// #57), so imported==0 no longer means "root unit" per-unit.
|
||||
// sepisdep (wwiout==nil <=> root/link-entry unit, #69)
|
||||
// re-mangles a dep's main; only the root's stays bare.
|
||||
if (!syntax.streq(d.str, "main") || d.imported != 0 || c.sepisdep != 0) {
|
||||
let m: *modent = alloc(modent{mname=d.str, nmod=d.nmod, omod=d.nmod, mnext=c.mods})!;
|
||||
c.mods = m;
|
||||
};
|
||||
|
||||
@@ -607,8 +607,11 @@ fn cgfn(c: *cgen, fn_: *syntax.node) void = {
|
||||
// (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.
|
||||
// #99: gate on sepisdep — under sep a dep unit's main is imported==0
|
||||
// (path-carrying `//ww:module-reset`, #57); only the root/link-entry
|
||||
// unit (wwiout==nil, #69) keeps the bare label.
|
||||
emitline("TEXT ");
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0) {
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0 && c.sepisdep == 0) {
|
||||
emitbytes(fn_.str.ptr, fn_.str.len: u64);
|
||||
} else {
|
||||
emitfnname(c, fn_.str, fn_.nmod);
|
||||
|
||||
@@ -41326,8 +41326,11 @@ fn cgfn(c: *cgen, fn_: *syntax.node) void = {
|
||||
// (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.
|
||||
// #99: gate on sepisdep — under sep a dep unit's main is imported==0
|
||||
// (path-carrying `//ww:module-reset`, #57); only the root/link-entry
|
||||
// unit (wwiout==nil, #69) keeps the bare label.
|
||||
emitline("TEXT ");
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0) {
|
||||
if (syntax.streq(fn_.str, "main") && fn_.imported == 0 && c.sepisdep == 0) {
|
||||
emitbytes(fn_.str.ptr, fn_.str.len: u64);
|
||||
} else {
|
||||
emitfnname(c, fn_.str, fn_.nmod);
|
||||
@@ -41932,6 +41935,14 @@ type cgen = struct {
|
||||
// must survive to the post-loop emitletdataw/emitdefconstants pass,
|
||||
// like strlits/ffis. Symmetric with cstage Cg.sep_mode.
|
||||
sepmode: i32,
|
||||
// #99: this unit is a sep DEPENDENCY, not the root/link-entry unit.
|
||||
// Set from `wwiout != nil` in main — the producer passes -I (.wwi
|
||||
// output) to DEP units only; the root's .wwi is stripped (#69), so
|
||||
// wwiout==nil <=> root/link-entry unit. Gates the bare-`main` carve-
|
||||
// out: a dep's `fn main` mangles on its path like any decl; only the
|
||||
// root entry stays bare. Like sepmode, NOT reset by cgeninit (per-fn).
|
||||
// Symmetric with cstage Cg.sep_isdep.
|
||||
sepisdep: i32,
|
||||
};
|
||||
|
||||
// Top-level mutable `let` registry. Mirrors cmd/w6c/cgen.c LetVar.
|
||||
@@ -45263,7 +45274,12 @@ fn collectmods(c: *cgen, file: *syntax.node) void = {
|
||||
// label). M1 #32: only ROOT main (imported==0) stays bare;
|
||||
// an IMPORTED `fn main` mangles on its path. Mirrors
|
||||
// cstage cgen.c mod_collect.
|
||||
if (!syntax.streq(d.str, "main") || d.imported != 0) {
|
||||
// #99: under sep a dep unit's main is imported==0 too (its
|
||||
// body is composed with a path-carrying `//ww:module-reset`,
|
||||
// #57), so imported==0 no longer means "root unit" per-unit.
|
||||
// sepisdep (wwiout==nil <=> root/link-entry unit, #69)
|
||||
// re-mangles a dep's main; only the root's stays bare.
|
||||
if (!syntax.streq(d.str, "main") || d.imported != 0 || c.sepisdep != 0) {
|
||||
let m: *modent = alloc(modent{mname=d.str, nmod=d.nmod, omod=d.nmod, mnext=c.mods})!;
|
||||
c.mods = m;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user