From: Rémy Oudompheng Date: Mon, 12 Nov 2012 23:08:04 +0000 (+0100) Subject: cmd/6g: extend componentgen to small arrays and structs. X-Git-Tag: go1.1rc2~1893 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=16072c749750b7e4e6e1e48d4724afdfec574efa;p=gostls13.git cmd/6g: extend componentgen to small arrays and structs. Fixes #4092. R=golang-dev, dave, rsc CC=golang-dev https://golang.org/cl/6819083 --- diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index 1333dc194f..34e70ded09 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -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: diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index ba1ad75f32..9f8e95ceb5 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -79,6 +79,7 @@ void allocparams(void); void checklabels(); void ginscall(Node*, int); int gen_as_init(Node*); +void clearslim(Node*); /* * cgen.c diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index 4f5aa3c3a6..456ca622fb 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.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: - ; } /*