Commit 9fc9246b authored by Russ Cox's avatar Russ Cox

gc: bug281 - bad overlap in stack copy

Fixes #807.

R=ken2
CC=golang-dev
https://golang.org/cl/1283041
parent 5c19c4e5
...@@ -1053,11 +1053,32 @@ stkof(Node *n) ...@@ -1053,11 +1053,32 @@ stkof(Node *n)
{ {
Type *t; Type *t;
Iter flist; Iter flist;
int32 off;
switch(n->op) { switch(n->op) {
case OINDREG: case OINDREG:
return n->xoffset; 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 OCALLMETH:
case OCALLINTER: case OCALLINTER:
case OCALLFUNC: case OCALLFUNC:
...@@ -1106,6 +1127,17 @@ sgen(Node *n, Node *res, int32 w) ...@@ -1106,6 +1127,17 @@ sgen(Node *n, Node *res, int32 w)
osrc = stkof(n); osrc = stkof(n);
odst = stkof(res); 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) if(osrc % 4 != 0 || odst %4 != 0)
fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst); fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst);
......
...@@ -938,11 +938,32 @@ stkof(Node *n) ...@@ -938,11 +938,32 @@ stkof(Node *n)
{ {
Type *t; Type *t;
Iter flist; Iter flist;
int32 off;
switch(n->op) { switch(n->op) {
case OINDREG: case OINDREG:
return n->xoffset; 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 OCALLMETH:
case OCALLINTER: case OCALLINTER:
case OCALLFUNC: case OCALLFUNC:
...@@ -968,7 +989,7 @@ stkof(Node *n) ...@@ -968,7 +989,7 @@ stkof(Node *n)
void void
sgen(Node *n, Node *ns, int32 w) sgen(Node *n, Node *ns, int32 w)
{ {
Node nodl, nodr, oldl, oldr, cx, oldcx; Node nodl, nodr, oldl, oldr, cx, oldcx, tmp;
int32 c, q, odst, osrc; int32 c, q, odst, osrc;
if(debug['g']) { if(debug['g']) {
...@@ -989,6 +1010,16 @@ sgen(Node *n, Node *ns, int32 w) ...@@ -989,6 +1010,16 @@ sgen(Node *n, Node *ns, int32 w)
osrc = stkof(n); osrc = stkof(n);
odst = stkof(ns); odst = stkof(ns);
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, ns, w);
return;
}
if(n->ullman >= ns->ullman) { if(n->ullman >= ns->ullman) {
savex(D_SI, &nodr, &oldr, N, types[tptr]); savex(D_SI, &nodr, &oldr, N, types[tptr]);
......
...@@ -439,7 +439,6 @@ Prog* ...@@ -439,7 +439,6 @@ Prog*
cgenindex(Node *n, Node *res) cgenindex(Node *n, Node *res)
{ {
Node tmp, lo, hi, zero; Node tmp, lo, hi, zero;
Prog *p;
if(!is64(n->type)) { if(!is64(n->type)) {
cgen(n, res); cgen(n, res);
...@@ -1043,11 +1042,32 @@ stkof(Node *n) ...@@ -1043,11 +1042,32 @@ stkof(Node *n)
{ {
Type *t; Type *t;
Iter flist; Iter flist;
int32 off;
switch(n->op) { switch(n->op) {
case OINDREG: case OINDREG:
return n->xoffset; 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 OCALLMETH:
case OCALLINTER: case OCALLINTER:
case OCALLFUNC: case OCALLFUNC:
...@@ -1093,6 +1113,17 @@ sgen(Node *n, Node *res, int32 w) ...@@ -1093,6 +1113,17 @@ sgen(Node *n, Node *res, int32 w)
// offset on the stack // offset on the stack
osrc = stkof(n); osrc = stkof(n);
odst = stkof(res); 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(&tsrc, n->type);
sgen(n, &tsrc, w);
sgen(&tsrc, res, w);
return;
}
nodreg(&dst, types[tptr], D_DI); nodreg(&dst, types[tptr], D_DI);
nodreg(&src, types[tptr], D_SI); nodreg(&src, types[tptr], D_SI);
......
// $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// http://code.google.com/p/go/issues/detail?id=807
package main
type Point struct {
X, Y int64
}
type Rect struct {
Min, Max Point
}
func (p Point) Sub(q Point) Point {
return Point{p.X-q.X, p.Y-q.Y}
}
type Obj struct {
bbox Rect
}
func (o *Obj) Bbox() Rect {
return o.bbox
}
func (o *Obj) Points() [2]Point{
return [2]Point{o.bbox.Min, o.bbox.Max}
}
var x = 0
func main() {
o := &Obj{Rect{Point{800, 0}, Point{}}}
p := Point{800, 300}
q := p.Sub(o.Bbox().Min)
if q.X != 0 || q.Y != 300 {
println("BUG dot: ", q.X, q.Y)
return
}
q = p.Sub(o.Points()[0])
if q.X != 0 || q.Y != 300 {
println("BUG index const: ", q.X, q.Y)
}
q = p.Sub(o.Points()[x])
if q.X != 0 || q.Y != 300 {
println("BUG index var: ", q.X, q.Y)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment