summaryrefslogtreecommitdiff
path: root/src/cmd/6g
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-02-15 10:58:55 -0500
committerRuss Cox <rsc@golang.org>2014-02-15 10:58:55 -0500
commit2efa8cf2ee4df13201b7038c07c439a0c9dfae16 (patch)
tree700e5edd9ff95dcc7e214100432f8a35675ed277 /src/cmd/6g
parentd5bec7f3a722f435e04fb6d66c68b400742a15b6 (diff)
downloadgo-2efa8cf2ee4df13201b7038c07c439a0c9dfae16.tar.gz
cmd/gc: correct liveness for fat variables
The VARDEF placement must be before the initialization but after any final use. If you have something like s = ... using s ... the rhs must be evaluated, then the VARDEF, then the lhs assigned. There is a large comment in pgen.c on gvardef explaining this in more detail. This CL also includes Ian's suggestions from earlier CLs, namely commenting the use of mode in link.h and fixing the precedence of the ~r check in dcl.c. This CL enables the check that if liveness analysis decides a variable is live on entry to the function, that variable must be a function parameter (not a result, and not a local variable). If this check fails, it indicates a bug in the liveness analysis or in the generated code being analyzed. The race detector generates invalid code for append(x, y...). The code declares a temporary t and then uses cap(t) before initializing t. The new liveness check catches this bug and stops the compiler from writing out the buggy code. Consequently, this CL disables the race detector tests in run.bash until the race detector bug can be fixed (golang.org/issue/7334). Except for the race detector bug, the liveness analysis check does not detect any problems (this CL and the previous CLs fixed all the detected problems). The net test still fails with GOGC=0 but the rest of the tests now pass or time out (because GOGC=0 is so slow). TBR=iant CC=golang-codereviews https://codereview.appspot.com/64170043
Diffstat (limited to 'src/cmd/6g')
-rw-r--r--src/cmd/6g/cgen.c18
-rw-r--r--src/cmd/6g/ggen.c18
-rw-r--r--src/cmd/6g/peep.c4
-rw-r--r--src/cmd/6g/reg.c2
4 files changed, 33 insertions, 9 deletions
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 05cdf54af..5afa25e40 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -813,6 +813,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);
@@ -1351,10 +1352,6 @@ sgen(Node *n, Node *ns, int64 w)
if(w < 0)
fatal("sgen copy %lld", w);
- // Record site of definition of ns for liveness analysis.
- if(ns->op == ONAME && ns->class != PEXTERN)
- gvardef(ns);
-
// 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)
@@ -1392,11 +1389,16 @@ sgen(Node *n, Node *ns, int64 w)
if(n->ullman >= ns->ullman) {
agenr(n, &nodr, N);
+ if(ns->op == ONAME && ns->class != PEXTERN)
+ gvardef(ns);
agenr(ns, &nodl, N);
} else {
+ if(ns->op == ONAME && ns->class != PEXTERN)
+ 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);
@@ -1573,6 +1575,8 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) {
case TARRAY:
// componentgen for arrays.
+ if(nl->op == ONAME && nl->class != PEXTERN)
+ gvardef(nl);
t = nl->type;
if(!isslice(t)) {
nodl.type = t->type;
@@ -1622,6 +1626,8 @@ componentgen(Node *nr, Node *nl)
goto yes;
case TSTRING:
+ if(nl->op == ONAME && nl->class != PEXTERN)
+ gvardef(nl);
nodl.xoffset += Array_array;
nodl.type = ptrto(types[TUINT8]);
@@ -1645,6 +1651,8 @@ componentgen(Node *nr, Node *nl)
goto yes;
case TINTER:
+ if(nl->op == ONAME && nl->class != PEXTERN)
+ gvardef(nl);
nodl.xoffset += Array_array;
nodl.type = ptrto(types[TUINT8]);
@@ -1668,6 +1676,8 @@ componentgen(Node *nr, Node *nl)
goto yes;
case TSTRUCT:
+ if(nl->op == ONAME && nl->class != PEXTERN)
+ gvardef(nl);
loffset = nodl.xoffset;
roffset = nodr.xoffset;
// funarg structs may not begin at offset zero.
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 7d0190022..b5c28bb08 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -60,13 +60,13 @@ void
markautoused(Prog* p)
{
for (; p; p = p->link) {
- if (p->as == ATYPE)
+ if (p->as == ATYPE || p->as == AVARDEF)
continue;
- if (p->from.type == D_AUTO && p->from.node)
+ if (p->from.node)
p->from.node->used = 1;
- if (p->to.type == D_AUTO && p->to.node)
+ if (p->to.node)
p->to.node->used = 1;
}
}
@@ -82,6 +82,16 @@ fixautoused(Prog *p)
*lp = p->link;
continue;
}
+ if (p->as == AVARDEF && p->to.node && !p->to.node->used) {
+ // Cannot remove VARDEF instruction, because - unlike TYPE handled above -
+ // VARDEFs are interspersed with other code, and a jump might be using the
+ // VARDEF as a target. Replace with a no-op instead. A later pass will remove
+ // the no-ops.
+ p->to.type = D_NONE;
+ p->to.node = N;
+ p->as = ANOP;
+ continue;
+ }
if (p->from.type == D_AUTO && p->from.node)
p->from.offset += p->from.node->stkdelta;
@@ -1023,8 +1033,6 @@ clearfat(Node *nl)
if(debug['g'])
dump("\nclearfat", nl);
- gvardef(nl);
-
w = nl->type->width;
// Avoid taking the address for simple enough types.
if(componentgen(N, nl))
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c
index dd3bc0590..99ce3a704 100644
--- a/src/cmd/6g/peep.c
+++ b/src/cmd/6g/peep.c
@@ -573,6 +573,8 @@ subprop(Flow *r0)
break;
}
p = r->prog;
+ if(p->as == AVARDEF)
+ continue;
proginfo(&info, p);
if(info.flags & Call) {
if(debug['P'] && debug['v'])
@@ -788,6 +790,8 @@ copyu(Prog *p, Adr *v, Adr *s)
return 0;
}
+ if(p->as == AVARDEF)
+ return 0;
proginfo(&info, p);
if((info.reguse|info.regset) & RtoB(v->type))
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index 2d8fe81b8..45bc4a267 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -195,6 +195,8 @@ regopt(Prog *firstp)
for(r = firstr; r != R; r = (Reg*)r->f.link) {
p = r->f.prog;
+ if(p->as == AVARDEF)
+ continue;
proginfo(&info, p);
// Avoid making variables for direct-called functions.