wcc: narrow integer pointer-deref load width via localloadop (#116)

TK_STAR integer arm now routes through localloadop (cstage cgen.c) /
localloadop (wwstage cgenexpr.ww) — load-twin of the landed signed-
narrow-scalar-reads fix, was omitting TK_STAR. Closes the *p (CMPQ,
full-width arith) miscompile family (#116 + 962/963 instances all
fixed by the same width-aware load). Float arm untouched (#96 already
routed via X0). New test 947 (10 rows): packed CMPQ + signed/unsigned
narrow widths + TY_NAMED/TBANG alias + TY_ENUM peel + i64/bool controls.
This commit is contained in:
2026-05-26 19:14:14 +09:00
parent e9620953a0
commit e6beb566ea
6 changed files with 373 additions and 4 deletions

View File

@@ -2831,7 +2831,24 @@ fn cgun(c: *cgen, n: *node) void = {
if (isf32type(c, n)) { mov = "MOVSS"; };
emitline("\t"); emitline(mov); emitline("\t(AX), X0\n");
} else {
emitline("\tMOVQ\t(AX), AX\n");
// Load-twin of the landed signed-narrow-scalar-reads
// sweep (selfhost/CLAUDE.md "Signed-narrow scalar
// reads sign-extend honestly"); TK_STAR was the
// omitted site, refiled as #116. A raw MOVQ pulls 8B
// through a narrow `*iN` and overlaps the next element
// — the `*p` value reads honest only when the caller's
// sink truncates (i32 store, i32 return). Width-
// preserving sinks (CMPQ, 64-bit arith) saw garbage in
// the high bytes. localloadop keys MOVSXD/MOVSWQ/
// MOVSBQ + MOVL/MOVZWQ/MOVZBQ off n.type_; n is the
// deref expression, n.type_ is the pointee tinfo
// (check.ww unoptype TK_STAR L1871-1886 with
// TY_NAMED/TY_ENUM peel pre-folded by
// tinfofornode/typeissigned), the same shape the
// float arm above feeds isfloattype.
let lop: str = localloadop(c, n);
emitline("\t"); emitline(lop);
emitline("\t(AX), AX\n");
};
return;
};