cgen: store a 2-byte struct-literal field with MOVW, not an over-wide MOVQ (#15)
cg_structlit_fill/cgstructlitfill dispatched scalar field stores as {1->MOVB, 4->MOVL, else->MOVQ} with no fsz==2 case, so a 2-byte field was stored with an 8-byte MOVQ. Interior over-stores were harmlessly overwritten by the next field, but the LAST field at the frame edge corrupted the saved base pointer: an (S|e) union success variant places the struct payload after the 8B tag, landing the last field at -4(BP), so MOVQ AX,-4(BP) wrote into saved [BP] and POPQ BP restored garbage — a silent both-stage caller-frame clobber. Route the scalar store through the existing fldstoreop/fieldstoreop helper ({1->MOVB,2->MOVW,4->MOVL,else->MOVQ}), both stages; the #13 graduation comments already pre-documented this resolution. Pure width fix, no loud-stop (scalar widths are always {1,2,4,8} and narrowing is always correct). Value-asserting pin: an i64 sentinel live across the union-maker call (detects the clobber directly) + all members, with a non-union control.
This commit is contained in:
@@ -3362,9 +3362,12 @@ cg_widen_tagged_push(Cg *c, Local **locals_p, Type *dst, Node *src, int sz)
|
||||
* because the existing inline code's reload-before-each-store pattern
|
||||
* matches the helper's per-store reload exactly.
|
||||
*
|
||||
* The scalar store dispatch stays at the explicit {1->MOVB, 4->MOVL,
|
||||
* else MOVQ} shape (not fieldstoreop, which emits MOVW for fsz==2) to
|
||||
* stay byte-identical with cstage pending task #13. */
|
||||
* The scalar store routes through fldstoreop {1->MOVB, 2->MOVW,
|
||||
* 4->MOVL, else MOVQ}: the missing MOVW for fsz==2 over-stored a
|
||||
* 2-byte tail field past its slot into saved BP on a union-return
|
||||
* success variant (#15). Natural field offsets aren't 8-aligned, so
|
||||
* MOVQ-rely-on-ceil-8-pad (sound for #10's 8-aligned scratch) is
|
||||
* wrong here; the store must be width-sized. */
|
||||
static void
|
||||
cg_structlit_fill(Cg *c, Local **locals_p, Type *lu, Node *lit,
|
||||
int mode, int srcoff, const char *name, int disp)
|
||||
@@ -3666,9 +3669,7 @@ cg_structlit_fill(Cg *c, Local **locals_p, Type *lu, Node *lit,
|
||||
amem(base_reg, disp + (int)foff));
|
||||
continue;
|
||||
}
|
||||
int op = A_MOVQ;
|
||||
if (fsz == 1) op = A_MOVB;
|
||||
else if (fsz == 4) op = A_MOVL;
|
||||
int op = fldstoreop(ft, fsz);
|
||||
ins2(c, op, areg(D_AX),
|
||||
amem(base_reg, disp + (int)foff));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user