wcc+w6c_ww: >48B tagged args from place-resolved sources (#38b cont.)
Task #40 (FB3): the #38b MEMORY-class staging only accepted ident / aggarg_srcaddr-enumerated sources, loud-stopping on a slice-element arg — the regex run_thread loop-condition shape is_consuming_inst(re.insts[threads[i].pc]) (regex.ha:602) and B4's (*p)[i] spelling. The staging now falls back to cgplaceaddr (the F6 resolver) for the slot's source address; the existing word-push machinery is unchanged. Placed AFTER aggarg_srcaddr so every pre-#40 shape keeps its asm byte-exact (verified vs a master w6c). Boundaries kept loud (rule 7): exact-type rvalue (no place to resolve), sret-class call source (#40-family follow-up), global tagged let (task #25), variadic element, register-overflow mixing. Diagnostic re-worded to match: slice-element is wired, rvalue and unresolvable-place sources are not. test/929 grows 6 run rows (element source with literal+computed index, deref-spine, nested re.insts[threads[i].pc] spelling, element mixed with register args both orders, fn-call index with two mem args per call — the inner CALL runs inside the mem pre-pass with the other slot already staged — and global-slice element, the storage-backed twin of the loud fail_global_src boundary — all build-fail loud at master) and 1 reject row pinning the new boundary text on both stages.
This commit is contained in:
@@ -29,8 +29,10 @@
|
||||
* Rows flagged `buildfail` must be rejected by BOTH stages with that
|
||||
* row's EXACT #38b diagnostic — pinning WHICH guard fired (the
|
||||
* remaining unwired sub-shapes: sret-class call source, global-let
|
||||
* source, variadic element, register-overflow mixing caller- and
|
||||
* callee-side).
|
||||
* source, exact-type rvalue, variadic element, register-overflow
|
||||
* mixing caller- and callee-side). #40/FB3 wired the place-resolved
|
||||
* sources (slice element, deref-spine, nested index) via the
|
||||
* cgplaceaddr fallback — those are run rows now.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -309,6 +311,140 @@ static const struct row rows[] = {
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$56, SP\n", NULL, 0, NULL },
|
||||
/* #40/FB3: exact-type SLICE-ELEMENT source — `f(xs[i])`, the
|
||||
* regex run_thread loop-condition shape
|
||||
* (is_consuming_inst(re.insts[threads[i].pc]), regex.ha:602).
|
||||
* Staged from a cgplaceaddr-resolved address; literal and
|
||||
* computed indices, every variant, late payload word per arm. */
|
||||
{ "mem56_elem_source",
|
||||
MEM56_TYPES
|
||||
MEM56_PROBE
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []t_u = [];\n"
|
||||
" let a: t_u = ('x': t_lit);\n"
|
||||
" append(xs, a);\n"
|
||||
" let r: t_rep = " MEM56_REP_LIT ";\n"
|
||||
" let b: t_u = r;\n"
|
||||
" append(xs, b);\n"
|
||||
" if (probe(xs[0]) != 1) { return 1; };\n"
|
||||
" if (probe(xs[1]) != 3) { return 2; };\n"
|
||||
" let i: size = 1;\n"
|
||||
" if (probe(xs[i]) != 3) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$56, SP\n", NULL, 0, NULL },
|
||||
/* #40/FB3: deref-spine element source — `f((*p)[i])`, B4's
|
||||
* actual spelling (slice reached through a pointer). */
|
||||
{ "mem56_elem_deref_spine",
|
||||
MEM56_TYPES
|
||||
MEM56_PROBE
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []t_u = [];\n"
|
||||
" let r: t_rep = " MEM56_REP_LIT ";\n"
|
||||
" let b: t_u = r;\n"
|
||||
" append(xs, b);\n"
|
||||
" let p: *[]t_u = &xs;\n"
|
||||
" if (probe((*p)[0]) != 3) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$56, SP\n", NULL, 0, NULL },
|
||||
/* #40/FB3: the full nested spelling — dot-base slice indexed
|
||||
* by a field of another indexed element
|
||||
* (re.insts[threads[i].pc]). */
|
||||
{ "mem56_elem_nested_spine",
|
||||
MEM56_TYPES
|
||||
"type re_t = struct { flag: i64, insts: []t_u };\n"
|
||||
"type thr = struct { pc: size, gen: i64 };\n"
|
||||
MEM56_PROBE
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []t_u = [];\n"
|
||||
" let a: t_u = ('x': t_lit);\n"
|
||||
" append(xs, a);\n"
|
||||
" let r: t_rep = " MEM56_REP_LIT ";\n"
|
||||
" let b: t_u = r;\n"
|
||||
" append(xs, b);\n"
|
||||
" let re: re_t = re_t { flag = 4, insts = xs };\n"
|
||||
" let threads: []thr = [];\n"
|
||||
" append(threads, thr { pc = 1, gen = 5 });\n"
|
||||
" if (probe(re.insts[threads[0].pc]) != 3) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$56, SP\n", NULL, 0, NULL },
|
||||
/* #40/FB3: element source mixed with register-class args, both
|
||||
* orders — the resolver's transient AX/CX clobbers must not
|
||||
* disturb the staged words or the register cursors. */
|
||||
{ "mem56_elem_mixed_regs",
|
||||
MEM56_TYPES
|
||||
"fn before(k: i64, s: str, a: t_u) i64 = {\n"
|
||||
" if (k != 5) { return 91; };\n"
|
||||
" if (s.len != 3) { return 92; };\n"
|
||||
" match (a) {\n"
|
||||
" case let r: t_rep => { return k + (r.m3: i64); };\n"
|
||||
" case => { return 93; };\n"
|
||||
" };\n"
|
||||
" return 99;\n"
|
||||
"};\n"
|
||||
"fn after(a: t_u, k: i64, s: str) i64 = {\n"
|
||||
" if (k != 6) { return 91; };\n"
|
||||
" if (s.len != 3) { return 92; };\n"
|
||||
" match (a) {\n"
|
||||
" case let r: t_rep => { return k + (r.m3: i64); };\n"
|
||||
" case => { return 93; };\n"
|
||||
" };\n"
|
||||
" return 99;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []t_u = [];\n"
|
||||
" let r: t_rep = " MEM56_REP_LIT ";\n"
|
||||
" let b: t_u = r;\n"
|
||||
" append(xs, b);\n"
|
||||
" if (before(5, \"abc\", xs[0]) != 1239) { return 1; };\n"
|
||||
" if (after(xs[0], 6, \"abc\") != 1240) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$56, SP\n", NULL, 0, NULL },
|
||||
/* #40/FB3: fn-CALL index (the 2c computed-pc shape) + TWO mem
|
||||
* args per call, both orders. The inner CALL runs inside the
|
||||
* mem pre-pass with the other arg's 7 words already staged —
|
||||
* pins the resolver's push-balance claim; $112 = both slots. */
|
||||
{ "mem56_elem_callidx_twomem",
|
||||
MEM56_TYPES
|
||||
MEM56_PROBE
|
||||
"fn pick() size = {\n"
|
||||
" return 1;\n"
|
||||
"};\n"
|
||||
"fn two(a: t_u, b: t_u) i32 = {\n"
|
||||
" return probe(a) * 10 + probe(b);\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []t_u = [];\n"
|
||||
" let a: t_u = ('x': t_lit);\n"
|
||||
" append(xs, a);\n"
|
||||
" let r: t_rep = " MEM56_REP_LIT ";\n"
|
||||
" let b: t_u = r;\n"
|
||||
" append(xs, b);\n"
|
||||
" if (two(xs[0], xs[pick()]) != 13) { return 1; };\n"
|
||||
" if (two(xs[pick()], xs[0]) != 31) { return 2; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$112, SP\n", NULL, 0, NULL },
|
||||
/* #40/FB3: element of a GLOBAL slice let — the resolver's
|
||||
* let_islet arm, sound because slice globals have DATA storage
|
||||
* (the element lives behind .ptr). The storage-LESS twin (a
|
||||
* global tagged VALUE, let_emit_size=0, task #25) must stay
|
||||
* loud — fail_global_src pins that side of the boundary. */
|
||||
{ "mem56_elem_global_slice",
|
||||
MEM56_TYPES
|
||||
"let gxs: []t_u;\n"
|
||||
MEM56_PROBE
|
||||
"export fn main() i32 = {\n"
|
||||
" let r: t_rep = " MEM56_REP_LIT ";\n"
|
||||
" let b: t_u = r;\n"
|
||||
" append(gxs, b);\n"
|
||||
" if (probe(gxs[0]) != 3) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, "\tADDQ\t$56, SP\n", NULL, 0, NULL },
|
||||
/* BOUNDARY: 40B payload = EXACTLY 48B slot — must stay on the
|
||||
* register convention (no mem cleanup ADDQ). An off-by-one in
|
||||
* tagged_memarg_size flips every 48B-slot call in the tree. */
|
||||
@@ -435,6 +571,21 @@ static const struct row rows[] = {
|
||||
0, NULL, NULL, 1,
|
||||
"#38b: >48B tagged arg mixed with register-overflow stack "
|
||||
"args unwired" },
|
||||
/* LOUD-STOP: exact-type RVALUE source (same-type cast) — no
|
||||
* place to resolve; stays loud post-#40. Marker is the
|
||||
* parenthetical tail shared verbatim by both stages (cstage
|
||||
* interposes the numeric node kind), complementing
|
||||
* fail_global_src's prefix pin of the same guard. */
|
||||
{ "fail_rvalue_cast",
|
||||
MEM56_TYPES
|
||||
MEM56_PROBE
|
||||
"export fn main() i32 = {\n"
|
||||
" let a: t_u = ('x': t_lit);\n"
|
||||
" if (probe((a: t_u)) != 1) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, NULL, NULL, 1,
|
||||
"(rvalue and unresolvable-place sources unwired)" },
|
||||
};
|
||||
|
||||
static const char *g_bin;
|
||||
|
||||
Reference in New Issue
Block a user