w6c+selfhost: cgen N_ASSIGN TY_STRUCT field branch (closes #25)
Parallel to TY_STR/TY_SLICE branches at cgen.c:1939/1962. Word-copy from src slot to field+k*8 via AX, MOVL/MOVB ragged tail. N_IDENT rhs only — struct-call-result and struct-literal rhs are different code paths, filed as task #27. Symmetric in N_ASSIGN field case AND spine-walker terminal; mirrored in wwstage cgassign four sub-shapes (*struct base, direct local, global, spine terminal).
This commit is contained in:
@@ -11619,6 +11619,53 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// struct-typed field, struct-ident rhs through
|
||||
// *struct base: cgexpr can't materialise a whole
|
||||
// struct value, so word-copy from the rhs slot
|
||||
// to *(struct_ptr + fi.foff). Other rhs shapes
|
||||
// (call result, struct literal) tracked as #27.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(lc.off: i64);
|
||||
emitline("(BP), BX\n");
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (n.op != tkind.TK_ASSIGN) {
|
||||
// compound: load current value
|
||||
emitline("\tMOVQ\t");
|
||||
@@ -11722,6 +11769,49 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// struct-typed field, struct-ident rhs:
|
||||
// word-copy direct, skipping cgexpr (no
|
||||
// register convention for a whole struct
|
||||
// value). #27 covers non-ident rhs.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((lc.off + fi.foff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((lc.off + fi.foff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
cgexpr(c, n.rhs);
|
||||
// str field: cgexpr left (AX=ptr, BX=len);
|
||||
// store both halves at +0/+8. Without this,
|
||||
@@ -11861,6 +11951,52 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) {
|
||||
// struct-typed field, struct-ident rhs on global
|
||||
// struct base: word-copy direct. Skips cgexpr —
|
||||
// no register convention for a whole struct value.
|
||||
// #27 covers non-ident rhs.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, bn);
|
||||
emitline("(SB), BX\n");
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
cgexpr(c, n.rhs);
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
@@ -12105,6 +12241,74 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
return;
|
||||
};
|
||||
// TY_STRUCT terminal: word-copy the rhs slot onto
|
||||
// base+totaloff. Only N_IDENT rhs is wired — other
|
||||
// shapes (call result, struct literal) route through
|
||||
// #27. cgexpr is skipped (no whole-struct register
|
||||
// convention); reads come straight from the rhs slot.
|
||||
if (n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& leaffi.tnode != nil
|
||||
&& leaffi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(leaffi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, leaffi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
if (viacx) {
|
||||
if (ptrroot) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(rootoff: i64);
|
||||
emitline("(BP), CX\n");
|
||||
} else {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
};
|
||||
};
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
if (viacx) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((totaloff + k): i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((rootoff + totaloff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
if (viacx) {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((totaloff + k): i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((rootoff + totaloff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (isfloattype(c, leaffi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
if (isf32type(c, leaffi.tnode)) { mov = "MOVSS"; };
|
||||
|
||||
@@ -3571,6 +3571,53 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// struct-typed field, struct-ident rhs through
|
||||
// *struct base: cgexpr can't materialise a whole
|
||||
// struct value, so word-copy from the rhs slot
|
||||
// to *(struct_ptr + fi.foff). Other rhs shapes
|
||||
// (call result, struct literal) tracked as #27.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(lc.off: i64);
|
||||
emitline("(BP), BX\n");
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (n.op != tkind.TK_ASSIGN) {
|
||||
// compound: load current value
|
||||
emitline("\tMOVQ\t");
|
||||
@@ -3674,6 +3721,49 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// struct-typed field, struct-ident rhs:
|
||||
// word-copy direct, skipping cgexpr (no
|
||||
// register convention for a whole struct
|
||||
// value). #27 covers non-ident rhs.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((lc.off + fi.foff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((lc.off + fi.foff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
cgexpr(c, n.rhs);
|
||||
// str field: cgexpr left (AX=ptr, BX=len);
|
||||
// store both halves at +0/+8. Without this,
|
||||
@@ -3813,6 +3903,52 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) {
|
||||
// struct-typed field, struct-ident rhs on global
|
||||
// struct base: word-copy direct. Skips cgexpr —
|
||||
// no register convention for a whole struct value.
|
||||
// #27 covers non-ident rhs.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, bn);
|
||||
emitline("(SB), BX\n");
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
cgexpr(c, n.rhs);
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
@@ -4057,6 +4193,74 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
return;
|
||||
};
|
||||
// TY_STRUCT terminal: word-copy the rhs slot onto
|
||||
// base+totaloff. Only N_IDENT rhs is wired — other
|
||||
// shapes (call result, struct literal) route through
|
||||
// #27. cgexpr is skipped (no whole-struct register
|
||||
// convention); reads come straight from the rhs slot.
|
||||
if (n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& leaffi.tnode != nil
|
||||
&& leaffi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(leaffi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, leaffi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
if (viacx) {
|
||||
if (ptrroot) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(rootoff: i64);
|
||||
emitline("(BP), CX\n");
|
||||
} else {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
};
|
||||
};
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
if (viacx) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((totaloff + k): i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((rootoff + totaloff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
if (viacx) {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((totaloff + k): i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((rootoff + totaloff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (isfloattype(c, leaffi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
if (isf32type(c, leaffi.tnode)) { mov = "MOVSS"; };
|
||||
|
||||
@@ -11619,6 +11619,53 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// struct-typed field, struct-ident rhs through
|
||||
// *struct base: cgexpr can't materialise a whole
|
||||
// struct value, so word-copy from the rhs slot
|
||||
// to *(struct_ptr + fi.foff). Other rhs shapes
|
||||
// (call result, struct literal) tracked as #27.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(lc.off: i64);
|
||||
emitline("(BP), BX\n");
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (n.op != tkind.TK_ASSIGN) {
|
||||
// compound: load current value
|
||||
emitline("\tMOVQ\t");
|
||||
@@ -11722,6 +11769,49 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
// struct-typed field, struct-ident rhs:
|
||||
// word-copy direct, skipping cgexpr (no
|
||||
// register convention for a whole struct
|
||||
// value). #27 covers non-ident rhs.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((lc.off + fi.foff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((lc.off + fi.foff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
cgexpr(c, n.rhs);
|
||||
// str field: cgexpr left (AX=ptr, BX=len);
|
||||
// store both halves at +0/+8. Without this,
|
||||
@@ -11861,6 +11951,52 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) {
|
||||
// struct-typed field, struct-ident rhs on global
|
||||
// struct base: word-copy direct. Skips cgexpr —
|
||||
// no register convention for a whole struct value.
|
||||
// #27 covers non-ident rhs.
|
||||
if (n.op == tkind.TK_ASSIGN
|
||||
&& n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& fi.tnode != nil
|
||||
&& fi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(fi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, bn);
|
||||
emitline("(SB), BX\n");
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((fi.foff + k): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
cgexpr(c, n.rhs);
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
@@ -12105,6 +12241,74 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
return;
|
||||
};
|
||||
// TY_STRUCT terminal: word-copy the rhs slot onto
|
||||
// base+totaloff. Only N_IDENT rhs is wired — other
|
||||
// shapes (call result, struct literal) route through
|
||||
// #27. cgexpr is skipped (no whole-struct register
|
||||
// convention); reads come straight from the rhs slot.
|
||||
if (n.rhs != nil
|
||||
&& n.rhs.kind == nkind.N_IDENT
|
||||
&& leaffi.tnode != nil
|
||||
&& leaffi.tnode.kind == nkind.N_TNAME
|
||||
&& primsize(leaffi.tnode.str) == 0) {
|
||||
let ssi: *structinfo = structlookup(c, leaffi.tnode.str);
|
||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||
if (ssi != nil) { if (srhs != nil) {
|
||||
if (viacx) {
|
||||
if (ptrroot) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(rootoff: i64);
|
||||
emitline("(BP), CX\n");
|
||||
} else {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
};
|
||||
};
|
||||
let ssz: i32 = ssi.totsize;
|
||||
let k: i32 = 0;
|
||||
for (k + 8 <= ssz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
if (viacx) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg((totaloff + k): i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((rootoff + totaloff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
k += 8;
|
||||
};
|
||||
if (k < ssz) {
|
||||
let tail: i32 = ssz - k;
|
||||
let lop: str = "MOVQ";
|
||||
if (tail == 4) { lop = "MOVL"; }
|
||||
else { if (tail == 1) { lop = "MOVB"; }; };
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\t");
|
||||
emitoff((srhs.off + k): i64);
|
||||
emitline("(BP), AX\n");
|
||||
if (viacx) {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitdispreg((totaloff + k): i64, "CX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(lop);
|
||||
emitline("\tAX, ");
|
||||
emitoff((rootoff + totaloff + k): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
};
|
||||
return;
|
||||
};};
|
||||
};
|
||||
if (isfloattype(c, leaffi.tnode)) {
|
||||
let mov: str = "MOVSD";
|
||||
if (isf32type(c, leaffi.tnode)) { mov = "MOVSS"; };
|
||||
|
||||
Reference in New Issue
Block a user