selfhost/cmd/wcc: cgalloc str-field store + regression test
wwstage cgalloc N_STRUCTLIT branch emitted MOVQ AX,foff(BX) for every non-float field. For a str field the cgexpr result is (AX=ptr, BX=len) and the single MOVQ clobbered BX with the heap pointer, dropping len. Mirror cmd/w6c/cgen.c:4184-4190: isstrtype branch routes through CX so BX=len survives. TY_STR only — slice/tagged/fn-pair have the same gap on both stages (task #23, parked behind Phase 2). New test/wcc/758_cgalloc_str_field.c is table-driven (6 rows), fails without the fix under wwstage with predicted exit codes.
This commit is contained in:
@@ -15984,6 +15984,19 @@ fn cgalloc(c: *cgen, n: *node) void = {
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(BX)\n");
|
||||
fi = nil;
|
||||
} else { if (isstrtype(c, fi.tnode)) {
|
||||
// alloc(T{ fval = s }) for str field: cgexpr
|
||||
// leaves (AX=ptr, BX=len). Use CX for the heap
|
||||
// base so BX=len survives both stores. Mirrors
|
||||
// cmd/w6c/cgen.c:4184-4190.
|
||||
emitline("\tMOVQ\t(SP), CX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(CX)\n");
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitint((fi.foff + 8): i64);
|
||||
emitline("(CX)\n");
|
||||
fi = nil;
|
||||
} else {
|
||||
emitline("\tMOVQ\t(SP), BX\n");
|
||||
let sop: str = fieldstoreop(c, fi);
|
||||
@@ -15993,7 +16006,7 @@ fn cgalloc(c: *cgen, n: *node) void = {
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(BX)\n");
|
||||
fi = nil;
|
||||
};
|
||||
};};
|
||||
} else {
|
||||
fi = fi.finext;
|
||||
};
|
||||
|
||||
@@ -2775,6 +2775,19 @@ fn cgalloc(c: *cgen, n: *node) void = {
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(BX)\n");
|
||||
fi = nil;
|
||||
} else { if (isstrtype(c, fi.tnode)) {
|
||||
// alloc(T{ fval = s }) for str field: cgexpr
|
||||
// leaves (AX=ptr, BX=len). Use CX for the heap
|
||||
// base so BX=len survives both stores. Mirrors
|
||||
// cmd/w6c/cgen.c:4184-4190.
|
||||
emitline("\tMOVQ\t(SP), CX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(CX)\n");
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitint((fi.foff + 8): i64);
|
||||
emitline("(CX)\n");
|
||||
fi = nil;
|
||||
} else {
|
||||
emitline("\tMOVQ\t(SP), BX\n");
|
||||
let sop: str = fieldstoreop(c, fi);
|
||||
@@ -2784,7 +2797,7 @@ fn cgalloc(c: *cgen, n: *node) void = {
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(BX)\n");
|
||||
fi = nil;
|
||||
};
|
||||
};};
|
||||
} else {
|
||||
fi = fi.finext;
|
||||
};
|
||||
|
||||
@@ -15984,6 +15984,19 @@ fn cgalloc(c: *cgen, n: *node) void = {
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(BX)\n");
|
||||
fi = nil;
|
||||
} else { if (isstrtype(c, fi.tnode)) {
|
||||
// alloc(T{ fval = s }) for str field: cgexpr
|
||||
// leaves (AX=ptr, BX=len). Use CX for the heap
|
||||
// base so BX=len survives both stores. Mirrors
|
||||
// cmd/w6c/cgen.c:4184-4190.
|
||||
emitline("\tMOVQ\t(SP), CX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(CX)\n");
|
||||
emitline("\tMOVQ\tBX, ");
|
||||
emitint((fi.foff + 8): i64);
|
||||
emitline("(CX)\n");
|
||||
fi = nil;
|
||||
} else {
|
||||
emitline("\tMOVQ\t(SP), BX\n");
|
||||
let sop: str = fieldstoreop(c, fi);
|
||||
@@ -15993,7 +16006,7 @@ fn cgalloc(c: *cgen, n: *node) void = {
|
||||
emitint(fi.foff: i64);
|
||||
emitline("(BX)\n");
|
||||
fi = nil;
|
||||
};
|
||||
};};
|
||||
} else {
|
||||
fi = fi.finext;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user