/*
* copy a composite value by moving its individual components.
* Slices, strings and interfaces are supported.
+ * Small structs or arrays with elements of basic type are
+ * also supported.
* nr is N when assigning a zero value.
* return 1 if can do, 0 if cant.
*/
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr;
+ Type *t;
int freel, freer;
+ vlong fldcount;
+ vlong loffset, roffset;
freel = 0;
freer = 0;
goto no;
case TARRAY:
- if(!isslice(nl->type))
+ t = nl->type;
+
+ // Slices are ok.
+ if(isslice(t))
+ break;
+ // Small arrays are ok.
+ if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
+ break;
+
+ goto no;
+
+ case TSTRUCT:
+ // Small structs with non-fat types are ok.
+ // Zero-sized structs are treated separately elsewhere.
+ fldcount = 0;
+ for(t=nl->type->type; t; t=t->down) {
+ if(isfat(t->type))
+ goto no;
+ if(t->etype != TFIELD)
+ fatal("componentgen: not a TFIELD: %lT", t);
+ fldcount++;
+ }
+ if(fldcount == 0 || fldcount > 3)
goto no;
+
+ break;
+
case TSTRING:
case TINTER:
break;
switch(nl->type->etype) {
case TARRAY:
+ // componentgen for arrays.
+ t = nl->type;
+ if(!isslice(t)) {
+ nodl.type = t->type;
+ nodr.type = nodl.type;
+ for(fldcount=0; fldcount < t->bound; fldcount++) {
+ if(nr == N)
+ clearslim(&nodl);
+ else
+ gmove(&nodr, &nodl);
+ nodl.xoffset += t->type->width;
+ nodr.xoffset += t->type->width;
+ }
+ goto yes;
+ }
+
+ // componentgen for slices.
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
gmove(&nodr, &nodl);
goto yes;
+
+ case TSTRUCT:
+ loffset = nodl.xoffset;
+ roffset = nodr.xoffset;
+ for(t=nl->type->type; t; t=t->down) {
+ nodl.xoffset = loffset + t->width;
+ nodl.type = t->type;
+
+ if(nr == N)
+ clearslim(&nodl);
+ else {
+ nodr.xoffset = roffset + t->width;
+ nodr.type = nodl.type;
+ gmove(&nodr, &nodl);
+ }
+ }
+ goto yes;
}
no:
}
}
+/*
+ * clearslim generates code to zero a slim node.
+ */
+void
+clearslim(Node *n)
+{
+ Node z;
+ Mpflt zero;
+
+ memset(&z, 0, sizeof(z));
+ z.op = OLITERAL;
+ z.type = n->type;
+ z.addable = 1;
+
+ switch(simtype[n->type->etype]) {
+ case TCOMPLEX64:
+ case TCOMPLEX128:
+ z.val.u.cval = mal(sizeof(z.val.u.cval));
+ mpmovecflt(&z.val.u.cval->real, 0.0);
+ mpmovecflt(&z.val.u.cval->imag, 0.0);
+ break;
+
+ case TFLOAT32:
+ case TFLOAT64:
+ mpmovecflt(&zero, 0.0);
+ z.val.ctype = CTFLT;
+ z.val.u.fval = &zero;
+ break;
+
+ case TPTR32:
+ case TPTR64:
+ case TCHAN:
+ case TMAP:
+ z.val.ctype = CTNIL;
+ break;
+
+ case TBOOL:
+ z.val.ctype = CTBOOL;
+ break;
+
+ case TINT8:
+ case TINT16:
+ case TINT32:
+ case TINT64:
+ case TUINT8:
+ case TUINT16:
+ case TUINT32:
+ case TUINT64:
+ z.val.ctype = CTINT;
+ z.val.u.xval = mal(sizeof(z.val.u.xval));
+ mpmovecfix(z.val.u.xval, 0);
+ break;
+
+ default:
+ fatal("clearslim called on type %T", n->type);
+ }
+
+ ullmancalc(&z);
+ cgen(&z, n);
+}
+
/*
* generate assignment:
* nl = nr
void
cgen_as(Node *nl, Node *nr)
{
- Node nc;
Type *tl;
- int iszer;
if(debug['g']) {
dump("cgen_as", nl);
return;
}
- iszer = 0;
if(nr == N || isnil(nr)) {
// externals and heaps should already be clear
if(nr == N) {
return;
if(isfat(tl)) {
clearfat(nl);
- goto ret;
- }
-
- /* invent a "zero" for the rhs */
- iszer = 1;
- nr = &nc;
- memset(nr, 0, sizeof(*nr));
- switch(simtype[tl->etype]) {
- default:
- fatal("cgen_as: tl %T", tl);
- break;
-
- case TINT8:
- case TUINT8:
- case TINT16:
- case TUINT16:
- case TINT32:
- case TUINT32:
- case TINT64:
- case TUINT64:
- nr->val.u.xval = mal(sizeof(*nr->val.u.xval));
- mpmovecfix(nr->val.u.xval, 0);
- nr->val.ctype = CTINT;
- break;
-
- case TFLOAT32:
- case TFLOAT64:
- nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
- mpmovecflt(nr->val.u.fval, 0.0);
- nr->val.ctype = CTFLT;
- break;
-
- case TBOOL:
- nr->val.u.bval = 0;
- nr->val.ctype = CTBOOL;
- break;
-
- case TPTR32:
- case TPTR64:
- nr->val.ctype = CTNIL;
- break;
-
- case TCOMPLEX64:
- case TCOMPLEX128:
- nr->val.u.cval = mal(sizeof(*nr->val.u.cval));
- mpmovecflt(&nr->val.u.cval->real, 0.0);
- mpmovecflt(&nr->val.u.cval->imag, 0.0);
- break;
+ return;
}
- nr->op = OLITERAL;
- nr->type = tl;
- nr->addable = 1;
- ullmancalc(nr);
+ clearslim(nl);
+ if(nl->addable)
+ gused(nl);
+ return;
}
tl = nl->type;
return;
cgen(nr, nl);
- if(iszer && nl->addable)
- gused(nl);
-
-ret:
- ;
}
/*