The arr[i].f=mk() assign arm had no aggregate-field sub-arm, so a by-value aggregate field receive fell to the scalar default (one MOVQ, dropping DX/CX) — silent on BOTH stages (byte-id blind). Add a dual-site symmetric in-cap N_CALL arm mirroring C2c (c83a340): scratch-first materialise AX/DX/CX, then word-copy to (fi.foff+k*8) within &arr[i], sizing from the natural field size fi.fsz (not slotsize). Rule-7 LOUD-STOP for the three cases the in-cap GP path cannot transport: over-cap sret (#11c/#234), a float-bearing field whose eightbyte classifies SSE (#11/#165), and a 3/5/6/7-byte sub-8 tail the single narrow tail MOV cannot express (the general cascade tail is the shared C2c/#11 follow-up, task #10). Value-asserting pins (poison-seeded, redden under each stage's independent revert) plus cfail pins for the three loud-stops.
Contained to the indexed base + in-cap call rhs; arr[i].f=src (#11b) and over-cap (#11c) are separate.
44 lines
1.9 KiB
Plaintext
44 lines
1.9 KiB
Plaintext
// idx_dot_aggret_recv_runonly_test — #11 sub-8-tail anti-clobber through a
|
|
// LOCAL [N]<struct-with-sub-8-tail-field> array. The fix's MOVL (not MOVQ) tail
|
|
// + foff-on-every-eightbyte are VALUE-verified here: the dropped eb1 would read
|
|
// the poison 9, and a tail WIDENED to MOVQ would write bytes 8..15 and smash the
|
|
// adjacent g at +12 — both caught by asserting f.c AND g. Exit-correct under
|
|
// BOTH stages.
|
|
//
|
|
// _runonly (excluded from the test-lang-byteid T2 gate) because a local
|
|
// [N]<sub-8-tail-struct> trips a SEPARATE PRE-EXISTING let-array slotsize cs!=ww
|
|
// FRAME divergence — ww sizes the array element by slotsize (S slot-padded to
|
|
// 24 -> [2]S=48), cstage by natural size (S=16 -> 32) — that PREDATES and is
|
|
// INDEPENDENT of #11: `let arr:[2]S; return arr[1].g` already diverges $32 vs
|
|
// $48 with no call involved. The #11 receive INSTRUCTIONS are byte-identical
|
|
// (both stages emit the MOVL tail); only the container's frame SIZE differs.
|
|
// The byte-id twin (idx_dot_aggret_recv_test) covers the same sub-8-tail shape
|
|
// via global-backed bases, where the slotsize bug does not bite.
|
|
|
|
package idx_dot_aggret_recv_runonly_test;
|
|
|
|
type t12 = struct { a: i32, b: i32, c: i32 };
|
|
type s12 = struct { f: t12, g: i32 };
|
|
|
|
fn mk12() t12 = { return t12{a=10i32, b=20i32, c=30i32}; };
|
|
fn one() i64 = { return 1i64; };
|
|
|
|
@test fn subtail_local_const() void = {
|
|
let a: [2]s12 = [s12{f=t12{a=9i32,b=9i32,c=9i32},g=9i32}, s12{f=t12{a=9i32,b=9i32,c=9i32},g=9i32}];
|
|
a[1].f = mk12();
|
|
assert(a[1].f.a == 10i32);
|
|
assert(a[1].f.b == 20i32);
|
|
assert(a[1].f.c == 30i32);
|
|
assert(a[1].g == 9i32);
|
|
assert(a[0].f.a == 9i32);
|
|
};
|
|
|
|
@test fn subtail_local_runtime() void = {
|
|
let a: [2]s12 = [s12{f=t12{a=9i32,b=9i32,c=9i32},g=9i32}, s12{f=t12{a=9i32,b=9i32,c=9i32},g=9i32}];
|
|
a[one()].f = mk12();
|
|
assert(a[1].f.a == 10i32);
|
|
assert(a[1].f.b == 20i32);
|
|
assert(a[1].f.c == 30i32);
|
|
assert(a[1].g == 9i32);
|
|
};
|