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)
/*
* 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.
*/
......@@ -1465,7 +1467,10 @@ int
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr;
Type *t;
int freel, freer;
vlong fldcount;
vlong loffset, roffset;
freel = 0;
freer = 0;
......@@ -1475,8 +1480,33 @@ componentgen(Node *nr, Node *nl)
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;
......@@ -1500,6 +1530,23 @@ componentgen(Node *nr, Node *nl)
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);
......@@ -1577,6 +1624,23 @@ componentgen(Node *nr, Node *nl)
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:
......
......@@ -79,6 +79,7 @@ void allocparams(void);
void checklabels();
void ginscall(Node*, int);
int gen_as_init(Node*);
void clearslim(Node*);
/*
* cgen.c
......
......@@ -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:
* nl = nr
......@@ -640,9 +701,7 @@ cgen_discard(Node *nr)
void
cgen_as(Node *nl, Node *nr)
{
Node nc;
Type *tl;
int iszer;
if(debug['g']) {
dump("cgen_as", nl);
......@@ -657,7 +716,6 @@ cgen_as(Node *nl, Node *nr)
return;
}
iszer = 0;
if(nr == N || isnil(nr)) {
// externals and heaps should already be clear
if(nr == N) {
......@@ -672,59 +730,12 @@ cgen_as(Node *nl, Node *nr)
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;
......@@ -732,11 +743,6 @@ cgen_as(Node *nl, Node *nr)
return;
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