mirror of
https://github.com/golang/go
synced 2024-11-22 01:04:40 -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;
|
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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*
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
// 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);
|
||||||
|
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