Files
ww/test/lang/global_chained_unwrap_test.ww

79 lines
3.5 KiB
Plaintext

// global_chained_unwrap_test — #16: a single-dot aggregate-field unwrap
// `g.f = mk()!` whose base is a module-GLOBAL value-struct, or `o.m.f = mk()!`
// whose base is a CHAINED struct field, dropped payload words (SILENT, both
// stages, byte-id-BLIND) — still broken after #12 fixed the LOCAL / via-ptr
// single-dot case. The #12 single-dot arm gated out the global base and its
// enclosing arm only admits an N_IDENT local base, so a global base fell to
// the generic single-word store (w1/w2 dropped) and a chained base never
// reached any field arm at all. The fix routes the destination ADDRESS
// through the cgplaceaddr spine (global LEAQ root + chained deref+offset) and
// feeds the SAME {AX=w0,DX=w1,CX=w2} producer-shift materialise the LOCAL arm
// uses.
//
// Both stages emit identically wrong asm pre-fix, so the byte-id gate is BLIND
// to the drop — these VALUE asserts are the sole tooth. POISON-SEED every dest
// member to 9 (the struct's init literal) so a dropped w1/w2 reads 9 != the
// expected value. Reverting either stage's #16 arm reverts the dropped word to
// 9 and reddens.
//
// Coverage = the global value-struct base (2-eightbyte w1 + 3-eightbyte w2
// teeth) and the chained base both as a value-local root (`o.m.f`) and through
// a pointer root (`p.m.f` = (*p).m.f). The sub-8-tail-THROUGH-unwrap case is
// NOT pinnable here for the same reasons as struct_unwrap_test (array success
// variant checker-rejected; sub-8-tail struct success trips #15's frame-edge
// class, now closed but covered there).
//
// Inline @test fns, not a row-table: the cases vary in LHS PLACE shape
// (gb.f / gb24.f / o.m.f / p.m.f) and struct width, not in data values over
// one operation, so a row-array `[](in,exp){}` cannot express them — and that
// form is itself blocked by cgen #111. Mirrors struct_unwrap_test's #12 pins.
package global_chained_unwrap_test;
type e = !i32;
type s2 = struct { a: i64, b: i64 }; // 2 eightbytes: w0=a, w1=b
type s24 = struct { a: i64, b: i64, c: i64 }; // 3 eightbytes: w0,w1,w2
type box = struct { f: s2, nb: i64 };
type box24 = struct { f: s24, nb: i64 };
type outer = struct { m: box, on: i64 };
fn mk2() (s2 | e) = { return s2 { a = 111i64, b = 222i64 }; };
fn mk24() (s24 | e) = { return s24 { a = 111i64, b = 222i64, c = 333i64 }; };
let gb: box = box { f = s2{a=9i64,b=9i64}, nb = 7i64 };
let gb24: box24 = box24 { f = s24{a=9i64,b=9i64,c=9i64}, nb = 7i64 };
@test fn global_dot() void = { // g.f = mk()! — module-global value base
gb.f = mk2()!;
assert(gb.f.a == 111i64);
assert(gb.f.b == 222i64); // w1 tooth
assert(gb.nb == 7i64); // neighbour field intact
};
@test fn global_dot_w2() void = { // 3-eightbyte global, w2 (R8->CX) tooth
gb24.f = mk24()!;
assert(gb24.f.a == 111i64);
assert(gb24.f.b == 222i64);
assert(gb24.f.c == 333i64); // w2 tooth
assert(gb24.nb == 7i64);
};
@test fn chained_dot() void = { // o.m.f = mk()! — chained, value-local root
let o: outer = outer { m = box { f = s2{a=9i64,b=9i64}, nb = 5i64 }, on = 3i64 };
o.m.f = mk2()!;
assert(o.m.f.a == 111i64);
assert(o.m.f.b == 222i64); // w1 tooth
assert(o.m.nb == 5i64); // neighbour field intact
assert(o.on == 3i64);
};
@test fn chained_dot_via_ptr() void = { // p.m.f = mk()! — chained, pointer root
let o: outer = outer { m = box { f = s2{a=9i64,b=9i64}, nb = 5i64 }, on = 3i64 };
let p: *outer = &o;
p.m.f = mk2()!;
assert(o.m.f.a == 111i64);
assert(o.m.f.b == 222i64); // w1 tooth
assert(o.m.nb == 5i64);
assert(o.on == 3i64);
};