summaryrefslogtreecommitdiff
path: root/src/cmd/6g/cgen.c
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2014-06-19 09:23:02 +0200
committerMichael Stapelberg <stapelberg@debian.org>2014-06-19 09:23:02 +0200
commit8fcc691d6fa80c9ddf38bf0d34b803bab0e421d5 (patch)
treeba71646a10b518372d110532d86fcf0b98edc14f /src/cmd/6g/cgen.c
parent3bb719bbf3cdb97b3901f3baaa2da9d02a5c3cdb (diff)
parent8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 (diff)
downloadgolang-8fcc691d6fa80c9ddf38bf0d34b803bab0e421d5.tar.gz
Merge tag 'upstream/1.3' into debian-sid
Upstream version 1.3
Diffstat (limited to 'src/cmd/6g/cgen.c')
-rw-r--r--src/cmd/6g/cgen.c100
1 files changed, 81 insertions, 19 deletions
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index ada2baa81..4dd505b08 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -247,6 +247,7 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
+ case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
if(a == AIMULB) {
@@ -813,6 +814,7 @@ agen(Node *n, Node *res)
// The generated code is just going to panic, so it need not
// be terribly efficient. See issue 3670.
tempname(&n1, n->type);
+ gvardef(&n1);
clearfat(&n1);
regalloc(&n2, types[tptr], res);
gins(ALEAQ, &n1, &n2);
@@ -1060,6 +1062,12 @@ bgen(Node *n, int true, int likely, Prog *to)
}
nr = N;
+ while(n->op == OCONVNOP) {
+ n = n->left;
+ if(n->ninit != nil)
+ genlist(n->ninit);
+ }
+
switch(n->op) {
default:
def:
@@ -1337,6 +1345,8 @@ sgen(Node *n, Node *ns, int64 w)
{
Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp;
vlong c, q, odst, osrc;
+ NodeList *l;
+ Prog *p;
if(debug['g']) {
print("\nsgen w=%lld\n", w);
@@ -1349,6 +1359,13 @@ sgen(Node *n, Node *ns, int64 w)
if(w < 0)
fatal("sgen copy %lld", w);
+
+ // If copying .args, that's all the results, so record definition sites
+ // for them for the liveness analysis.
+ if(ns->op == ONAME && strcmp(ns->sym->name, ".args") == 0)
+ for(l = curfn->dcl; l != nil; l = l->next)
+ if(l->n->class == PPARAMOUT)
+ gvardef(l->n);
// Avoid taking the address for simple enough types.
if(componentgen(n, ns))
@@ -1380,11 +1397,16 @@ sgen(Node *n, Node *ns, int64 w)
if(n->ullman >= ns->ullman) {
agenr(n, &nodr, N);
+ if(ns->op == ONAME)
+ gvardef(ns);
agenr(ns, &nodl, N);
} else {
+ if(ns->op == ONAME)
+ gvardef(ns);
agenr(ns, &nodl, N);
agenr(n, &nodr, N);
}
+
nodreg(&noddi, types[tptr], D_DI);
nodreg(&nodsi, types[tptr], D_SI);
gmove(&nodl, &noddi);
@@ -1403,23 +1425,23 @@ sgen(Node *n, Node *ns, int64 w)
// reverse direction
gins(ASTD, N, N); // set direction flag
if(c > 0) {
- gconreg(AADDQ, w-1, D_SI);
- gconreg(AADDQ, w-1, D_DI);
+ gconreg(addptr, w-1, D_SI);
+ gconreg(addptr, w-1, D_DI);
- gconreg(AMOVQ, c, D_CX);
+ gconreg(movptr, c, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSB, N, N); // MOVB *(SI)-,*(DI)-
}
if(q > 0) {
if(c > 0) {
- gconreg(AADDQ, -7, D_SI);
- gconreg(AADDQ, -7, D_DI);
+ gconreg(addptr, -7, D_SI);
+ gconreg(addptr, -7, D_DI);
} else {
- gconreg(AADDQ, w-8, D_SI);
- gconreg(AADDQ, w-8, D_DI);
+ gconreg(addptr, w-8, D_SI);
+ gconreg(addptr, w-8, D_DI);
}
- gconreg(AMOVQ, q, D_CX);
+ gconreg(movptr, q, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSQ, N, N); // MOVQ *(SI)-,*(DI)-
}
@@ -1427,23 +1449,48 @@ sgen(Node *n, Node *ns, int64 w)
gins(ACLD, N, N);
} else {
// normal direction
- if(q >= 4) {
- gconreg(AMOVQ, q, D_CX);
+ if(q > 128 || (nacl && q >= 4)) {
+ gconreg(movptr, q, D_CX);
gins(AREP, N, N); // repeat
gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
+ } else if (q >= 4) {
+ p = gins(ADUFFCOPY, N, N);
+ p->to.type = D_ADDR;
+ p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
+ // 14 and 128 = magic constants: see ../../pkg/runtime/asm_amd64.s
+ p->to.offset = 14*(128-q);
} else
while(q > 0) {
gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
q--;
}
-
- if(c >= 4) {
- gins(AMOVSL, N, N); // MOVL *(SI)+,*(DI)+
- c -= 4;
- }
- while(c > 0) {
- gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
- c--;
+ // copy the remaining c bytes
+ if(w < 4 || c <= 1 || (odst < osrc && osrc < odst+w)) {
+ while(c > 0) {
+ gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
+ c--;
+ }
+ } else if(w < 8 || c <= 4) {
+ nodsi.op = OINDREG;
+ noddi.op = OINDREG;
+ nodsi.type = types[TINT32];
+ noddi.type = types[TINT32];
+ if(c > 4) {
+ nodsi.xoffset = 0;
+ noddi.xoffset = 0;
+ gmove(&nodsi, &noddi);
+ }
+ nodsi.xoffset = c-4;
+ noddi.xoffset = c-4;
+ gmove(&nodsi, &noddi);
+ } else {
+ nodsi.op = OINDREG;
+ noddi.op = OINDREG;
+ nodsi.type = types[TINT64];
+ noddi.type = types[TINT64];
+ nodsi.xoffset = c-8;
+ noddi.xoffset = c-8;
+ gmove(&nodsi, &noddi);
}
}
@@ -1513,7 +1560,7 @@ componentgen(Node *nr, Node *nl)
fatal("componentgen: not a TFIELD: %lT", t);
fldcount++;
}
- if(fldcount == 0 || fldcount > 3)
+ if(fldcount == 0 || fldcount > 4)
goto no;
break;
@@ -1538,10 +1585,19 @@ 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.
+ // (And also the assignments are useless.)
+ if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
+ goto yes;
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;
@@ -1591,6 +1647,8 @@ componentgen(Node *nr, Node *nl)
goto yes;
case TSTRING:
+ if(nl->op == ONAME)
+ gvardef(nl);
nodl.xoffset += Array_array;
nodl.type = ptrto(types[TUINT8]);
@@ -1614,6 +1672,8 @@ componentgen(Node *nr, Node *nl)
goto yes;
case TINTER:
+ if(nl->op == ONAME)
+ gvardef(nl);
nodl.xoffset += Array_array;
nodl.type = ptrto(types[TUINT8]);
@@ -1637,6 +1697,8 @@ componentgen(Node *nr, Node *nl)
goto yes;
case TSTRUCT:
+ if(nl->op == ONAME)
+ gvardef(nl);
loffset = nodl.xoffset;
roffset = nodr.xoffset;
// funarg structs may not begin at offset zero.