{
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:
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);
{
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:
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']) {
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]);
cgenindex(Node *n, Node *res)
{
Node tmp, lo, hi, zero;
- Prog *p;
if(!is64(n->type)) {
cgen(n, res);
{
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:
// 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);
--- /dev/null
+// $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)
+ }
+}