// Depth-≥2 chained-DOT struct-field store from a // struct IDENT source (`t.m.l = s;`, lhs.lhs is itself an N_DOT), migrated from // test/wcc/949_chained_dot_struct_copy_run.c (#107-class sibling). The copy // length is the field's NATURAL (non-slot-padded) struct size; cstage's tail // selector handled only {4,1} and over-MOVQ'd every other tail {2,3,5,6,7}, // clobbering the @packed neighbour `z` that follows the field within 8 bytes — // silently, and divergent from wwstage's descending 8/4/2/1 ladder. The fix // aligns cstage UP. The oracle is the neighbour `z` read back AFTER the copy // (a wrong width over-writes it); T2 keeps the cs==ww net. Coverage = the tail // widths the bug lived in {2,3,5,6,7} plus boundaries {0,1,4} + the via-CX // (global dest) arm a BP-local `t` never reaches. package chained_dot_struct_copy_test; type L2 = struct { a: u16, b: [8]u8 }; type M2 = struct @packed { l: L2, z: u8 }; type T2 = struct { m: M2, tail: u64 }; type L3 = struct @packed { a: u8, b: u8, c: u8 }; type M3 = struct @packed { l: L3, z: u8 }; type T3 = struct { m: M3, tail: u64 }; type L4 = struct @packed { a: u32 }; type M4 = struct @packed { l: L4, z: u8 }; type T4 = struct { m: M4, tail: u64 }; type L5 = struct @packed { a: u8, b: u32 }; type M5 = struct @packed { l: L5, z: u8 }; type T5 = struct { m: M5, tail: u64 }; type L6 = struct @packed { a: u16, b: u32 }; type M6 = struct @packed { l: L6, z: u8 }; type T6 = struct { m: M6, tail: u64 }; type L7 = struct @packed { a: u8, b: u16, c: u32 }; type M7 = struct @packed { l: L7, z: u8 }; type T7 = struct { m: M7, tail: u64 }; type Lg = struct { a: u16, b: [8]u8 }; type Mg = struct @packed { l: Lg, z: u8 }; type Tg = struct { m: Mg, tail: u64 }; type L1 = struct @packed { a: u8 }; type M1 = struct @packed { l: L1, z: u8 }; type T1 = struct { m: M1, tail: u64 }; type L0 = struct { a: i64, b: i64 }; type M0 = struct { l: L0, z: u8 }; type T0 = struct { m: M0, tail: u64 }; let g_viacx: Tg = Tg { m = Mg { l = Lg { a = 0u16, b = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8] }, z = 222u8 }, tail = 0u64 }; @test fn tail2_leaf10() void = { let s = L2 { a = 0u16, b = [9u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8] }; let t = T2 { m = M2 { l = L2 { a = 0u16, b = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8] }, z = 222u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 222); }; @test fn tail3_leaf3() void = { let s = L3 { a = 1u8, b = 2u8, c = 3u8 }; let t = T3 { m = M3 { l = L3 { a = 0u8, b = 0u8, c = 0u8 }, z = 88u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 88); }; @test fn tail4_leaf4() void = { let s = L4 { a = 7u32 }; let t = T4 { m = M4 { l = L4 { a = 0u32 }, z = 123u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 123); }; @test fn tail5_leaf5() void = { let s = L5 { a = 1u8, b = 0u32 }; let t = T5 { m = M5 { l = L5 { a = 0u8, b = 0u32 }, z = 177u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 177); }; @test fn tail6_leaf6() void = { let s = L6 { a = 1u16, b = 0u32 }; let t = T6 { m = M6 { l = L6 { a = 0u16, b = 0u32 }, z = 99u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 99); }; @test fn tail7_leaf7() void = { let s = L7 { a = 1u8, b = 2u16, c = 0u32 }; let t = T7 { m = M7 { l = L7 { a = 0u8, b = 0u16, c = 0u32 }, z = 111u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 111); }; @test fn viacx_global_tail2() void = { let s = Lg { a = 0u16, b = [9u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8] }; g_viacx.m.l = s; assert(g_viacx.m.z: i32 == 222); }; @test fn tail1_leaf1() void = { let s = L1 { a = 5u8 }; let t = T1 { m = M1 { l = L1 { a = 0u8 }, z = 144u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 144); }; @test fn tail0_leaf16() void = { let s = L0 { a = 5i64, b = 6i64 }; let t = T0 { m = M0 { l = L0 { a = 0i64, b = 0i64 }, z = 200u8 }, tail = 0u64 }; t.m.l = s; assert(t.m.z: i32 == 200); };