Commit 16072c74 authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/6g: extend componentgen to small arrays and structs.

Fixes #4092.

R=golang-dev, dave, rsc
CC=golang-dev
https://golang.org/cl/6819083
parent eb4f4d16
...@@ -1458,6 +1458,8 @@ cadable(Node *n) ...@@ -1458,6 +1458,8 @@ cadable(Node *n)
/* /*
* copy a composite value by moving its individual components. * copy a composite value by moving its individual components.
* Slices, strings and interfaces are supported. * 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. * nr is N when assigning a zero value.
* return 1 if can do, 0 if cant. * return 1 if can do, 0 if cant.
*/ */
...@@ -1465,7 +1467,10 @@ int ...@@ -1465,7 +1467,10 @@ int
componentgen(Node *nr, Node *nl) componentgen(Node *nr, Node *nl)
{ {
Node nodl, nodr; Node nodl, nodr;
Type *t;
int freel, freer; int freel, freer;
vlong fldcount;
vlong loffset, roffset;
freel = 0; freel = 0;
freer = 0; freer = 0;
...@@ -1475,8 +1480,33 @@ componentgen(Node *nr, Node *nl) ...@@ -1475,8 +1480,33 @@ componentgen(Node *nr, Node *nl)
goto no; goto no;
case TARRAY: 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; goto no;
break;
case TSTRING: case TSTRING:
case TINTER: case TINTER:
break; break;
...@@ -1500,6 +1530,23 @@ componentgen(Node *nr, Node *nl) ...@@ -1500,6 +1530,23 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) { switch(nl->type->etype) {
case TARRAY: 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.xoffset += Array_array;
nodl.type = ptrto(nl->type->type); nodl.type = ptrto(nl->type->type);
...@@ -1577,6 +1624,23 @@ componentgen(Node *nr, Node *nl) ...@@ -1577,6 +1624,23 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl); gmove(&nodr, &nodl);
goto yes; 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: no:
......
...@@ -79,6 +79,7 @@ void allocparams(void); ...@@ -79,6 +79,7 @@ void allocparams(void);
void checklabels(); void checklabels();
void ginscall(Node*, int); void ginscall(Node*, int);
int gen_as_init(Node*); int gen_as_init(Node*);
void clearslim(Node*);
/* /*
* cgen.c * cgen.c
......
...@@ -632,6 +632,67 @@ cgen_discard(Node *nr) ...@@ -632,6 +632,67 @@ cgen_discard(Node *nr)
} }
} }
/*
* 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: * generate assignment:
* nl = nr * nl = nr
...@@ -640,9 +701,7 @@ cgen_discard(Node *nr) ...@@ -640,9 +701,7 @@ cgen_discard(Node *nr)
void void
cgen_as(Node *nl, Node *nr) cgen_as(Node *nl, Node *nr)
{ {
Node nc;
Type *tl; Type *tl;
int iszer;
if(debug['g']) { if(debug['g']) {
dump("cgen_as", nl); dump("cgen_as", nl);
...@@ -657,7 +716,6 @@ cgen_as(Node *nl, Node *nr) ...@@ -657,7 +716,6 @@ cgen_as(Node *nl, Node *nr)
return; return;
} }
iszer = 0;
if(nr == N || isnil(nr)) { if(nr == N || isnil(nr)) {
// externals and heaps should already be clear // externals and heaps should already be clear
if(nr == N) { if(nr == N) {
...@@ -672,59 +730,12 @@ cgen_as(Node *nl, Node *nr) ...@@ -672,59 +730,12 @@ cgen_as(Node *nl, Node *nr)
return; return;
if(isfat(tl)) { if(isfat(tl)) {
clearfat(nl); clearfat(nl);
goto ret; return;
}
/* 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;
} }
nr->op = OLITERAL; clearslim(nl);
nr->type = tl; if(nl->addable)
nr->addable = 1; gused(nl);
ullmancalc(nr); return;
} }
tl = nl->type; tl = nl->type;
...@@ -732,11 +743,6 @@ cgen_as(Node *nl, Node *nr) ...@@ -732,11 +743,6 @@ cgen_as(Node *nl, Node *nr)
return; return;
cgen(nr, nl); cgen(nr, nl);
if(iszer && nl->addable)
gused(nl);
ret:
;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment