1
0
mirror of https://github.com/golang/go synced 2024-11-22 00:04:41 -07:00

gc: bug281 - bad overlap in stack copy

Fixes #807.

R=ken2
CC=golang-dev
https://golang.org/cl/1283041
This commit is contained in:
Russ Cox 2010-05-24 16:54:24 -07:00
parent 5c19c4e5e3
commit 9fc9246bf3
4 changed files with 151 additions and 2 deletions

View File

@ -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);

View File

@ -938,11 +938,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:
@ -968,7 +989,7 @@ stkof(Node *n)
void
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;
if(debug['g']) {
@ -989,6 +1010,16 @@ sgen(Node *n, Node *ns, int32 w)
osrc = stkof(n);
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) {
savex(D_SI, &nodr, &oldr, N, types[tptr]);

View File

@ -439,7 +439,6 @@ Prog*
cgenindex(Node *n, Node *res)
{
Node tmp, lo, hi, zero;
Prog *p;
if(!is64(n->type)) {
cgen(n, res);
@ -1043,11 +1042,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:
@ -1093,6 +1113,17 @@ sgen(Node *n, Node *res, int32 w)
// offset on the stack
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(&tsrc, n->type);
sgen(n, &tsrc, w);
sgen(&tsrc, res, w);
return;
}
nodreg(&dst, types[tptr], D_DI);
nodreg(&src, types[tptr], D_SI);

55
test/fixedbugs/bug281.go Normal file
View File

@ -0,0 +1,55 @@
// $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)
}
}