cgen: address module-global str/slice pseudo-field stores via the symbol
A module-global base has no frame slot; treating its local-lookup miss as offset zero wrote .ptr/.len/.cap at the caller return address. LEAQ the symbol like the struct-field global arms do. Both stages.
This commit is contained in:
@@ -11170,9 +11170,9 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// Top-level struct global field assignment: `g.f = expr;` and
|
||||
// `g.f += expr;` for a scalar/str field. Reached when the local
|
||||
// lookup miss but the IDENT base is a registered struct `let`.
|
||||
// Top-level global field assignment: `g.f = expr;` and `g.f += expr;`
|
||||
// for a struct field or str/slice pseudo-field. Reached when the local
|
||||
// lookup misses but the IDENT base is a registered module `let`.
|
||||
// LEAQ name(SB) into BX/CX takes the place of the frame slot
|
||||
// addressing the local branches use. Compound (PLUSEQ/MINUSEQ)
|
||||
// follows the same load → push → eval → combine → store shape
|
||||
@@ -11185,6 +11185,37 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
if (base.kind == syntax.nkind.N_IDENT) {
|
||||
let bn: str = base.str;
|
||||
if (localfindnode(c, bn) == nil) {
|
||||
let btype: *syntax.tinfo = base.type_: *syntax.tinfo;
|
||||
if (isletvar(c, bn) &&
|
||||
(syntax.typeisstr(btype) || syntax.typeisslice(btype))) {
|
||||
let delta: i32 = -1;
|
||||
if (syntax.streq(fld, "ptr")) { delta = 0; };
|
||||
if (syntax.streq(fld, "len")) { delta = 8; };
|
||||
if (syntax.streq(fld, "cap")) { delta = 16; };
|
||||
if (delta >= 0) {
|
||||
if (n.op != syntax.tkind.TK_ASSIGN) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, bn);
|
||||
emitline("(SB), BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(delta: i64, "BX");
|
||||
emitline(", BX\n");
|
||||
emitline("\tPUSHQ\tBX\n");
|
||||
};
|
||||
cgexpr(c, n.rhs);
|
||||
if (n.op != syntax.tkind.TK_ASSIGN) {
|
||||
emitline("\tPOPQ\tBX\n");
|
||||
cgdotfieldcombine(c, n.op, false);
|
||||
};
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, bn);
|
||||
emitline("(SB), BX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg(delta: i64, "BX");
|
||||
emitline("\n");
|
||||
return;
|
||||
};
|
||||
};
|
||||
// #31: resolve the global value-struct field OFFSET + type
|
||||
// off the checker-STAMPED receiver tinfo (tichase(base.type_)),
|
||||
// NOT the name-keyed global-struct leaf lookup. A global decl
|
||||
|
||||
Reference in New Issue
Block a user