ww: finish initialization validation parity
This commit is contained in:
@@ -2,15 +2,15 @@ package collide_test;
|
||||
|
||||
// Cross-module leaf-name collision observers on both driver stages.
|
||||
// Ports of the retired native carriers test/wcc/989_fnptrcollide_run.c
|
||||
// and 989_barefn_collide_run.c; every assertion preserved.
|
||||
// and 989_barefn_collide_run.c; their collision teeth remain explicit under
|
||||
// the package-initialization contract.
|
||||
//
|
||||
// fnptrcollide (#14 F7-c7) — a data global `slot: i64` whose LEAF
|
||||
// collides with the imported fn bar.slot must FAIL to build on BOTH
|
||||
// stages: type-keyed nodefnptr refuses to fold `&slot` into the fn's
|
||||
// TEXT reloc. Pre-fix wwstage was name-keyed and silently BUILT it
|
||||
// (a DATAR to the fn symbol — cat-A: cs loud-fails, ww builds). The
|
||||
// collision REQUIRES the import path (imported fn leaf vs local data
|
||||
// global), so a single-file fixture cannot express it.
|
||||
// fnptrcollide (#14 F7-c7) — a data global `slot: i64` whose leaf
|
||||
// collides with imported fn bar.slot. `let fp: *i64 = &slot` is valid
|
||||
// runtime package initialization: both stages must address main.slot,
|
||||
// initialize fp before main, and run 7. The old loud-reject expectation
|
||||
// predated runtime package lets. The collision still requires an import,
|
||||
// and name-keyed lowering to bar.slot is rejected by exact asm/runtime pins.
|
||||
//
|
||||
// barefn (#84/#24a) — a `package main;` root `fn run` coexists with
|
||||
// imported aa.run: build+run exit 9 on BOTH stages while an explicit
|
||||
@@ -52,32 +52,86 @@ fn runcode(dir: str, name: str, argv: []str) i32 = {
|
||||
};
|
||||
|
||||
@test fn fnptrcollide() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let bar: str = strings.concat(td, "/bar");
|
||||
let main: str = strings.concat(td, "/main");
|
||||
assert(os.mkdir(bar, 493) == 0);
|
||||
assert(os.mkdir(main, 493) == 0);
|
||||
testenv.writefile(strings.concat(bar, "/bar.ww"), strings.concat(
|
||||
"package bar;\n",
|
||||
"export fn slot() i64 = { return 99; };\n"));
|
||||
testenv.writefile(strings.concat(main, "/main.ww"), strings.concat(
|
||||
"package main;\n",
|
||||
"import bar;\n",
|
||||
"let slot: i64 = 7;\n",
|
||||
"let fp: *i64 = &slot;\n",
|
||||
"export fn main() int = { let _ = bar.slot(); ",
|
||||
"return (*fp): int; };\n"));
|
||||
let drvs: []str = ["ww", "ww_ww"];
|
||||
let tags: []str = ["cs", "ww"];
|
||||
let works: []str = [strings.concat(td, "/work-c"),
|
||||
strings.concat(td, "/work-ww")];
|
||||
let progs: []str = [strings.concat(td, "/prog.cs"),
|
||||
strings.concat(td, "/prog.ww")];
|
||||
let i: i32 = 0;
|
||||
for (i < 2) {
|
||||
let td: str = testenv.fresh();
|
||||
assert(os.mkdir(strings.concat(td, "/bar"), 493) == 0);
|
||||
testenv.writefile(strings.concat(td, "/bar/bar.ww"),
|
||||
strings.concat(
|
||||
"package bar;\n",
|
||||
"export fn slot() i64 = { return 99; };\n"));
|
||||
testenv.writefile(strings.concat(td, "/main.ww"), strings.concat(
|
||||
"package main;\n",
|
||||
"import bar;\n",
|
||||
"let slot: i64 = 7;\n",
|
||||
"let fp: *i64 = &slot;\n",
|
||||
"export fn main() int = { let _ = bar.slot(); ",
|
||||
"return (*fp): int; };\n"));
|
||||
let av: []str = [testenv.driver(drvs[i]), "build", "-I", "bar",
|
||||
"main.ww"];
|
||||
if (runcode(td, strings.concat("build_", drvs[i]), av) == 0) {
|
||||
fail("fnptrcollide", strings.concat(drvs[i], " built ok, ",
|
||||
"expected the leaf-name collision to be rejected (#14 -- ",
|
||||
"&slot mis-folded to the fn TEXT reloc)"));
|
||||
assert(os.mkdir(works[i], 493) == 0);
|
||||
let av: []str = [testenv.driver(drvs[i]), "build", "-w", works[i],
|
||||
"-I", td, "-o", progs[i], "main"];
|
||||
if (runcode(td, strings.concat("build_", tags[i]), av) != 0) {
|
||||
fail("fnptrcollide", strings.concat(drvs[i], " build failed"));
|
||||
};
|
||||
let rav: []str = [progs[i]];
|
||||
if (runcode(td, strings.concat("run_", tags[i]), rav) != 7) {
|
||||
fail("fnptrcollide", strings.concat(drvs[i], " exit != 7"));
|
||||
};
|
||||
let sourceasm: str = testenv.readfile(strings.concat(works[i],
|
||||
"/main.s"));
|
||||
let initasm: str = testenv.readfile(strings.concat(works[i],
|
||||
"/main.init.s"));
|
||||
let barasm: str = testenv.readfile(strings.concat(works[i], "/bar.s"));
|
||||
if (testenv.occurrences(sourceasm, "DATAW main.slot(SB)") != 1
|
||||
|| testenv.occurrences(sourceasm, "DATAW main.fp(SB)") != 1
|
||||
|| testenv.occurrences(sourceasm,
|
||||
"CALL\t__ww..dispatch(SB)") != 1
|
||||
|| testenv.occurrences(sourceasm,
|
||||
"LEAQ\tmain.slot(SB), AX") != 1
|
||||
|| testenv.occurrences(sourceasm,
|
||||
"MOVQ\tAX, main.fp(SB)") != 1
|
||||
|| testenv.has(sourceasm, "LEAQ\tbar.slot(SB)")
|
||||
|| testenv.has(sourceasm, "DATAR main.fp")
|
||||
|| testenv.occurrences(initasm,
|
||||
"CALL\t__ww..pkg.p.bar.v0.r0.init(SB)") != 1
|
||||
|| testenv.occurrences(initasm,
|
||||
"CALL\t__ww..pkg.p.main.v0.r0.init(SB)") != 1
|
||||
|| testenv.occurrences(barasm, "TEXT bar.slot,") != 1) {
|
||||
fail("fnptrcollide", "runtime initializer selected the colliding fn");
|
||||
};
|
||||
testenv.clean(td);
|
||||
i += 1;
|
||||
};
|
||||
let wantdispatch: str = strings.concat(
|
||||
"//ww:init-root __ww..pkg.p.main.v0.r0.init\n",
|
||||
"//ww:init-call __ww..pkg.p.bar.v0.r0.init\n",
|
||||
"//ww:init-call __ww..pkg.p.main.v0.r0.init\n");
|
||||
if (!testenv.same(wantdispatch, testenv.readfile(strings.concat(works[0],
|
||||
"/main.init.unit.ww")))) {
|
||||
fail("fnptrcollide", "dispatcher did not initialize dependency first");
|
||||
};
|
||||
let names: []str = ["bar.unit.ww", "bar.wwi", "bar.s", "bar.o", "bar.a",
|
||||
"main.unit.ww", "main.wwi", "main.s", "main.o", "main.a",
|
||||
"main.init.unit.ww", "main.init.s", "main.init.o"];
|
||||
i = 0;
|
||||
for (i < names.len) {
|
||||
if (!testenv.same(testenv.readfile(strings.concat(works[0], "/", names[i])),
|
||||
testenv.readfile(strings.concat(works[1], "/", names[i])))) {
|
||||
fail("fnptrcollide", strings.concat(names[i], " differs by stage"));
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(progs[0]), testenv.readfile(progs[1]))) {
|
||||
fail("fnptrcollide", "Cstage/WWstage binaries differ");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
// __root.s then aa.s: the carrier's fixed #93 sep concat order.
|
||||
|
||||
Reference in New Issue
Block a user