summaryrefslogtreecommitdiff
path: root/src/cmd/5g/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r--src/cmd/5g/cgen.c81
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: