diff options
author | Russ Cox <rsc@golang.org> | 2014-05-29 13:47:31 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-05-29 13:47:31 -0400 |
commit | c3a33fa71bb22fc6e1948c97e6ae877adb9c0e29 (patch) | |
tree | bf95d7a8ad6837f31d08997204a8a44332933687 /src/cmd/8g | |
parent | 112af3545d8afbaf7a95891ea78f94de9d79996d (diff) | |
download | go-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/8g')
-rw-r--r-- | src/cmd/8g/cgen.c | 7 | ||||
-rw-r--r-- | src/cmd/8g/gsubr.c | 9 |
2 files changed, 16 insertions, 0 deletions
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index 1aae7771c..d626c2eb0 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -1397,6 +1397,13 @@ componentgen(Node *nr, Node *nl) } } + // 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/8g/gsubr.c b/src/cmd/8g/gsubr.c index e83ae5d7a..2f3cb28c8 100644 --- a/src/cmd/8g/gsubr.c +++ b/src/cmd/8g/gsubr.c @@ -1044,6 +1044,7 @@ Node* nodarg(Type *t, int fp) { Node *n; + NodeList *l; Type *first; Iter savet; @@ -1068,6 +1069,14 @@ nodarg(Type *t, int fp) break; case TFIELD: + if(fp == 1 && t->sym != S && !isblanksym(t->sym)) { + for(l=curfn->dcl; l; l=l->next) { + n = l->n; + if((n->class == PPARAM || n->class == PPARAMOUT) && n->sym == t->sym) + return n; + } + } + n = nod(ONAME, N, N); n->type = t->type; n->sym = t->sym; |