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

@@ -2315,7 +2315,22 @@ cgexpr(Cg *c, Node *n, Local *locals)
ins2(c, node_isf32(n) ? A_MOVSS : A_MOVSD,
amem(D_AX, 0), areg(D_X0));
} else {
ins2(c, A_MOVQ, amem(D_AX, 0), areg(D_AX));
/* Load-twin of the signed-narrow-scalar-reads
* sweep (project_cgen_int_cast_no_truncate);
* TK_STAR was the omitted site, refiled as
* #116. A raw MOVQ pulls 8 bytes through a
* narrow `*iN` and overlaps the next element
* — the `*p` value reads honest only when the
* caller's sink happens to truncate (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, with the
* TY_NAMED / TY_ENUM peel pre-folded so an
* aliased narrow (`type err = !i32`) lands on
* the right opcode. */
ins2(c, localloadop(n->type),
amem(D_AX, 0), areg(D_AX));
}
break;
default: break;