]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/8c: fix store to complex uint64 ptr
authorRuss Cox <rsc@golang.org>
Tue, 10 Apr 2012 14:45:58 +0000 (10:45 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 10 Apr 2012 14:45:58 +0000 (10:45 -0400)
Assignment of a computed uint64 value to an
address derived with a function call was executing
the call after computing the value, which trashed
the value (held in registers).

long long *f(void) { return 0; }
void g(int x, int y) {
        *f() = (long long)x | (long long)y<<32;
}

Before:

(x.c:3) TEXT g+0(SB),(gok(71))
...
(x.c:4) ORL AX,DX
(x.c:4) ORL CX,BX
(x.c:4) CALL ,f+0(SB)
(x.c:4) MOVL DX,(AX)
(x.c:4) MOVL BX,4(AX)

After:
(x.c:3) TEXT g+0(SB),(gok(71))
(x.c:4) CALL ,f+0(SB)
...
(x.c:4) ORL CX,BX
(x.c:4) ORL DX,BP
(x.c:4) MOVL BX,(AX)
(x.c:4) MOVL BP,4(AX)

Fixes #3501.

R=ken2
CC=golang-dev
https://golang.org/cl/5998043

src/cmd/8c/cgen64.c

index 3424f762c53a817e964e3a3db073bc5088d858b9..21619b89306a73c3c8ff5cc2c7f3e784110a8ab5 100644 (file)
@@ -1601,6 +1601,33 @@ cgen64(Node *n, Node *nn)
                prtree(n, "cgen64");
                print("AX = %d\n", reg[D_AX]);
        }
+
+       if(nn != Z && nn->complex >= FNX) {
+               // Evaluate nn address to register
+               // before we use registers for n.
+               // Otherwise the call during computation of nn
+               // will smash the registers.  See
+               // http://golang.org/issue/3501.
+
+               // If both n and nn want calls, refuse to compile.
+               if(n != Z && n->complex >= FNX)
+                       diag(n, "cgen64 miscompile");
+
+               reglcgen(&nod1, nn, Z);
+               m = cgen64(n, &nod1);
+               regfree(&nod1);
+               
+               if(m == 0) {
+                       // Now what?  We computed &nn, which involved a
+                       // function call, and didn't use it.  The caller will recompute nn,
+                       // calling the function a second time.
+                       // We can figure out what to do later, if this actually happens.
+                       diag(n, "cgen64 miscompile");
+               }
+
+               return m;
+       }
+
        cmp = 0;
        sh = 0;