selfhost: graduate wwstage &N_DOT[N_INDEX] to cstage canonical lean form (#21)
Latent #21 has two surface shapes — register polarity in cgun TK_AMP N_INDEX's complex-base arm, and indexbaseesz's over-broad .ptr pseudo-field gate — that share a single semantic path: &N_DOT[N_INDEX] where the inner N_DOT cannot be peeled into a plain ident base. Polarity-A (cgenexpr.ww) lifted to cstage's three-line shape; stride-B (cgenutil.ww) narrowed so the .ptr arm only fires on actual str/slice inners and falls through to the generic struct-field arm for struct N_TNAME bases. The fixes compose at the same call site (esz from indexbaseesz, then the IMULQ-or-elide gate, then complex-base emit), so splitting them into two commits would leave a half-fixed intermediate — neither half stands alone as a bisect-clean closure. Sentinel 755_amp_dot_idx exercises both shapes across 4 stride classes (slice-elem 24, struct-elem 16, u8 stride-1 elide, i64 stride-8); pre-fix 5/12 fail, post-fix 12/12 ok. Latent silent miscompile in lib/memio + lib/bufio's .ptr[i] shape also unmasked.
This commit is contained in:
@@ -2484,11 +2484,16 @@ fn cgun(c: *cgen, n: *node) void = {
|
||||
};
|
||||
} else {
|
||||
// Complex base: spill scaled idx, eval
|
||||
// base to AX, move to BX, restore idx.
|
||||
// base to AX, restore idx into BX.
|
||||
// Mirrors cstage's lean three-line shape
|
||||
// (cmd/w6c/cgen.c TK_AMP N_INDEX complex
|
||||
// base 2104-2107); the prior MOVQ AX, BX
|
||||
// + POPQ AX scratch shuffle was rule-10
|
||||
// verbose-defensive on the wwstage side
|
||||
// with no semantic asymmetry (task #21).
|
||||
emitline("\tPUSHQ\tAX\n");
|
||||
cgexpr(c, base);
|
||||
emitline("\tMOVQ\tAX, BX\n");
|
||||
emitline("\tPOPQ\tAX\n");
|
||||
emitline("\tPOPQ\tBX\n");
|
||||
};};};
|
||||
emitline("\tADDQ\tBX, AX\n");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user