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.
42 lines
1.6 KiB
Plaintext
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);
|
|
};
|