diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2014-06-19 09:23:02 +0200 |
---|---|---|
committer | Michael Stapelberg <stapelberg@debian.org> | 2014-06-19 09:23:02 +0200 |
commit | 8fcc691d6fa80c9ddf38bf0d34b803bab0e421d5 (patch) | |
tree | ba71646a10b518372d110532d86fcf0b98edc14f /src/cmd/6g/cgen.c | |
parent | 3bb719bbf3cdb97b3901f3baaa2da9d02a5c3cdb (diff) | |
parent | 8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 (diff) | |
download | golang-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.c | 100 |
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. |