Commit Graph

4 Commits

Author SHA1 Message Date
11afd82e16 test: pin i64-sink chained global-ptr read is full-width, guards #18
#18 verified there is no spurious load-narrow on a chained global-ptr field
read into an i64 sink -- the only MOVSXD is the legitimate :i32 return cast,
byte-identical in both stages. Lock it: a chain_i64_sink row reads q:i64 =
0x1_0000_0001 and asserts the high word == 1. A truncating load-narrow would
drop the high word to 0, so the row pins the spine-narrow family (runtime +
byte-id, both stages).
2026-06-24 00:28:25 +09:00
d6ea497da1 wwstage: align direct-ptr tagged-field READ word-order to cstage (#17)
A >32B tagged-union field (slice payload) read through a direct *struct
pointer byte-diverged: wwstage's cgloadtaggedfield always loaded R8@+24
before CX@+16, but cstage's direct-*struct-ptr arm (cgen.c ~11926) loads in
offset order CX@+16 then R8@+24. Both ran correct -- a pre-existing rule-10
asm divergence, for a local *struct ptr as well as a global one.

Thread a cxlast flag through cgloadtaggedfield: the direct-ptr site
(cgptrfieldload, the shared local+global chokepoint) passes cxlast=false to
match cstage's offset order; the other 5 callers keep cxlast=true (byte
unchanged). A global flip was rejected -- it would clobber the CX-base
callers (CX@+16 first destroys the base before the R8@+24 read), and the
chained-BX caller must stay R8-first to mirror cstage's chained twin
(cgen.c ~12021); the order is a genuine per-arm property of cstage, not
derivable from the base register.

Test: +2 rows (tagged_slice_field via global *struct ptr, _local via local
*struct ptr), runtime + byte-id; both proven to fail byte-id with only the
compiler files reverted.
2026-06-24 00:07:24 +09:00
ab3ac67afd wwstage: fold chained global-ptr field READ to cstage offset-fold (#16)
wwstage's chained-N_DOT resolver (dotchainresolve) didn't resolve a global
*struct root (only local *T and global value-struct), so gp.sf.len / gp.x.y
bailed to an inner-dot load + shuffle, byte-diverging from cstage's offset-fold.
Both stages already ran correct after #15 (475c003) -- a pure rule-10 asm
divergence. cstage is untouched (the oracle); wwstage aligns up.

Resolve a global N_TPTR root, and extract emitchainbase for the viacx base-load
(byte-identical across the 5 read + 2 store sites it replaces). The chained
STORE caller declines the global-ptr root (yok=false) so it falls to cstage's
address-spine mirror -- matching the #6/#15 decline-to-resolver discipline;
local *T chained stores still fold.

Test: +2 chained rows (gp.sf.len, gp.x.q), runtime + byte-id; proven to fail
byte-id with only the compiler files reverted, pass with the fix.

Sibling follow-ups filed: #17 (>32B tagged word-order), #18 (chained read into
an i64 sink MOVSXD check).
2026-06-23 07:25:33 +09:00
475c003b0d cgen: fix global-ptr field READ, load ptr value via SB before offset (#15)
Reading gp.f through a module-global pointer miscompiled in BOTH stages,
differently: cstage classified gp as a local at boff 0 and derefed BP
(MOVQ (BP),BX), wwstage collapsed gp.f to an undefined global symbol f
(MOVQ f(SB)). Both now load the pointer value from the global's data slot
before the field offset, converging on MOVQ gp(SB),BX; MOVQ off(BX),AX.
cstage mirrors the #6 store decline; wwstage gains a global-ptr arm and
shares a cgptrfieldload helper with the local arm.

Fused, not split: the two stages must emit byte-identical asm, so a
one-stage commit would fail the byte-id gate. Sibling byte-divergences
filed: #16 (chained-spine gp.x.y), #17 (>32B tagged word-order).

Test: table-driven 689_globptr_field_read_run (24 rows, runtime + byte-id).
2026-06-23 06:42:38 +09:00