mirror of https://github.com/golang/go.git
cmd/8c: fix store to complex uint64 ptr
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
This commit is contained in:
parent
ae382129f1
commit
30bc5d7bbd
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue