]> Cypherpunks repositories - gostls13.git/commitdiff
get function calls out of the way before
authorRuss Cox <rsc@golang.org>
Wed, 5 Aug 2009 02:16:57 +0000 (19:16 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 5 Aug 2009 02:16:57 +0000 (19:16 -0700)
allocating registers in shift and div.

fix behavior when res == a reserved register.

R=ken
OCL=32765
CL=32767

src/cmd/6g/ggen.c
src/pkg/time/time_test.go
test/fixedbugs/bug180.go [new file with mode: 0644]

index f51839f49b2fa599598a13a2ecd535cae8cf4ad4..63dbd68354b9176234e3f7a291c12482fe881763 100644 (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);
index 41e6736e8360a431d6f8ef6cc1f1b577661e1cb2..2457d8561ada638d055c61f46c09bb17d0a1fac0 100644 (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);
                }
        }
 }
diff --git a/test/fixedbugs/bug180.go b/test/fixedbugs/bug180.go
new file mode 100644 (file)
index 0000000..e293448
--- /dev/null
@@ -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);
+       }
+}