summaryrefslogtreecommitdiff
path: root/src/cmd/5g
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-05-29 13:47:31 -0400
committerRuss Cox <rsc@golang.org>2014-05-29 13:47:31 -0400
commitc3a33fa71bb22fc6e1948c97e6ae877adb9c0e29 (patch)
treebf95d7a8ad6837f31d08997204a8a44332933687 /src/cmd/5g
parent112af3545d8afbaf7a95891ea78f94de9d79996d (diff)
downloadgo-c3a33fa71bb22fc6e1948c97e6ae877adb9c0e29.tar.gz
cmd/gc: fix x=x crash
[Same as CL 102820043 except applied changes to 6g/gsubr.c also to 5g/gsubr.c and 8g/gsubr.c. The problem I had last night trying to do that was that 8g's copy of nodarg has different (but equivalent) control flow and I was pasting the new code into the wrong place.] Description from CL 102820043: The 'nodarg' function is used to obtain a Node* representing a function argument or result. It returned a brand new Node*, but that violates the guarantee in most places in the compiler that two Node*s refer to the same variable if and only if they are the same Node* pointer. Reestablish that invariant by making nodarg return a preexisting named variable if present. Having fixed that, avoid any copy during x=x in componentgen, because the VARDEF we emit before the copy marks the lhs x as dead incorrectly. The change in walk.c avoids modifying the result of nodarg. This was the only place in the compiler that did so. Fixes issue 8097. LGTM=khr R=golang-codereviews, khr CC=golang-codereviews, iant, khr, r https://codereview.appspot.com/103750043
Diffstat (limited to 'src/cmd/5g')
-rw-r--r--src/cmd/5g/cgen.c8
-rw-r--r--src/cmd/5g/gsubr.c9
2 files changed, 17 insertions, 0 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 9faf75461..9011b2022 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -1490,6 +1490,7 @@ sgen(Node *n, Node *res, int64 w)
}
if(osrc%align != 0 || odst%align != 0)
fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
+
// if we are copying forward on the stack and
// the src and dst overlap, then reverse direction
dir = align;
@@ -1674,6 +1675,13 @@ 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:
if(nl->op == ONAME)
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 528e8f8cc..f66c87b5a 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -470,6 +470,7 @@ Node*
nodarg(Type *t, int fp)
{
Node *n;
+ NodeList *l;
Type *first;
Iter savet;
@@ -491,6 +492,14 @@ nodarg(Type *t, int fp)
if(t->etype != TFIELD)
fatal("nodarg: not field %T", t);
+ if(fp == 1) {
+ for(l=curfn->dcl; l; l=l->next) {
+ n = l->n;
+ if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
+ return n;
+ }
+ }
+
n = nod(ONAME, N, N);
n->type = t->type;
n->sym = t->sym;