diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/cmd/8g/cgen.c | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/cmd/8g/cgen.c')
-rw-r--r-- | src/cmd/8g/cgen.c | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index d626c2eb0..2735fb6a5 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -242,7 +242,6 @@ cgen(Node *n, Node *res) case OOR: case OXOR: case OADD: - case OADDPTR: case OMUL: a = optoas(n->op, nl->type); if(a == AIMULB) { @@ -347,8 +346,11 @@ cgen(Node *n, Node *res) if(istype(nl->type, TCHAN)) { // chan has cap in the second 32-bit word. // a zero pointer means zero length - regalloc(&n1, types[tptr], res); + tempname(&n1, types[tptr]); cgen(nl, &n1); + regalloc(&n2, types[tptr], N); + gmove(&n1, &n2); + n1 = n2; nodconst(&n2, types[tptr], 0); gins(optoas(OCMP, types[tptr]), &n1, &n2); @@ -1324,7 +1326,7 @@ sgen(Node *n, Node *res, int64 w) p = gins(ADUFFCOPY, N, N); p->to.type = D_ADDR; p->to.sym = linksym(pkglookup("duffcopy", runtimepkg)); - // 10 and 128 = magic constants: see ../../pkg/runtime/asm_386.s + // 10 and 128 = magic constants: see ../../runtime/asm_386.s p->to.offset = 10*(128-q); } else while(q > 0) { @@ -1364,7 +1366,10 @@ int componentgen(Node *nr, Node *nl) { Node nodl, nodr; + Type *t; int freel, freer; + vlong fldcount; + vlong loffset, roffset; freel = 0; freer = 0; @@ -1374,8 +1379,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 > 4) goto no; + + break; + case TSTRING: case TINTER: break; @@ -1396,7 +1426,7 @@ componentgen(Node *nr, Node *nl) freer = 1; } } - + // nl and nr are 'cadable' which basically means they are names (variables) now. // If they are the same variable, don't generate any code, because the // VARDEF we generate will mark the old value as dead incorrectly. @@ -1406,8 +1436,25 @@ componentgen(Node *nr, Node *nl) switch(nl->type->etype) { case TARRAY: + // componentgen for arrays. if(nl->op == ONAME) gvardef(nl); + 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); @@ -1419,7 +1466,7 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); nodl.xoffset += Array_nel-Array_array; - nodl.type = types[TUINT32]; + nodl.type = types[simtype[TUINT]]; if(nr != N) { nodr.xoffset += Array_nel-Array_array; @@ -1429,7 +1476,7 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); nodl.xoffset += Array_cap-Array_nel; - nodl.type = types[TUINT32]; + nodl.type = types[simtype[TUINT]]; if(nr != N) { nodr.xoffset += Array_cap-Array_nel; @@ -1454,7 +1501,7 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); nodl.xoffset += Array_nel-Array_array; - nodl.type = types[TUINT32]; + nodl.type = types[simtype[TUINT]]; if(nr != N) { nodr.xoffset += Array_nel-Array_array; @@ -1489,6 +1536,31 @@ componentgen(Node *nr, Node *nl) gmove(&nodr, &nodl); goto yes; + + case TSTRUCT: + if(nl->op == ONAME) + gvardef(nl); + loffset = nodl.xoffset; + roffset = nodr.xoffset; + // funarg structs may not begin at offset zero. + if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type) + loffset -= nl->type->type->width; + if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type) + roffset -= nr->type->type->width; + + 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: |