get function calls out of the way before

allocating registers in shift and div.

fix behavior when res == a reserved register.

R=ken
OCL=32765
CL=32767
This commit is contained in:
Russ Cox 2009-08-04 19:16:57 -07:00
parent aa347c4a0d
commit 4dec8ef35a
3 changed files with 68 additions and 15 deletions

View file

@ -534,28 +534,37 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
void
cgen_div(int op, Node *nl, Node *nr, Node *res)
{
Node ax, dx, oldax, olddx;
Node ax, dx, oldax, olddx, n1, n2;
int rax, rdx;
if(nl->ullman >= UINF || nr->ullman >= UINF)
fatal("cgen_div UINF");
if(nl->ullman >= UINF) {
tempname(&n1, nl->type);
cgen(nl, &n1);
nl = &n1;
}
if(nr->ullman >= UINF) {
tempname(&n2, nr->type);
cgen(nr, &n2);
nr = &n2;
}
rax = reg[D_AX];
rdx = reg[D_DX];
nodreg(&ax, types[TINT64], D_AX);
nodreg(&dx, types[TINT64], D_DX);
regalloc(&ax, nl->type, &ax);
regalloc(&dx, nl->type, &dx);
// save current ax and dx if they are live
// and not the destination
memset(&oldax, 0, sizeof oldax);
memset(&olddx, 0, sizeof olddx);
if(rax > 0) {
if(rax > 0 && !samereg(&ax, res)) {
regalloc(&oldax, nl->type, N);
gmove(&ax, &oldax);
}
if(rdx > 0) {
if(rdx > 0 && !samereg(&dx, res)) {
regalloc(&olddx, nl->type, N);
gmove(&dx, &olddx);
}
@ -565,11 +574,11 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
regfree(&ax);
regfree(&dx);
if(rax > 0) {
if(oldax.op != 0) {
gmove(&oldax, &ax);
regfree(&oldax);
}
if(rdx > 0) {
if(olddx.op != 0) {
gmove(&olddx, &dx);
regfree(&olddx);
}
@ -584,8 +593,8 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
void
cgen_shift(int op, Node *nl, Node *nr, Node *res)
{
Node n1, n2, n3;
int a;
Node n1, n2, n3, n4, n5, cx, oldcx;
int a, rcx;
Prog *p1;
uvlong sc;
@ -607,11 +616,33 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
goto ret;
}
if(nl->ullman >= UINF) {
tempname(&n4, nl->type);
cgen(nl, &n4);
nl = &n4;
}
if(nr->ullman >= UINF) {
tempname(&n5, nr->type);
cgen(nr, &n5);
nr = &n5;
}
rcx = reg[D_CX];
nodreg(&n1, types[TUINT32], D_CX);
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
regalloc(&n3, types[TUINT64], &n1); // to clear high bits of CX
regalloc(&n2, nl->type, res);
nodreg(&cx, types[TUINT64], D_CX);
memset(&oldcx, 0, sizeof oldcx);
if(rcx > 0 && !samereg(&cx, res)) {
regalloc(&oldcx, types[TUINT64], N);
gmove(&cx, &oldcx);
}
if(samereg(&cx, res))
regalloc(&n2, nl->type, N);
else
regalloc(&n2, nl->type, res);
if(nl->ullman >= nr->ullman) {
cgen(nl, &n2);
cgen(nr, &n1);
@ -637,6 +668,11 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
patch(p1, pc);
gins(a, &n1, &n2);
if(oldcx.op != 0) {
gmove(&oldcx, &cx);
regfree(&oldcx);
}
gmove(&n2, res);
regfree(&n1);

View file

@ -60,8 +60,8 @@ func TestSecondsToUTC(t *testing.T) {
}
if !same(tm, golden) {
t.Errorf("SecondsToUTC(%d):", sec);
t.Errorf(" want=%v", *golden);
t.Errorf(" have=%v", *tm);
t.Errorf(" want=%+v", *golden);
t.Errorf(" have=%+v", *tm);
}
}
}
@ -77,8 +77,8 @@ func TestSecondsToLocalTime(t *testing.T) {
}
if !same(tm, golden) {
t.Errorf("SecondsToLocalTime(%d):", sec);
t.Errorf(" want=%v", *golden);
t.Errorf(" have=%v", *tm);
t.Errorf(" want=%+v", *golden);
t.Errorf(" have=%+v", *tm);
}
}
}

17
test/fixedbugs/bug180.go Normal file
View file

@ -0,0 +1,17 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 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.
package main
func shift(x int) int {
return 1<<(1<<(1<<(uint(x))));
}
func main() {
if n := shift(2); n != 1<<(1<<(1<<2)) {
panicln("bad shift", n);
}
}