Files
ww/test/lang/str_tuple_elem_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

42 lines
1.6 KiB
Plaintext

// str_tuple_elem_cap_test — a tuple POSITIONAL str element read `t.N` (N_IDENT
// base, TY_TUPLE) must load the full 24B {ptr,len,cap} header, not just
// {ptr,len}, migrated from test/wcc/935_str_tuple_elem_cap_run.c (C4.6 S3). str
// is 24B since Phase 2 (#1); pre-S3 the tuple str-element arm loaded 2 words
// (ptr in AX, len in BX) and dropped cap. The miscompile was cs==ww, so the
// 990-997 byte-id gates stayed GREEN while the runtime was wrong — behavioral
// @test is the net. UNLIKE the field/elem arms there is no adjacent slice-
// element arm to fold onto, so the 3-word triple is authored directly to the
// canonical slice-header ABI (AX=ptr, BX=len, CX=cap).
//
// The tuple is built by a (i64, str)-returning mk() so the poisoned cap=8 rides
// the 4-word return ABI into the tuple slot's +24 word (do NOT simplify to a
// local tuple literal — different codegen path); `t.1` then reads it back
// 3-word. spoil() interposes a CX-clobbering call between the build and the
// `t.1` read so a broken 2-word read observes 44 not 8, not a stale CX.
package str_tuple_elem_cap_test;
fn mk() (i64, str) = {
let p: str = "hi";
p.cap = 8i32;
return (5i64, p);
};
fn spoil() i32 = {
let z: str = "zzzz";
z.cap = 44i32;
let w: str = z;
return w.cap: i32;
};
@test fn tuple_positional_str_elem() void = {
// `t.1` positional str element of a local (i64, str) tuple. Poison cap=8
// (len=2) rides mk()'s return ABI into the str element's slot.
let t: (i64, str) = mk();
let junk: i32 = spoil();
let s: str = t.1;
assert(s.cap: i32 == 8);
assert(s.len: i32 == 2);
assert(junk == 44);
};