wcc: tuple slice-element read loads the full 24B header, both stages

Reading a slice-typed tuple element (t.0) loaded only the pointer
word; len and cap took whatever was left in BX/CX — silent garbage in
BOTH stages once anything clobbered the registers between build and
read. Load all three header words at the tuple-element arm. Review
item #28.

Both stages move in one commit: one emission contract; splitting
would leave the byte-id gates red between the halves.
This commit is contained in:
2026-06-12 21:04:35 +09:00
parent 850746cfa8
commit 0a6f500b8c
5 changed files with 73 additions and 12 deletions

View File

@@ -3495,7 +3495,14 @@ fn cgdot(c: *cgen, n: *node) void = {
};
if (tp != nil) {
let tpt: *node = tp.lhs;
if (isstrtype(c, tpt)) {
// str IS []u8, and a slice is the same 24B
// {ptr,len,cap} header — load all three words
// into (AX, BX, CX). #28: pre-fix the gate was
// str-only, so a SLICE tuple element fell to
// the scalar tail below (one ptr word; len/cap
// took stale registers). base is BP (frame),
// so the triple order has no clobber risk.
if (isstrtype(c, tpt) || isslicetype(c, tpt)) {
emitline("\tMOVQ\t");
emitoff((lc.off + foff + 0): i64);
emitline("(BP), AX\n");