diff options
author | Russ Cox <rsc@golang.org> | 2010-05-24 16:54:24 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2010-05-24 16:54:24 -0700 |
commit | 3574911597e5f2aec3e8efa653d361eb6d500fec (patch) | |
tree | 8c2bfc47fbce61b2edf121fdc1c11809087ec58e /src/cmd/5g/cgen.c | |
parent | efe2fcc938b0b1a852117e3c2ffb0aa130e6a514 (diff) | |
download | golang-3574911597e5f2aec3e8efa653d361eb6d500fec.tar.gz |
gc: bug281 - bad overlap in stack copy
Fixes issue 807.
R=ken2
CC=golang-dev
http://codereview.appspot.com/1283041
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r-- | src/cmd/5g/cgen.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index cf701a50a..8072c3ceb 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -1053,11 +1053,32 @@ stkof(Node *n) { Type *t; Iter flist; + int32 off; switch(n->op) { case OINDREG: return n->xoffset; + case ODOT: + t = n->left->type; + if(isptr[t->etype]) + break; + off = stkof(n->left); + if(off == -1000 || off == 1000) + return off; + return off + n->xoffset; + + case OINDEX: + t = n->left->type; + if(!isfixedarray(t)) + break; + off = stkof(n->left); + if(off == -1000 || off == 1000) + return off; + if(isconst(n->right, CTINT)) + return off + t->type->width * mpgetfix(n->right->val.u.xval); + return 1000; + case OCALLMETH: case OCALLINTER: case OCALLFUNC: @@ -1106,6 +1127,17 @@ sgen(Node *n, Node *res, int32 w) osrc = stkof(n); odst = stkof(res); + if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) { + // osrc and odst both on stack, and at least one is in + // an unknown position. Could generate code to test + // for forward/backward copy, but instead just copy + // to a temporary location first. + tempname(&tmp, n->type); + sgen(n, &tmp, w); + sgen(&tmp, res, w); + return; + } + if(osrc % 4 != 0 || odst %4 != 0) fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst); |