mirror of
https://github.com/golang/go
synced 2024-11-21 18:24:46 -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:
parent
5c19c4e5e3
commit
9fc9246bf3
@ -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);
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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
55
test/fixedbugs/bug281.go
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user