The five symmetric rows compile their r764_amp_fn_ident_* fixture sources in place (runtime owned by those fixtures; pre-fix junk-store still exits 0, so the LEAQ window is the discriminator) and keep the cs==ws byte-id leg. The cross-module row stays cstage-only pending #184; its wwstage/byte-id legs graduate with that task.
128 lines
4.6 KiB
Plaintext
128 lines
4.6 KiB
Plaintext
package ampfn_test;
|
|
|
|
// Direct-w6c asm-window gate over `&fn` address-of lowering (#180).
|
|
// Port of the retired native carrier test/wcc/764_amp_fn_ident.c;
|
|
// every unowned assertion preserved. Runtime for the five symmetric
|
|
// rows is owned by the r764_amp_fn_ident_* fixtures (their sources
|
|
// are compiled here IN PLACE so fixture and window can never drift);
|
|
// pre-fix those fixtures still exit 0 on the junk store — the LEAQ
|
|
// presence below is the actual discriminator the corpus cannot own.
|
|
//
|
|
// Rows 1-5: the cstage .s must contain the row's `LEAQ <sym>(SB)`
|
|
// line (absent pre-#180: the cgen N_UN TK_AMP IDENT arm had no TY_FN
|
|
// branch, so the assign site stored stale AX junk), and cstage vs
|
|
// wwstage .s must be byte-identical (rule 10; the carrier compared
|
|
// driver __root.s — same emitter output, direct w6c form per the
|
|
// residual audit).
|
|
//
|
|
// cross_module: `&pkg.fn` over a real import tree. CSTAGE-ONLY —
|
|
// wwstage bails asserttyped on the N_UN TK_AMP N_DOT-mod-ident shape
|
|
// (open #184); its build/run and byte-id legs graduate when #184
|
|
// lifts. The M1 path-mangled `LEAQ wcamffn764mod.somefn(SB)` and the
|
|
// build+run exit 0 are pinned; separate fresh trees keep the -S
|
|
// compile and the full build from sharing a stale sepwork.
|
|
|
|
import os;
|
|
import os.exec;
|
|
import strings;
|
|
import testenv;
|
|
import time;
|
|
|
|
fn fail(label: str, why: str) void = {
|
|
let m: str = strings.concat("ampfn 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;
|
|
};
|
|
|
|
fn emit(td: str, label: str, stage: str, drv: str, src: str,
|
|
outname: str) void = {
|
|
let av: []str = [drv, "-o", strings.concat(td, "/", outname), src];
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(td, td, stage, av, tmo(), &co);
|
|
if (co.termination != exec.termination.EXIT || co.code != 0) {
|
|
fail(label, strings.concat(stage, " compile failed"));
|
|
};
|
|
};
|
|
|
|
fn leaqrow(label: str, fixture: str, needle: str) void = {
|
|
let src: str = strings.concat(testenv.repo(),
|
|
"/test/wcc/data/r764_amp_fn_ident_", fixture, "/case.ww");
|
|
let td: str = testenv.fresh();
|
|
emit(td, label, "cstage", testenv.driver("w6c"), src, "cs.s");
|
|
emit(td, label, "wwstage", testenv.driver("w6c_ww"), src, "ws.s");
|
|
let cs: str = testenv.readfile(strings.concat(td, "/cs.s"));
|
|
let ws: str = testenv.readfile(strings.concat(td, "/ws.s"));
|
|
if (!testenv.has(cs, needle)) {
|
|
fail(label, strings.concat("missing `", needle,
|
|
"` in cstage .s (silent TK_AMP IDENT drop)"));
|
|
};
|
|
if (!testenv.same(cs, ws)) {
|
|
fail(label, "cstage vs wwstage asm differs");
|
|
};
|
|
testenv.clean(td);
|
|
};
|
|
|
|
@test fn ampfnleaq() void = {
|
|
leaqrow("minimal", "minimal", "LEAQ\tmain.add1(SB)");
|
|
leaqrow("branched_callee", "branched", "LEAQ\tmain.bb(SB)");
|
|
leaqrow("alias_chain", "alias_chain", "LEAQ\tmain.add1(SB)");
|
|
leaqrow("fn_with_args", "args", "LEAQ\tmain.many(SB)");
|
|
leaqrow("fn_tuple_return", "tuple_return", "LEAQ\tmain.pair(SB)");
|
|
};
|
|
|
|
fn xmodtree() str = {
|
|
let td: str = testenv.fresh();
|
|
assert(os.mkdir(strings.concat(td, "/wcamffn764mod"), 493) == 0);
|
|
testenv.writefile(
|
|
strings.concat(td, "/wcamffn764mod/wcamffn764mod.ww"),
|
|
strings.concat(
|
|
"package wcamffn764mod;\n",
|
|
"export fn somefn(x: i32) i32 = { return x + 1; };\n"));
|
|
testenv.writefile(strings.concat(td, "/main764.ww"), strings.concat(
|
|
"package main;\n",
|
|
"import wcamffn764mod;\n",
|
|
"export fn main() i32 = {\n",
|
|
" let f = &wcamffn764mod.somefn;\n",
|
|
" return 0;\n",
|
|
"};\n"));
|
|
return td;
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
@test fn crossmodule() void = {
|
|
let tda: str = xmodtree();
|
|
let av: []str = [testenv.driver("ww"), "build", "-S", "-o",
|
|
strings.concat(tda, "/main764"), "main764.ww"];
|
|
if (runcode(tda, "compile", av) != 0) {
|
|
fail("cross_module", "cstage ww build -S failed");
|
|
};
|
|
let s: str = testenv.readfile(
|
|
strings.concat(tda, "/main764.sepwork/__root.s"));
|
|
if (!testenv.has(s, "LEAQ\twcamffn764mod.somefn(SB)")) {
|
|
fail("cross_module",
|
|
"missing path-mangled LEAQ wcamffn764mod.somefn(SB)");
|
|
};
|
|
testenv.clean(tda);
|
|
let tdb: str = xmodtree();
|
|
let bav: []str = [testenv.driver("ww"), "build", "-o",
|
|
strings.concat(tdb, "/main764"), "main764.ww"];
|
|
if (runcode(tdb, "build", bav) != 0) {
|
|
fail("cross_module", "cstage ww build failed");
|
|
};
|
|
let rav: []str = [strings.concat(tdb, "/main764")];
|
|
if (runcode(tdb, "run", rav) != 0) {
|
|
fail("cross_module", "run-exit != 0");
|
|
};
|
|
testenv.clean(tdb);
|
|
};
|