test: migrate Fam10 alias value tests to @test, carve divergences to pins (#5-C3)
fold-2 chunk C3 (drew's Fam8-13 plan): 8 alias value-row C drivers, 205 rows
re-homed with zero loss -- 177 value -> 8 test/lang/alias_*_test.ww @test
row-tables; 16 reject -> runww //ww:error carriers (both stages reject);
3 cs!=ww value rows -> 2 *_runonly_test.ww (T1, byte-id-excluded, #60/#81);
9 irreducible asymmetric rows -> slim C pins, each ticket-cited and
mutation-proven non-vacuous:
- accept amplen1/2,ampcap2: cs runs / ww rejects 'unsupported address-of
shape' (#96)
- cgen_b5 g73_heapfill: cs!=ww .s + ww link-fails on self-contained alloc;
compile-smoke pin (#24)
- cgen_b6 fsarg2_bound: both reject, different msgs, each vs the correct
stage (#271/#165 cs vs #272/#276/#277 ww)
- emit_b7 slc/slcstr/slctag _2lvl + slc_plain_ctl: slice-literal static-init
divergence (#120/#29-kin, ken-d2-oracle)
4 fully-migrated drivers deleted, 4 slimmed-in-place to hold only the
irreducible pins. LANGBYTEID floor 74->82 (8 new byte-id @test files); test
count 388->384 (4 deleted; 4 slimmed kept). do-not-auto-batch files not in
Fam10.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,118 +1,19 @@
|
||||
/*
|
||||
* 944_alias_cgen_b5_run — #5 alias arc F2b (B5 train): cstage cgen
|
||||
* helper + funnel internalization through type_chase_named (c1), the
|
||||
* #73 tripwire graduation (c2), the #89 cgreturn return-position widen
|
||||
* (c3) and the #93 deref-index pointee chase (c4). All cs-only: every
|
||||
* graduation is a DIVERGE→byte-id flip (cs aligns UP to ww's already-
|
||||
* chasing asm); zero selfhost/lib bytes move across the train, so the
|
||||
* _ww binaries stay bit-identical (the crossing detector).
|
||||
* 944_alias_cgen_b5_run — SLIM CARRIER (#5-C3 alias fold-2). The 27 K_RUN value
|
||||
* rows migrated to test/lang/alias_cgen_b5_test.ww (@test, cs==ww byte-id); the
|
||||
* symmetric K_BUILDERR rejects (fill0_ctl, fill2_loud, g73_static_str) to
|
||||
* test/wcc/data/alias_{fill0_ctl,fill2_loud,g73_static_str}/case.ww runww.
|
||||
*
|
||||
* Row sources are ken's B5 oracle probes (/tmp/ken_b5/src,
|
||||
* .ai/ken-b5-oracle.md + its c1-BOUNDARY ADDENDUM) and the c3/c4
|
||||
* seeds (/tmp/ken_na, kb4).
|
||||
*
|
||||
* row | shape (oracle row) | cs/ww
|
||||
* --------------------+-------------------------------------+------
|
||||
* signed_ctl | kb5_signed: 2-lvl alias i8 field |
|
||||
* | load (fld_issigned) — classifiers |
|
||||
* | recurse, NO-mover control | 0/0
|
||||
* targ_2lvl | kb5_targ: 2-lvl alias (void|i64) |
|
||||
* | param ≤48B (tagged_arg_size) — was |
|
||||
* | cs LIVE exit-1, c1 graduation | 0/0
|
||||
* tmem_2lvl | kb5_tmem: >48B memarg twin |
|
||||
* | (tagged_memarg_size) — graduation | 0/0
|
||||
* wpush_2lvl | kb5_wpush: call-site widen, literal |
|
||||
* | arg (:2905 du) — divergence flip | 0/0
|
||||
* wstore_2lvl/_1lvl | kb5_wstore/wstore1: let-route |
|
||||
* | controls (du arrives chased |
|
||||
* | upstream — ken FLAG-1), NEUTRAL | 0/0
|
||||
* wstore_a_2lvl | kb5_wstore_a: ASSIGN-route re-store |
|
||||
* | — was both-correct divergent; the |
|
||||
* | ident-lhs N_ASSIGN gate (:6359) is |
|
||||
* | cgexpr INLINE, NOT the :2456 funnel |
|
||||
* | (C1-CORR-2) — GRADUATED at B6-c1 | 0/0
|
||||
* succ_2lvl | kb5_succ: `?`-success remap over |
|
||||
* | 2-lvl alias result — was divergent |
|
||||
* | at RETURN positions only (C1-CORR-1)|
|
||||
* | — GRADUATED at c3 with the rt chase | 0/0
|
||||
* null_2lvl | kb5_null: nullable fold + deref |
|
||||
* | (type_isnullable/nullable_ptr_tag) |
|
||||
* | — divergence flip | 0/0
|
||||
* f32p_2lvl | kb5_f32p: nested 2-lvl-alias f64 |
|
||||
* | field struct param |
|
||||
* | (struct_float_class) — flip | 0/0
|
||||
* fill0_ctl | kb5_fill0: named-struct array elem |
|
||||
* | in struct lit — LOUD both stages |
|
||||
* | (twin texts share the experr) | err/err
|
||||
* fill2_loud | kb5_fill2: 1-alias-lvl elem — was |
|
||||
* | both-wrong-IDENTICAL gate-blind, |
|
||||
* | then cs-loud/ww-silent for the one |
|
||||
* | R4-blessed train; #100's ww twin |
|
||||
* | chase closed the window — LOUD-HOLD |
|
||||
* | pair, twin texts share the experr | err/err
|
||||
* tuparg_bound99 / | alias-tuple fn-arg (2-lvl / 1-lvl |
|
||||
* tuparg1_bound99 / | / cast spelling) + alias-tuple |
|
||||
* tuparg_cast_bound99/| global. #99 GRADUATED: cstage |
|
||||
* tupglobal_bound99 | type.c chase accepts the coercion, |
|
||||
* | wwstage cgendecl.ww spill chase |
|
||||
* | sizes the alias param 16B (was |
|
||||
* | dropping SI → t.1 garbage). All |
|
||||
* | now 0/0 byte-id | 0/0
|
||||
* ---- c2 (#73 graduation: tripwire deleted, 6 fu gates chased) --
|
||||
* g73_idxstore / | slice / str / tagged 2-lvl alias |
|
||||
* g73_strfield / | field at the indexed-elem STORE |
|
||||
* g73_tagfield | gate — pre = loud "#73" fatal | 0/0
|
||||
* g73_idxread / | slice arm at the indexed-elem READ, |
|
||||
* g73_ptrread / | ptr-chain READ and tuple-elem READ |
|
||||
* g73_tupread | gates — pre = loud "#73" fatal | 0/0
|
||||
* g73_static_struct | nested-struct arm at the static |
|
||||
* | struct-lit emit gate — pre = "#73" | 0/0
|
||||
* g73_heapfill | str arm at the heap struct-lit fill |
|
||||
* | gate — COMPILE-only pin: bare /tmp |
|
||||
* | programs never link malloc (both |
|
||||
* | stages, pre-existing infra) and the |
|
||||
* | ww deref-field READ carries the |
|
||||
* | #24-kin field(SB) leak, so run + |
|
||||
* | byte-id cells are unavailable; the |
|
||||
* | FILL bytes themselves verified |
|
||||
* | byte-id by hand (= plain control) | asm
|
||||
* g73_static_str | str-field static emit: the #73 |
|
||||
* | fatal gave way to the #129 A.2 |
|
||||
* | foldability loud — now fill0-class |
|
||||
* | both-loud (twin texts) | err/err
|
||||
* ---- c3 (#89: cgreturn return-position widen rt/vu chase) ------
|
||||
* g89_ret_widen | alias-struct return into union — |
|
||||
* | was cs word0-to-DX + CX zeroed |
|
||||
* | (payload dropped, silent exit 1) | 0/0
|
||||
* g89_ret_errunion | 1-LVL alias error-union return — |
|
||||
* | cs MOVQ AX,DX dropped e.aux (the |
|
||||
* | live-truncation seed) | 0/0
|
||||
* g89_ret_named_ctl | bare NAMED struct return control — |
|
||||
* | held 0/0 byte-id throughout | 0/0
|
||||
* ---- c4 (#93: deref-index pointee chase, #263-polarity) --------
|
||||
* g93_l2_local | `(*p)[2]` over *arr2 (arr2=arr= |
|
||||
* | [3]int) — cs emitted ONE spurious |
|
||||
* | MOVQ (AX),AX (pointee ARRAY skip |
|
||||
* | missed at 2 levels), SEGV 139; ww |
|
||||
* | was the runtime-correct side | 0/0
|
||||
* g93_def | def twin: `(*p)[2]` over &D, D a |
|
||||
* | 2-lvl alias def array (kb5_def93) | 0/0
|
||||
* g93_1lvl_ctl | 1-level pointee control — held 0/0 |
|
||||
* | byte-id throughout | 0/0
|
||||
*
|
||||
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
|
||||
* and assert cstage/wwstage asm byte-id. K_RUN_NOID asserts both run
|
||||
* cells but waives byte-id — cite the blocking task/commit at the row.
|
||||
* K_CSERR_WWRUN is the dual-cell bound kind (the inverse of
|
||||
* 944_alias_accept_run's K_RUN_CS_WWERR): the cstage build must FAIL
|
||||
* with experr AND the wwstage build+run must exit wwwant — both cells
|
||||
* asserted so neither the cs loudness nor the ww behavior can drift
|
||||
* silently while the cited task is parked. NNN<950, self-contained
|
||||
* /tmp sources, no imports (944 precedent).
|
||||
* What survives here is the one IRREDUCIBLE K_COMPILES row: both stages
|
||||
* FRONTEND-compile (w6c / w6c_ww → .s, rc 0) but the asm diverges (the ww
|
||||
* deref-field READ carries the #24 field(SB) leak) so run + byte-id cells are
|
||||
* unavailable, and a full `ww build` can't link this self-contained `alloc()`
|
||||
* case (no rt malloc) — runww //ww:compile links and so cannot host it. The
|
||||
* pin is the ABSENCE of the pre-c2 cstage #73 fatal at the heap struct-lit
|
||||
* str-arm fill; the ww-side leak rides task #24. Compile-smoke only.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -126,407 +27,40 @@ runwait(const char *cmd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* both w6c and w6c_ww must FRONTEND-compile (rc 0); no run, no byte-id (#24). */
|
||||
static int
|
||||
slurp_eq(const char *a, const char *b)
|
||||
run_row(const char *bin, const char *label, const char *src, int i)
|
||||
{
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
char dir[96], srcf[160], ss[160], rm[200], cmd[2048];
|
||||
snprintf(dir, sizeof dir, "/tmp/ab5_%d_%d", getpid(), i);
|
||||
mkdir(dir, 0755);
|
||||
snprintf(srcf, sizeof srcf, "%s/c.ww", dir);
|
||||
snprintf(ss, sizeof ss, "%s/o.s", dir);
|
||||
snprintf(rm, sizeof rm, "rm -rf %s", dir);
|
||||
|
||||
#define K_RUN 0 /* build+run BOTH, exits==wants, + byte-id */
|
||||
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers */
|
||||
#define K_RUN_NOID 2 /* build+run BOTH, exits==wants, byte-id
|
||||
* SKIPPED — cite the blocking task */
|
||||
#define K_CSERR_WWRUN 3 /* dual-cell bound row: cstage build must
|
||||
* FAIL with experr; wwstage build+run,
|
||||
* exit==wwwant — cite the blocking task */
|
||||
#define K_COMPILES 4 /* w6c AND w6c_ww must COMPILE (no run, no
|
||||
* byte-id) — cite why the other cells are
|
||||
* unavailable at the row */
|
||||
|
||||
struct row { const char *label; const char *src;
|
||||
int cswant; int wwwant; int kind; const char *experr; };
|
||||
|
||||
/* errlog_has — a builderr cell must fail WITH its diagnostic; any other
|
||||
* failure (parse error, crash, hang-kill) is a vacuous reject (940
|
||||
* precedent). */
|
||||
static int
|
||||
errlog_has(const char *path, const char *needle)
|
||||
{
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f) return 0;
|
||||
char buf[8192];
|
||||
size_t got = fread(buf, 1, sizeof buf - 1, f);
|
||||
FILE *f = fopen(srcf, "wb");
|
||||
if (!f) { runwait(rm); return -1; }
|
||||
fputs(src, f);
|
||||
fclose(f);
|
||||
buf[got] = '\0';
|
||||
return strstr(buf, needle) != NULL;
|
||||
|
||||
int ok = 1;
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, ss, srcf);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: cstage frontend compile failed\n", label);
|
||||
ok = 0;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null", bin, ss, srcf);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: wwstage frontend compile failed\n", label);
|
||||
ok = 0;
|
||||
}
|
||||
runwait(rm);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
struct row { const char *label; const char *src; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
/* ---- c1: helper + funnel internalization (the F2c-cs fuse) */
|
||||
{ "signed_ctl",
|
||||
"package main;\n"
|
||||
"type s0 = i8;\n"
|
||||
"type s1 = s0;\n"
|
||||
"type st = struct { f: s1, g: s1 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st;\n"
|
||||
" x.f = -5;\n"
|
||||
" x.g = 3;\n"
|
||||
" if (x.f >= 0) { return 1; };\n"
|
||||
" let w: i64 = x.f: i64;\n"
|
||||
" if (w != -5) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* LIVE c1 graduation: tagged_arg_size single-peeled the 2-level
|
||||
* alias union param to 0 → wrong arg path (cs exit 1 SILENT, ww
|
||||
* correct). */
|
||||
{ "targ_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"fn h(v: u) i32 = {\n"
|
||||
" match (v) {\n"
|
||||
" case let n: i64 => { if (n != 42) { return 1; }; return 0; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: u = 42i64;\n"
|
||||
" return h(x);\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* LIVE c1 graduation: the >48B MEMORY-class twin
|
||||
* (tagged_memarg_size). LAST payload word checked. */
|
||||
{ "tmem_2lvl",
|
||||
"package main;\n"
|
||||
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };\n"
|
||||
"type m0 = (void | big);\n"
|
||||
"type m = m0;\n"
|
||||
"fn h(v: m) i32 = {\n"
|
||||
" match (v) {\n"
|
||||
" case let s: big => { if (s.g != 77) { return 1; }; return 0; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: big;\n"
|
||||
" s.a = 11; s.b = 22; s.c = 33; s.d = 44; s.e = 55; s.f = 66; s.g = 77;\n"
|
||||
" let x: m = s;\n"
|
||||
" return h(x);\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "wpush_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"fn h(v: u) i32 = {\n"
|
||||
" match (v) {\n"
|
||||
" case let n: i64 => { if (n != 42) { return 1; }; return 0; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" return h(42i64);\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "wstore_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: u = 42i64;\n"
|
||||
" match (v) {\n"
|
||||
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "wstore_1lvl",
|
||||
"package main;\n"
|
||||
"type u = (void | i64);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: u = 42i64;\n"
|
||||
" match (v) {\n"
|
||||
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* C1-CORR-2 → GRADUATED at B6-c1: the ident-lhs N_ASSIGN tagged
|
||||
* store gate (:6359) was the cgexpr INLINE peel B5 could not
|
||||
* reach; the B6-c1 chase closed it (pins-follow-the-layer, ken
|
||||
* B6 oracle C1 seed). */
|
||||
{ "wstore_a_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: u = void;\n"
|
||||
" v = 42i64;\n"
|
||||
" match (v) {\n"
|
||||
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL }, /* graduated: B6-c1 */
|
||||
/* C1-CORR-1 → GRADUATED at c3: the residual divergence was
|
||||
* exactly three paired return-position tag syntheses — the
|
||||
* cgreturn return-route family; the c3 rt chase closed it
|
||||
* (pins-follow-the-layer, ken c1-boundary addendum). */
|
||||
{ "succ_2lvl",
|
||||
"package main;\n"
|
||||
"type e0 = !i64;\n"
|
||||
"type r0 = (i64 | e0);\n"
|
||||
"type r = r0;\n"
|
||||
"fn w(bad: bool) r = {\n"
|
||||
" if (bad) { return 7: e0; };\n"
|
||||
" return 42;\n"
|
||||
"};\n"
|
||||
"fn outer() r = {\n"
|
||||
" let v = w(false)?;\n"
|
||||
" return v + 1;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" match (outer()) {\n"
|
||||
" case let n: i64 => { if (n != 43) { return 1; }; };\n"
|
||||
" case e0 => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL }, /* graduated: #89 (B5-c3) */
|
||||
{ "null_2lvl",
|
||||
"package main;\n"
|
||||
"type np0 = (*i64 | void);\n"
|
||||
"type np = np0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let n: i64 = 31;\n"
|
||||
" let p: np = &n;\n"
|
||||
" match (p) {\n"
|
||||
" case let q: *i64 => { if (*q != 31) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "f32p_2lvl",
|
||||
"package main;\n"
|
||||
"type in0 = struct { a: f64 };\n"
|
||||
"type in1 = in0;\n"
|
||||
"type pt = struct { x: in1, y: f64 };\n"
|
||||
"fn g(p: pt) f64 = { return p.x.a + p.y; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let p: pt;\n"
|
||||
" p.x.a = 2.5;\n"
|
||||
" p.y = 1.5;\n"
|
||||
" if (g(p) != 4.0) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* fill loudness control: named-struct array elem louds on BOTH
|
||||
* stages with twin texts — the experr substring is shared. */
|
||||
{ "fill0_ctl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64 };\n"
|
||||
"type S = struct { arr: [2]el0, n: i64 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };\n"
|
||||
" if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"has a str/slice/struct/tagged element" },
|
||||
/* #100 GRADUATION (closes the B5 re-rule R4 designed divergence):
|
||||
* pre-B5 this was both-wrong-IDENTICAL-silent (gate-blind #263
|
||||
* class — both stages accepted and ran exit 1 byte-id); B5-c1's
|
||||
* cs-only :3195 chase made it cs-loud/ww-silent-wrong for one
|
||||
* train. The ww twin gate now keys off the chased stamped tinfo
|
||||
* (cgenutil.ww, task #100) — LOUD-HOLD pair, twin texts share
|
||||
* the experr tail (fill0-class). */
|
||||
{ "fill2_loud",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64 };\n"
|
||||
"type el = el0;\n"
|
||||
"type S = struct { arr: [2]el, n: i64 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };\n"
|
||||
" if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"has a str/slice/struct/tagged element" },
|
||||
/* #99 GRADUATION: both halves landed — the cstage type.c
|
||||
* type_chase_named tuple-arm (init/fn-arg untyped->alias coercion
|
||||
* reject->accept) AND the wwstage cgendecl.ww tuple-PARAM spill
|
||||
* chase (alias param fell to the scalar path, dropped SI, t.1
|
||||
* garbage). All four rows now build+run 0 on BOTH stages and the
|
||||
* .s is byte-identical (full 0/0 byte-id, the designed path). */
|
||||
{ "tuparg_bound99",
|
||||
"package main;\n"
|
||||
"type tp0 = (i64, i64);\n"
|
||||
"type tp = tp0;\n"
|
||||
"fn f(t: tp) i64 = { return t.0 + t.1; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let t: tp = (4, 9);\n"
|
||||
" if (f(t) != 13) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "tuparg1_bound99", /* 1-LEVEL identical — not alias-depth */
|
||||
"package main;\n"
|
||||
"type tp = (i64, i64);\n"
|
||||
"fn f(t: tp) i64 = { return t.0 + t.1; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let t: tp = (4, 9);\n"
|
||||
" if (f(t) != 13) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* cast spelling — was the LIVE-cs / wrong-ww K_RUN_NOID pin; the
|
||||
* wwstage spill chase reds the old ww-1 cell and graduates it to
|
||||
* full 0/0 byte-id alongside its siblings. */
|
||||
{ "tuparg_cast_bound99",
|
||||
"package main;\n"
|
||||
"type tp0 = (i64, i64);\n"
|
||||
"type tp = tp0;\n"
|
||||
"fn f(t: tp) i64 = { return t.0 + t.1; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let t: tp = (4, 9): tp;\n"
|
||||
" if (f(t) != 13) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* alias-tuple module-global — the cstage chase accepts the global
|
||||
* init and ww already read it correctly; now both 0/0 byte-id. */
|
||||
{ "tupglobal_bound99",
|
||||
"package main;\n"
|
||||
"type tp0 = (i64, i64);\n"
|
||||
"type tp = tp0;\n"
|
||||
"let G: tp = (4, 9);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G.0 + G.1 != 13) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* ---- c2: #73 graduation — the F1 tripwire's containment
|
||||
* replaced by the designed chase (close-by-construction). Each
|
||||
* row was the loud "#73" fatal on cs at the c1 tip (ww ok/0);
|
||||
* post-c2 the gates read the chased field type and every
|
||||
* runnable arm lands 0/0 byte-id. Values exceed 255 / use the
|
||||
* LAST element so a word0 tail can't pass by prefix-luck;
|
||||
* noise() clobbers BX/CX on the read rows. */
|
||||
{ "g73_idxstore",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"type sl2 = sl;\n"
|
||||
"type box = struct { s: sl2, n: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||||
" let xs: [2]box;\n"
|
||||
" xs[0].s = a[0:3];\n"
|
||||
" if (xs[0].s.len != 3) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g73_strfield",
|
||||
"package main;\n"
|
||||
"type s1t = str;\n"
|
||||
"type s2t = s1t;\n"
|
||||
"type box = struct { s: s2t, n: int };\n"
|
||||
"fn noise(x: int) int = { return x * 7 + 3; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: [2]box;\n"
|
||||
" xs[1].s = \"hello\";\n"
|
||||
" xs[1].n = 4;\n"
|
||||
" let k = noise(9);\n"
|
||||
" if (k != 66) { return 9; };\n"
|
||||
" let w = xs[1].s;\n"
|
||||
" if (w.len != 5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g73_tagfield",
|
||||
"package main;\n"
|
||||
"type tu0 = (void | i64);\n"
|
||||
"type tu = tu0;\n"
|
||||
"type box = struct { u: tu, n: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: [2]box;\n"
|
||||
" xs[0].n = 5;\n"
|
||||
" xs[0].u = 42i64;\n"
|
||||
" if (xs[0].n != 5) { return 1; };\n"
|
||||
" match (xs[0].u) {\n"
|
||||
" case let v: i64 => { if (v != 42) { return 2; }; };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* store rides the (F1-chased) single-dot via-ptr route so the
|
||||
* indexed-elem READ gate fires in isolation. */
|
||||
{ "g73_idxread",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"type sl2 = sl;\n"
|
||||
"type box = struct { s: sl2, n: int };\n"
|
||||
"fn noise(x: int) int = { return x * 7 + 3; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||||
" let xs: [2]box;\n"
|
||||
" let p = &xs[1];\n"
|
||||
" p.s = a[0:3];\n"
|
||||
" p.n = 4;\n"
|
||||
" let k = noise(9);\n"
|
||||
" if (k != 66) { return 9; };\n"
|
||||
" let w = xs[1].s;\n"
|
||||
" if (w.len != 3) { return 1; };\n"
|
||||
" if (w[2] != 900) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g73_ptrread",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"type sl2 = sl;\n"
|
||||
"type inner = struct { s: sl2, n: int };\n"
|
||||
"type outer = struct { pi: *inner };\n"
|
||||
"fn noise(x: int) int = { return x * 7 + 3; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||||
" let i: inner;\n"
|
||||
" i.s = a[0:3];\n"
|
||||
" i.n = 1;\n"
|
||||
" let v: outer;\n"
|
||||
" v.pi = &i;\n"
|
||||
" let k = noise(9);\n"
|
||||
" if (k != 66) { return 9; };\n"
|
||||
" let w = v.pi.s;\n"
|
||||
" if (w.len != 3) { return 1; };\n"
|
||||
" if (w[2] != 900) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g73_tupread",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"type sl2 = sl;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||||
" let t: (sl2, int) = (a[0:3], 5);\n"
|
||||
" let s = t.0;\n"
|
||||
" if (s.len != 3) { return 1; };\n"
|
||||
" if (t.1 != 5) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g73_static_struct",
|
||||
"package main;\n"
|
||||
"type in0 = struct { a: i64, b: i64 };\n"
|
||||
"type in1 = in0;\n"
|
||||
"type box = struct { i: in1, n: i64 };\n"
|
||||
"let g: box = box { i = in0 { a = 4, b = 9 }, n = 5 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.n != 5) { return 1; };\n"
|
||||
" if (g.i.b != 9) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* COMPILE-only pin: bare /tmp programs never link malloc (both
|
||||
* stages, pre-existing infra) and the ww deref-field READ
|
||||
* carries the #24-kin field(SB) leak — run + byte-id cells are
|
||||
* unavailable. The chased FILL bytes were verified byte-id by
|
||||
* hand against the plain control (/tmp/b5/work). Pre-c2 the cs
|
||||
* cell was the "#73" fatal — this row pins its absence. */
|
||||
{ "g73_heapfill",
|
||||
"package main;\n"
|
||||
"type s1t = str;\n"
|
||||
@@ -537,223 +71,9 @@ static const struct row rows[] = {
|
||||
" if (p.n != 5) { return 1; };\n"
|
||||
" if (p.s.len != 5) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_COMPILES, NULL },
|
||||
/* str-field static emit: the #73 fatal gave way to the
|
||||
* pre-existing #129 A.2 foldability loud — both-loud twin texts
|
||||
* now (the fill0 class), pinned so neither side regresses to a
|
||||
* silent emit. */
|
||||
{ "g73_static_str",
|
||||
"package main;\n"
|
||||
"type s1t = str;\n"
|
||||
"type s2t = s1t;\n"
|
||||
"type box = struct { s: s2t, n: int };\n"
|
||||
"let g: box = box { s = \"hello\", n = 5: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.n != 5) { return 1; };\n"
|
||||
" if (g.s.len != 5) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"#129 A.2 scope" },
|
||||
/* ---- c3: #89 — the cgreturn rt/vu single peels left a 2-level
|
||||
* alias RETURN TYPE un-tagged (no tag synthesis at all, the succ
|
||||
* shape) and an alias-struct SOURCE un-structed (the scalar arm
|
||||
* shuffled word0 into DX and ZEROED the rest — s.b/e.aux
|
||||
* dropped, cs silent exit 1, ww runtime-correct since B2-c2). */
|
||||
{ "g89_ret_widen",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type ali = base;\n"
|
||||
"fn mk() (void | ali) = {\n"
|
||||
" let x: ali;\n"
|
||||
" x.a = 4; x.b = 9;\n"
|
||||
" return x;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" match (mk()) {\n"
|
||||
" case let s: ali => { if (s.b != 9) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g89_ret_errunion",
|
||||
"package main;\n"
|
||||
"type failure = struct { code: i32, aux: size };\n"
|
||||
"type myerr = failure;\n"
|
||||
"fn work(bad: bool) (i32 | myerr) = {\n"
|
||||
" if (bad) {\n"
|
||||
" let e: myerr;\n"
|
||||
" e.code = 7; e.aux = 99;\n"
|
||||
" return e;\n"
|
||||
" };\n"
|
||||
" return 42;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" match (work(true)) {\n"
|
||||
" case let e: myerr => { if (e.aux != 99) { return 1; }; };\n"
|
||||
" case i32 => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g89_ret_named_ctl",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"fn make() (void | base) = {\n"
|
||||
" let x: base;\n"
|
||||
" x.a = 4; x.b = 9;\n"
|
||||
" return x;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v = make();\n"
|
||||
" match (v) {\n"
|
||||
" case let s: base => { if (s.b != 9) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* ---- c4: #93 — the N_UN(STAR) pointee classify single-peeled,
|
||||
* so a 2-level alias ARRAY pointee missed the array skip (an
|
||||
* array value IS its address, #270-1a) and the scalar load
|
||||
* pulled a[0]'s VALUE as the index base — ONE spurious
|
||||
* MOVQ (AX),AX, SIGSEGV on cs. ww chases (the runtime-correct
|
||||
* reference, #263 polarity): cs converges on WW's asm. */
|
||||
{ "g93_l2_local",
|
||||
"package main;\n"
|
||||
"type arr = [3]int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr2 = [1000: int, 2000: int, 3000: int];\n"
|
||||
" let p: *arr2 = &a;\n"
|
||||
" if ((*p)[2] != 3000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g93_def",
|
||||
"package main;\n"
|
||||
"type arr0 = [3]i64;\n"
|
||||
"type arr = arr0;\n"
|
||||
"def D: arr = [18i64, 29i64, 40i64];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let p: *arr = &D;\n"
|
||||
" if ((*p)[2] != 40i64) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "g93_1lvl_ctl",
|
||||
"package main;\n"
|
||||
"type arr = [3]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr = [1000: int, 2000: int, 3000: int];\n"
|
||||
" let p: *arr = &a;\n"
|
||||
" if ((*p)[2] != 3000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
"};\n" },
|
||||
};
|
||||
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i, int expect_err,
|
||||
int want)
|
||||
{
|
||||
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[176], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/ab5_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/ab5_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/ab5_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (expect_err) {
|
||||
int ok = (brc != 0)
|
||||
&& (r->experr == NULL || errlog_has(errf, r->experr));
|
||||
if (!ok)
|
||||
fprintf(stderr, "row[%s]: %s expected loud builderr "
|
||||
"\"%s\" (brc=%d)\n", r->label, driver,
|
||||
r->experr ? r->experr : "", brc);
|
||||
runwait(rmcmd);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* asm_compiles — K_COMPILES cell: the named stage compiler must emit
|
||||
* asm without a fatal. */
|
||||
static int
|
||||
asm_compiles(const char *bin, const char *cc, const struct row *r, int i)
|
||||
{
|
||||
char src[96], outs[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/ab5_cmp_%d_%d.ww", getpid(), i);
|
||||
snprintf(outs, sizeof outs, "/tmp/ab5_cmp_%d_%d.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/%s -o %s %s 2>/dev/null",
|
||||
bin, cc, outs, src);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: %s failed to compile\n",
|
||||
r->label, cc);
|
||||
unlink(src); unlink(outs);
|
||||
return rc != 0;
|
||||
}
|
||||
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/ab5_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/ab5_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/ab5_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@@ -767,50 +87,15 @@ main(void)
|
||||
bin = absbin;
|
||||
}
|
||||
|
||||
char cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (rows[i].kind == K_COMPILES) {
|
||||
if (asm_compiles(bin, "w6c", &rows[i], i) != 0)
|
||||
fail++;
|
||||
continue;
|
||||
}
|
||||
int cs_err = rows[i].kind == K_BUILDERR
|
||||
|| rows[i].kind == K_CSERR_WWRUN;
|
||||
if (run_driver(cdrv, &rows[i], i, cs_err,
|
||||
rows[i].cswant) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (rows[i].kind == K_COMPILES) {
|
||||
if (asm_compiles(bin, "w6c_ww",
|
||||
&rows[i], i) != 0) fail++;
|
||||
continue;
|
||||
}
|
||||
int ww_err = rows[i].kind == K_BUILDERR;
|
||||
if (run_driver(wdrv, &rows[i], i, ww_err,
|
||||
rows[i].wwwant) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (rows[i].kind != K_RUN)
|
||||
continue;
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
int fail = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (run_row(bin, rows[i].label, rows[i].src, i) != 0) fail++;
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_cgen_b5: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
fprintf(stderr, "alias_cgen_b5 (slim): %d/%d rows failed\n", fail, n);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_cgen_b5: %d/%d ok\n", total, total);
|
||||
printf("alias_cgen_b5 (slim): %d/%d ok\n", n, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,133 +1,16 @@
|
||||
/*
|
||||
* 944_alias_cgen_b6_run — #5 alias arc F2b (B6 train): the cgen.c
|
||||
* cgexpr/cgstmt INLINE single-peel sweep through type_chase_named, by
|
||||
* consumer family — c1 assign/reassign (9 lines), c2 call-arg (8),
|
||||
* c3 addr-of/field-walk/index spine (14), c4 cast/is/try (10),
|
||||
* c5 reads/len/globals (8). All cs-only: every graduation is a
|
||||
* DIVERGE→byte-id flip (cs aligns UP to ww's already-chasing asm);
|
||||
* zero selfhost/lib bytes move across the train, so the _ww binaries
|
||||
* stay bit-identical (the crossing detector).
|
||||
* 944_alias_cgen_b6_run — SLIM CARRIER (#5-C3 alias fold-2). The 23 K_RUN value
|
||||
* rows migrated to test/lang/alias_cgen_b6_test.ww (@test, cs==ww byte-id); the
|
||||
* symmetric K_BUILDERR rejects (fsarg0_loud_ctl, try_loud_38b) to
|
||||
* test/wcc/data/alias_{fsarg0_loud,try_loud_38b}/case.ww runww.
|
||||
*
|
||||
* Row sources are ken's B6 first-position oracle probes
|
||||
* (/tmp/ken_b5/src/kb6_*, .ai/ken-b6-oracle.md, matrix at 4cac1cb).
|
||||
*
|
||||
* row | shape (oracle row) | cs/ww
|
||||
* --------------------+-------------------------------------+------
|
||||
* ---- c1 (assign/reassign: :6359 :6403/:6405 :6460/:6462 -------
|
||||
* :6518 + cgstmt :11696 :12047 :13625) -------------------
|
||||
* streassign_2lvl | kb6_streassign: 2-lvl alias str |
|
||||
* | reassign `b = a` — cs copied WORD0 |
|
||||
* | (ptr) ONLY, len/cap stale (silent |
|
||||
* | exit 1); the :6518 lu gate fell to |
|
||||
* | the scalar default. LIVE graduation | 0/0
|
||||
* wstore_a (B5 file) | kb5_wstore_a graduates K_RUN_NOID → |
|
||||
* | K_RUN in 944_alias_cgen_b5_run.c — |
|
||||
* | the ident-lhs N_ASSIGN tagged gate |
|
||||
* | (:6359) was the divergence (ken |
|
||||
* | C1-CORR-2, he owns the flip) | 0/0
|
||||
* sreassign_2lvl | kb6_sreassign: whole-struct alias |
|
||||
* | reassign — latent control | 0/0
|
||||
* dassign_2lvl | kb6_dassign: (*p).f= over alias ptr |
|
||||
* | — latent control | 0/0
|
||||
* ---- c2 (call-arg: :8402 :8435 :8561/:8563/:8577/:8579 --------
|
||||
* + LOUD-PRESERVING :8829 :8934) ------------------------
|
||||
* fsarg0_loud_ctl | kb6_fsarg0: PLAIN float-struct from |
|
||||
* | a non-ident source — #271/#165 loud |
|
||||
* | BOTH stages (control, twin texts) | err/err
|
||||
* fsarg2_bound | kb6_fsarg2: 1-alias-level respell — |
|
||||
* | pre-c2 the :8829 single-peel let |
|
||||
* | the alias DODGE the fatal; cs GP- |
|
||||
* | passed by self-consistent luck. |
|
||||
* | DESIGNED NARROWING: cs now louds |
|
||||
* | with the pinned #271/#165 text |
|
||||
* | ("widen what the gate SEES, never |
|
||||
* | what it ACCEPTS"). ww's loud is its |
|
||||
* | own alias-return bound (#272/#277 |
|
||||
* | class, experr_ww) — per-stage texts | err/err
|
||||
* fsarg_ident_ctl | kb6_fsarg: IDENT-source alias twin |
|
||||
* | — ident domain out of the :8829 |
|
||||
* | gate, latent control | 0/0
|
||||
* sarg_2lvl | kb6_sarg: >16B alias struct arg — |
|
||||
* | latent (B5 helper chases carry the |
|
||||
* | type layer) | 0/0
|
||||
* strarg_2lvl | kb6_strarg: alias str arg — latent | 0/0
|
||||
* (:8934 tuple loud is WATCH-ONLY: alias spellings are |
|
||||
* checker-blocked upstream (#86/#99) — the pin is the b5 |
|
||||
* suite's tuparg_cast_bound99 two-key cells, which must |
|
||||
* not move.) |
|
||||
* ---- c3 (addr-of/field-walk/index spine: :3949 :4006 ---------
|
||||
* :4124/:4128 :5029/:5035/:5052 :5937 :10953/:10956 -----
|
||||
* :11046/:11052/:11067 :11285, numbering at 4cac1cb) ----
|
||||
* idxf_2lvl / | kb6_idxf (indexed-elem struct field |
|
||||
* ampf_2lvl | write+read) / kb6_ampf (&p.b over |
|
||||
* | alias ptr): the c3 chase moved cs |
|
||||
* | onto the PLAIN-canonical dedicated |
|
||||
* | shape (cs_alias == ww_PLAIN, bit- |
|
||||
* | proven, ken c3-STOP addendum) — and |
|
||||
* | WWSTAGE was the alias-blind side at |
|
||||
* | these two sites (generic-but-correct |
|
||||
* | routes). GRADUATED to full byte-id |
|
||||
* | by the W2 ww fold, task #102 (the |
|
||||
* | two gates now chase the alias chain |
|
||||
* | via structlookupchain). ampf's |
|
||||
* | pre-c3 byte-id was both-on-generic |
|
||||
* | identity, not latency (oracle |
|
||||
* | self-correction) | 0/0
|
||||
* idxf_plain_ctl / | plain no-alias twins — pin the |
|
||||
* ampf_plain_ctl | canonical dedicated shape byte-id |
|
||||
* | BOTH stages (the convergence target |
|
||||
* | the NOID rows graduate onto) | 0/0
|
||||
* ampv_2lvl / | W2-review-found #102 sibling: &x.f |
|
||||
* ampv_plain_ctl | over an alias-NAMED VALUE struct — |
|
||||
* | the leg one below the &p.f gate had |
|
||||
* | the same alias-blind bare lookup |
|
||||
* | (ww_alias != ww_plain; cs_alias == |
|
||||
* | ww_plain, same bit-proven mechanism).|
|
||||
* | Chased in the W2 review amendment | 0/0
|
||||
* chdot_2lvl | kb6_chdot: chained dot over alias |
|
||||
* | hops — latent control | 0/0
|
||||
* esub_2lvl | kb6_esub: [3]my32b narrow-elem index |
|
||||
* | (#61/#101-kin at the INDEX sites) — |
|
||||
* | latent control | 0/0
|
||||
* ---- c4 (cast/is/try: :9422 :9598 :9674 :9718 :9819 ----------
|
||||
* :9986/:9991 :10103/:10105 :10131, numbering at 4cac1cb) -
|
||||
* strcast_2lvl | kb6_strcast: str→[]u8 over 2-lvl |
|
||||
* | alias — was both-correct divergent; |
|
||||
* | the :10103/:10105 tu/fu chase FLIPS |
|
||||
* | it (cs → ww's unchanged asm, #263 |
|
||||
* | polarity; alias == plain shape) | 0/0
|
||||
* idcast_2lvl | kb6_idcast: identity cast over alias |
|
||||
* | union (Family-C peel) — latent | 0/0
|
||||
* is_2lvl | kb6_is: `is` over alias union — |
|
||||
* | latent control | 0/0
|
||||
* try_loud_38b | kb6_try: `?` on a >48B sret-class |
|
||||
* | call result — the #38b loud is |
|
||||
* | ALIAS-INDEPENDENT (documented bound);|
|
||||
* | :9819's chase is loud-preserving |
|
||||
* | ONLY — twin texts, shared experr | err/err
|
||||
* ---- c5 (reads/len/globals: :3820 :7201 :7807 :7900 :9944 ----
|
||||
* :10224 :10750 :10873, numbering at 4cac1cb) ------------
|
||||
* tfread_2lvl | kb6_tfread: tagged-union field load |
|
||||
* | direct + through-ptr over alias |
|
||||
* | struct — was both-correct divergent; |
|
||||
* | the :10750/:10873 tag_fu chases FLIP |
|
||||
* | it (cs → ww's unchanged asm, #263 |
|
||||
* | polarity; alias == plain shape) | 0/0
|
||||
* len_2lvl | kb6_len: str+array len over 2-lvl |
|
||||
* | alias — latent control | 0/0
|
||||
* gref_2lvl | kb6_gref: alias scalar global value- |
|
||||
* | ref — latent control | 0/0
|
||||
* memread_40b | kb6_memread: 40B union, the :9944 |
|
||||
* | #37 cap-watch row — the `is` chase |
|
||||
* | keys the cap test on the CHASED size |
|
||||
* | (mirrors ww taggedmemread); byte- |
|
||||
* | NEUTRALITY here is the regression net| 0/0
|
||||
*
|
||||
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
|
||||
* and assert cstage/wwstage asm byte-id. K_BUILDERR rows must FAIL
|
||||
* with experr on BOTH drivers; experr_ww overrides the ww-side text
|
||||
* when the two stages loud at DIFFERENT sites (per-stage texts).
|
||||
* NNN<950, self-contained /tmp sources, no imports (944 precedent).
|
||||
* What survives here is the one IRREDUCIBLE Group-B row: BOTH stages reject the
|
||||
* same input but with DIFFERENT diagnostics — a held cs!=ww divergence (a
|
||||
* rule-10 smell, tracked not silently merged). A single-substring runww
|
||||
* //ww:error would erase the distinction; this carrier asserts EACH stage's own
|
||||
* substring. cstage rejects with the #271/#165 SSE-eightbyte-transport reason;
|
||||
* wwstage rejects with the #272/#276/#277 aggregate-return scalar-default
|
||||
* reason (the float-bearing alias struct arg from a non-ident source).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -145,35 +28,6 @@ runwait(const char *cmd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define K_RUN 0 /* build+run BOTH, exits==wants, + byte-id */
|
||||
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers;
|
||||
* experr_ww overrides the ww-side text */
|
||||
#define K_RUN_NOID 2 /* build+run BOTH, exits==wants, byte-id
|
||||
* SKIPPED — cite the blocking task */
|
||||
|
||||
struct row { const char *label; const char *src;
|
||||
int cswant; int wwwant; int kind;
|
||||
const char *experr; const char *experr_ww; };
|
||||
|
||||
/* errlog_has — a builderr cell must fail WITH its diagnostic; any other
|
||||
* failure (parse error, crash, hang-kill) is a vacuous reject (940
|
||||
* precedent). */
|
||||
static int
|
||||
errlog_has(const char *path, const char *needle)
|
||||
{
|
||||
@@ -186,69 +40,48 @@ errlog_has(const char *path, const char *needle)
|
||||
return strstr(buf, needle) != NULL;
|
||||
}
|
||||
|
||||
/* cstage (w6c) rejects with cserr; wwstage (w6c_ww) rejects with wwerr. */
|
||||
static int
|
||||
run_row(const char *bin, const char *label, const char *src,
|
||||
const char *cserr, const char *wwerr, int i)
|
||||
{
|
||||
char dir[96], srcf[160], cse[160], wwe[160], ss[160], rm[200], cmd[2048];
|
||||
snprintf(dir, sizeof dir, "/tmp/ab6_%d_%d", getpid(), i);
|
||||
mkdir(dir, 0755);
|
||||
snprintf(srcf, sizeof srcf, "%s/c.ww", dir);
|
||||
snprintf(cse, sizeof cse, "%s/cs.err", dir);
|
||||
snprintf(wwe, sizeof wwe, "%s/ww.err", dir);
|
||||
snprintf(ss, sizeof ss, "%s/o.s", dir);
|
||||
snprintf(rm, sizeof rm, "rm -rf %s", dir);
|
||||
|
||||
FILE *f = fopen(srcf, "wb");
|
||||
if (!f) { runwait(rm); return -1; }
|
||||
fputs(src, f);
|
||||
fclose(f);
|
||||
|
||||
int ok = 1;
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>%s", bin, ss, srcf, cse);
|
||||
int crc = runwait(cmd);
|
||||
if (!(crc != 0 && errlog_has(cse, cserr))) {
|
||||
fprintf(stderr, "row[%s]: cstage expected reject \"%s\" (rc=%d)\n",
|
||||
label, cserr, crc);
|
||||
ok = 0;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>%s", bin, ss, srcf, wwe);
|
||||
int wrc = runwait(cmd);
|
||||
if (!(wrc != 0 && errlog_has(wwe, wwerr))) {
|
||||
fprintf(stderr, "row[%s]: wwstage expected reject \"%s\" (rc=%d)\n",
|
||||
label, wwerr, wrc);
|
||||
ok = 0;
|
||||
}
|
||||
runwait(rm);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
struct row { const char *label; const char *src; const char *cserr;
|
||||
const char *wwerr; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
/* ---- c1: assign/reassign family */
|
||||
/* LIVE c1 graduation: the :6518 reassign gate single-peeled the
|
||||
* 2-level alias str lhs, missed the TY_STR kind test, and fell
|
||||
* to the scalar default — ONE MOVQ stored the ptr word, len/cap
|
||||
* kept the dead value's header (cs silent exit 1, ww correct:
|
||||
* full 3-word {ptr,len,cap} store, Hare value semantics). */
|
||||
{ "streassign_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
"type ms = ms0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: ms = \"hello\";\n"
|
||||
" let b: ms = \"x\";\n"
|
||||
" b = a;\n"
|
||||
" if (len(b) != 5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "sreassign_2lvl",
|
||||
"package main;\n"
|
||||
"type st0 = struct { a: i64, b: i64, c: i64 };\n"
|
||||
"type st = st0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st; x.a = 1; x.b = 2; x.c = 3;\n"
|
||||
" let y: st; y.a = 0; y.b = 0; y.c = 0;\n"
|
||||
" y = x;\n"
|
||||
" if (y.c != 3 || y.b != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "dassign_2lvl",
|
||||
"package main;\n"
|
||||
"type st0 = struct { a: i64, b: i64 };\n"
|
||||
"type st = st0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st; x.a = 1; x.b = 2;\n"
|
||||
" let p: *st = &x;\n"
|
||||
" (*p).b = 9;\n"
|
||||
" if (x.b != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ---- c2: call-arg family */
|
||||
{ "fsarg0_loud_ctl",
|
||||
"package main;\n"
|
||||
"type fs0 = struct { x: f64 };\n"
|
||||
"fn mk() fs0 = {\n"
|
||||
" let s: fs0; s.x = 2.5;\n"
|
||||
" return s;\n"
|
||||
"};\n"
|
||||
"fn g(p: fs0) f64 = { return p.x; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g(mk()) != 2.5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"#271/#165: float-bearing struct arg from a non-ident source",
|
||||
NULL },
|
||||
/* DESIGNED ACCEPTANCE NARROWING (B6-c2): pre-c2 cs accepted and
|
||||
* GP-passed this float struct correct-by-self-consistent-luck
|
||||
* (caller+callee agreed on the wrong transport) — the :8829
|
||||
* single peel let a 1-level alias dodge the rule-7 fatal. The
|
||||
* chase widens what the gate SEES; the loud stays loud for the
|
||||
* shapes it guards. ww's cell was ALREADY loud at its own
|
||||
* alias-return bound (#272/#276/#277 class) — different site,
|
||||
* per-stage experr. */
|
||||
{ "fsarg2_bound",
|
||||
"package main;\n"
|
||||
"type fs0 = struct { x: f64 };\n"
|
||||
@@ -261,381 +94,11 @@ static const struct row rows[] = {
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g(mk()) != 2.5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"};\n",
|
||||
"#271/#165: float-bearing struct arg from a non-ident source",
|
||||
"#272/#276/#277: aggregate return reaches scalar default" },
|
||||
{ "fsarg_ident_ctl",
|
||||
"package main;\n"
|
||||
"type fs0 = struct { x: f64 };\n"
|
||||
"type fs = fs0;\n"
|
||||
"fn mk() fs0 = {\n"
|
||||
" let s: fs0; s.x = 2.5;\n"
|
||||
" return s;\n"
|
||||
"};\n"
|
||||
"fn g(p: fs) f64 = { return p.x; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: fs = mk();\n"
|
||||
" if (g(v) != 2.5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "sarg_2lvl",
|
||||
"package main;\n"
|
||||
"type big0 = struct { a: i64, b: i64, c: i64 };\n"
|
||||
"type big = big0;\n"
|
||||
"fn g(p: big) i64 = { return p.a + p.c; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: big; s.a = 4; s.b = 5; s.c = 9;\n"
|
||||
" if (g(s) != 13) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "strarg_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
"type ms = ms0;\n"
|
||||
"fn g(s: ms) i64 = { return len(s): i64; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: ms = \"hello\";\n"
|
||||
" if (g(a) != 5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ---- c3: addr-of/field-walk/index spine */
|
||||
/* The c3 chase put cs on the PLAIN-canonical dedicated shape
|
||||
* (cs_alias == ww_PLAIN, bit-proven — ken c3-STOP addendum);
|
||||
* WWSTAGE was the alias-blind side here: its indexed-elem
|
||||
* struct-field store gate fell to a generic-but-correct route
|
||||
* on alias bases. GRADUATED: the W2 ww fold (task #102) chases
|
||||
* the alias chain (structlookupchain), restoring full byte-id —
|
||||
* idxf_plain_ctl pins the canonical shape both rows now share. */
|
||||
{ "idxf_2lvl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64, b: i64 };\n"
|
||||
"type el = el0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: [2]el;\n"
|
||||
" xs[0].a = 1; xs[0].b = 2;\n"
|
||||
" xs[1].a = 3; xs[1].b = 4;\n"
|
||||
" if (xs[1].b != 4 || xs[0].b != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL }, /* graduated: #102 (W2) */
|
||||
{ "idxf_plain_ctl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64, b: i64 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: [2]el0;\n"
|
||||
" xs[0].a = 1; xs[0].b = 2;\n"
|
||||
" xs[1].a = 3; xs[1].b = 4;\n"
|
||||
" if (xs[1].b != 4 || xs[0].b != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* &p.b ptr-field fallback twin of the same re-attribution: the
|
||||
* pre-c3 byte-id here was BOTH stages on the generic spine
|
||||
* (gate-blind identity, not M5 latency — oracle self-correction
|
||||
* banked in ken's c3-STOP addendum). GRADUATED with #102 (W2). */
|
||||
{ "ampf_2lvl",
|
||||
"package main;\n"
|
||||
"type st0 = struct { a: i64, b: i64 };\n"
|
||||
"type st = st0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st; x.a = 1; x.b = 2;\n"
|
||||
" let p: *st = &x;\n"
|
||||
" let q: *i64 = &p.b;\n"
|
||||
" *q = 9;\n"
|
||||
" if (x.b != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL }, /* graduated: #102 (W2) */
|
||||
{ "ampf_plain_ctl",
|
||||
"package main;\n"
|
||||
"type st0 = struct { a: i64, b: i64 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st0; x.a = 1; x.b = 2;\n"
|
||||
" let p: *st0 = &x;\n"
|
||||
" let q: *i64 = &p.b;\n"
|
||||
" *q = 9;\n"
|
||||
" if (x.b != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* W2-review-found #102 sibling: the value-struct &x.f leg sits
|
||||
* one leg below the &p.f gate in the same cgun single-DOT arm
|
||||
* and had the same alias-blind bare structlookup (ww_alias !=
|
||||
* ww_plain, cs_alias == ww_plain — the c3-STOP bit-test
|
||||
* mechanism verbatim). Chased in the W2 review amendment. */
|
||||
{ "ampv_2lvl",
|
||||
"package main;\n"
|
||||
"type st0 = struct { a: i64, b: i64 };\n"
|
||||
"type st = st0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st; x.a = 1; x.b = 2;\n"
|
||||
" let q: *i64 = &x.b;\n"
|
||||
" *q = 9;\n"
|
||||
" if (x.b != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL }, /* amendment: #102 (W2) */
|
||||
{ "ampv_plain_ctl",
|
||||
"package main;\n"
|
||||
"type st0 = struct { a: i64, b: i64 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: st0; x.a = 1; x.b = 2;\n"
|
||||
" let q: *i64 = &x.b;\n"
|
||||
" *q = 9;\n"
|
||||
" if (x.b != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "chdot_2lvl",
|
||||
"package main;\n"
|
||||
"type in0 = struct { v: i64 };\n"
|
||||
"type in1 = in0;\n"
|
||||
"type out0 = struct { inner: in1, n: i64 };\n"
|
||||
"type out1 = out0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: out1; s.inner.v = 7; s.n = 3;\n"
|
||||
" let p: *out1 = &s;\n"
|
||||
" if (p.inner.v != 7) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "esub_2lvl",
|
||||
"package main;\n"
|
||||
"type my32 = u32;\n"
|
||||
"type my32b = my32;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: [3]my32b;\n"
|
||||
" xs[0] = 5; xs[1] = 6; xs[2] = 7;\n"
|
||||
" if (xs[0]: i64 + xs[1]: i64 + xs[2]: i64 != 18) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* #101: NARROW-alias struct-FILL stride (the cgstructlitfill
|
||||
* :4791 leg, twin of esub_2lvl's INDEX leg). Pre-fold ww sized
|
||||
* the [3]my32 element off primsize("my32")=0 → 8B-default stride,
|
||||
* so the fill stored at -24/-16/-8 and field n collided with
|
||||
* arr[2] (run exit 1); cs chased my32→u32→4 (MOVL stride-4). The
|
||||
* aliasprimsize route aligns ww UP — kw1_101 was the SOLE corpus
|
||||
* mover (cs0/ww1 byteid-NO → byteid-YES + run 0). */
|
||||
{ "kw1_101",
|
||||
"package main;\n"
|
||||
"type my32 = u32;\n"
|
||||
"type S = struct { arr: [3]my32, n: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s = S { arr = [10u32, 20u32, 30u32], n = 4 };\n"
|
||||
" if (s.arr[0] + s.arr[1] + s.arr[2] != 60u32) { return 1; };\n"
|
||||
" if (s.n != 4) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* #101 control: a DIFFERENT narrow width (u16, stride-2 MOVW)
|
||||
* proves the routed esz is width-general, not a 4-only patch.
|
||||
* fld n must survive the fill untouched. */
|
||||
{ "kw1_ctl16",
|
||||
"package main;\n"
|
||||
"type my16 = u16;\n"
|
||||
"type S2 = struct { arr: [4]my16, n: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s = S2 { arr = [1u16, 2u16, 3u16, 4u16], n = 9 };\n"
|
||||
" if (s.arr[0] + s.arr[1] + s.arr[2] + s.arr[3] != 10u16) { return 1; };\n"
|
||||
" if (s.n != 9) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ---- c4: cast/is/try family */
|
||||
{ "strcast_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
"type ms = ms0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: ms = \"hey\";\n"
|
||||
" let b: []u8 = a: []u8;\n"
|
||||
" if (len(b) != 3) { return 1; };\n"
|
||||
" if (b[0] != 'h') { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "idcast_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: u = 42i64;\n"
|
||||
" let w: u = (v: u);\n"
|
||||
" match (w) {\n"
|
||||
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "is_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: u = 42i64;\n"
|
||||
" if (!(v is i64)) { return 1; };\n"
|
||||
" if (v is void) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ALIAS-INDEPENDENT #38b bound (ken's row is >48B sret-class):
|
||||
* the :9819 chase must stay loud-preserving — this pins the
|
||||
* fatal so a future chase can't silently green it. */
|
||||
{ "try_loud_38b",
|
||||
"package main;\n"
|
||||
"type e0 = !i64;\n"
|
||||
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };\n"
|
||||
"type r0 = (big | e0);\n"
|
||||
"type r = r0;\n"
|
||||
"fn w() r = {\n"
|
||||
" let s: big;\n"
|
||||
" s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 5; s.f = 6; s.g = 77;\n"
|
||||
" return s;\n"
|
||||
"};\n"
|
||||
"fn outer() (i64 | e0) = {\n"
|
||||
" let v = w()?;\n"
|
||||
" return v.g;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" match (outer()) {\n"
|
||||
" case let n: i64 => { if (n != 77) { return 1; }; };\n"
|
||||
" case e0 => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR,
|
||||
"#38b: `?`/`!` on an sret-class call result unwired", NULL },
|
||||
/* ---- c5: reads/len/globals family */
|
||||
{ "tfread_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
"type u = u0;\n"
|
||||
"type st0 = struct { f: u, n: i64 };\n"
|
||||
"type st = st0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: st;\n"
|
||||
" s.f = 42i64;\n"
|
||||
" s.n = 3;\n"
|
||||
" if (!(s.f is i64)) { return 1; };\n"
|
||||
" let p: *st = &s;\n"
|
||||
" if (!(p.f is i64)) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "len_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
"type ms = ms0;\n"
|
||||
"type ar0 = [4]i64;\n"
|
||||
"type ar = ar0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: ms = \"hello\";\n"
|
||||
" if (len(a) != 5) { return 1; };\n"
|
||||
" let xs: ar = [1, 2, 3, 4];\n"
|
||||
" if (len(xs) != 4) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "gref_2lvl",
|
||||
"package main;\n"
|
||||
"type my64 = i64;\n"
|
||||
"type my64b = my64;\n"
|
||||
"let G: my64b = 7;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G != 7) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* :9944 #37 cap-watch: the `is` site's >32B mem-read predicate
|
||||
* must key the CHASED size — byte-neutrality of this 40B-union
|
||||
* row across the c5 chase is the regression net. */
|
||||
{ "memread_40b",
|
||||
"package main;\n"
|
||||
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64 };\n"
|
||||
"type m0 = (void | big);\n"
|
||||
"type m = m0;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let s: big;\n"
|
||||
" s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 55;\n"
|
||||
" let v: m = s;\n"
|
||||
" if (!(v is big)) { return 1; };\n"
|
||||
" match (v) {\n"
|
||||
" case let w: big => { if (w.e != 55) { return 2; }; };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
};
|
||||
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i, int expect_err,
|
||||
int want, const char *experr)
|
||||
{
|
||||
char tmpdir[96], src[128], outbin[128], errf[128], rmcmd[160];
|
||||
char cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/ab6_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/ab6_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/ab6_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (expect_err) {
|
||||
int ok = (brc != 0)
|
||||
&& (experr == NULL || errlog_has(errf, experr));
|
||||
if (!ok)
|
||||
fprintf(stderr, "row[%s]: %s expected loud builderr "
|
||||
"\"%s\" (brc=%d)\n", r->label, driver,
|
||||
experr ? experr : "", brc);
|
||||
runwait(rmcmd);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/ab6_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/ab6_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/ab6_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@@ -649,41 +112,17 @@ main(void)
|
||||
bin = absbin;
|
||||
}
|
||||
|
||||
char cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int cs_err = rows[i].kind == K_BUILDERR;
|
||||
if (run_driver(cdrv, &rows[i], i, cs_err,
|
||||
rows[i].cswant, rows[i].experr) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int ww_err = rows[i].kind == K_BUILDERR;
|
||||
const char *we = rows[i].experr_ww
|
||||
? rows[i].experr_ww : rows[i].experr;
|
||||
if (run_driver(wdrv, &rows[i], i, ww_err,
|
||||
rows[i].wwwant, we) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (rows[i].kind != K_RUN)
|
||||
continue;
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
int fail = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (run_row(bin, rows[i].label, rows[i].src, rows[i].cserr,
|
||||
rows[i].wwerr, i) != 0)
|
||||
fail++;
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_cgen_b6: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
fprintf(stderr, "alias_cgen_b6 (slim): %d/%d rows failed\n", fail, n);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_cgen_b6: %d/%d ok\n", total, total);
|
||||
printf("alias_cgen_b6 (slim): %d/%d ok\n", n, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,426 +0,0 @@
|
||||
/*
|
||||
* 944_alias_decl_order_size_run — #62 rider (alias arc pre-F1): type-
|
||||
* table layout must be DECL-ORDER-INDEPENDENT. cstage check_file used
|
||||
* to resolve typedecl bodies in file order with an eager under->size
|
||||
* copy, so any body referencing a typedecl declared LATER read its
|
||||
* size-0 placeholder and baked it in: alias size 0, tagged-union
|
||||
* maxsz 0 (the F0 m5_match $48-frame under-allocated box), struct
|
||||
* field offsets collapsed, array element stride 0. wwstage (demand-
|
||||
* driven tinfofornode) was order-independent on every row — the
|
||||
* measured-sound side cstage now mirrors via resolve_typedecl's
|
||||
* resolve-on-first-reference. Oracle: ken /tmp/ken_62_oracle.md
|
||||
* (size((void|ali)) = 8B tag + roundup8(chased member size); every
|
||||
* behavior indistinguishable from the (void|base) spelling).
|
||||
*
|
||||
* row | shape | want
|
||||
* -----------------+-----------------------------------------+-----
|
||||
* sizes_norm | base,ali decl order; size(base/ali/ |
|
||||
* | (void|ali)) = 16/16/24 | 0
|
||||
* sizes_fwd | ali BEFORE base (fwd-ref); same asserts | 0
|
||||
* union_decl_norm | named u=(void|ali) declared LAST | 0
|
||||
* union_decl_fwd | named u=(void|ali) declared FIRST | 0
|
||||
* field_fwd | outer{i,j:inner} before inner — total |
|
||||
* | size AND j.b offset readback (4/9/7/3 |
|
||||
* | break prefix-luck; last word checked) | 0
|
||||
* field_norm | inner before outer; same asserts | 0
|
||||
* arrelem_fwd | arr=[2]base before base — stride + |
|
||||
* | a[1].b last-word readback | 0
|
||||
* arrelem_norm | base before arr; same asserts | 0
|
||||
* chain2_fwd | a2=a1=base full fwd chain; 16/16 | 0
|
||||
* chain2_norm | base,a1,a2 decl order; same asserts | 0
|
||||
* union_base_ctl | (void|base) match payload readback — |
|
||||
* | the m5b_match0 no-regress control | 0
|
||||
* cycle_alias | type a=b; type b=a — loud BUILDERR |
|
||||
* | both stages (#69: pre-fix cs silent-0, |
|
||||
* | ww HANG) | err
|
||||
* cycle_self | type a=a — loud BUILDERR both stages | err
|
||||
* cycle_struct_value | s1{x:s2}/s2{x:s1} — loud BUILDERR |
|
||||
* | both stages (pre-fix ww stack overflow) | err
|
||||
* ptr_selfref_ok | node{v,next:*node} legal self-ref stays |
|
||||
* | accepted + byte-id (guard no-over-fire) | 0
|
||||
*
|
||||
* NOT pinned here: the alias-in-union match payload readback
|
||||
* (m5b_match1) — its word0-only box STORE is the Layer-2 cgen family
|
||||
* (cstage cg_widen_tagged_store single NAMED peel; wwstage
|
||||
* rhsstructpayload name-keyed structlookup without alias chase),
|
||||
* EXPECTED-FAIL until the F1/F2 copy-width fix lands. See task #62.
|
||||
*
|
||||
* Every row also asserts cstage/wwstage asm byte-id, except rows
|
||||
* flagged nobyteid (arrelem_fwd — the pre-existing task-#60 index-
|
||||
* over-alias divergence; see the row comment). NNN<950,
|
||||
* self-contained (/tmp, no imports) — rule-14's selfhost-sibling
|
||||
* race does not apply (941 precedent).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
runwait(const char *cmd)
|
||||
{
|
||||
int rc = system(cmd);
|
||||
if (rc == -1) return -1;
|
||||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define K_RUN 0 /* build+run both drivers, exit==want, + cs==ww byte-id */
|
||||
#define K_BUILDERR 1 /* build must FAIL with experr on BOTH drivers (rule 7) */
|
||||
|
||||
/* nobyteid: the row's RUNTIME behavior is pinned on both stages but
|
||||
* its asm is excluded from the byte-id sweep — cite the filed task at
|
||||
* the row. */
|
||||
struct row { const char *label; const char *src; int want; int nobyteid;
|
||||
int kind; const char *experr; };
|
||||
|
||||
/* errlog_has — a BUILDERR row must fail WITH its diagnostic; any other
|
||||
* failure (parse error, crash, hang-kill) is a vacuous reject (940
|
||||
* precedent). */
|
||||
static int
|
||||
errlog_has(const char *path, const char *needle)
|
||||
{
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f) return 0;
|
||||
char buf[8192];
|
||||
size_t got = fread(buf, 1, sizeof buf - 1, f);
|
||||
fclose(f);
|
||||
buf[got] = '\0';
|
||||
return strstr(buf, needle) != NULL;
|
||||
}
|
||||
|
||||
static const struct row rows[] = {
|
||||
{ "sizes_norm",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type ali = base;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(base) != 16) { return 1; };\n"
|
||||
" if (size(ali) != 16) { return 2; };\n"
|
||||
" if (size((void | ali)) != 24) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "sizes_fwd",
|
||||
"package main;\n"
|
||||
"type ali = base;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(base) != 16) { return 1; };\n"
|
||||
" if (size(ali) != 16) { return 2; };\n"
|
||||
" if (size((void | ali)) != 24) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "union_decl_norm",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type ali = base;\n"
|
||||
"type u = (void | ali);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(u) != 24) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "union_decl_fwd",
|
||||
"package main;\n"
|
||||
"type u = (void | ali);\n"
|
||||
"type ali = base;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(u) != 24) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* fwd field: a size-0 inner collapsed outer's offsets too — pin
|
||||
* the LAST word of the SECOND field, values all distinct. */
|
||||
{ "field_fwd",
|
||||
"package main;\n"
|
||||
"type outer = struct { i: inner, j: inner };\n"
|
||||
"type inner = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(inner) != 16) { return 1; };\n"
|
||||
" if (size(outer) != 32) { return 2; };\n"
|
||||
" let o: outer;\n"
|
||||
" o.i.a = 4; o.i.b = 9; o.j.a = 7; o.j.b = 3;\n"
|
||||
" if (o.i.a != 4) { return 3; };\n"
|
||||
" if (o.i.b != 9) { return 4; };\n"
|
||||
" if (o.j.a != 7) { return 5; };\n"
|
||||
" if (o.j.b != 3) { return 6; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "field_norm",
|
||||
"package main;\n"
|
||||
"type inner = struct { a: size, b: size };\n"
|
||||
"type outer = struct { i: inner, j: inner };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(inner) != 16) { return 1; };\n"
|
||||
" if (size(outer) != 32) { return 2; };\n"
|
||||
" let o: outer;\n"
|
||||
" o.i.a = 4; o.i.b = 9; o.j.a = 7; o.j.b = 3;\n"
|
||||
" if (o.i.a != 4) { return 3; };\n"
|
||||
" if (o.i.b != 9) { return 4; };\n"
|
||||
" if (o.j.a != 7) { return 5; };\n"
|
||||
" if (o.j.b != 3) { return 6; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* nobyteid: indexing an alias-NAMED array local is the task-#60
|
||||
* family — wwstage emits a ptr-load/ADDQ spine vs cstage's direct
|
||||
* 8(BX); PRE-EXISTING on master, order-independent, runtime-
|
||||
* correct here (8B-multiple elements). The size assert + element
|
||||
* readback below stay pinned on both stages; flip this flag when
|
||||
* #60 lands. */
|
||||
{ "arrelem_fwd",
|
||||
"package main;\n"
|
||||
"type arr = [2]base;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(arr) != 32) { return 1; };\n"
|
||||
" let a: arr;\n"
|
||||
" a[0].a = 4; a[0].b = 9; a[1].a = 7; a[1].b = 3;\n"
|
||||
" if (a[0].b != 9) { return 2; };\n"
|
||||
" if (a[1].a != 7) { return 3; };\n"
|
||||
" if (a[1].b != 3) { return 4; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 1, K_RUN, NULL },
|
||||
/* nobyteid: same #60 cite as arrelem_fwd — the index-over-alias
|
||||
* divergence is order-INDEPENDENT (verified on master). */
|
||||
{ "arrelem_norm",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type arr = [2]base;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(arr) != 32) { return 1; };\n"
|
||||
" let a: arr;\n"
|
||||
" a[0].a = 4; a[0].b = 9; a[1].a = 7; a[1].b = 3;\n"
|
||||
" if (a[0].b != 9) { return 2; };\n"
|
||||
" if (a[1].a != 7) { return 3; };\n"
|
||||
" if (a[1].b != 3) { return 4; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 1, K_RUN, NULL },
|
||||
{ "chain2_fwd",
|
||||
"package main;\n"
|
||||
"type a2 = a1;\n"
|
||||
"type a1 = base;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(a1) != 16) { return 1; };\n"
|
||||
" if (size(a2) != 16) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
{ "chain2_norm",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type a1 = base;\n"
|
||||
"type a2 = a1;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(a1) != 16) { return 1; };\n"
|
||||
" if (size(a2) != 16) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* m5b_match0 no-regress control: direct base member, full payload
|
||||
* readback through the box, last word checked. */
|
||||
{ "union_base_ctl",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: base;\n"
|
||||
" x.a = 4; x.b = 9;\n"
|
||||
" let v: (void | base) = x;\n"
|
||||
" match (v) {\n"
|
||||
" case let s: base => {\n"
|
||||
" if (s.a != 4) { return 1; };\n"
|
||||
" if (s.b != 9) { return 2; };\n"
|
||||
" };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
/* #62/#69 cycle guard (rob's rider condition): TRUE typedecl
|
||||
* cycles loud-reject on BOTH stages — pre-guard cs silently sized
|
||||
* them 0 and wwstage HUNG (alias cycle) / stack-overflowed (struct
|
||||
* value cycle). harec cite: check.c:4767 "Circular dependency". */
|
||||
{ "cycle_alias",
|
||||
"package main;\n"
|
||||
"type a = b;\n"
|
||||
"type b = a;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(a) != 8) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR, "circular type dependency" },
|
||||
{ "cycle_self",
|
||||
"package main;\n"
|
||||
"type a = a;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(a) != 8) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR, "circular type dependency" },
|
||||
{ "cycle_struct_value",
|
||||
"package main;\n"
|
||||
"type s1 = struct { x: s2 };\n"
|
||||
"type s2 = struct { x: s1 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (size(s1) != 8) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_BUILDERR, "circular type dependency" },
|
||||
/* The LEGAL self-reference (pointer field never reads the
|
||||
* target's size) must stay accepted — the io.stream / list-node
|
||||
* shape the cycle guard is forbidden from breaking. */
|
||||
{ "ptr_selfref_ok",
|
||||
"package main;\n"
|
||||
"type node = struct { v: size, next: *node };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let n: node;\n"
|
||||
" n.v = 7;\n"
|
||||
" n.next = &n;\n"
|
||||
" if (size(node) != 16) { return 1; };\n"
|
||||
" if (n.v != 7) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL },
|
||||
};
|
||||
|
||||
/* build+run via a driver (ww / ww_ww); returns 0 pass, nonzero fail. */
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i)
|
||||
{
|
||||
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[160], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/ados_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/ados_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/ados_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
/* timeout: the pre-#69 wwstage HANG on a cycle must fail the row,
|
||||
* not wedge the suite. */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (r->kind == K_BUILDERR) {
|
||||
int ok = (brc != 0)
|
||||
&& (r->experr == NULL || errlog_has(errf, r->experr));
|
||||
if (!ok)
|
||||
fprintf(stderr, "row[%s]: %s expected loud builderr "
|
||||
"\"%s\" (brc=%d)\n", r->label, driver,
|
||||
r->experr ? r->experr : "", brc);
|
||||
runwait(rmcmd);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != r->want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, r->want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cs==ww .s byte-id (rule 10). */
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/ados_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/ados_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/ados_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bin = getenv("BIN");
|
||||
if (!bin) bin = "out/bin";
|
||||
char absbin[2080];
|
||||
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 cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(cdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (rows[i].nobyteid || rows[i].kind == K_BUILDERR)
|
||||
continue;
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_decl_order_size: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_decl_order_size: %d/%d ok\n", total, total);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,88 +1,22 @@
|
||||
/*
|
||||
* 944_alias_emit_b7_run — #5 alias arc B7 (finale): the four cgen.c
|
||||
* static-DATA emitter ELEM-type chases. All four sites already chased
|
||||
* the OUTER type; the residual single peel was on the ELEMENT type
|
||||
* (u->sub), so a 2-level-elem-alias global missed the TY_STRUCT /
|
||||
* TY_STR / TY_TAGGED kind tests and fell off the foldable-literal
|
||||
* path. cs-only: every graduation is a cs-side flip onto ww's
|
||||
* already-correct emit (align cs UP); _ww binaries bit-identical
|
||||
* across the commit (comment-only ww annotation bytes are
|
||||
* codegen-inert).
|
||||
* 944_alias_emit_b7_run — SLIM CARRIER (#5-C3 alias fold-2). The 8 K_RUN value
|
||||
* rows migrated to test/lang/alias_emit_b7_test.ww (@test, cs==ww byte-id); the
|
||||
* symmetric K_BUILDERR rejects (slcstr_plain_ctl, slcslc_2lvl) to
|
||||
* test/wcc/data/alias_{slcstr_plain,slcslc}/case.ww runww //ww:error.
|
||||
*
|
||||
* Sites (numbering at 05f7af7): emit_array_lit_bytes:14356 (struct
|
||||
* arm + raw-bytes path), emit_strarray_data:14574 (str DATAW+DATAR
|
||||
* rows), emit_slice_data:14788 (3-way slice-of-{str,slice,tagged}
|
||||
* fatal), let_pre_intern:15088 (the :14574 row's label-order leg —
|
||||
* MUST chase in the same commit or _S_ labels intern in emit order,
|
||||
* not decl order; strarr_2lvl's byte-id IS the coupling proof).
|
||||
*
|
||||
* Row sources: ken's B7 first-position oracle (/tmp/ken_b5/src/kb7_*,
|
||||
* .ai/ken-b7-oracle.md, matrix at 05f7af7) + impl pre-state probes.
|
||||
* NOTE: `type el = el0` where el0 is itself a type decl is ALREADY two
|
||||
* NAMED layers (NAMED(el)→NAMED(el0)→struct), so the "_1lvl" struct
|
||||
* spelling graduates with the 2-level rows; only a direct alias of a
|
||||
* primitive (type ms = str) is a true single layer.
|
||||
*
|
||||
* row | shape | cs/ww
|
||||
* -------------------+--------------------------------------+------
|
||||
* sarr_2lvl | kb7_sarr [2]el 2-lvl alias struct |
|
||||
* | elem: cs emitted NO DATA (eu peel |
|
||||
* | missed TY_STRUCT → return 0 → caller |
|
||||
* | skipped the def) → link-loud. LIVE |
|
||||
* | graduation → 0/0 byte-id | 0/0
|
||||
* sarr_1lvl | [2]el, el = el0 — two NAMED layers |
|
||||
* | by construction; same graduation | 0/0
|
||||
* sarr_plain_ctl | kb7_sarr0 [2]el0 control | 0/0
|
||||
* sarr_unref_2lvl | NEVER-REFERENCED 2-lvl-elem global: |
|
||||
* | pre-B7 cs silently lacked DATA (no |
|
||||
* | reference → no link error → latent |
|
||||
* | silence, ken's caveat). Closure pin: |
|
||||
* | byte-id vs ww (which always emitted) | 0/0
|
||||
* strarr_2lvl | kb7_strarr [2]ms 2-lvl alias str: |
|
||||
* | eu != TY_STR → generic path can't |
|
||||
* | fold strlits → link-loud. Graduation |
|
||||
* | + the :15088 intern-order coupling | 0/0
|
||||
* strarr_1lvl_ctl | type ms = str — TRUE 1-level; worked |
|
||||
* | pre-B7, byte-NEUTRAL regression net | 0/0
|
||||
* strarr_plain_ctl | kb7_strarr0 [2]str control | 0/0
|
||||
* scalararr_2lvl | [3]my64b raw-bytes path: scalar fold |
|
||||
* | never consulted eu — worked pre-B7, |
|
||||
* | byte-NEUTRAL regression net | 0/0
|
||||
* slc_2lvl | kb7_slc []my64b: cs ok (synthesized- |
|
||||
* | array choke-point + mirrored esz), |
|
||||
* | ww checker-rejects ALL slice-literal |
|
||||
* | globals ("let: not assignable", |
|
||||
* | pre-existing acceptance divergence, |
|
||||
* | #66-R2/#29 kin) — ww cell MUST NOT |
|
||||
* | move across B7 | 0/err
|
||||
* slc_plain_ctl | kb7_slc0 []i64 — same split | 0/err
|
||||
* slcstr_2lvl | kb7_slcstr []ms: pre-B7 the alias |
|
||||
* | ESCAPED the 3-way fatal and hit the |
|
||||
* | downstream "not a foldable constant" |
|
||||
* | — loud but WRONG DIAGNOSTIC. Post: |
|
||||
* | the intended 3-way text (== control) | err/err
|
||||
* slcstr_plain_ctl | kb7_slcstr0 []str pins the 3-way |
|
||||
* | text on the control | err/err
|
||||
* slctag_2lvl | []u1 2-lvl alias tagged elem: pre-B7 |
|
||||
* | the alias DODGED the 3-way fatal |
|
||||
* | ENTIRELY — silent accept + run |
|
||||
* | (wrong-DATA latency). DESIGNED |
|
||||
* | NARROWING: post-B7 louds with the |
|
||||
* | 3-way text ("widen what the gate |
|
||||
* | SEES", B6-c2 fsarg2 precedent) | err/err
|
||||
* slcslc_2lvl | []ms (ms = []i64): nested slice-lit |
|
||||
* | rejected UPSTREAM by the cs checker |
|
||||
* | ("let G init not assignable") — the |
|
||||
* | TY_SLICE arm of the 3-way is not |
|
||||
* | reachable via a literal; pin the |
|
||||
* | checker bound (alias-independent) | err/err
|
||||
*
|
||||
* K_RUN rows build+run BOTH drivers (exit==want) and assert cs/ww asm
|
||||
* byte-id. K_BUILDERR rows must FAIL with experr on BOTH drivers;
|
||||
* experr_ww overrides the ww text when the stages loud at different
|
||||
* sites. K_CSRUN_WWERR rows run on the cs driver and must FAIL with
|
||||
* experr_ww on the ww driver (ken's observation cells; byte-id N/A).
|
||||
* NNN<950, self-contained /tmp sources, no imports (944 precedent).
|
||||
* What survives here are the 4 IRREDUCIBLE per-stage rows neither in-language
|
||||
* surface can host (ken's emit_slice_data observation cells — load-bearing
|
||||
* codegen pins, MUST NOT move):
|
||||
* • slc_2lvl / slc_plain_ctl (Group A): cstage builds+RUNS exit 0; wwstage
|
||||
* LOUD-REJECTS at the let checker ("let: not assignable"). cstage emits the
|
||||
* []my64b / []i64 slice-literal global DATA and runs; the ww checker
|
||||
* rejects every slice-literal global (the #120/#29-kin acceptance
|
||||
* divergence, ken-d2-oracle; pre-slim #66-R2/#29). @test needs ww to
|
||||
* build, //ww:error needs cs to fail — neither fits.
|
||||
* • slcstr_2lvl / slctag_2lvl (Group B): BOTH reject but with DIFFERENT
|
||||
* diagnostics (cs at emit_slice_data 3-way "static-init unsupported"; ww at
|
||||
* the let checker "not assignable") — a held cs!=ww divergence; the two
|
||||
* messages ARE the pin, so each stage's own substring is asserted.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -100,37 +34,6 @@ runwait(const char *cmd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define K_RUN 0 /* build+run BOTH, exits==wants, + byte-id */
|
||||
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers;
|
||||
* experr_ww overrides the ww-side text */
|
||||
#define K_CSRUN_WWERR 2 /* cs builds+runs (exit==cswant); ww must
|
||||
* FAIL with experr_ww (pre-existing
|
||||
* acceptance divergence cell); byte-id
|
||||
* N/A — ww emits nothing */
|
||||
|
||||
struct row { const char *label; const char *src;
|
||||
int cswant; int wwwant; int kind;
|
||||
const char *experr; const char *experr_ww; };
|
||||
|
||||
/* errlog_has — a builderr cell must fail WITH its diagnostic; any other
|
||||
* failure (parse error, crash, hang-kill) is a vacuous reject (940
|
||||
* precedent). */
|
||||
static int
|
||||
errlog_has(const char *path, const char *needle)
|
||||
{
|
||||
@@ -143,90 +46,65 @@ errlog_has(const char *path, const char *needle)
|
||||
return strstr(buf, needle) != NULL;
|
||||
}
|
||||
|
||||
#define ERR_3WAY "slice-of-{str,slice,tagged} literal static-init unsupported"
|
||||
#define ERR_WWLET "let: not assignable"
|
||||
#define M_CSRUN_WWERR 0 /* cstage build+run exit 0; wwstage w6c_ww rejects wwerr */
|
||||
#define M_BOTHERR 1 /* cstage w6c rejects cserr; wwstage w6c_ww rejects wwerr */
|
||||
|
||||
struct row { const char *label; const char *src; int mode;
|
||||
const char *cserr; const char *wwerr; };
|
||||
|
||||
static int
|
||||
run_row(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char dir[96], srcf[160], outbin[160], cse[160], wwe[160], ss[160],
|
||||
rm[200], cmd[2048];
|
||||
snprintf(dir, sizeof dir, "/tmp/ab7_%d_%d", getpid(), i);
|
||||
mkdir(dir, 0755);
|
||||
snprintf(srcf, sizeof srcf, "%s/c.ww", dir);
|
||||
snprintf(outbin, sizeof outbin, "%s/bin", dir);
|
||||
snprintf(cse, sizeof cse, "%s/cs.err", dir);
|
||||
snprintf(wwe, sizeof wwe, "%s/ww.err", dir);
|
||||
snprintf(ss, sizeof ss, "%s/o.s", dir);
|
||||
snprintf(rm, sizeof rm, "rm -rf %s", dir);
|
||||
|
||||
FILE *f = fopen(srcf, "wb");
|
||||
if (!f) { runwait(rm); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
int ok = 1;
|
||||
if (r->mode == M_CSRUN_WWERR) {
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s/ww build -o %s %s >/dev/null 2>&1",
|
||||
bin, outbin, srcf);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: cstage build failed (want run)\n",
|
||||
r->label);
|
||||
ok = 0;
|
||||
} else if (runwait(outbin) != 0) {
|
||||
fprintf(stderr, "row[%s]: cstage run != 0\n", r->label);
|
||||
ok = 0;
|
||||
}
|
||||
} else {
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>%s", bin, ss, srcf, cse);
|
||||
int crc = runwait(cmd);
|
||||
if (!(crc != 0 && errlog_has(cse, r->cserr))) {
|
||||
fprintf(stderr, "row[%s]: cstage expected reject \"%s\" (rc=%d)\n",
|
||||
r->label, r->cserr, crc);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>%s", bin, ss, srcf, wwe);
|
||||
int wrc = runwait(cmd);
|
||||
if (!(wrc != 0 && errlog_has(wwe, r->wwerr))) {
|
||||
fprintf(stderr, "row[%s]: wwstage expected reject \"%s\" (rc=%d)\n",
|
||||
r->label, r->wwerr, wrc);
|
||||
ok = 0;
|
||||
}
|
||||
runwait(rm);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
static const struct row rows[] = {
|
||||
/* ---- emit_array_lit_bytes struct arm (:14356) */
|
||||
{ "sarr_2lvl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64, b: i64 };\n"
|
||||
"type el1 = el0;\n"
|
||||
"type el = el1;\n"
|
||||
"let G: [2]el = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G[0].a + G[0].b + G[1].a + G[1].b != 10) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "sarr_1lvl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64, b: i64 };\n"
|
||||
"type el = el0;\n"
|
||||
"let G: [2]el = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G[0].a + G[0].b + G[1].a + G[1].b != 10) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "sarr_plain_ctl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64, b: i64 };\n"
|
||||
"let G: [2]el0 = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G[0].a + G[0].b + G[1].a + G[1].b != 10) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* Zero-consumer latent silence (ken's caveat): unreferenced, so
|
||||
* the pre-B7 missing DATA never linked-loud — the byte-id cell
|
||||
* vs ww (which always emitted the row) is the closure pin. */
|
||||
{ "sarr_unref_2lvl",
|
||||
"package main;\n"
|
||||
"type el0 = struct { a: i64, b: i64 };\n"
|
||||
"type el1 = el0;\n"
|
||||
"type el = el1;\n"
|
||||
"let G: [2]el = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ---- emit_strarray_data (:14574) + let_pre_intern (:15088) */
|
||||
{ "strarr_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
"type ms = ms0;\n"
|
||||
"let G: [2]ms = [\"aa\", \"bbb\"];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G[0]) != 2) { return 1; };\n"
|
||||
" if (len(G[1]) != 3) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "strarr_1lvl_ctl",
|
||||
"package main;\n"
|
||||
"type ms = str;\n"
|
||||
"let G: [2]ms = [\"aa\", \"bbb\"];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G[0]) != 2) { return 1; };\n"
|
||||
" if (len(G[1]) != 3) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
{ "strarr_plain_ctl",
|
||||
"package main;\n"
|
||||
"let G: [2]str = [\"aa\", \"bbb\"];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G[0]) != 2) { return 1; };\n"
|
||||
" if (len(G[1]) != 3) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* Raw-bytes scalar fold never consulted eu — byte-NEUTRAL net. */
|
||||
{ "scalararr_2lvl",
|
||||
"package main;\n"
|
||||
"type my64 = i64;\n"
|
||||
"type my64b = my64;\n"
|
||||
"let G: [3]my64b = [5, 6, 7];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G[0] + G[1] + G[2] != 18) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0, K_RUN, NULL, NULL },
|
||||
/* ---- emit_slice_data (:14788) — ken's ww observation cells
|
||||
* (checker-rejects every slice-literal global) MUST NOT move. */
|
||||
{ "slc_2lvl",
|
||||
"package main;\n"
|
||||
"type my64 = i64;\n"
|
||||
@@ -236,7 +114,7 @@ static const struct row rows[] = {
|
||||
" if (G[0] + G[1] + G[2] != 18) { return 1; };\n"
|
||||
" if (len(G) != 3) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 1, K_CSRUN_WWERR, NULL, ERR_WWLET },
|
||||
"};\n", M_CSRUN_WWERR, NULL, "let: not assignable" },
|
||||
{ "slc_plain_ctl",
|
||||
"package main;\n"
|
||||
"let G: []i64 = [5, 6, 7];\n"
|
||||
@@ -244,10 +122,7 @@ static const struct row rows[] = {
|
||||
" if (G[0] + G[1] + G[2] != 18) { return 1; };\n"
|
||||
" if (len(G) != 3) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 1, K_CSRUN_WWERR, NULL, ERR_WWLET },
|
||||
/* Diagnostic-routing fix: pre-B7 the 2-lvl alias escaped the
|
||||
* 3-way fatal onto the downstream "not a foldable constant"
|
||||
* text — loud either way, wrong message. Post: == control. */
|
||||
"};\n", M_CSRUN_WWERR, NULL, "let: not assignable" },
|
||||
{ "slcstr_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = str;\n"
|
||||
@@ -256,22 +131,9 @@ static const struct row rows[] = {
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G[0]) != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 1, 1, K_BUILDERR, ERR_3WAY, ERR_WWLET },
|
||||
/* ww cell observed: plain []str PASSES the ww checker and louds
|
||||
* at ww's own emitslicedata 3-way — the shared needle pins both
|
||||
* stages' texts (cs "emit_slice_data:", ww "emitslicedata:");
|
||||
* only ALIAS slice spellings reject at the ww checker. */
|
||||
{ "slcstr_plain_ctl",
|
||||
"package main;\n"
|
||||
"let G: []str = [\"aa\", \"bbb\"];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G[0]) != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 1, 1, K_BUILDERR, ERR_3WAY, NULL },
|
||||
/* DESIGNED NARROWING: pre-B7 the tagged-elem alias dodged the
|
||||
* 3-way fatal entirely — cs silently accepted and ran (wrong-
|
||||
* DATA latency). The chase widens what the gate SEES (B6-c2
|
||||
* fsarg2 precedent); the loud stays loud for what it guards. */
|
||||
"};\n", M_BOTHERR,
|
||||
"slice-of-{str,slice,tagged} literal static-init unsupported",
|
||||
"let: not assignable" },
|
||||
{ "slctag_2lvl",
|
||||
"package main;\n"
|
||||
"type u0 = (void | i64);\n"
|
||||
@@ -280,104 +142,11 @@ static const struct row rows[] = {
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G) != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 1, 1, K_BUILDERR, ERR_3WAY, ERR_WWLET },
|
||||
/* Slice-of-slice literal never reaches the emitter: the cs
|
||||
* checker bounds it upstream, alias-independent. Pin the bound
|
||||
* so a checker widening re-opens this row deliberately. */
|
||||
{ "slcslc_2lvl",
|
||||
"package main;\n"
|
||||
"type ms0 = []i64;\n"
|
||||
"type ms = ms0;\n"
|
||||
"let G: []ms = [[1, 2], [3]];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (len(G) != 2) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 1, 1, K_BUILDERR, "let G init not assignable", ERR_WWLET },
|
||||
"};\n", M_BOTHERR,
|
||||
"slice-of-{str,slice,tagged} literal static-init unsupported",
|
||||
"let: not assignable" },
|
||||
};
|
||||
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i, int expect_err,
|
||||
int want, const char *experr)
|
||||
{
|
||||
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[160], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/ab7_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/ab7_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/ab7_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (expect_err) {
|
||||
int ok = (brc != 0)
|
||||
&& (experr == NULL || errlog_has(errf, experr));
|
||||
if (!ok)
|
||||
fprintf(stderr, "row[%s]: %s expected loud builderr "
|
||||
"\"%s\" (brc=%d)\n", r->label, driver,
|
||||
experr ? experr : "", brc);
|
||||
runwait(rmcmd);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/ab7_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/ab7_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/ab7_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@@ -391,42 +160,15 @@ main(void)
|
||||
bin = absbin;
|
||||
}
|
||||
|
||||
char cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int cs_err = rows[i].kind == K_BUILDERR;
|
||||
if (run_driver(cdrv, &rows[i], i, cs_err,
|
||||
rows[i].cswant, rows[i].experr) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int ww_err = rows[i].kind == K_BUILDERR
|
||||
|| rows[i].kind == K_CSRUN_WWERR;
|
||||
const char *we = rows[i].experr_ww
|
||||
? rows[i].experr_ww : rows[i].experr;
|
||||
if (run_driver(wdrv, &rows[i], i, ww_err,
|
||||
rows[i].wwwant, we) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (rows[i].kind != K_RUN)
|
||||
continue;
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
int fail = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (run_row(bin, &rows[i], i) != 0) fail++;
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_emit_b7: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
fprintf(stderr, "alias_emit_b7 (slim): %d/%d rows failed\n", fail, n);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_emit_b7: %d/%d ok\n", total, total);
|
||||
printf("alias_emit_b7 (slim): %d/%d ok\n", n, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,451 +0,0 @@
|
||||
/*
|
||||
* 944_alias_global_decl_run — g-fold (#77 + #78 fused): alias-typed
|
||||
* GLOBAL declarations, both stages. The decl/emit dispatch was
|
||||
* alias-blind on both sides:
|
||||
*
|
||||
* cs (#78): the let_* helper family (let_emit_size + the five kind
|
||||
* predicates, cgen.c) single-peeled — a 2-level alias chain (or ONE
|
||||
* user alias over a named struct) left the type TY_NAMED, so the
|
||||
* global was never registered, no DATA was emitted, and reads fell
|
||||
* to the frame-local path at offset 0: silent saved-BP reads (garr2
|
||||
* exit-wrong, gst1 SEGV, gstr2/gsl2 silent-wrong). The routed-to
|
||||
* DATA emitters re-peeled at entry and return-0'd into the silent
|
||||
* skip (condition-3 members, enrollment ruling in
|
||||
* .ai/rob-gfold-spec.md).
|
||||
*
|
||||
* ww (#77): emitletdataw's array gates + letpreintern's array leg
|
||||
* keyed on the UNCHASED N_TARRAY tnode — an alias-typed global's
|
||||
* N_TNAME matched no arm and the skip-policy ate the decl: loud
|
||||
* `w6l: undefined reference to main.g` on every alias-global ARRAY
|
||||
* row. Fix: ONE tichase at the dispatch entry (dti), array gates +
|
||||
* emitarraydata read it.
|
||||
*
|
||||
* THIS TABLE IS THE PERMANENT GUARD, not scaffolding: the global decl
|
||||
* path is lint-invisible to the future peellint — the ww side was a
|
||||
* NO-PEEL consumer (zero `.under` tokens; nothing for a peel-shape
|
||||
* lint to flag), and the cs helpers now spell the one chased accessor.
|
||||
* Only a runtime+byte-id row pins this behavior.
|
||||
*
|
||||
* Train trajectory (two commits, one gated train; per-leg states were
|
||||
* probe-verified, banked /tmp/implG_probes.md):
|
||||
* pre-G1: garr2 cs EXIT-WRONG / gst1 cs SEGV / gstr2+gsl2+gstlit cs
|
||||
* silent-wrong / gsc2+gflt2 cs loud / ww array rows link-ERR
|
||||
* post-G1 (cs half): every cs row runs 0; ww array rows STILL
|
||||
* link-ERR (loud, documented)
|
||||
* post-G2 (ww half): every row 0/0 byte-id — this file's assertion.
|
||||
*
|
||||
* Probe-OUT, documented NOT pinned (failed at a DIFFERENT site, filed):
|
||||
* named-tuple global init — cs checker loud-reject, ww accepts (#86)
|
||||
* plain tagged global — cs silent-wrong, ww loud-reject (#87, not
|
||||
* alias-family; control row fails)
|
||||
*
|
||||
* row | shape | want
|
||||
* -------------+----------------------------------------------+-----
|
||||
* ctl_plain | control: plain [4]int global r/w | 0
|
||||
* garr1_read | alias arr 1-lvl, read first+LAST | 0
|
||||
* garr1_wr | alias arr 1-lvl, write+read | 0
|
||||
* garr_ord | alias arr, type decl AFTER let | 0
|
||||
* garr2_read | alias arr 2-LVL read (#78 saved-BP row) | 0
|
||||
* garr2_ordwr | alias arr 2-lvl, order-permuted, w+r | 0
|
||||
* garr_u32 | alias [4]u32 w+r LAST (narrow esz anti-luck) | 0
|
||||
* gsc2 | alias int 2-lvl r/w | 0
|
||||
* gsc2_ord | alias int 2-lvl read, decl-after-let | 0
|
||||
* gstr2 | alias str 2-lvl, len readback | 0
|
||||
* gflt2 | alias f64 2-lvl | 0
|
||||
* gflt2_f32 | alias f32 2-lvl (load-width pin) | 0
|
||||
* gst1 | alias of named struct, field w/r (SEGV row) | 0
|
||||
* gst2 | alias-of-alias named struct | 0
|
||||
* gstlit | alias struct, STRUCTLIT init | 0
|
||||
* gsl2 | alias slice 2-lvl, literal init + idx read | 0
|
||||
* gstrarr1 | alias [2]str 1-lvl (letpreintern label leg) | 0
|
||||
* gstrarr2 | alias [2]str 2-LVL | 0
|
||||
* gdef_a2 | DEF: 2-lvl alias array, index read | 0
|
||||
* gdef_st | DEF: alias struct, structlit + field read | 0
|
||||
* gdef_f2 | DEF: 2-lvl alias f64 | 0
|
||||
* hold_slice1 | alias global SLICE 1-lvl (pre-fold green) | 0
|
||||
* hold_elem | alias ELEMENT type [2]row (batch-1 win) | 0
|
||||
*
|
||||
* Values exceed 255 (no little-endian prefix-luck) and readbacks
|
||||
* assert the LAST element. Every row runs BOTH drivers and asserts
|
||||
* cstage/wwstage asm byte-identity. NNN<950, self-contained /tmp
|
||||
* sources, no imports (944 precedent).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
runwait(const char *cmd)
|
||||
{
|
||||
int rc = system(cmd);
|
||||
if (rc == -1) return -1;
|
||||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct row { const char *label; const char *src; int want; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
{ "ctl_plain",
|
||||
"package main;\n"
|
||||
"let g: [4]int = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[3] != 1004) { return 1; };\n"
|
||||
" g[3] = 9999;\n"
|
||||
" if (g[3] != 9999) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "garr1_read",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"let g: arr = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[0] != 1001) { return 1; };\n"
|
||||
" if (g[3] != 1004) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "garr1_wr",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"let g: arr = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" g[3] = 8888;\n"
|
||||
" if (g[3] != 8888) { return 1; };\n"
|
||||
" if (g[2] != 1003) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "garr_ord",
|
||||
"package main;\n"
|
||||
"let g: arr = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"type arr = [4]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[3] != 1004) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* #78 headline: pre-fix cs emitted NO DATA, never referenced
|
||||
* main.g, and resolved g frame-local at offset 0 — LEAQ (BP) read
|
||||
* the saved-BP word, exiting silently wrong. */
|
||||
{ "garr2_read",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"let g: arr2 = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[0] != 1001) { return 1; };\n"
|
||||
" if (g[3] != 1004) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "garr2_ordwr",
|
||||
"package main;\n"
|
||||
"let g: arr2 = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"type arr2 = arr;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[3] != 1004) { return 1; };\n"
|
||||
" g[1] = 7777;\n"
|
||||
" if (g[1] != 7777) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "garr_u32",
|
||||
"package main;\n"
|
||||
"type au = [4]u32;\n"
|
||||
"let g: au = [1001: u32, 1002: u32, 1003: u32, 1004: u32];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[3] != 1004) { return 1; };\n"
|
||||
" g[3] = 8888;\n"
|
||||
" if (g[3] != 8888) { return 2; };\n"
|
||||
" if (g[2] != 1003) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gsc2",
|
||||
"package main;\n"
|
||||
"type myint = int;\n"
|
||||
"type myint2 = myint;\n"
|
||||
"let g: myint2 = 4242;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g != 4242) { return 1; };\n"
|
||||
" g = 9999;\n"
|
||||
" if (g != 9999) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gsc2_ord",
|
||||
"package main;\n"
|
||||
"let g: myint2 = 4242;\n"
|
||||
"type myint2 = myint;\n"
|
||||
"type myint = int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g != 4242) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gstr2",
|
||||
"package main;\n"
|
||||
"type ms = str;\n"
|
||||
"type ms2 = ms;\n"
|
||||
"let g: ms2 = \"hello\";\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.len != 5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gflt2",
|
||||
"package main;\n"
|
||||
"type mf = f64;\n"
|
||||
"type mf2 = mf;\n"
|
||||
"let g: mf2 = 1.5;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g != 1.5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gflt2_f32",
|
||||
"package main;\n"
|
||||
"type mg = f32;\n"
|
||||
"type mg2 = mg;\n"
|
||||
"let g: mg2 = 1.5f32;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g != 1.5f32) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* ONE user alias level sufficed to SEGV cs pre-fix: the named
|
||||
* struct already costs the single peel, so `pt1 = pt` is two
|
||||
* TY_NAMED layers at the decl. */
|
||||
{ "gst1",
|
||||
"package main;\n"
|
||||
"type pt = struct { x: int, y: int };\n"
|
||||
"type pt1 = pt;\n"
|
||||
"let g: pt1;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" g.y = 2002;\n"
|
||||
" if (g.y != 2002) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gst2",
|
||||
"package main;\n"
|
||||
"type pt = struct { x: int, y: int };\n"
|
||||
"type pt1 = pt;\n"
|
||||
"type pt2 = pt1;\n"
|
||||
"let g: pt2;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" g.y = 2002;\n"
|
||||
" if (g.y != 2002) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gstlit",
|
||||
"package main;\n"
|
||||
"type pt = struct { x: int, y: int };\n"
|
||||
"type pt1 = pt;\n"
|
||||
"let g: pt1 = pt { x = 1001, y = 2002 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.y != 2002) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gsl2",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"type sl2 = sl;\n"
|
||||
"let g: sl2 = [1001: int, 1002: int, 1003: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.len != 3) { return 1; };\n"
|
||||
" if (g[2] != 1003) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* [N]str rows also pin letpreintern's chased array-leg gate: a
|
||||
* missed pre-intern desyncs _S_ label order vs cstage (byte-id
|
||||
* would catch it as a label-number diff). */
|
||||
{ "gstrarr1",
|
||||
"package main;\n"
|
||||
"type sa = [2]str;\n"
|
||||
"let g: sa = [\"hello\", \"worlds!\"];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[1].len != 7) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gstrarr2",
|
||||
"package main;\n"
|
||||
"type sa = [2]str;\n"
|
||||
"type sa2 = sa;\n"
|
||||
"let g: sa2 = [\"hello\", \"worlds!\"];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[1].len != 7) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gdef_a2",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"def G: arr2 = [1001: int, 1002: int, 1003: int, 1004: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G[3] != 1004) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gdef_st",
|
||||
"package main;\n"
|
||||
"type pt = struct { x: int, y: int };\n"
|
||||
"type pt1 = pt;\n"
|
||||
"def G: pt1 = pt { x = 1001, y = 2002 };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G.y != 2002) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "gdef_f2",
|
||||
"package main;\n"
|
||||
"type mf = f64;\n"
|
||||
"type mf2 = mf;\n"
|
||||
"def G: mf2 = 1.5;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (G != 1.5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* No-regression holds: alias global SLICE (green before this
|
||||
* fold) and alias ELEMENT type (batch-1 win). */
|
||||
{ "hold_slice1",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"let g: sl = [1001: int, 1002: int, 1003: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.len != 3) { return 1; };\n"
|
||||
" if (g[2] != 1003) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "hold_elem",
|
||||
"package main;\n"
|
||||
"type row = [3]int;\n"
|
||||
"let g: [2]row = [[1010: int, 1020: int, 1030: int], [1040: int, 1050: int, 1060: int]];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[0][0] != 1010) { return 1; };\n"
|
||||
" if (g[1][2] != 1060) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
};
|
||||
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i)
|
||||
{
|
||||
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[176], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/agd_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/agd_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/agd_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != r->want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, r->want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/agd_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/agd_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/agd_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bin = getenv("BIN");
|
||||
if (!bin) bin = "out/bin";
|
||||
char absbin[2080];
|
||||
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 cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(cdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_global_decl: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_global_decl: %d/%d ok\n", total, total);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,470 +0,0 @@
|
||||
/*
|
||||
* 944_alias_idx_family_run — #5 alias arc F2a batch 1 (task #60 +
|
||||
* the #79 init-store rider): wwstage INDEX / SLICE / FOR-RANGE /
|
||||
* LITERAL-INIT over an alias-NAMED base type. The tnode-keyed cgen
|
||||
* walks saw only the N_TNAME leaf — esz fell to the 1-sentinel (8 on
|
||||
* the init-store side) and the base classified as a POINTER (MOVQ of
|
||||
* array words + no IMULQ): m8b_idx1/range1 SEGV 139, m8b_slice1
|
||||
* silent-wrong past prefix-luck (m8c_slice1big exit 2), alias-[4]u32
|
||||
* literal-init MOVQ stride-8 over a stride-4 slot = saved-BP/RIP
|
||||
* smash (#79, masked when esz==8). cstage reads everything off the
|
||||
* chased stamped type (type_chase_named/idx_eff, post-F1), so it is
|
||||
* the runtime-correct reference; the fix re-keys the ww sites off
|
||||
* tichase'd stamped tinfos (cgindex/cgassign-N_INDEX/cgslice/
|
||||
* cgbasecap in cgenexpr.ww, cgforrange + cgarrlitfillbp + bare-let
|
||||
* classify in cgenstmt.ww, pusharg N_SLICE in cgenutil.ww) and every
|
||||
* row graduates to 0/0 byte-id.
|
||||
*
|
||||
* row | shape | want
|
||||
* ------------------+------------------------------------------+-----
|
||||
* idx0_ctl | named [4]int base read/store (control) | 0
|
||||
* idx1_alias | m8b_idx1: r/w via 1-level alias arr | 0
|
||||
* idx2_2level | write+read via arr2 = arr (944 pin) | 0
|
||||
* idx_fwdref | decl-order permuted chain + compound += | 0
|
||||
* init_u32_alias | #79: type A=[4]u32 literal-init, LAST |
|
||||
* | elem readback (pre-fix BP/RIP smash) | 0
|
||||
* initrep_u32_alias | #79: alias `[v...]` repeat fill — bound |
|
||||
* | off the chased alen, LAST elem | 0
|
||||
* loopfill_1024 | uninit alias [1024]int + loop-fill, LAST |
|
||||
* | elem (pins the bare-let array classify: |
|
||||
* | no composite zero-fill, cs-identical) | 0
|
||||
* slice0_ctl | named base slice (control) | 0
|
||||
* slice1_alias | m8b_slice1 + 1-level alias ARRAY base: |
|
||||
* | sl dest + store + readback | 0
|
||||
* slice2_2level | sl2 = sl, len/read/store + RE-SLICE of |
|
||||
* | the alias slice | 0
|
||||
* slice1big | m8c: 1000 elems, values > 255, LAST-elem |
|
||||
* | readback + default-hi + .cap + range cnt | 0
|
||||
* slice_fwdref | decl-after-use chain over 2-level alias |
|
||||
* | array base, s[1] *= 3 compound | 0
|
||||
* range0_ctl | named [4]int range (control) | 0
|
||||
* range1_alias | m8b_range1: sum over alias arr | 0
|
||||
* range2_2level | sum over arr2 = arr | 0
|
||||
* range_slicealias | for-range over an alias SLICE | 0
|
||||
* m7c_global2d | global [2]row (row = [3]int): g[1][2] | 0
|
||||
* gslice_alias | GLOBAL alias-slice: .len + indexed read | 0
|
||||
* slicearg_alias | slice-of-alias as CALL ARG (pusharg leg) | 0
|
||||
*
|
||||
* Values exceed 255 so an esz=1 byte-load cannot pass by little-endian
|
||||
* prefix-luck; readbacks assert the LAST element. Every row runs BOTH
|
||||
* drivers and asserts cstage/wwstage asm byte-identity (alias rows are
|
||||
* graduations: ww aligned UP to the cs runtime-correct side). NNN<950,
|
||||
* self-contained /tmp sources, no imports (944 precedent).
|
||||
*
|
||||
* Deliberately NOT pinned (g-fold territory, tasks #77/#78): any
|
||||
* DIRECT alias-typed global ARRAY row. Expected state at this commit,
|
||||
* probe-verified UNCHANGED by the fix: `let g: arr = [...]` — ww
|
||||
* link-ERR (no DATA emitted for the alias-typed global), cs 1-level
|
||||
* runs 0, cs 2-level runs WRONG (silent).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
runwait(const char *cmd)
|
||||
{
|
||||
int rc = system(cmd);
|
||||
if (rc == -1) return -1;
|
||||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct row { const char *label; const char *src; int want; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
{ "idx0_ctl",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" if (a[3] != 4000) { return 1; };\n"
|
||||
" a[3] = 9999;\n"
|
||||
" if (a[3] != 9999) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "idx1_alias",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" if (a[2] != 3000) { return 1; };\n"
|
||||
" if (a[3] != 4000) { return 2; };\n"
|
||||
" a[3] = 8888;\n"
|
||||
" if (a[3] != 8888) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "idx2_2level",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" if (a[2] != 3000) { return 1; };\n"
|
||||
" a[1] = 9999;\n"
|
||||
" if (a[1] != 9999) { return 2; };\n"
|
||||
" if (a[3] != 4000) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "idx_fwdref",
|
||||
"package main;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" if (a[3] != 4000) { return 1; };\n"
|
||||
" a[3] += 500;\n"
|
||||
" if (a[3] != 4500) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* #79: narrow-elem alias literal-init. Pre-fix the per-element
|
||||
* store rode the esz=8 sentinel + MOVQ over a stride-4 slot —
|
||||
* elements 2/3 landed at 0(BP)/+8(BP) = saved-BP/RIP smash
|
||||
* (masked when esz==8). LAST element read back. */
|
||||
{ "init_u32_alias",
|
||||
"package main;\n"
|
||||
"type A = [4]u32;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: A = [1: u32, 2: u32, 3: u32, 4: u32];\n"
|
||||
" if (a[3] != 4) { return 1; };\n"
|
||||
" if (a[0] != 1) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* #79 repeat leg: the `[v...]` fill bound comes off the chased
|
||||
* tinfo's alen (an alias arrtn has no length tnode). */
|
||||
{ "initrep_u32_alias",
|
||||
"package main;\n"
|
||||
"type A = [6]u32;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: A = [7: u32...];\n"
|
||||
" if (a[5] != 7) { return 1; };\n"
|
||||
" if (a[0] != 7) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* Uninit alias array + per-index loop fill. Also pins the
|
||||
* bare-let classify: an alias-to-array keeps the per-index-write
|
||||
* contract (no composite zero-fill — cstage-identical asm). */
|
||||
{ "loopfill_1024",
|
||||
"package main;\n"
|
||||
"type arrk = [1024]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arrk;\n"
|
||||
" let i: int = 0;\n"
|
||||
" for (i < 1024) {\n"
|
||||
" a[i] = i * 3 + 1000;\n"
|
||||
" i += 1;\n"
|
||||
" };\n"
|
||||
" if (a[1023] != 1023 * 3 + 1000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "slice0_ctl",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let s: []int = a[1:3];\n"
|
||||
" if (s.len != 2) { return 1; };\n"
|
||||
" if (s[1] != 3000) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* alias slice DEST over a 1-level alias ARRAY base (slice-expr
|
||||
* over alias base, 1-level leg). */
|
||||
{ "slice1_alias",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"type sl = []int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let s: sl = a[1:3];\n"
|
||||
" if (s.len != 2) { return 1; };\n"
|
||||
" if (s[0] != 2000) { return 2; };\n"
|
||||
" s[1] = 7777;\n"
|
||||
" if (a[2] != 7777) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* 2-level alias slice dest + RE-SLICE of the alias slice (the
|
||||
* cgslice alias-SLICE-base leg). */
|
||||
{ "slice2_2level",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"type sl2 = sl;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let s: sl2 = a[1:3];\n"
|
||||
" if (s.len != 2) { return 1; };\n"
|
||||
" if (s[0] != 2000) { return 2; };\n"
|
||||
" s[1] = 7777;\n"
|
||||
" if (a[2] != 7777) { return 3; };\n"
|
||||
" if (s[1] != 7777) { return 4; };\n"
|
||||
" let r: sl = s[0:2];\n"
|
||||
" if (r.len != 2) { return 5; };\n"
|
||||
" if (r[1] != 7777) { return 6; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* 1000 elements, values 300..7293: an esz=1 stride/byte load
|
||||
* cannot land on the right word, and the LAST-element readback
|
||||
* breaks prefix-luck (m8c). Also pins alias default-hi (a[2:]),
|
||||
* .cap via the chased cgbasecap leg, and range over the
|
||||
* 2-level-alias sub-slice. Base array stays plain [1000]int so
|
||||
* this row pins the slice legs in isolation — the alias bare-let
|
||||
* + loop-fill shape is loopfill_1024's pin (the #79-rider
|
||||
* bare-let array classify). */
|
||||
{ "slice1big",
|
||||
"package main;\n"
|
||||
"type slk = []int;\n"
|
||||
"type slk2 = slk;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [1000]int;\n"
|
||||
" let i: int = 0;\n"
|
||||
" for (i < 1000) {\n"
|
||||
" a[i] = i * 7 + 300;\n"
|
||||
" i += 1;\n"
|
||||
" };\n"
|
||||
" let s: slk = a[1:1000];\n"
|
||||
" if (s.len != 999) { return 1; };\n"
|
||||
" if (s[998] != 999 * 7 + 300) { return 2; };\n"
|
||||
" s[998] = 123456;\n"
|
||||
" if (a[999] != 123456) { return 3; };\n"
|
||||
" let t: slk2 = a[2:];\n"
|
||||
" if (t.len != 998) { return 4; };\n"
|
||||
" if (t.cap != 998) { return 5; };\n"
|
||||
" if (t[997] != 123456) { return 6; };\n"
|
||||
" let cnt: int = 0;\n"
|
||||
" for (let x .. t) { cnt = cnt + 1; if (x < 0) { return 8; }; };\n"
|
||||
" if (cnt != 998) { return 7; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "slice_fwdref",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let s: sl2 = a[1:3];\n"
|
||||
" if (s[1] != 3000) { return 1; };\n"
|
||||
" s[1] *= 3;\n"
|
||||
" if (a[2] != 9000) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n"
|
||||
"type sl2 = sl;\n"
|
||||
"type sl = []int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"type arr = [4]int;\n", 0 },
|
||||
{ "range0_ctl",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [4]int = [1: int, 2: int, 3: int, 4: int];\n"
|
||||
" let sum: int = 0;\n"
|
||||
" for (let x .. a) { sum = sum + x; };\n"
|
||||
" if (sum != 10) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "range1_alias",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let sum: int = 0;\n"
|
||||
" for (let x .. a) { sum = sum + x; };\n"
|
||||
" if (sum != 10000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "range2_2level",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let sum: int = 0;\n"
|
||||
" for (let x .. a) { sum = sum + x; };\n"
|
||||
" if (sum != 10000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ "range_slicealias",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let t: sl = a[0:4];\n"
|
||||
" let sum: int = 0;\n"
|
||||
" for (let x .. t) { sum = sum + x; };\n"
|
||||
" if (sum != 10000) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* m7c: the BASE is a plain [2]row global — the alias sits on the
|
||||
* ELEMENT (row = [3]int). elemisarrayc's node walk can't see
|
||||
* through the element's N_TNAME, so g[0] loaded a VALUE where the
|
||||
* sub-array ADDRESS was needed (ww SEGV on the read; DATA emit
|
||||
* was already correct both stages, F0). LAST element checked. */
|
||||
{ "m7c_global2d",
|
||||
"package main;\n"
|
||||
"type row = [3]int;\n"
|
||||
"let g: [2]row = [[10: int, 20: int, 30: int], [40: int, 50: int, 60: int]];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g[0][0] != 10) { return 1; };\n"
|
||||
" if (g[1][2] != 60) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* GLOBAL alias-typed SLICE: DATA emit + .len + indexed read all
|
||||
* resolve (the global ARRAY twin does NOT — see the header note;
|
||||
* g-fold #77/#78). */
|
||||
{ "gslice_alias",
|
||||
"package main;\n"
|
||||
"type sl = []int;\n"
|
||||
"let g: sl = [1000: int, 2000: int, 3000: int];\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (g.len != 3) { return 1; };\n"
|
||||
" if (g[2] != 3000) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* slice-of-alias-array as a CALL ARG exercises the pusharg
|
||||
* N_SLICE leg (cgenutil.ww), a distinct lowering from cgslice;
|
||||
* plus the inferred-let receive of an alias-base slice. */
|
||||
{ "slicearg_alias",
|
||||
"package main;\n"
|
||||
"type arr = [4]int;\n"
|
||||
"type arr2 = arr;\n"
|
||||
"fn sum(s: []int) int = {\n"
|
||||
" let t: int = 0;\n"
|
||||
" for (let x .. s) { t = t + x; };\n"
|
||||
" return t;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||||
" let s = a[1:3];\n"
|
||||
" if (s.len != 2) { return 1; };\n"
|
||||
" if (s[1] != 3000) { return 2; };\n"
|
||||
" if (sum(a[0:4]) != 10000) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
};
|
||||
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i)
|
||||
{
|
||||
char src[128], tmpdir[96], outbin[128], errf[128], rmcmd[160], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/aif_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/aif_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/aif_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != r->want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, r->want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/aif_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/aif_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/aif_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bin = getenv("BIN");
|
||||
if (!bin) bin = "out/bin";
|
||||
char absbin[2080];
|
||||
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 cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(cdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_idx_family: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_idx_family: %d/%d ok\n", total, total);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
* 944_alias_structlit_init_run — #63: let-init from an alias-NAMED
|
||||
* struct LITERAL. wwstage's cglet N_STRUCTLIT arm resolved the struct
|
||||
* by a BARE structlookup(c, sname): for an alias `type rep2 = rep`
|
||||
* only the base `rep` is registered, so the lookup returned nil and
|
||||
* the field-fill never fired. The nil then split by slot size —
|
||||
* • <=8B: the small-let scalar default zeroed the slot and DROPPED
|
||||
* the literal (SILENT wrong: `let r = rep2{id=6}` read 0), and
|
||||
* • >8B: no fill arm matched -> the cglet "unhandled rhs shape"
|
||||
* LOUD (task #7/rule-7).
|
||||
* Same root, two symptoms. The fix routes the arm through
|
||||
* structlookupchain (the #92/W2 SSoT already used at cgenstmt:1974 /
|
||||
* :2687), which chases the alias chain to the base struct. cstage
|
||||
* operates on the resolved Type* via type_chase_named and was always
|
||||
* correct, so this is ww-only align-UP; cs UNTOUCHED. Oracle: ken
|
||||
* .ai/ken-63-oracle.md.
|
||||
*
|
||||
* The N_IDENT-copy (cgenstmt:2625) and N_CALL-recv (:2511) sibling
|
||||
* arms are also bare-structlookup but are NOT in scope: the copy
|
||||
* falls through to a generic path byte-identical with cstage (both
|
||||
* stages run correct), and the recv is blocked upstream by the
|
||||
* aggregate-return shape (#272/#277), and the ≤24B return (:1363)
|
||||
* likewise louds via the scalar-default catch. The >24B sret RETURN
|
||||
* (:1250) had NO such catch — it was silently wrong (returned an
|
||||
* uninitialised sret buffer); reviewer-63 routed it through
|
||||
* structlookupchain in the same commit (see sret_return_alias32).
|
||||
* The N_IDENT struct-copy (:2625) falls through to a generic path
|
||||
* both stages run correct (asm divergence is the #81/#65 alias
|
||||
* field-READ class). See the #63 ledger.
|
||||
*
|
||||
* row | shape | want
|
||||
* -------------------+---------------------------------------+-----
|
||||
* letinit_typed | type rep2=rep(8B); let r: rep2 = |
|
||||
* | rep2{id=6}; read r.id (was silent 0) | 6
|
||||
* letinit_untyped | inferred: let r = rep2{id=6}; r.id | 6
|
||||
* letlit_alias16 | type row=st(16B); let a: row = |
|
||||
* | row{a=3,b=4}; read a.a+a.b (was LOUD) | 7
|
||||
* control_direct | non-alias pt2{...} 16B let-init — the |
|
||||
* | no-regress control (alias hop is the |
|
||||
* | trigger), byte-id both stages | 7
|
||||
* sret_return_alias32| type biga=big(32B); mk() returns |
|
||||
* | biga{...}; the >24B sret RETURN twin |
|
||||
* | (:1250, was silent 0) | 10
|
||||
*
|
||||
* Every row asserts cstage/wwstage asm byte-id (rule 10). NNN<950,
|
||||
* self-contained (/tmp, no imports) — rule-14's selfhost-sibling race
|
||||
* does not apply (941/944 precedent).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
runwait(const char *cmd)
|
||||
{
|
||||
int rc = system(cmd);
|
||||
if (rc == -1) return -1;
|
||||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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), cb = fgetc(fb);
|
||||
if (ca != cb) { rc = -1; break; }
|
||||
if (ca == EOF) break;
|
||||
}
|
||||
fclose(fa); fclose(fb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct row { const char *label; const char *src; int want; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
{ "letinit_typed",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size };\n"
|
||||
"type rep2 = rep;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let r: rep2 = rep2{id=6};\n"
|
||||
" return r.id: i32;\n"
|
||||
"};\n", 6 },
|
||||
{ "letinit_untyped",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size };\n"
|
||||
"type rep2 = rep;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let r = rep2{id=6};\n"
|
||||
" return r.id: i32;\n"
|
||||
"};\n", 6 },
|
||||
{ "letlit_alias16",
|
||||
"package main;\n"
|
||||
"type st = struct { a: size, b: size };\n"
|
||||
"type row = st;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: row = row{a=3, b=4};\n"
|
||||
" return (a.a + a.b): i32;\n"
|
||||
"};\n", 7 },
|
||||
{ "control_direct",
|
||||
"package main;\n"
|
||||
"type pt2 = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let x: pt2 = pt2{a=3, b=4};\n"
|
||||
" return (x.a + x.b): i32;\n"
|
||||
"};\n", 7 },
|
||||
/* reviewer-63 survivor leg: the >24B sret-RETURN twin of the
|
||||
* let-init site (cgenstmt:1250). sretretsize chases the alias for
|
||||
* the size gate so the sret arm fires, but the field-fill used a
|
||||
* bare structlookup(sname) that missed the alias name -> the fill
|
||||
* was SKIPPED and the callee returned an uninitialised sret buffer
|
||||
* (ww silent 0; cs correct 10). The impl ledger wrongly declined
|
||||
* :1250 as "already chases"; routed through structlookupchain. */
|
||||
{ "sret_return_alias32",
|
||||
"package main;\n"
|
||||
"type big = struct { a: size, b: size, c: size, d: size };\n"
|
||||
"type biga = big;\n"
|
||||
"fn mk() biga = { return biga{a=1, b=2, c=3, d=4}; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let r: biga = mk();\n"
|
||||
" return (r.a + r.b + r.c + r.d): i32;\n"
|
||||
"};\n", 10 },
|
||||
};
|
||||
|
||||
/* build+run via a driver (ww / ww_ww); returns 0 pass, nonzero fail. */
|
||||
static int
|
||||
run_driver(const char *driver, const struct row *r, int i)
|
||||
{
|
||||
char tmpdir[96], src[128], outbin[128], errf[128], rmcmd[128], cmd[1024];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/asli_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(src, sizeof src, "%s/asli_%d_%d.ww", tmpdir, getpid(), i);
|
||||
snprintf(outbin, sizeof outbin, "%s/asli_%d_%d", tmpdir, getpid(), i);
|
||||
snprintf(errf, sizeof errf, "%s/err", tmpdir);
|
||||
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) { runwait(rmcmd); return -1; }
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
|
||||
driver, outbin, src, errf);
|
||||
int brc = runwait(cmd);
|
||||
if (brc != 0) {
|
||||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||||
r->label, driver);
|
||||
runwait(rmcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int got = runwait(outbin);
|
||||
|
||||
runwait(rmcmd);
|
||||
if (got != r->want) {
|
||||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||||
r->label, driver, got, r->want);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cs==ww .s byte-id (rule 10). */
|
||||
static int
|
||||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||||
{
|
||||
char src[96], cs[96], ws[96], cmd[1024];
|
||||
snprintf(src, sizeof src, "/tmp/asli_asm_%d_%d.ww", getpid(), i);
|
||||
snprintf(cs, sizeof cs, "/tmp/asli_asm_%d_%d_c.s", getpid(), i);
|
||||
snprintf(ws, sizeof ws, "/tmp/asli_asm_%d_%d_w.s", getpid(), i);
|
||||
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return -1;
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||||
unlink(src);
|
||||
return -1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||||
bin, ws, src);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||||
unlink(src); unlink(cs);
|
||||
return -1;
|
||||
}
|
||||
int rc = slurp_eq(cs, ws);
|
||||
if (rc != 0)
|
||||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||||
r->label);
|
||||
unlink(src); unlink(cs); unlink(ws);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bin = getenv("BIN");
|
||||
if (!bin) bin = "out/bin";
|
||||
char absbin[2080];
|
||||
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 cdrv[2120], wdrv[2120];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(cdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
if (access(wdrv, X_OK) == 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "alias_structlit_init: %d/%d checks failed\n",
|
||||
fail, total);
|
||||
return 1;
|
||||
}
|
||||
printf("alias_structlit_init: %d/%d ok\n", total, total);
|
||||
return 0;
|
||||
}
|
||||
8
test/wcc/data/alias_assert_bool/case.ww
Normal file
8
test/wcc/data/alias_assert_bool/case.ww
Normal file
@@ -0,0 +1,8 @@
|
||||
//ww:error "assert: cond must be bool"
|
||||
package main;
|
||||
type myb = bool;
|
||||
export fn main() i32 = {
|
||||
let b: myb = true;
|
||||
assert(b);
|
||||
return 0;
|
||||
};
|
||||
13
test/wcc/data/alias_binop_vs_alias/case.ww
Normal file
13
test/wcc/data/alias_binop_vs_alias/case.ww
Normal file
@@ -0,0 +1,13 @@
|
||||
//ww:error "operands have differing types"
|
||||
// #5-C3 Q4: the historical "cs loud / ww silent by design" tag is SUPERSEDED
|
||||
// — at HEAD 07b3c74 BOTH stages reject with this substring (divergence closed).
|
||||
// Do NOT re-split this into a cs-only pin: the reject is now symmetric.
|
||||
package main;
|
||||
type k1 = int;
|
||||
type k2 = int;
|
||||
export fn main() i32 = {
|
||||
let a: k1 = 3;
|
||||
let b: k2 = 4;
|
||||
let c = a + b;
|
||||
return c: i32;
|
||||
};
|
||||
8
test/wcc/data/alias_cycle_alias/case.ww
Normal file
8
test/wcc/data/alias_cycle_alias/case.ww
Normal file
@@ -0,0 +1,8 @@
|
||||
//ww:error "circular type dependency"
|
||||
package main;
|
||||
type a = b;
|
||||
type b = a;
|
||||
export fn main() i32 = {
|
||||
if (size(a) != 8) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
7
test/wcc/data/alias_cycle_self/case.ww
Normal file
7
test/wcc/data/alias_cycle_self/case.ww
Normal file
@@ -0,0 +1,7 @@
|
||||
//ww:error "circular type dependency"
|
||||
package main;
|
||||
type a = a;
|
||||
export fn main() i32 = {
|
||||
if (size(a) != 8) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
8
test/wcc/data/alias_cycle_struct/case.ww
Normal file
8
test/wcc/data/alias_cycle_struct/case.ww
Normal file
@@ -0,0 +1,8 @@
|
||||
//ww:error "circular type dependency"
|
||||
package main;
|
||||
type s1 = struct { x: s2 };
|
||||
type s2 = struct { x: s1 };
|
||||
export fn main() i32 = {
|
||||
if (size(s1) != 8) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
9
test/wcc/data/alias_fill0_ctl/case.ww
Normal file
9
test/wcc/data/alias_fill0_ctl/case.ww
Normal file
@@ -0,0 +1,9 @@
|
||||
//ww:error "has a str/slice/struct/tagged element"
|
||||
package main;
|
||||
type el0 = struct { a: i64 };
|
||||
type S = struct { arr: [2]el0, n: i64 };
|
||||
export fn main() i32 = {
|
||||
let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };
|
||||
if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
10
test/wcc/data/alias_fill2_loud/case.ww
Normal file
10
test/wcc/data/alias_fill2_loud/case.ww
Normal file
@@ -0,0 +1,10 @@
|
||||
//ww:error "has a str/slice/struct/tagged element"
|
||||
package main;
|
||||
type el0 = struct { a: i64 };
|
||||
type el = el0;
|
||||
type S = struct { arr: [2]el, n: i64 };
|
||||
export fn main() i32 = {
|
||||
let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };
|
||||
if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
12
test/wcc/data/alias_fsarg0_loud/case.ww
Normal file
12
test/wcc/data/alias_fsarg0_loud/case.ww
Normal file
@@ -0,0 +1,12 @@
|
||||
//ww:error "float-bearing struct arg from a non-ident source"
|
||||
package main;
|
||||
type fs0 = struct { x: f64 };
|
||||
fn mk() fs0 = {
|
||||
let s: fs0; s.x = 2.5;
|
||||
return s;
|
||||
};
|
||||
fn g(p: fs0) f64 = { return p.x; };
|
||||
export fn main() i32 = {
|
||||
if (g(mk()) != 2.5) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
11
test/wcc/data/alias_g73_static_str/case.ww
Normal file
11
test/wcc/data/alias_g73_static_str/case.ww
Normal file
@@ -0,0 +1,11 @@
|
||||
//ww:error "#129 A.2 scope"
|
||||
package main;
|
||||
type s1t = str;
|
||||
type s2t = s1t;
|
||||
type box = struct { s: s2t, n: int };
|
||||
let g: box = box { s = "hello", n = 5: int };
|
||||
export fn main() i32 = {
|
||||
if (g.n != 5) { return 1; };
|
||||
if (g.s.len != 5) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
9
test/wcc/data/alias_slcslc/case.ww
Normal file
9
test/wcc/data/alias_slcslc/case.ww
Normal file
@@ -0,0 +1,9 @@
|
||||
//ww:error "not assignable"
|
||||
package main;
|
||||
type ms0 = []i64;
|
||||
type ms = ms0;
|
||||
let G: []ms = [[1, 2], [3]];
|
||||
export fn main() i32 = {
|
||||
if (len(G) != 2) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
7
test/wcc/data/alias_slcstr_plain/case.ww
Normal file
7
test/wcc/data/alias_slcstr_plain/case.ww
Normal file
@@ -0,0 +1,7 @@
|
||||
//ww:error "slice-of-{str,slice,tagged} literal static-init unsupported"
|
||||
package main;
|
||||
let G: []str = ["aa", "bbb"];
|
||||
export fn main() i32 = {
|
||||
if (len(G[0]) != 2) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
22
test/wcc/data/alias_try_loud_38b/case.ww
Normal file
22
test/wcc/data/alias_try_loud_38b/case.ww
Normal file
@@ -0,0 +1,22 @@
|
||||
//ww:error "sret-class call result unwired"
|
||||
package main;
|
||||
type e0 = !i64;
|
||||
type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };
|
||||
type r0 = (big | e0);
|
||||
type r = r0;
|
||||
fn w() r = {
|
||||
let s: big;
|
||||
s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 5; s.f = 6; s.g = 77;
|
||||
return s;
|
||||
};
|
||||
fn outer() (i64 | e0) = {
|
||||
let v = w()?;
|
||||
return v.g;
|
||||
};
|
||||
export fn main() i32 = {
|
||||
match (outer()) {
|
||||
case let n: i64 => { if (n != 77) { return 1; }; };
|
||||
case e0 => { return 2; };
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
13
test/wcc/data/alias_union_as_bound/case.ww
Normal file
13
test/wcc/data/alias_union_as_bound/case.ww
Normal file
@@ -0,0 +1,13 @@
|
||||
//ww:error "aggregate init from unhandled rhs shape"
|
||||
package main;
|
||||
type base = struct { a: size, b: size };
|
||||
type ali = base;
|
||||
export fn main() i32 = {
|
||||
let x: ali;
|
||||
x.a = 4; x.b = 9;
|
||||
let v: (void | ali) = x;
|
||||
if (!(v is ali)) { return 1; };
|
||||
let w = v as ali;
|
||||
if (w.b != 9) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
12
test/wcc/data/alias_untyped_nestvar/case.ww
Normal file
12
test/wcc/data/alias_untyped_nestvar/case.ww
Normal file
@@ -0,0 +1,12 @@
|
||||
//ww:error "not assignable"
|
||||
// #5-C3 Q4: the historical "cs loud / ww silent by design" tag is SUPERSEDED
|
||||
// — at HEAD 07b3c74 BOTH stages reject (common substring "not assignable";
|
||||
// divergence closed). Do NOT re-split into a cs-only pin.
|
||||
package main;
|
||||
type inner = (i64 | str);
|
||||
type inner2 = inner;
|
||||
export fn main() i32 = {
|
||||
let v: (void | inner2) = 7;
|
||||
if (v is void) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
10
test/wcc/data/alias_v2_ambig/case.ww
Normal file
10
test/wcc/data/alias_v2_ambig/case.ww
Normal file
@@ -0,0 +1,10 @@
|
||||
//ww:error "bare source structurally matches >=2 NAMED variants"
|
||||
package main;
|
||||
type p1 = *i64;
|
||||
type p2 = *i64;
|
||||
export fn main() i32 = {
|
||||
let x: i64 = 7;
|
||||
let v: (void | p1 | p2) = &x;
|
||||
if (v is p1) { return 0; };
|
||||
return 1;
|
||||
};
|
||||
12
test/wcc/data/alias_v2_ambig2/case.ww
Normal file
12
test/wcc/data/alias_v2_ambig2/case.ww
Normal file
@@ -0,0 +1,12 @@
|
||||
//ww:error "bare source structurally matches >=2 NAMED variants"
|
||||
package main;
|
||||
type q1 = *i64;
|
||||
type p1 = q1;
|
||||
type q2 = *i64;
|
||||
type p2 = q2;
|
||||
export fn main() i32 = {
|
||||
let x: i64 = 7;
|
||||
let v: (void | p1 | p2) = &x;
|
||||
if (v is p1) { return 0; };
|
||||
return 1;
|
||||
};
|
||||
Reference in New Issue
Block a user