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:
@@ -17045,7 +17045,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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -17045,7 +17045,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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user