wcc: for-range destructure copies the full str/slice binding, both stages
The per-binding copy loop moved ONE word of a 24B str/slice binding — .len and .cap read zero/garbage in BOTH stages (byte-identical, the deepest both-wrong-identical of the drain: the F7-era stride fix asserted convergence without re-measuring the absolute). Copy the full extent for an sz>8 str/slice binding; the rewritten 989_tupfieldsize pins all three header words with sliced caps so cap!=len has teeth. The tagged-binding arm remains open as task #53 (wwstage paramfieldsize). Review-era task #40, recategorized #263 fused. 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:
@@ -39696,6 +39696,54 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
} else {
|
||||
let b: i32 = 0;
|
||||
for (b < nbinds) {
|
||||
// #40 (#263): a str/slice/struct destructure binding
|
||||
// (24B header / aggregate, sz>8) copies its FULL extent
|
||||
// — the single load word truncated a slice binding to
|
||||
// its .ptr, dropping .len/.cap (both stages identically,
|
||||
// byte-id-WRONG; F7-c4 fixed only the STRIDE). Same
|
||||
// word-run + sized-tail idiom as the non-destructure
|
||||
// aggregate copy above.
|
||||
if (bind_sz[b] > 8) {
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= bind_sz[b]) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k + 4 <= bind_sz[b]) {
|
||||
emitline("\tMOVL\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVL\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 4;
|
||||
};
|
||||
if (k + 2 <= bind_sz[b]) {
|
||||
emitline("\tMOVW\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVW\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 2;
|
||||
};
|
||||
if (k + 1 <= bind_sz[b]) {
|
||||
emitline("\tMOVB\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVB\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 1;
|
||||
};
|
||||
b += 1;
|
||||
continue;
|
||||
};
|
||||
let op: str = loadopsz(bind_signed[b], bind_sz[b]);
|
||||
emitline("\t");
|
||||
emitline(op);
|
||||
|
||||
@@ -4144,6 +4144,54 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
} else {
|
||||
let b: i32 = 0;
|
||||
for (b < nbinds) {
|
||||
// #40 (#263): a str/slice/struct destructure binding
|
||||
// (24B header / aggregate, sz>8) copies its FULL extent
|
||||
// — the single load word truncated a slice binding to
|
||||
// its .ptr, dropping .len/.cap (both stages identically,
|
||||
// byte-id-WRONG; F7-c4 fixed only the STRIDE). Same
|
||||
// word-run + sized-tail idiom as the non-destructure
|
||||
// aggregate copy above.
|
||||
if (bind_sz[b] > 8) {
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= bind_sz[b]) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k + 4 <= bind_sz[b]) {
|
||||
emitline("\tMOVL\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVL\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 4;
|
||||
};
|
||||
if (k + 2 <= bind_sz[b]) {
|
||||
emitline("\tMOVW\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVW\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 2;
|
||||
};
|
||||
if (k + 1 <= bind_sz[b]) {
|
||||
emitline("\tMOVB\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVB\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 1;
|
||||
};
|
||||
b += 1;
|
||||
continue;
|
||||
};
|
||||
let op: str = loadopsz(bind_signed[b], bind_sz[b]);
|
||||
emitline("\t");
|
||||
emitline(op);
|
||||
|
||||
@@ -39696,6 +39696,54 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
} else {
|
||||
let b: i32 = 0;
|
||||
for (b < nbinds) {
|
||||
// #40 (#263): a str/slice/struct destructure binding
|
||||
// (24B header / aggregate, sz>8) copies its FULL extent
|
||||
// — the single load word truncated a slice binding to
|
||||
// its .ptr, dropping .len/.cap (both stages identically,
|
||||
// byte-id-WRONG; F7-c4 fixed only the STRIDE). Same
|
||||
// word-run + sized-tail idiom as the non-destructure
|
||||
// aggregate copy above.
|
||||
if (bind_sz[b] > 8) {
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= bind_sz[b]) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k + 4 <= bind_sz[b]) {
|
||||
emitline("\tMOVL\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVL\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 4;
|
||||
};
|
||||
if (k + 2 <= bind_sz[b]) {
|
||||
emitline("\tMOVW\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVW\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 2;
|
||||
};
|
||||
if (k + 1 <= bind_sz[b]) {
|
||||
emitline("\tMOVB\t");
|
||||
emitoff((bind_foff[b] + k): i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVB\tAX, ");
|
||||
emitoff((bind_off[b] + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 1;
|
||||
};
|
||||
b += 1;
|
||||
continue;
|
||||
};
|
||||
let op: str = loadopsz(bind_signed[b], bind_sz[b]);
|
||||
emitline("\t");
|
||||
emitline(op);
|
||||
|
||||
Reference in New Issue
Block a user