complexmove(Node *f, Node *t)
{
int ft, tt;
- Node n1, n2, n3, n4;
+ Node n1, n2, n3, n4, t3, t4;
if(debug['g']) {
dump("\ncomplexmove-f", f);
subnode(&n1, &n2, f);
subnode(&n3, &n4, t);
- cgen(&n1, &n3);
- cgen(&n2, &n4);
+ // Copy fully into registers before doing stores,
+ // in case the source and destination overlap.
+ // Might be picking up a complex128 from one
+ // location on the stack and writing it 8 bytes
+ // (half a complex128) later, in which case the
+ // first write would smash the source for the second read.
+ regalloc(&t3, types[tt+TFLOAT64-TCOMPLEX128], N);
+ regalloc(&t4, types[tt+TFLOAT64-TCOMPLEX128], N);
+ cgen(&n1, &t3);
+ cgen(&n2, &t4);
+
+ cgen(&t3, &n3);
+ cgen(&t4, &n4);
+ regfree(&t3);
+ regfree(&t4);
break;
}
}
--- /dev/null
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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.
+
+// Test that when moving a complex128 returned by one function
+// into the argument position for another function, the right thing
+// happens, even when the two positions half-overlap.
+
+package main
+
+type Value struct {
+ X interface{}
+ Y int
+}
+
+type Struct struct {
+ X complex128
+}
+
+const magic = 1+2i
+
+func (Value) Complex(x complex128) {
+ if x != magic {
+ println(x)
+ panic("bad complex magic")
+ }
+}
+
+func f(x *byte, y, z int) complex128 {
+ return magic
+}
+
+func (Value) Struct(x Struct) {
+ if x.X != magic {
+ println(x.X)
+ panic("bad struct magic")
+ }
+}
+
+func f1(x *byte, y, z int) Struct {
+ return Struct{magic}
+}
+
+func main() {
+ var v Value
+ v.Struct(f1(nil, 0, 0)) // ok
+ v.Complex(f(nil, 0, 0)) // used to fail
+}