diff options
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r-- | src/cmd/5g/cgen.c | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 9011b2022..c535cfbef 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -254,7 +254,6 @@ cgen(Node *n, Node *res) case OOR: case OXOR: case OADD: - case OADDPTR: case OMUL: a = optoas(n->op, nl->type); goto sbop; @@ -1107,11 +1106,10 @@ bgen(Node *n, int true, int likely, Prog *to) { int et, a; Node *nl, *nr, *r; - Node n1, n2, n3, n4, tmp; + Node n1, n2, n3, tmp; NodeList *ll; Prog *p1, *p2; - USED(n4); // in unreachable code below if(debug['g']) { dump("\nbgen", n); } @@ -1497,7 +1495,7 @@ sgen(Node *n, Node *res, int64 w) if(osrc < odst && odst < osrc+w) dir = -dir; - if(op == AMOVW && dir > 0 && c >= 4 && c <= 128) { + if(op == AMOVW && !nacl && dir > 0 && c >= 4 && c <= 128) { r0.op = OREGISTER; r0.val.u.reg = REGALLOC_R0; r1.op = OREGISTER; @@ -1524,7 +1522,7 @@ sgen(Node *n, Node *res, int64 w) f = sysfunc("duffcopy"); p = gins(ADUFFCOPY, N, f); afunclit(&p->to, f); - // 8 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s + // 8 and 128 = magic constants: see ../../runtime/asm_arm.s p->to.offset = 8*(128-c); regfree(&tmp); @@ -1636,7 +1634,10 @@ int componentgen(Node *nr, Node *nl) { Node nodl, nodr, tmp; + Type *t; int freel, freer; + vlong fldcount; + vlong loffset, roffset; freel = 0; freer = 0; @@ -1646,8 +1647,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; @@ -1675,6 +1701,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. @@ -1684,8 +1711,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); @@ -1760,6 +1804,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: |