diff --git a/Makefile b/Makefile index f4b3f4ba..5d7ffc74 100644 --- a/Makefile +++ b/Makefile @@ -395,10 +395,10 @@ BYTEID_WRAPPER_SOURCES = test/wcc/631_def_neg_global.c \ test/wcc/795_xmod_valglobal_run.c \ test/wcc/796_xmod_valglobal_dot_run.c \ test/wcc/798_tuple_sret_callee.c \ - test/wcc/815_fmt_int_run.c test/wcc/844_size_untyped_int.c \ + test/wcc/844_size_untyped_int.c \ test/wcc/926_tagscr_sizes_run.c test/wcc/930_free_noop_run.c \ - test/wcc/940_global_sret_run.c test/wcc/946_structparam_run.c \ - test/wcc/946_structret_run.c test/wcc/951_defdim_struct_run.c \ + test/wcc/946_structparam_run.c \ + test/wcc/946_structret_run.c \ test/wcc/989_m1mangle_sym.c test/wcc/989_m1union_run.c \ test/wcc/989_m2wwi_run.c test/wcc/989_structlocal_frame.c \ test/wcc/989_wwileaf_run.c test/wcc/989_lib_byteid.c diff --git a/docs/test-system-v2.md b/docs/test-system-v2.md index d5efd18b..39a8fc2c 100644 --- a/docs/test-system-v2.md +++ b/docs/test-system-v2.md @@ -36,17 +36,21 @@ The live declarative compiler corpus has 1,229 fixtures and 2,458 C/WW cells: 314 expected rejections (290 shared and 24 stage-specific), 12 compile-only successes, 137 exit-zero programs, and 766 explicit-exit programs. -174 native C carriers remain. They are partitioned exactly once as five -in-process units, 27 byte/artifact gates, six bootstrap gates, one platform +171 native C carriers remain. They are partitioned exactly once as five +in-process units, 24 byte/artifact gates, six bootstrap gates, one platform gate, and 135 residual compiler, package-layout, ABI, diagnostic-observer, driver, linker, or FFI gates. Rows migrated to fixtures or native `@test` owners were removed from those carriers; there is no compatibility execution path for retired rows. 61 former byte/artifact carriers whose only assertion was a cstage-vs-wwstage `.s` byte-compare of corpus fixtures were retired -into the blanket `test-data-byteid` comparator; the 27 survivors observe +into the blanket `test-data-byteid` comparator; the survivors observe something the blanket cannot: assembly patterns, symbol tables, frame layouts, `.wwi` round-trips, inline sources with no corpus twin, or the -wwstage-driver leg. +wwstage-driver leg. Wwstage-driver-leg byte identity (`ww_ww` versus `ww` +over the emitted `.s` set) has one owner, `989_lib_byteid`, whose unit +sweep spans lib test fixtures, import probes, and a zero-dep root-only +build; the former 815/940/951 driver-parity carriers were folded into it, +their content identity already owned by their corpus twins. ## Public targets diff --git a/test/wcc/815_fmt_int_run.c b/test/wcc/815_fmt_int_run.c deleted file mode 100644 index 34380056..00000000 --- a/test/wcc/815_fmt_int_run.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 815: residual separated-package cstage/wwstage assembly identity. - * Runtime is owned by r815_*; -S stops both driver legs before assembly, - * archive creation, and linking. The sorted package-assembly concatenation - * remains the byte oracle. - */ -#include -#include -#include -#include -#include - -struct row { const char *label, *path; }; -static const struct row rows[] = { - { "bare_int", "test/wcc/data/r815_bare_int/case.ww" }, - { "bare_int_neg", "test/wcc/data/r815_bare_int_neg/case.ww" }, - { "bare_uint", "test/wcc/data/r815_bare_uint/case.ww" }, - { "uint_highbit", "test/wcc/data/r815_uint_highbit/case.ww" }, - { "int_printf", "test/wcc/data/r815_int_printf/case.ww" }, - { "unaffected_i64", "test/wcc/data/r815_unaffected_i64/case.ww" }, - { "unaffected_str", "test/wcc/data/r815_unaffected_str/case.ww" }, - { "mixed", "test/wcc/data/r815_mixed/case.ww" }, -}; - -static int runwait(const char *cmd) { - int rc = system(cmd); - return rc != -1 && WIFEXITED(rc) ? WEXITSTATUS(rc) : -1; -} - -static int copyfile(const char *src, const char *dst) { - char buf[8192]; size_t n; int rc = 0; - FILE *in = fopen(src, "rb"), *out; - if (!in) return -1; - out = fopen(dst, "wb"); - if (!out) { fclose(in); return -1; } - while ((n = fread(buf, 1, sizeof buf, in)) != 0) - if (fwrite(buf, 1, n, out) != n) { rc = -1; break; } - if (ferror(in)) rc = -1; - if (fclose(out) != 0) rc = -1; - fclose(in); return rc; -} - -static int samefile(const char *a, const char *b) { - FILE *fa = fopen(a, "rb"), *fb = fopen(b, "rb"); int rc = 0; - if (!fa || !fb) rc = -1; - else for (;;) { int ca = fgetc(fa), cb = fgetc(fb); if (ca != cb) { rc = -1; break; } if (ca == EOF) break; } - if (fa) fclose(fa); if (fb) fclose(fb); return rc; -} - -static int byteid(const char *cdrv, const char *wdrv, const char *cwd, - const struct row *r, int seq) { - char tmp[256], src[512], cs[512], ws[512], cmd[2048]; int rc = -1; - snprintf(tmp, sizeof tmp, "/tmp/fic_%d_b_%d", getpid(), seq); - snprintf(src, sizeof src, "%s/main815b.ww", tmp); - snprintf(cs, sizeof cs, "%s/all_cs.s", tmp); - snprintf(ws, sizeof ws, "%s/all_ww.s", tmp); - /* an unowned path (stale dir, full /tmp) must not be built in — or - * rm -rf'd — below. */ - if (mkdir(tmp, 0755) != 0) { perror(tmp); return -1; } - if (copyfile(r->path, src) != 0) goto out; - snprintf(cmd, sizeof cmd, - "cd %s && timeout 180 %s build -S -I %s/lib " - "-o %s/main815b_c %s 2>/dev/null", tmp, cdrv, cwd, tmp, src); - if (runwait(cmd) != 0) goto out; - snprintf(cmd, sizeof cmd, - "cd %s && timeout 180 %s build -S -I %s/lib " - "-o %s/main815b_w %s 2>/dev/null", tmp, wdrv, cwd, tmp, src); - if (runwait(cmd) != 0) goto out; - snprintf(cmd, sizeof cmd, - "cat %s/main815b_c.sepwork/*.s > %s 2>/dev/null", tmp, cs); - if (runwait(cmd) != 0) goto out; - snprintf(cmd, sizeof cmd, - "cat %s/main815b_w.sepwork/*.s > %s 2>/dev/null", tmp, ws); - if (runwait(cmd) != 0) goto out; - rc = samefile(cs, ws); -out: - if (rc != 0) fprintf(stderr, "fmt_int_run[%s]: byte mismatch/error\n", r->label); - snprintf(cmd, sizeof cmd, "rm -rf %s", tmp); - if (runwait(cmd) != 0) { - fprintf(stderr, "fmt_int_run[%s]: cleanup %s failed\n", r->label, tmp); - if (rc == 0) rc = -1; - } - return rc; -} - -int main(void) { - const char *bin = getenv("BIN"); char cwd[1024], absbin[1024]; - char cdrv[1024], wdrv[1024]; - if (!getcwd(cwd, sizeof cwd)) return 1; - if (!bin) bin = "out/bin"; - if (bin[0] != '/') { snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); bin = absbin; } - snprintf(cdrv, sizeof cdrv, "%s/ww", bin); - snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin); - if (access(wdrv, X_OK) != 0) { fprintf(stderr, "fmt_int_run: skip wwstage\n"); return 0; } - int n = (int)(sizeof rows / sizeof rows[0]), fail = 0; - for (int i = 0; i < n; i++) if (byteid(cdrv, wdrv, cwd, &rows[i], i) != 0) fail++; - if (fail) { fprintf(stderr, "fmt_int_run: %d/%d byte rows failed\n", fail, n); return 1; } - printf("fmt_int_run: %d/%d byte rows ok\n", n, n); return 0; -} diff --git a/test/wcc/940_global_sret_run.c b/test/wcc/940_global_sret_run.c deleted file mode 100644 index 4bd6124f..00000000 --- a/test/wcc/940_global_sret_run.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * 940_global_sret_run — project #220. sret (>24B by-value struct - * return) assigned into a GLOBAL lvalue must land the whole struct, - * not a truncated 8-byte store. - * - * Gate-blind family (sibling of #211): pre-fix BOTH stages emitted the - * SAME broken `MOVQ AX, g(SB)` (only the sret return pointer reached - * the global; the struct body, written to a scratch temp, was lost), so - * asm byte-id stayed GREEN while runtime was wrong — g.pos == 0 for the - * #94 io vtable cgoutstream pattern. The runtime rows below are the net. - * - * Surfacing case: the eFinal FLIP repointed cgen.ww's per-fn body output - * through a GLOBAL `let cgoutstream: memio.stream` (>24B) wired once via - * `cgoutstream = memio.dynamic()`; the truncated store left pos==0 so - * the buffered body never flushed and w6c_ww emitted prologue-only. - * - * The fix routes the sret dest pointer to the global's symbol address - * (LEAQ g(SB), DI) — zero-copy, the same discipline the local case - * already used (LEAQ off(BP), DI). Local rows pin no regression at the - * shared cgassign / cglet sret-receive sites. - * - * Runtime behavior is carried by the r940_global_sret_* wwfixtures. This - * wrapper retains the separate-build assembly artifacts and their byte - * identity (cs.s == ww.s, rule 10). - */ -#include -#include -#include -#include -#include -#include -#include "wwtestpkg.h" - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -struct row { const char *label; const char *src; int want; }; - -static const struct row rows[] = { - /* GLOBAL sret assign: `let g: quad;` at module scope, `g = mk()` - * in main. Pre-fix the global got only `MOVQ AX, g(SB)` and the - * field reads returned garbage. */ - { "global_assign", - "type quad = struct { a: i64, b: i64, c: i64, d: i64 };\n" - "fn mk(x: i64) quad = {\n" - " return quad { a = x, b = x + 1i64, c = x + 2i64, d = x + 3i64 };\n" - "};\n" - "let g: quad;\n" - "export fn main() i32 = {\n" - " g = mk(10i64);\n" - " if (g.a != 10i64) { return 1; };\n" - " if (g.b != 11i64) { return 2; };\n" - " if (g.c != 12i64) { return 3; };\n" - " if (g.d != 13i64) { return 4; };\n" - " return 0;\n" - "};\n", - 0 }, - /* GLOBAL sret with a BRANCHED callee (#105): the returned value - * is selected at runtime so a constant-fold coincidence can't mask - * the register/dest routing. */ - { "global_branched", - "type quad = struct { a: i64, b: i64, c: i64, d: i64 };\n" - "fn mk1() quad = { return quad { a = 1i64, b = 2i64, c = 3i64, d = 4i64 }; };\n" - "fn mk2() quad = { return quad { a = 50i64, b = 0i64, c = 0i64, d = 0i64 }; };\n" - "fn pick(w: i64) quad = {\n" - " if (w == 1i64) { return mk1(); };\n" - " return mk2();\n" - "};\n" - "let g: quad;\n" - "export fn main() i32 = {\n" - " g = pick(1i64);\n" - " if (g.a != 1i64) { return 1; };\n" - " if (g.b != 2i64) { return 2; };\n" - " if (g.c != 3i64) { return 3; };\n" - " if (g.d != 4i64) { return 4; };\n" - " return 0;\n" - "};\n", - 0 }, - /* GLOBAL mutated THROUGH A POINTER after the sret assign — the io - * vtable-callback shape that surfaced #220 (callback receives &g, - * mutates a field). */ - { "global_through_pointer", - "type quad = struct { a: i64, b: i64, c: i64, d: i64 };\n" - "fn mk(x: i64) quad = {\n" - " return quad { a = x, b = x + 1i64, c = x + 2i64, d = x + 3i64 };\n" - "};\n" - "fn bump(p: *quad) void = { p.a += 100i64; };\n" - "let g: quad;\n" - "export fn main() i32 = {\n" - " g = mk(7i64);\n" - " bump(&g);\n" - " if (g.a != 107i64) { return 1; };\n" - " if (g.b != 8i64) { return 2; };\n" - " if (g.c != 9i64) { return 3; };\n" - " if (g.d != 10i64) { return 4; };\n" - " return 0;\n" - "};\n", - 0 }, - /* LOCAL decl+assign regression: `let g: quad; g = mk();` routes - * through the same cgassign sret-receive site the fix touches. */ - { "local_assign_regression", - "type quad = struct { a: i64, b: i64, c: i64, d: i64 };\n" - "fn mk(x: i64) quad = {\n" - " return quad { a = x, b = x + 1i64, c = x + 2i64, d = x + 3i64 };\n" - "};\n" - "export fn main() i32 = {\n" - " let g: quad;\n" - " g = mk(20i64);\n" - " if (g.a != 20i64) { return 1; };\n" - " if (g.b != 21i64) { return 2; };\n" - " if (g.c != 22i64) { return 3; };\n" - " if (g.d != 23i64) { return 4; };\n" - " return 0;\n" - "};\n", - 0 }, - /* LOCAL let-init regression: `let g: quad = mk();` routes through - * cglet's sret-receive branch (the sister site). */ - { "local_init_regression", - "type quad = struct { a: i64, b: i64, c: i64, d: i64 };\n" - "fn mk(x: i64) quad = {\n" - " return quad { a = x, b = x + 1i64, c = x + 2i64, d = x + 3i64 };\n" - "};\n" - "export fn main() i32 = {\n" - " let g: quad = mk(30i64);\n" - " if (g.a != 30i64) { return 1; };\n" - " if (g.b != 31i64) { return 2; };\n" - " if (g.c != 32i64) { return 3; };\n" - " if (g.d != 33i64) { return 4; };\n" - " return 0;\n" - "};\n", - 0 }, -}; - -/* #94 sep layout: concat the per-package asm the cstage sep build emitted - * (/gsret_c_.sepwork) and the wwstage sep build emitted - * (/gsret_w_.sepwork), then assert byte-identical. Returns 0 ok, - * 1 differ, -1 harness error. */ -static int -byteid(const char *dir, int i) -{ - char cs[256], ws[256], cmd[1024]; - int rc; - snprintf(cs, sizeof cs, "%s/bid_cs_%d.s", dir, i); - snprintf(ws, sizeof ws, "%s/bid_ww_%d.s", dir, i); - - /* an unmatched sepwork glob must be a loud harness error — two - * empty concatenations would otherwise cmp equal (vacuous green). */ - snprintf(cmd, sizeof cmd, "cat %s/gsret_c_%d.sepwork/*.s > %s 2>/dev/null", - dir, i, cs); - if (runwait(cmd) != 0) { - rc = -1; - goto cleanup; - } - snprintf(cmd, sizeof cmd, "cat %s/gsret_w_%d.sepwork/*.s > %s 2>/dev/null", - dir, i, ws); - if (runwait(cmd) != 0) { - rc = -1; - goto cleanup; - } - - snprintf(cmd, sizeof cmd, "cmp -s %s %s", cs, ws); - rc = runwait(cmd) == 0 ? 0 : 1; -cleanup: - if (unlink(cs) != 0 && errno != ENOENT) { perror(cs); if (rc == 0) rc = -1; } - if (unlink(ws) != 0 && errno != ENOENT) { perror(ws); if (rc == 0) rc = -1; } - return rc; -} - -/* Build `r` with `driver -o /` (per-package asm in - * /.sepwork/), returning zero on build success. */ -static int -run_driver(const char *driver, const struct row *r, const char *dir, - int i, const char *stem) -{ - char src[256], taggedstem[128], cmd[1024]; - snprintf(src, sizeof src, "%s/gsret_%d.ww", dir, i); - snprintf(taggedstem, sizeof taggedstem, "%s_%d", stem, i); - - FILE *f = fopen(src, "wb"); - if (!f) return -1; - wwtest_fputs(r->src, f); - int werr = ferror(f); - if (fclose(f) != 0 || werr) { - fprintf(stderr, "row[%s]: writing %s failed\n", r->label, src); - return -1; - } - - snprintf(cmd, sizeof cmd, - "cd %s && %s build -S -o %s/%s %s", - dir, driver, dir, taggedstem, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: build via %s failed\n", - r->label, driver); - return -1; - } - - return 0; -} - -int -main(void) -{ - const char *bin = getenv("BIN"); - if (!bin) bin = "out/bin"; - char absbin[512]; - if (bin[0] != '/') { - char cwd[256]; - if (getcwd(cwd, sizeof cwd) == NULL) return 1; - snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); - bin = absbin; - } - - char cdrv[640], wdrv[640]; - snprintf(cdrv, sizeof cdrv, "%s/ww", bin); - snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin); - char wwc[640]; - snprintf(wwc, sizeof wwc, "%s/w6c_ww", bin); - int have_ww = (access(wdrv, X_OK) == 0); - int have_wwc = (access(wwc, X_OK) == 0); - - char dir[] = "/tmp/gsret_XXXXXX"; - if (mkdtemp(dir) == NULL) { - perror("mkdtemp"); - return 1; - } - - int n = (int)(sizeof rows / sizeof rows[0]); - int total = 0, fail = 0, cleanfail = 0; - - for (int i = 0; i < n; i++) { - /* cstage separate build → /gsret_c_.sepwork/. */ - int gc = run_driver(cdrv, &rows[i], dir, i, "gsret_c"); - total++; - if (gc != rows[i].want) { - fprintf(stderr, "global_sret_run[cstage][%s]: " - "build=%d want=%d\n", rows[i].label, gc, - rows[i].want); - fail++; - } - - /* wwstage separate build → /gsret_w_.sepwork/. */ - if (have_ww) { - int gw = run_driver(wdrv, &rows[i], dir, i, "gsret_w"); - total++; - if (gw != rows[i].want) { - fprintf(stderr, "global_sret_run[wwstage][%s]: " - "build=%d want=%d\n", rows[i].label, gw, - rows[i].want); - fail++; - } - - /* byte-id (rule 10): the per-package w6c asm (cstage sep - * build) == the w6c_ww asm (wwstage sep build). */ - if (have_wwc) { - total++; - int bid = byteid(dir, i); - if (bid != 0) { - fprintf(stderr, "global_sret_run[byteid][%s]: " - "%s\n", rows[i].label, - bid == 1 ? "cs.s != ww.s" - : "harness error"); - fail++; - } - } - } - - char p[640]; - snprintf(p, sizeof p, "%s/gsret_%d.ww", dir, i); - /* ENOENT = the row failed before writing the source. */ - if (unlink(p) != 0 && errno != ENOENT) { - perror(p); - cleanfail = 1; - } - snprintf(p, sizeof p, "rm -rf %s/gsret_c_%d.sepwork " - "%s/gsret_w_%d.sepwork %s/gsret_c_%d %s/gsret_w_%d", - dir, i, dir, i, dir, i, dir, i); - if (runwait(p) != 0) { - fprintf(stderr, "global_sret_run: cleanup row %d " - "failed\n", i); - cleanfail = 1; - } - } - if (rmdir(dir) != 0) { - perror(dir); - cleanfail = 1; - } - - if (!have_ww) - fprintf(stderr, "global_sret_run: skip wwstage (no %s)\n", wdrv); - - if (fail) { - fprintf(stderr, "global_sret_run: %d/%d checks failed\n", - fail, total); - return 1; - } - /* cleanup diagnostics already printed; must not stay green. */ - if (cleanfail) - return 1; - printf("global_sret_run: %d/%d ok\n", total, total); - return 0; -} diff --git a/test/wcc/951_defdim_struct_run.c b/test/wcc/951_defdim_struct_run.c deleted file mode 100644 index cf7ae705..00000000 --- a/test/wcc/951_defdim_struct_run.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 951_defdim_struct_run — byte-id net for #141: a struct - * field whose array dimension is a `def` (`[MAX]u8`, MAX a same-module - * def), not an integer literal. BOTH stages were wrong, oppositely: - * - * cstage LOUD-rejected ("array length must be an integer literal"). - * resolve_type's N_TARRAY arm folded only N_INTLIT dims; a def-ref - * fell through to the err. Root was a phase-ordering trap: def names - * weren't bound in scope when resolve_typedecl walked the struct - * body, so eval_def_const couldn't see MAX. Fix binds def-name stubs - * before type-body resolution, then folds the dim via eval_def_const. - * - * wwstage SILENTLY mis-laid-out the struct. astsize sized the def-dim - * field to 0 (only N_INTLIT dims were read), so the N_TSTRUCT - * `off += astsize(field)` loop gave the NEXT field the array's offset - * — the trailing scalar overlapped the array, reading/writing the - * wrong bytes (ken pdefM4: end != written). Fix routes every N_TARRAY - * length reader through a shared arrayelen() that folds the def. - * - * The TEETH row is the trailing scalar after the def-dim array: pre-fix - * ww read a corrupted `end`; post-fix it round-trips and cs==ww byte-id. - * Closes #13's def-dim half (the slice-repeat clause stays open). - * - * Runtime values live in r951_defdim_* fixtures. This carrier compares the - * `ww build`-produced - * .combined.ww, not the raw src: w6c does no import resolution, so the - * cross-module row (C1, `import os`) only folds once concatenated, and a - * same-module row combines to itself. The last row is the ACTUAL - * path::buffer shape — a cross-module `os.PATH_MAX` def dimension (the - * N_DOT fold arm). u8 array elements + i32 trailing scalars only (the - * i32 return is MOVL/MOVSXD byte-id; see 949_dotbase_arr_run). - */ -#include -#include -#include -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -struct row { const char *label; const char *src; }; - -static const struct row rows[] = { - /* TEETH: def-dim array FOLLOWED by a scalar; write both, read the - * scalar back. Pre-fix ww laid `end` at the array's offset (array - * sized 0) → end read garbage. Post-fix end at offset 4 → 42. */ - { "m4_end", - "package main;\n" - "def M: i32 = 4;\n" - "type t = struct { b: [M]u8, end: i32 };\n" - "export fn main() i32 = {\n" - " let s: t;\n" - " s.b[3] = 9u8;\n" - " s.end = 42;\n" - " return s.end;\n" - "};\n" }, - /* the array element itself must survive too — read the last byte - * (pre-fix the overlapping `end` write would clobber it). */ - { "m4_belem", - "package main;\n" - "def M: i32 = 4;\n" - "type t = struct { b: [M]u8, end: i32 };\n" - "export fn main() i32 = {\n" - " let s: t;\n" - " s.b[3] = 200u8;\n" - " s.end = 7;\n" - " return s.b[3]: i32;\n" - "};\n" }, - /* the ~4KB path::buffer shape — def MAX=4095, read the trailing - * scalar after a 4095-byte array. */ - { "m4095_end", - "package main;\n" - "def MAX: i32 = 4095;\n" - "type t = struct { b: [MAX]u8, end: i32 };\n" - "export fn main() i32 = {\n" - " let s: t;\n" - " s.b[4094] = 5u8;\n" - " s.end = 99;\n" - " return s.end;\n" - "};\n" }, - /* two scalars after the def-dim array — pins the cumulative offset - * (a+c read their written values: 11+22=33). */ - { "twoafter", - "package main;\n" - "def M: i32 = 4;\n" - "type t = struct { b: [M]u8, a: i32, c: i32 };\n" - "export fn main() i32 = {\n" - " let s: t;\n" - " s.a = 11;\n" - " s.c = 22;\n" - " return s.a + s.c;\n" - "};\n" }, - /* C1 (rob-mandatory): the ACTUAL path::buffer shape — a CROSS- - * MODULE def dimension. `def MAX = os.PATH_MAX - 1` folds an N_DOT - * (os.PATH_MAX) const-ref through eval_def_const's cross-module arm, - * which the same-module rows don't exercise. os.PATH_MAX is 4096, so - * MAX is 4095. Byte-id runs on the ww-build combined.ww (w6c alone - * does no import resolution, so it can't compile the raw `import os` - * source). */ - { "xmod_pathmax", - "package main;\n" - "import os;\n" - "def MAX: i32 = os.PATH_MAX - 1;\n" - "type t = struct { b: [MAX]u8, end: i32 };\n" - "export fn main() i32 = {\n" - " let s: t;\n" - " s.b[4094] = 7u8;\n" - " s.end = 77;\n" - " return s.end;\n" - "};\n" }, - { NULL, NULL } -}; - -static int -slurp_eq(const char *a, const char *b) -{ - FILE *fa = fopen(a, "rb"); - FILE *fb = fopen(b, "rb"); - if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; } - int rc = 0; - for (;;) { - int ca = fgetc(fa); - int cb = fgetc(fb); - if (ca != cb) { rc = -1; break; } - if (ca == EOF) break; - } - fclose(fa); fclose(fb); - return rc; -} - -int -main(void) -{ - const char *bin = getenv("BIN"); - if (!bin) bin = "out/bin"; - char absbin[1024]; - if (bin[0] != '/') { - char cwd[1024]; - if (getcwd(cwd, sizeof cwd) == NULL) return 1; - snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); - bin = absbin; - } - - char wdrv[1100]; - snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin); - if (access(wdrv, X_OK) != 0) { - fprintf(stderr, "defdim_struct: ww_ww missing — cannot run " - "the cs==ww byte-id gate (the whole point of this test)\n"); - return 1; - } - - int n = 0, fail = 0; - for (int i = 0; rows[i].src; i++, n++) { - char src[64]; - snprintf(src, sizeof src, "/tmp/wwdds_%d_%d.ww", getpid(), i); - FILE *f = fopen(src, "wb"); - if (f == NULL) { perror(src); fail++; continue; } - fputs(rows[i].src, f); - fclose(f); - - char tmpdir[64]; - snprintf(tmpdir, sizeof tmpdir, "/tmp/wwdds_%d_d_%d", - getpid(), i); - if (mkdir(tmpdir, 0755) != 0) { - /* not owned — must not rm a path we failed to create */ - perror(tmpdir); - fail++; - if (unlink(src) != 0 && errno != ENOENT) - perror(src); - continue; - } - - char base[64]; - const char *b = strrchr(src, '/'); - b = b ? b + 1 : src; - snprintf(base, sizeof base, "%s", b); - char *dot = strrchr(base, '.'); - if (dot && strcmp(dot, ".ww") == 0) *dot = '\0'; - - /* #94 sep layout: each driver's build emits the runnable - * binary at + per-package asm under .sepwork/. - * Distinct stems so the wwstage sepwork doesn't clobber cstage's; - * pin all outputs stay under tmpdir. A - * cross-module row's `import os` resolves per-package, a same- - * module row is just __root — both compare via the sorted glob. */ - char cmd[2048], stem_c[160], stem_w[160]; - snprintf(stem_c, sizeof stem_c, "%s/%s_c", tmpdir, base); - snprintf(stem_w, sizeof stem_w, "%s/%s_w", tmpdir, base); - - char cs_s[64], ws_s[64]; - snprintf(cs_s, sizeof cs_s, "/tmp/wwdds_%d_%d_cs.s", - getpid(), i); - snprintf(ws_s, sizeof ws_s, "/tmp/wwdds_%d_%d_ww.s", - getpid(), i); - - snprintf(cmd, sizeof cmd, - "cd %s && %s/ww build -S -o %s %s", - tmpdir, bin, stem_c, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: cstage build failed\n", - rows[i].label); - fail++; - goto rowdone; - } - - snprintf(cmd, sizeof cmd, - "cd %s && %s/ww_ww build -S -o %s %s " - ">/dev/null 2>&1", tmpdir, bin, stem_w, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: ww_ww build failed\n", - rows[i].label); - fail++; - } else { - /* a failed cat (e.g. an empty sepwork glob) must fail - * the row — two absent trees would compare equal-empty. */ - snprintf(cmd, sizeof cmd, - "cat %s.sepwork/*.s > %s 2>/dev/null", stem_c, cs_s); - int catc = runwait(cmd); - snprintf(cmd, sizeof cmd, - "cat %s.sepwork/*.s > %s 2>/dev/null", stem_w, ws_s); - int catw = runwait(cmd); - if (catc != 0 || catw != 0) { - fprintf(stderr, - "row[%s]: sepwork .s concat failed " - "(cstage=%d wwstage=%d)\n", - rows[i].label, catc, catw); - fail++; - } else if (slurp_eq(cs_s, ws_s) != 0) { - fprintf(stderr, - "row[%s]: cstage/wwstage .s DIFFER " - "(rule-10 byte-id violation)\n", - rows[i].label); - fail++; - } - } - -rowdone: - /* a failed cleanup must fail the carrier, not leak silently; - * ENOENT is fine — an early leg may exit before creating the - * concat files. */ - snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir); - int cleanfail = runwait(cmd) != 0; - if (unlink(src) != 0 && errno != ENOENT) { - perror(src); - cleanfail = 1; - } - if (unlink(cs_s) != 0 && errno != ENOENT) { - perror(cs_s); - cleanfail = 1; - } - if (unlink(ws_s) != 0 && errno != ENOENT) { - perror(ws_s); - cleanfail = 1; - } - if (cleanfail) { - fprintf(stderr, "row[%s]: cleanup failed\n", - rows[i].label); - fail++; - } - } - - if (fail) { - fprintf(stderr, "%d/%d defdim-struct tests failed\n", - fail, n); - return 1; - } - printf("defdim_struct: %d/%d ok (cs==ww byte-id)\n", - n, n); - return 0; -} diff --git a/test/wcc/989_lib_byteid.c b/test/wcc/989_lib_byteid.c index 84b5fc49..2f653955 100644 --- a/test/wcc/989_lib_byteid.c +++ b/test/wcc/989_lib_byteid.c @@ -52,7 +52,7 @@ #include #include -enum { M_ID, M_DIVERGE, M_WWREJECT, NENT_EXPECT = 43 }; +enum { M_ID, M_DIVERGE, M_WWREJECT, NENT_EXPECT = 44 }; struct ent { const char *fixture; /* repo-relative .ww; NULL → probe entry */ @@ -141,6 +141,13 @@ static const struct ent ents[] = { .mode = M_ID, .sentinel = "fn rotl32", .moddir = "lib/crypto/math" }, { .probe = "package main;\nimport c.libc;\nfn main() i32 = { return 0; };\n", .mode = M_ID, .sentinel = "package libc;", .moddir = "lib/c/libc" }, + /* root-only, ZERO-dep build -S: the one driver-leg edge every + * import probe misses (dep-count-0 unit composition). Folded in + * from the retired 815/940/951 driver-parity carriers, whose + * content byteid the corpus twins (r815_/r940_/r951_) own via + * test-data-byteid. No sentinel: there is no dep unit to prove. */ + { .probe = "package main;\nfn main() i32 = { return 0; };\n", + .mode = M_ID }, /* -------- documented-allowed cs≠ww (task #59) ------------ */ { .fixture = "lib/ascii/asciitest.ww", .mode = M_ID, .cite = "#59.1 graduated by #146 str==" }, @@ -253,7 +260,8 @@ check_one(const char *bin, const char *cwd, const struct ent *e, int idx) if (!f) goto out; fputs(e->probe, f); fclose(f); - label = e->moddir; + if (e->moddir) + label = e->moddir; } /* dirname(fixture) leads the search path so bare same-module diff --git a/test/wcc/data/r940_global_sret_assign/case.ww b/test/wcc/data/r940_global_sret_assign/case.ww index 27d3d53f..029a05c3 100644 --- a/test/wcc/data/r940_global_sret_assign/case.ww +++ b/test/wcc/data/r940_global_sret_assign/case.ww @@ -1,5 +1,5 @@ //ww:run -// Runtime half of 940_global_sret_run.c global_assign. +// #220 global-sret family: sret assign into a module-global lvalue. package main; type quad = struct { a: i64, b: i64, c: i64, d: i64 }; fn mk(x: i64) quad = { diff --git a/test/wcc/data/r940_global_sret_branched/case.ww b/test/wcc/data/r940_global_sret_branched/case.ww index cf477f69..fa46c2af 100644 --- a/test/wcc/data/r940_global_sret_branched/case.ww +++ b/test/wcc/data/r940_global_sret_branched/case.ww @@ -1,5 +1,5 @@ //ww:run -// Runtime half of 940_global_sret_run.c global_branched. +// #220 global-sret family: runtime-branched callee (no constant-fold masking). package main; type quad = struct { a: i64, b: i64, c: i64, d: i64 }; fn mk1() quad = { return quad { a = 1i64, b = 2i64, c = 3i64, d = 4i64 }; }; diff --git a/test/wcc/data/r940_global_sret_local_assign/case.ww b/test/wcc/data/r940_global_sret_local_assign/case.ww index afdd8ba8..169eb6b1 100644 --- a/test/wcc/data/r940_global_sret_local_assign/case.ww +++ b/test/wcc/data/r940_global_sret_local_assign/case.ww @@ -1,5 +1,5 @@ //ww:run -// Runtime half of 940_global_sret_run.c local_assign_regression. +// #220 global-sret family: local decl+assign regression leg. package main; type quad = struct { a: i64, b: i64, c: i64, d: i64 }; fn mk(x: i64) quad = { diff --git a/test/wcc/data/r940_global_sret_local_init/case.ww b/test/wcc/data/r940_global_sret_local_init/case.ww index ea537497..9961f07e 100644 --- a/test/wcc/data/r940_global_sret_local_init/case.ww +++ b/test/wcc/data/r940_global_sret_local_init/case.ww @@ -1,5 +1,5 @@ //ww:run -// Runtime half of 940_global_sret_run.c local_init_regression. +// #220 global-sret family: local let-init regression leg (cglet sret receive). package main; type quad = struct { a: i64, b: i64, c: i64, d: i64 }; fn mk(x: i64) quad = { diff --git a/test/wcc/data/r940_global_sret_pointer/case.ww b/test/wcc/data/r940_global_sret_pointer/case.ww index fe08e276..67700884 100644 --- a/test/wcc/data/r940_global_sret_pointer/case.ww +++ b/test/wcc/data/r940_global_sret_pointer/case.ww @@ -1,5 +1,5 @@ //ww:run -// Runtime half of 940_global_sret_run.c global_through_pointer. +// #220 global-sret family: global mutated through a pointer after the sret assign. package main; type quad = struct { a: i64, b: i64, c: i64, d: i64 }; fn mk(x: i64) quad = {