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.
71 lines
2.7 KiB
Plaintext
71 lines
2.7 KiB
Plaintext
// str_arrfield_store_cap_test — STORING a str into a FIELD of an INDEXED
|
|
// element `arr[i].f = v` must write the full 24B {ptr,len,cap} header, not just
|
|
// {ptr,len}, migrated from test/wcc/937_str_arrfield_store_cap_run.c (G1 fold).
|
|
// str is 24B since Phase 2 (#1); the write-side mirror of the arrfield READ
|
|
// (936) 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 to a value
|
|
// DISTINCT from its len (a bare literal carries cap==len, hiding a dropped cap).
|
|
// PRE-POISON: before the G1 store under test, all three slot words are seeded
|
|
// with a DIFFERENT str (ptr='q', len=4, cap=5) via a PROVEN already-3-word store
|
|
// path DISTINCT from G1 — A/B via &arr[i] + a *struct field store, D via the
|
|
// proven s1local field store (st.f=q). 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_arrfield_store_cap_test;
|
|
|
|
type rec = struct { f: str };
|
|
|
|
@test fn arrfield_store_array_value() void = {
|
|
// A — `arr[i].f = v` into a [N]S local array (LEAQ base, value
|
|
// element). Poison the slot (cap=5,len=4,'q') via &arr[1] + a *struct
|
|
// field store; then the G1 store lands the test str (cap=8,len=2,'h').
|
|
let q: str = "qqqq"; q.cap = 5i32;
|
|
let p: str = "hi"; p.cap = 8i32;
|
|
let arr: [3]rec;
|
|
let pr: *rec = &arr[1];
|
|
pr.f = q;
|
|
arr[1].f = p;
|
|
let s: str = arr[1].f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|
|
|
|
@test fn arrfield_store_slice_value() void = {
|
|
// B — `sl[i].f = v` into a []S local slice (MOVQ slice.ptr base, value
|
|
// element). The slice views the same backing array; poison the element
|
|
// through the array pointer, store and read back through the slice.
|
|
let q: str = "qqqq"; q.cap = 5i32;
|
|
let p: str = "hi"; p.cap = 8i32;
|
|
let arr: [3]rec;
|
|
let pr: *rec = &arr[1];
|
|
pr.f = q;
|
|
let sl: []rec = arr[0:3];
|
|
sl[1].f = p;
|
|
let s: str = sl[1].f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|
|
|
|
@test fn arrfield_store_ptr_elem() void = {
|
|
// D — `arr[i].f = v` into a [N]*S pointer element (LEAQ base, MOVQ deref
|
|
// to the *S, then store at the field). The element points at a
|
|
// separately-built struct poisoned via the proven s1local field store
|
|
// (st.f=q); the G1 store derefs arr[1] and overwrites st.f.
|
|
let q: str = "qqqq"; q.cap = 5i32;
|
|
let p: str = "hi"; p.cap = 8i32;
|
|
let st: rec;
|
|
st.f = q;
|
|
let arr: [3]*rec;
|
|
arr[1] = &st;
|
|
arr[1].f = p;
|
|
let s: str = arr[1].f;
|
|
assert(s.cap: i32 == 8);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 104u8);
|
|
};
|