test: port the M3 .wwi-consumer keystone to ww; retire 989_m3sep
m3sep_test.ww drives the raw w6c/w6a/w6l toolchains (+_ww twins) over hand-composed //ww:module units splicing produced .wwi bytes: the bodies==.wwi keystone on both stages per package (mid/root/smid) with determinism, rule-10 and the value-global DATA guard; the end-to-end i32 chain (exit 59) with final-exe byte-id; and the #49 str-label / #53 export-leaf link legs (exits 160/140) with their .s needle proofs. Each @test re-produces its .wwi cold instead of sharing the carrier's single scratch dir (same claims, sharper isolation).
This commit is contained in:
491
test/sep/m3sep_test.ww
Normal file
491
test/sep/m3sep_test.ww
Normal file
@@ -0,0 +1,491 @@
|
||||
package m3sep_test;
|
||||
|
||||
// M3 `.wwi` separate-compilation CONSUMER gate (task #22 arc). Port of
|
||||
// the retired native carrier test/wcc/989_m3sep_run.c; every assertion
|
||||
// preserved. Drives the raw w6c/w6a/w6l toolchains (+_ww twins), never
|
||||
// the ww driver: the composed //ww:module units splice PRODUCED .wwi
|
||||
// bytes between compile steps — an inter-stage artifact flow no
|
||||
// driver invocation or fixture can express.
|
||||
//
|
||||
// keystone (rob §4.1, the load-bearing claim) — compiling package P
|
||||
// under `-c` with deps as `.wwi` emits byte-identical codegen to deps
|
||||
// as full BODIES, holding the -c filter constant and varying only the
|
||||
// dep-source form; proven per package (mid, root, smid) on BOTH
|
||||
// stages (a wwstage-only guard regression cannot hide behind the
|
||||
// .wwi-sourced sep unit), plus cs==ww on the sep unit (rule 10),
|
||||
// sep-path determinism (same input twice -> identical), and the
|
||||
// value-global guard: an imported `export let` must never re-emit its
|
||||
// DATA[W] definition (link collision). The smid row exercises the
|
||||
// strlit-intern guard: neutralize it and sleaf.banner interns ahead
|
||||
// of smid.label in the bodies-unit, desyncing `_S_` -> keystone RED.
|
||||
//
|
||||
// chain — end-to-end: leaf/mid/root compiled -c, assembled, linked
|
||||
// with libwwrt.a and RUN through both full toolchains -> exit 59 (the
|
||||
// real cross-boundary computation over all four fact-classes: fn
|
||||
// signature, struct layout, def const, export-let global); the two
|
||||
// final executables byte-identical (rule 10 end-to-end).
|
||||
//
|
||||
// str49 (#49) — two str-bearing packages sep-LINK without an `_S_`
|
||||
// label collision (per-unit prefix): exit 160 reads a distinguishing
|
||||
// byte THROUGH each str's .ptr; cstage .s carries `sleaf._S_` /
|
||||
// `smid._S_` and no bare `DATA _S_0(SB)`.
|
||||
//
|
||||
// leaf53 (#53) — two packages exporting the SAME-named non-fn leaves
|
||||
// (`let v`, `def K`) sep-LINK because every exported decl
|
||||
// path-qualifies (cea.v/ceb.v, cea.K/ceb.K, no bare v/K DATA): exit
|
||||
// 140 proves each getter reads its OWN module's data.
|
||||
//
|
||||
// Dropped C machinery, not assertions: the ~70-entry remove_child
|
||||
// cleanup ledger (testenv.clean asserts the recursive removal).
|
||||
|
||||
import os;
|
||||
import os.exec;
|
||||
import strings;
|
||||
import testenv;
|
||||
import time;
|
||||
|
||||
fn fail(label: str, why: str) void = {
|
||||
let m: str = strings.concat("m3sep FAIL: ", label, " -- ", why, "\n");
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
assert(false);
|
||||
};
|
||||
|
||||
fn tmo() time.duration = {
|
||||
return (180i64 * (time.second: i64)): time.duration;
|
||||
};
|
||||
|
||||
// -1 encodes an abnormal (non-EXIT) termination, never a valid code.
|
||||
fn runcode(dir: str, name: str, argv: []str) i32 = {
|
||||
let co: testenv.commandout;
|
||||
testenv.runcommand(dir, dir, name, argv, tmo(), &co);
|
||||
if (co.termination != exec.termination.EXIT) { return -1; };
|
||||
return co.code;
|
||||
};
|
||||
|
||||
// one //ww:module section: directive line, body bytes, closing newline
|
||||
// (the exact append_section shape the carrier composed).
|
||||
fn sec(directive: str, body: str) str = {
|
||||
return strings.concat(directive, "\n", body, "\n");
|
||||
};
|
||||
|
||||
// The fixture: leaf -> mid -> root carries all FOUR cross-boundary
|
||||
// fact-classes (fn signature, struct layout, def const, export-let
|
||||
// global). root exit = combine(mkpoint(3,4)) + add(1,2) = 56 + 3 = 59.
|
||||
fn leafsrc() str = {
|
||||
return strings.concat(
|
||||
"package leaf;\n",
|
||||
"export type Point = struct { x: i32, y: i32 };\n",
|
||||
"export def SCALE: i32 = 7;\n",
|
||||
"export let origin_tag: i32 = 42;\n",
|
||||
"export fn add(a: i32, b: i32) i32 = { return a + b; };\n",
|
||||
"export fn mkpoint(x: i32, y: i32) Point = { return Point { x = x, y = y }; };\n",
|
||||
"fn leafpriv(z: i32) i32 = { return z * SCALE; };\n");
|
||||
};
|
||||
|
||||
fn midsrc() str = {
|
||||
return strings.concat(
|
||||
"package mid;\n",
|
||||
"import leaf;\n",
|
||||
"export fn combine(p: leaf.Point) i32 = {\n",
|
||||
" return leaf.add(p.x, p.y) + leaf.SCALE + leaf.origin_tag;\n",
|
||||
"};\n");
|
||||
};
|
||||
|
||||
fn rootsrc() str = {
|
||||
return strings.concat(
|
||||
"package main;\n",
|
||||
"import leaf;\n",
|
||||
"import mid;\n",
|
||||
"fn main() i32 = {\n",
|
||||
" let p = leaf.mkpoint(3, 4);\n",
|
||||
" let r = mid.combine(p);\n",
|
||||
" r = r + leaf.add(1, 2);\n",
|
||||
" return r;\n",
|
||||
"};\n");
|
||||
};
|
||||
|
||||
// str sub-fixture: sleaf's export-let interns a strlit in sleaf's own
|
||||
// compile but is stripped from sleaf.wwi — the strlit-intern guard's
|
||||
// non-vacuity source (see keystone smid row).
|
||||
fn sleafsrc() str = {
|
||||
return strings.concat(
|
||||
"package sleaf;\n",
|
||||
"export let banner: str = \"sleaf-banner\";\n",
|
||||
"export fn tag(a: i32) i32 = { return a + 1; };\n",
|
||||
"export fn getbanner() str = { return banner; };\n");
|
||||
};
|
||||
|
||||
fn smidsrc() str = {
|
||||
return strings.concat(
|
||||
"package smid;\n",
|
||||
"import sleaf;\n",
|
||||
"export let label: str = \"smid-label\";\n",
|
||||
"export fn use(a: i32) i32 = { return sleaf.tag(a); };\n",
|
||||
"export fn getlabel() str = { return label; };\n");
|
||||
};
|
||||
|
||||
// getbanner()[0] = 's'(115), getlabel()[4] = '-'(45) -> 160; a collided
|
||||
// `_S_0` resolving to the wrong package's bytes corrupts the exit.
|
||||
fn srootsrc() str = {
|
||||
return strings.concat(
|
||||
"package main;\n",
|
||||
"import sleaf;\n",
|
||||
"import smid;\n",
|
||||
"fn main() i32 = {\n",
|
||||
" let a: str = sleaf.getbanner();\n",
|
||||
" let b: str = smid.getlabel();\n",
|
||||
" return (a[0]: i32) + (b[4]: i32);\n",
|
||||
"};\n");
|
||||
};
|
||||
|
||||
// cea.val()=43, ceb.val()=97 -> 140; a collided bare v/K resolving to
|
||||
// the wrong package's data corrupts the exit.
|
||||
fn ceasrc() str = {
|
||||
return strings.concat(
|
||||
"package cea;\n",
|
||||
"export let v: i64 = 40;\n",
|
||||
"export def K: i64 = 3;\n",
|
||||
"export fn val() i64 = { return v + K; };\n");
|
||||
};
|
||||
|
||||
fn cebsrc() str = {
|
||||
return strings.concat(
|
||||
"package ceb;\n",
|
||||
"export let v: i64 = 90;\n",
|
||||
"export def K: i64 = 7;\n",
|
||||
"export fn val() i64 = { return v + K; };\n");
|
||||
};
|
||||
|
||||
fn cxrootsrc() str = {
|
||||
return strings.concat(
|
||||
"package main;\n",
|
||||
"import cea;\n",
|
||||
"import ceb;\n",
|
||||
"fn main() i32 = { return (cea.val(): i32) + (ceb.val(): i32); };\n");
|
||||
};
|
||||
|
||||
// produce a package's .wwi (w6c -I, .s discarded); the production
|
||||
// itself must succeed.
|
||||
fn produce(td: str, name: str, unit: str, wwi: str) void = {
|
||||
let av: []str = [testenv.driver("w6c"), "-I", wwi, "-o", "/dev/null",
|
||||
unit];
|
||||
if (runcode(td, strings.concat("prod_", name), av) != 0) {
|
||||
fail(name, ".wwi produce failed");
|
||||
};
|
||||
};
|
||||
|
||||
fn compilestep(td: str, label: str, step: str, comp: str, outs: str,
|
||||
unit: str) void = {
|
||||
let av: []str = [testenv.driver(comp), "-c", "-o", outs, unit];
|
||||
if (runcode(td, strings.concat(label, "_", step), av) != 0) {
|
||||
fail(label, strings.concat(comp, " -c failed (", step, ")"));
|
||||
};
|
||||
};
|
||||
|
||||
// the per-package keystone: 5 compiles over the bodies/sep unit pair,
|
||||
// then bodies==sep (both stages), cs==ww, determinism, and the
|
||||
// imported-value-global DATA guard.
|
||||
fn keystone(td: str, label: str, bodies: str, sepu: str) void = {
|
||||
let bf: str = strings.concat(td, "/", label, ".bodies.ww");
|
||||
testenv.writefile(bf, bodies);
|
||||
let sf: str = strings.concat(td, "/", label, ".sep.ww");
|
||||
testenv.writefile(sf, sepu);
|
||||
let csb: str = strings.concat(td, "/", label, ".bodies.cs.s");
|
||||
let css: str = strings.concat(td, "/", label, ".sep.cs.s");
|
||||
let wws: str = strings.concat(td, "/", label, ".sep.ww.s");
|
||||
let css2: str = strings.concat(td, "/", label, ".sep.cs2.s");
|
||||
let wwb: str = strings.concat(td, "/", label, ".bodies.ww.s");
|
||||
compilestep(td, label, "bcs", "w6c", csb, bf);
|
||||
compilestep(td, label, "scs", "w6c", css, sf);
|
||||
compilestep(td, label, "sww", "w6c_ww", wws, sf);
|
||||
compilestep(td, label, "scs2", "w6c", css2, sf);
|
||||
compilestep(td, label, "bww", "w6c_ww", wwb, bf);
|
||||
if (!testenv.same(testenv.readfile(csb), testenv.readfile(css))) {
|
||||
fail(label, strings.concat("bodies.s != sep.s (the .wwi does not ",
|
||||
"convey the dep facts P's codegen needs)"));
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(wwb), testenv.readfile(wws))) {
|
||||
fail(label, "ww bodies.s != ww sep.s (wwstage keystone)");
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(css), testenv.readfile(wws))) {
|
||||
fail(label, "cs sep.s != ww sep.s (rule 10)");
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(css), testenv.readfile(css2))) {
|
||||
fail(label, "sep codegen non-deterministic");
|
||||
};
|
||||
// definition guard only: a READ (LEAQ origin_tag) is legitimate in a
|
||||
// dependent; the DATA[W] definition belongs to leaf's compile alone.
|
||||
let s: str = testenv.readfile(css);
|
||||
if (testenv.has(s, "DATAW origin_tag(SB)")
|
||||
|| testenv.has(s, "DATA origin_tag(SB)")) {
|
||||
fail(label, "imported value-global re-emitted (link collision)");
|
||||
};
|
||||
};
|
||||
|
||||
// compile (-c) + assemble one package unit through one toolchain.
|
||||
fn buildpkg(td: str, name: str, comp: str, asmtool: str, unit: str,
|
||||
sf: str, of: str) void = {
|
||||
let cav: []str = [testenv.driver(comp), "-c", "-o", sf, unit];
|
||||
if (runcode(td, strings.concat("c_", name), cav) != 0) {
|
||||
fail(name, strings.concat(comp, " -c failed"));
|
||||
};
|
||||
let aav: []str = [testenv.driver(asmtool), "-o", of, sf];
|
||||
if (runcode(td, strings.concat("a_", name), aav) != 0) {
|
||||
fail(name, strings.concat(asmtool, " failed"));
|
||||
};
|
||||
};
|
||||
|
||||
// materialize leaf.ww + leaf.wwi + mid.prod.ww + mid.wwi under td.
|
||||
fn producecore(td: str) void = {
|
||||
let leafww: str = strings.concat(td, "/leaf.ww");
|
||||
testenv.writefile(leafww, leafsrc());
|
||||
produce(td, "leaf", leafww, strings.concat(td, "/leaf.wwi"));
|
||||
let prod: str = strings.concat(td, "/mid.prod.ww");
|
||||
testenv.writefile(prod, strings.concat(
|
||||
sec("//ww:module leaf",
|
||||
testenv.readfile(strings.concat(td, "/leaf.wwi"))),
|
||||
sec("//ww:module-reset", midsrc())));
|
||||
produce(td, "mid", prod, strings.concat(td, "/mid.wwi"));
|
||||
};
|
||||
|
||||
// materialize sleaf.ww + sleaf.wwi (+ optionally smid.wwi) under td.
|
||||
fn producestr(td: str, withsmid: bool) void = {
|
||||
let sleafww: str = strings.concat(td, "/sleaf.ww");
|
||||
testenv.writefile(sleafww, sleafsrc());
|
||||
produce(td, "sleaf", sleafww, strings.concat(td, "/sleaf.wwi"));
|
||||
if (!withsmid) { return; };
|
||||
let prod: str = strings.concat(td, "/smid.prod.ww");
|
||||
testenv.writefile(prod, strings.concat(
|
||||
sec("//ww:module sleaf",
|
||||
testenv.readfile(strings.concat(td, "/sleaf.wwi"))),
|
||||
sec("//ww:module-reset", smidsrc())));
|
||||
produce(td, "smid", prod, strings.concat(td, "/smid.wwi"));
|
||||
};
|
||||
|
||||
@test fn m3keystone() void = {
|
||||
let td: str = testenv.fresh();
|
||||
producecore(td);
|
||||
producestr(td, false);
|
||||
let rl: str = testenv.readfile(strings.concat(td, "/leaf.wwi"));
|
||||
let rm: str = testenv.readfile(strings.concat(td, "/mid.wwi"));
|
||||
let rsl: str = testenv.readfile(strings.concat(td, "/sleaf.wwi"));
|
||||
keystone(td, "mid",
|
||||
strings.concat(sec("//ww:module leaf", leafsrc()),
|
||||
sec("//ww:module-reset", midsrc())),
|
||||
strings.concat(sec("//ww:module leaf", rl),
|
||||
sec("//ww:module-reset", midsrc())));
|
||||
keystone(td, "root",
|
||||
strings.concat(sec("//ww:module leaf", leafsrc()),
|
||||
sec("//ww:module mid", midsrc()),
|
||||
sec("//ww:module-reset", rootsrc())),
|
||||
strings.concat(sec("//ww:module leaf", rl),
|
||||
sec("//ww:module mid", rm),
|
||||
sec("//ww:module-reset", rootsrc())));
|
||||
keystone(td, "smid",
|
||||
strings.concat(sec("//ww:module sleaf", sleafsrc()),
|
||||
sec("//ww:module-reset", smidsrc())),
|
||||
strings.concat(sec("//ww:module sleaf", rsl),
|
||||
sec("//ww:module-reset", smidsrc())));
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
@test fn m3chain() void = {
|
||||
let td: str = testenv.fresh();
|
||||
producecore(td);
|
||||
let rl: str = testenv.readfile(strings.concat(td, "/leaf.wwi"));
|
||||
let rm: str = testenv.readfile(strings.concat(td, "/mid.wwi"));
|
||||
let midsep: str = strings.concat(td, "/mid.sep.ww");
|
||||
testenv.writefile(midsep, strings.concat(
|
||||
sec("//ww:module leaf", rl),
|
||||
sec("//ww:module-reset", midsrc())));
|
||||
let rootsep: str = strings.concat(td, "/root.sep.ww");
|
||||
testenv.writefile(rootsep, strings.concat(
|
||||
sec("//ww:module leaf", rl),
|
||||
sec("//ww:module mid", rm),
|
||||
sec("//ww:module-reset", rootsrc())));
|
||||
|
||||
let comps: []str = ["w6c", "w6c_ww"];
|
||||
let asms: []str = ["w6a", "w6a_ww"];
|
||||
let lnks: []str = ["w6l", "w6l_ww"];
|
||||
let tags: []str = ["cs", "ww"];
|
||||
let rt: str = strings.concat(testenv.repo(), "/out/lib/libwwrt.a");
|
||||
let exes: []str = ["", ""];
|
||||
let t: i32 = 0;
|
||||
for (t < 2) {
|
||||
let lo: str = strings.concat(td, "/leaf.", tags[t], ".o");
|
||||
let mo: str = strings.concat(td, "/mid.", tags[t], ".o");
|
||||
let ro: str = strings.concat(td, "/root.", tags[t], ".o");
|
||||
buildpkg(td, strings.concat("leaf_", tags[t]), comps[t], asms[t],
|
||||
strings.concat(td, "/leaf.ww"),
|
||||
strings.concat(td, "/leaf.", tags[t], ".s"), lo);
|
||||
buildpkg(td, strings.concat("mid_", tags[t]), comps[t], asms[t],
|
||||
midsep, strings.concat(td, "/mid.", tags[t], ".s"), mo);
|
||||
buildpkg(td, strings.concat("root_", tags[t]), comps[t], asms[t],
|
||||
rootsep, strings.concat(td, "/root.", tags[t], ".s"), ro);
|
||||
let exe: str = strings.concat(td, "/prog.", tags[t]);
|
||||
let lav: []str = [testenv.driver(lnks[t]), "-o", exe, ro, mo, lo,
|
||||
rt];
|
||||
if (runcode(td, strings.concat("l_", tags[t]), lav) != 0) {
|
||||
fail("chain", strings.concat(lnks[t], " link failed"));
|
||||
};
|
||||
let rav: []str = [exe];
|
||||
if (runcode(td, strings.concat("run_", tags[t]), rav) != 59) {
|
||||
fail("chain", strings.concat(tags[t], " sep program exit != 59 ",
|
||||
"(cross-boundary behavior wrong)"));
|
||||
};
|
||||
exes[t] = exe;
|
||||
t += 1;
|
||||
};
|
||||
// symbol order is identical (same object set, same order); the .s
|
||||
// are byte-id, so the linked images must match too.
|
||||
if (!testenv.same(testenv.readfile(exes[0]),
|
||||
testenv.readfile(exes[1]))) {
|
||||
fail("chain", "cs exe != ww exe (rule 10, final image)");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
@test fn m3str49() void = {
|
||||
let td: str = testenv.fresh();
|
||||
producestr(td, true);
|
||||
let rsl: str = testenv.readfile(strings.concat(td, "/sleaf.wwi"));
|
||||
let rsm: str = testenv.readfile(strings.concat(td, "/smid.wwi"));
|
||||
let smidsep: str = strings.concat(td, "/smid.sep.ww");
|
||||
testenv.writefile(smidsep, strings.concat(
|
||||
sec("//ww:module sleaf", rsl),
|
||||
sec("//ww:module-reset", smidsrc())));
|
||||
let srootsep: str = strings.concat(td, "/sroot.sep.ww");
|
||||
testenv.writefile(srootsep, strings.concat(
|
||||
sec("//ww:module sleaf", rsl),
|
||||
sec("//ww:module smid", rsm),
|
||||
sec("//ww:module-reset", srootsrc())));
|
||||
|
||||
let comps: []str = ["w6c", "w6c_ww"];
|
||||
let asms: []str = ["w6a", "w6a_ww"];
|
||||
let lnks: []str = ["w6l", "w6l_ww"];
|
||||
let tags: []str = ["cs", "ww"];
|
||||
let rt: str = strings.concat(testenv.repo(), "/out/lib/libwwrt.a");
|
||||
let exes: []str = ["", ""];
|
||||
let t: i32 = 0;
|
||||
for (t < 2) {
|
||||
let ls: str = strings.concat(td, "/sleaf.", tags[t], ".s");
|
||||
let ms: str = strings.concat(td, "/smid.", tags[t], ".s");
|
||||
let lo: str = strings.concat(td, "/sleaf.", tags[t], ".o");
|
||||
let mo: str = strings.concat(td, "/smid.", tags[t], ".o");
|
||||
let ro: str = strings.concat(td, "/sroot.", tags[t], ".o");
|
||||
buildpkg(td, strings.concat("sleaf_", tags[t]), comps[t], asms[t],
|
||||
strings.concat(td, "/sleaf.ww"), ls, lo);
|
||||
buildpkg(td, strings.concat("smid_", tags[t]), comps[t], asms[t],
|
||||
smidsep, ms, mo);
|
||||
buildpkg(td, strings.concat("sroot_", tags[t]), comps[t], asms[t],
|
||||
srootsep, strings.concat(td, "/sroot.", tags[t], ".s"), ro);
|
||||
// #49 structural proof (cstage .s once): module-prefixed strlit
|
||||
// labels, never a shared bare _S_0
|
||||
if (t == 0) {
|
||||
let sl: str = testenv.readfile(ls);
|
||||
let sm: str = testenv.readfile(ms);
|
||||
if (!testenv.has(sl, "sleaf._S_")
|
||||
|| !testenv.has(sm, "smid._S_")) {
|
||||
fail("str49", "strlit label not module-prefixed");
|
||||
};
|
||||
if (testenv.has(sl, "DATA _S_0(SB)")
|
||||
|| testenv.has(sm, "DATA _S_0(SB)")) {
|
||||
fail("str49",
|
||||
"bare _S_0 survives (cross-unit link collision)");
|
||||
};
|
||||
};
|
||||
let exe: str = strings.concat(td, "/sprog.", tags[t]);
|
||||
let lav: []str = [testenv.driver(lnks[t]), "-o", exe, ro, mo, lo,
|
||||
rt];
|
||||
if (runcode(td, strings.concat("l_", tags[t]), lav) != 0) {
|
||||
fail("str49", strings.concat(lnks[t],
|
||||
" str-pkg sep link failed (#49)"));
|
||||
};
|
||||
let rav: []str = [exe];
|
||||
if (runcode(td, strings.concat("run_", tags[t]), rav) != 160) {
|
||||
fail("str49", strings.concat(tags[t], " str-link exit != 160 ",
|
||||
"(#49 _S_ collision corrupts the linked strings)"));
|
||||
};
|
||||
exes[t] = exe;
|
||||
t += 1;
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(exes[0]),
|
||||
testenv.readfile(exes[1]))) {
|
||||
fail("str49", "cs str-exe != ww str-exe (rule 10, #49)");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
@test fn m3leaf53() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let ceaww: str = strings.concat(td, "/cea.ww");
|
||||
testenv.writefile(ceaww, ceasrc());
|
||||
let cebww: str = strings.concat(td, "/ceb.ww");
|
||||
testenv.writefile(cebww, cebsrc());
|
||||
produce(td, "cea", ceaww, strings.concat(td, "/cea.wwi"));
|
||||
produce(td, "ceb", cebww, strings.concat(td, "/ceb.wwi"));
|
||||
let cxsep: str = strings.concat(td, "/cxroot.sep.ww");
|
||||
testenv.writefile(cxsep, strings.concat(
|
||||
sec("//ww:module cea",
|
||||
testenv.readfile(strings.concat(td, "/cea.wwi"))),
|
||||
sec("//ww:module ceb",
|
||||
testenv.readfile(strings.concat(td, "/ceb.wwi"))),
|
||||
sec("//ww:module-reset", cxrootsrc())));
|
||||
|
||||
let comps: []str = ["w6c", "w6c_ww"];
|
||||
let asms: []str = ["w6a", "w6a_ww"];
|
||||
let lnks: []str = ["w6l", "w6l_ww"];
|
||||
let tags: []str = ["cs", "ww"];
|
||||
let rt: str = strings.concat(testenv.repo(), "/out/lib/libwwrt.a");
|
||||
let exes: []str = ["", ""];
|
||||
let t: i32 = 0;
|
||||
for (t < 2) {
|
||||
let as_: str = strings.concat(td, "/cea.", tags[t], ".s");
|
||||
let bs: str = strings.concat(td, "/ceb.", tags[t], ".s");
|
||||
let ao: str = strings.concat(td, "/cea.", tags[t], ".o");
|
||||
let bo: str = strings.concat(td, "/ceb.", tags[t], ".o");
|
||||
let ro: str = strings.concat(td, "/cxroot.", tags[t], ".o");
|
||||
buildpkg(td, strings.concat("cea_", tags[t]), comps[t], asms[t],
|
||||
ceaww, as_, ao);
|
||||
buildpkg(td, strings.concat("ceb_", tags[t]), comps[t], asms[t],
|
||||
cebww, bs, bo);
|
||||
buildpkg(td, strings.concat("cxroot_", tags[t]), comps[t], asms[t],
|
||||
cxsep, strings.concat(td, "/cxroot.", tags[t], ".s"), ro);
|
||||
// #53 structural proof (cstage .s once): module-prefixed exported
|
||||
// non-fn leaves, never a shared bare v/K
|
||||
if (t == 0) {
|
||||
let sa: str = testenv.readfile(as_);
|
||||
let sb: str = testenv.readfile(bs);
|
||||
if (!testenv.has(sa, "cea.v(SB)") || !testenv.has(sa, "cea.K(SB)")
|
||||
|| !testenv.has(sb, "ceb.v(SB)")
|
||||
|| !testenv.has(sb, "ceb.K(SB)")) {
|
||||
fail("leaf53", "exported non-fn leaf not module-prefixed");
|
||||
};
|
||||
if (testenv.has(sa, "DATAW v(SB)") || testenv.has(sa, "DATA K(SB)")
|
||||
|| testenv.has(sb, "DATAW v(SB)")
|
||||
|| testenv.has(sb, "DATA K(SB)")) {
|
||||
fail("leaf53",
|
||||
"bare exported leaf survives (cross-unit link collision)");
|
||||
};
|
||||
};
|
||||
let exe: str = strings.concat(td, "/cxprog.", tags[t]);
|
||||
let lav: []str = [testenv.driver(lnks[t]), "-o", exe, ro, ao, bo,
|
||||
rt];
|
||||
if (runcode(td, strings.concat("l_", tags[t]), lav) != 0) {
|
||||
fail("leaf53", strings.concat(lnks[t],
|
||||
" export-leaf sep link failed (#53)"));
|
||||
};
|
||||
let rav: []str = [exe];
|
||||
if (runcode(td, strings.concat("run_", tags[t]), rav) != 140) {
|
||||
fail("leaf53", strings.concat(tags[t], " export-leaf exit != 140 ",
|
||||
"(#53 same-leaf collision corrupts the linked data)"));
|
||||
};
|
||||
exes[t] = exe;
|
||||
t += 1;
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(exes[0]),
|
||||
testenv.readfile(exes[1]))) {
|
||||
fail("leaf53", "cs export-leaf exe != ww exe (rule 10, #53)");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
Reference in New Issue
Block a user