// widen_pad_test — widening a NARROW scalar/float value into a tagged-union // slot whose payload is WIDER than one word must ZERO the high pad words // (slot+16, slot+24), not leave them at whatever the frame slot last held, // migrated from test/wcc/793_widen_pad_zero_run.c (#227). cg_widen_tagged_store // (cstage) and cgwidentaggedstorebp (wwstage) wrote only the tag (slot+0) and // value (slot+8) in their scalar/float arms, leaving the rest uninitialised. // For a >16B union (e.g. `(i64 | str)`, whose str variant makes the slot 32B = // 4 words) a later `*u8` reinterpret then read stack garbage at slot+16/+24. // // Both stages were wrong the SAME way, so the byte-id gates were GREEN while // the runtime was wrong — dead in the bootstrap corpus. Each shape first // widens a STR into the slot (which fills slot+16/+24 with the str's len/cap), // then reassigns a SCALAR / FLOAT into the SAME slot, then reads slot+16/+24 // back through a `*u8` reinterpret (the bit-pinning idiom from // 715_tagged_widen_f64). Pre-fix the reassign left the str's stale len/cap in // the pad; post-fix the pad reads back 0. These are distinct widen SHAPES // (scalar arm, float arm, repeated-reassign), not data, so per-shape asserts. package widen_pad_test; @test fn scalar_i64_after_str() void = { // Reassign a scalar i64 over a str-occupied (i64|str) slot: the str // write fills slot+16 (len) and slot+24 (cap); the scalar reassign must // zero them. payload == 123, tag == 0 (i64 is variant 0). let a: (i64 | str) = "abcdefgh"; a = 123i64; let pp: *(i64 | str) = &a; let pu: *u8 = pp: *u8; let tagp: *i64 = pu: *i64; let valp: *i64 = (pu + 8u64): *i64; let pad1: *i64 = (pu + 16u64): *i64; let pad2: *i64 = (pu + 24u64): *i64; assert(*valp == 123i64); assert(*pad1 == 0i64); assert(*pad2 == 0i64); assert(*tagp == 0i64); }; @test fn float_f64_after_str() void = { // The float arm: reassign an f64 over a str-occupied (f64|str) slot. // f64 1.0 == 0x3FF0000000000000 == 4607182418800017408. tag == 0. let a: (f64 | str) = "abcdefgh"; a = 1.0; let pp: *(f64 | str) = &a; let pu: *u8 = pp: *u8; let tagp: *i64 = pu: *i64; let valp: *u64 = (pu + 8u64): *u64; let pad1: *i64 = (pu + 16u64): *i64; let pad2: *i64 = (pu + 24u64): *i64; assert(*valp == 4607182418800017408u64); assert(*pad1 == 0i64); assert(*pad2 == 0i64); assert(*tagp == 0i64); }; @test fn scalar_after_str_twice() void = { // Reassign a scalar over a str TWICE — confirms the tail-zero is emitted // on EVERY scalar widen (not just a first write), with a str's len/cap // dirtying the pad in between. Final payload == 222. let a: (i64 | str) = "firstone"; a = 11i64; a = "secondxx"; a = 222i64; let pp: *(i64 | str) = &a; let pu: *u8 = pp: *u8; let valp: *i64 = (pu + 8u64): *i64; let pad1: *i64 = (pu + 16u64): *i64; let pad2: *i64 = (pu + 24u64): *i64; assert(*valp == 222i64); assert(*pad1 == 0i64); assert(*pad2 == 0i64); };