Files
ww/test/lang/str_arrfield_store_cap_test.ww
Hojun-Cho e1740fff10 test: migrate 933-939 str-cap family to test/lang @test
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.
2026-06-22 03:54:54 +09:00

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);
};