wwstage: displacement store for global-ptr scalar field, align to cstage
cgassign had dedicated N_DOT-store arms for a local-ptr base, a global value-struct, and chained bases, but none for a global-pointer scalar field. That case fell through to the generic cgplaceaddr/dotchainaddr route, which folds the field offset (ADDQ $foff,BX) then stores to (BX). cstage emits a single displacement store (MOVQ AX,foff(BX)) via its via_ptr global scalar arm, so the two stages diverged on asm shape (rule 10). Both forms are runtime-correct here -- BX is a fresh throwaway in the generic route -- so this was a byte-id divergence, not a miscompile. Add the missing displacement-store arm, predicate-mirroring cstage's via_ptr global scalar arm exactly: plain assignment only, scalar field only; non-scalar field types stay on the generic path (their global-ptr deref is a separate deferred item). glob_ptr_field_test.ww gains an off-8 row as the regression pin -- offset-0 cannot catch it because ADDQ $0 is suppressed. Surfaced by the fold-2 Fam-5 migration.
This commit is contained in:
@@ -24,3 +24,17 @@ let gp: *S = nil;
|
||||
gp.f = 7;
|
||||
assert(backing.f: i32 == 7);
|
||||
};
|
||||
|
||||
@test fn store_off8() void = {
|
||||
// #8 (rule-10): a NON-zero-offset field (g at +8) through the global
|
||||
// pointer. wwstage folded the offset into BX (`ADDQ $8,BX` + plain
|
||||
// `MOVQ AX,(BX)`) while cstage emitted the displacement store
|
||||
// `MOVQ AX,8(BX)` — a cs!=ww .s divergence T2 catches. Offset-0 rows
|
||||
// CANNOT pin this (`ADDQ $0` is suppressed). backing.g is poisoned
|
||||
// non-zero first, then overwritten via gp.g, so a store that lands at
|
||||
// the wrong displacement is caught on read-back.
|
||||
gp = &backing;
|
||||
backing.g = 11;
|
||||
gp.g = 7;
|
||||
assert(backing.g: i32 == 7);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user