Fan out the str-cap read (933-936) and store (937-939) families into in-language @test files, following the 932 str_elem_cap template. Additive: the *_run.c stay in the C corpus (they are the only wwstage-runtime net for these cs==ww byte-id-blind shapes); de-dup deferred to fold 6. Per-shape @test fns, not a data table: each fn varies the codegen shape (base reg / chain depth / tuple return-ABI / store position), so the row-array idiom (blocked by #111) would lose coverage. Read family keeps the spoil()/register-clobber + junk==44 discrimination where the .c has it; store family pre-poisons the slot via a path distinct from the store under test. Asserts are primitives only.
60 lines
2.3 KiB
Plaintext
60 lines
2.3 KiB
Plaintext
// str_chainfield_store_cap_test — STORING a str into a FIELD reached through a
|
|
// *struct-VALUED EXPRESSION (`r.sym.f = v`, the chained-N_DOT store) must write
|
|
// the full 24B {ptr,len,cap} header, not just {ptr,len}, migrated from
|
|
// test/wcc/938_str_chainfield_store_cap_run.c (G2 fold). str is 24B since
|
|
// Phase 2 (#1); the chained-store arm previously stored only 2 words (ptr@+0,
|
|
// len@+8) and silently DROPPED cap. cs==ww held (byte-id-blind), so behavioral
|
|
// @test is the net.
|
|
//
|
|
// RHS cap!=len: each test str is a literal whose .cap is mutated DISTINCT from
|
|
// its len (a bare literal carries cap==len, hiding a dropped cap). PRE-POISON:
|
|
// the three slot words are seeded with a DIFFERENT str (ptr='q', len=4, cap=5)
|
|
// via the PROVEN already-3-word DIRECT field store (st.f=q, N_IDENT base) —
|
|
// never the G2 chained store itself. A broken 2-word store never touches +16,
|
|
// so the read-back observes the poison cap 5, never 8. The full-triple assert
|
|
// (s[0]='h'=104, len=2, cap=8) catches a register slip that clobbers ptr/len.
|
|
|
|
package str_chainfield_store_cap_test;
|
|
|
|
type inner = struct { f: str };
|
|
type outer2 = struct { sym: *inner };
|
|
type mid = struct { b: *inner };
|
|
type outer3 = struct { a: *mid };
|
|
|
|
@test fn chainfield_store_depth2() void = {
|
|
// A — depth-2 `r.sym.f = v`. r.sym is a *inner pointing at a local st.
|
|
// Poison st.f (cap=5,len=4,'q') via the DIRECT s.f=v 3-word store; then
|
|
// the G2 chained store lands the test str (cap=8,len=2,'h') through r.sym.
|
|
let q: str = "qqqq"; q.cap = 5i32;
|
|
let p: str = "hi"; p.cap = 8i32;
|
|
let st: inner;
|
|
st.f = q;
|
|
let r: outer2;
|
|
r.sym = &st;
|
|
r.sym.f = p;
|
|
let s: str = r.sym.f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|
|
|
|
@test fn chainfield_store_depth3() void = {
|
|
// B — depth-3 `r.a.b.f = v`. Two pointer hops (r.a: *mid, mid.b: *inner).
|
|
// Poison the leaf via the DIRECT store (leaf.f=q); the G2 chained store
|
|
// derefs r.a then .b and overwrites leaf.f. The deeper base eval clobbers
|
|
// more registers, confirming the spilled triple survives.
|
|
let q: str = "qqqq"; q.cap = 5i32;
|
|
let p: str = "hi"; p.cap = 8i32;
|
|
let leaf: inner;
|
|
leaf.f = q;
|
|
let m: mid;
|
|
m.b = &leaf;
|
|
let r: outer3;
|
|
r.a = &m;
|
|
r.a.b.f = p;
|
|
let s: str = r.a.b.f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|