]> Cypherpunks repositories - gostls13.git/commitdiff
fix bug206.
authorRuss Cox <rsc@golang.org>
Fri, 11 Sep 2009 00:33:01 +0000 (17:33 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 11 Sep 2009 00:33:01 +0000 (17:33 -0700)
delay calls to savex as long as possible.

R=ken
OCL=34535
CL=34546

src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
test/fixedbugs/bug206.go [moved from test/bugs/bug206.go with 100% similarity]
test/golden.out

index 0b01ada3d6fb2fab2b1f28f51bb1f8e8d6681620..5cceefd8f98d0554cbc2e90e3904262b0c0f47df 100644 (file)
@@ -898,7 +898,7 @@ stkof(Node *n)
 void
 sgen(Node *n, Node *ns, int32 w)
 {
-       Node nodl, nodr;
+       Node nodl, nodr, oldl, oldr, cx, oldcx;
        int32 c, q, odst, osrc;
 
        if(debug['g']) {
@@ -919,20 +919,30 @@ sgen(Node *n, Node *ns, int32 w)
        osrc = stkof(n);
        odst = stkof(ns);
 
-       nodreg(&nodl, types[tptr], D_DI);
-       nodreg(&nodr, types[tptr], D_SI);
 
        if(n->ullman >= ns->ullman) {
+               savex(D_SI, &nodr, &oldr, N, types[tptr]);
                agen(n, &nodr);
+
+               regalloc(&nodr, types[tptr], &nodr);    // mark nodr as live
+               savex(D_DI, &nodl, &oldl, N, types[tptr]);
                agen(ns, &nodl);
+               regfree(&nodr);
        } else {
+               savex(D_DI, &nodl, &oldl, N, types[tptr]);
                agen(ns, &nodl);
+
+               regalloc(&nodl, types[tptr], &nodl);    // mark nodl as live
+               savex(D_SI, &nodr, &oldr, N, types[tptr]);
                agen(n, &nodr);
+               regfree(&nodl);
        }
 
        c = w % 8;      // bytes
        q = w / 8;      // quads
 
+       savex(D_CX, &cx, &oldcx, N, types[TINT64]);
+
        // if we are copying forward on the stack and
        // the src and dst overlap, then reverse direction
        if(osrc < odst && odst < osrc+w) {
@@ -982,4 +992,9 @@ sgen(Node *n, Node *ns, int32 w)
                        c--;
                }
        }
+
+
+       restx(&nodl, &oldl);
+       restx(&nodr, &oldr);
+       restx(&cx, &oldcx);
 }
index 388a1069a7a4ab83612567178d8106abffe993c6..75f6c7918b5648017cfd2329b355655dfb600f9f 100644 (file)
@@ -95,6 +95,8 @@ int   samaddr(Node*, Node*);
 void   naddr(Node*, Addr*);
 void   cgen_aret(Node*, Node*);
 int    cgen_inline(Node*, Node*);
+void   restx(Node*, Node*);
+void   savex(int, Node*, Node*, Node*, Type*);
 
 /*
  * gsubr.c
index e94b3e5fdb25583de0ff82c0f55d37ecc8d2d076..ba6199f6db90d4a5d84c196e817b04b1fbd46cf0 100644 (file)
@@ -461,6 +461,8 @@ ret:
 int
 samereg(Node *a, Node *b)
 {
+       if(a == N || b == N)
+               return 0;
        if(a->op != OREGISTER)
                return 0;
        if(b->op != OREGISTER)
@@ -481,11 +483,12 @@ samereg(Node *a, Node *b)
  * according to op.
  */
 void
-dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
+dodiv(int op, Node *nl, Node *nr, Node *res)
 {
        int a;
        Node n3, n4;
        Type *t;
+       Node ax, dx, oldax, olddx;
 
        t = nl->type;
        if(t->width == 1) {
@@ -495,62 +498,73 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
                        t = types[TUINT32];
        }
        a = optoas(op, t);
-       ax->type = t;
-       dx->type = t;
 
        regalloc(&n3, t, N);
        if(nl->ullman >= nr->ullman) {
-               cgen(nl, ax);
-               if(!issigned[t->etype]) {
-                       nodconst(&n4, t, 0);
-                       gmove(&n4, dx);
-               } else
-                       gins(optoas(OEXTEND, t), N, N);
+               savex(D_AX, &ax, &oldax, res, t);
+               cgen(nl, &ax);
+               regalloc(&ax, t, &ax);  // mark ax live during cgen
                cgen(nr, &n3);
+               regfree(&ax);
        } else {
                cgen(nr, &n3);
-               cgen(nl, ax);
-               if(!issigned[t->etype]) {
-                       nodconst(&n4, t, 0);
-                       gmove(&n4, dx);
-               } else
-                       gins(optoas(OEXTEND, t), N, N);
+               savex(D_AX, &ax, &oldax, res, t);
+               cgen(nl, &ax);
        }
+       savex(D_DX, &dx, &olddx, res, t);
+       if(!issigned[t->etype]) {
+               nodconst(&n4, t, 0);
+               gmove(&n4, &dx);
+       } else
+               gins(optoas(OEXTEND, t), N, N);
        gins(a, &n3, N);
        regfree(&n3);
 
        if(op == ODIV)
-               gmove(ax, res);
+               gmove(&ax, res);
        else
-               gmove(dx, res);
+               gmove(&dx, res);
+       restx(&ax, &oldax);
+       restx(&dx, &olddx);
 }
 
-static void
+/*
+ * register dr is one of the special ones (AX, CX, DI, SI, etc.).
+ * we need to use it.  if it is already allocated as a temporary
+ * (r > 1; can only happen if a routine like sgen passed a
+ * special as cgen's res and then cgen used regalloc to reuse
+ * it as its own temporary), then move it for now to another
+ * register.  caller must call restx to move it back.
+ * the move is not necessary if dr == res, because res is
+ * known to be dead.
+ */
+void
 savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
 {
        int r;
 
        r = reg[dr];
-       nodreg(x, types[TINT64], dr);
 
        // save current ax and dx if they are live
        // and not the destination
        memset(oldx, 0, sizeof *oldx);
-       if(r > 0 && !samereg(x, res)) {
+       nodreg(x, t, dr);
+       if(r > 1 && !samereg(x, res)) {
                regalloc(oldx, types[TINT64], N);
+               x->type = types[TINT64];
                gmove(x, oldx);
+               x->type = t;
+               oldx->ostk = r; // squirrel away old r value
+               reg[dr] = 1;
        }
-
-       regalloc(x, t, x);
 }
 
-static void
+void
 restx(Node *x, Node *oldx)
 {
-       regfree(x);
-
        if(oldx->op != 0) {
                x->type = types[TINT64];
+               reg[x->val.u.reg] = oldx->ostk;
                gmove(oldx, x);
                regfree(oldx);
        }
@@ -564,8 +578,8 @@ restx(Node *x, Node *oldx)
 void
 cgen_div(int op, Node *nl, Node *nr, Node *res)
 {
-       Node ax, dx, oldax, olddx;
        Node n1, n2, n3, savl, savr;
+       Node ax, dx, oldax, olddx;
        int n, w, s, a;
        Magic m;
 
@@ -701,12 +715,12 @@ divbymul:
                if(op == OMOD)
                        goto longmod;
 
-               savex(D_AX, &ax, &oldax, res, nl->type);
-               savex(D_DX, &dx, &olddx, res, nl->type);
-
                regalloc(&n1, nl->type, N);
                cgen(nl, &n1);                          // num -> reg(n1)
 
+               savex(D_AX, &ax, &oldax, res, nl->type);
+               savex(D_DX, &dx, &olddx, res, nl->type);
+
                nodconst(&n2, nl->type, m.um);
                gmove(&n2, &ax);                        // const->ax
 
@@ -751,12 +765,12 @@ divbymul:
                if(op == OMOD)
                        goto longmod;
 
-               savex(D_AX, &ax, &oldax, res, nl->type);
-               savex(D_DX, &dx, &olddx, res, nl->type);
-
                regalloc(&n1, nl->type, N);
                cgen(nl, &n1);                          // num -> reg(n1)
 
+               savex(D_AX, &ax, &oldax, res, nl->type);
+               savex(D_DX, &dx, &olddx, res, nl->type);
+
                nodconst(&n2, nl->type, m.sm);
                gmove(&n2, &ax);                        // const->ax
 
@@ -798,11 +812,7 @@ divbymul:
 
 longdiv:
        // division and mod using (slow) hardware instruction
-       savex(D_AX, &ax, &oldax, res, nl->type);
-       savex(D_DX, &dx, &olddx, res, nl->type);
-       dodiv(op, nl, nr, res, &ax, &dx);
-       restx(&ax, &oldax);
-       restx(&dx, &olddx);
+       dodiv(op, nl, nr, res);
        return;
 
 longmod:
@@ -979,7 +989,7 @@ void
 clearfat(Node *nl)
 {
        uint32 w, c, q;
-       Node n1;
+       Node n1, oldn1, ax, oldax;
 
        /* clear a fat object */
        if(debug['g'])
@@ -989,10 +999,12 @@ clearfat(Node *nl)
        c = w % 8;      // bytes
        q = w / 8;      // quads
 
-       gconreg(AMOVQ, 0, D_AX);
-       nodreg(&n1, types[tptr], D_DI);
+       savex(D_DI, &n1, &oldn1, N, types[tptr]);
        agen(nl, &n1);
 
+       savex(D_AX, &ax, &oldax, N, types[tptr]);
+       gconreg(AMOVQ, 0, D_AX);
+
        if(q >= 4) {
                gconreg(AMOVQ, q, D_CX);
                gins(AREP, N, N);       // repeat
@@ -1012,6 +1024,9 @@ clearfat(Node *nl)
                gins(ASTOSB, N, N);     // STOB AL,*(DI)+
                c--;
        }
+
+       restx(&n1, &oldn1);
+       restx(&ax, &oldax);
 }
 
 int
index e2fdceff48877f1e523a3249aeee2b7e3e293ec5..8358abf16bdedde705c7212a6ea5abcfc652d417 100644 (file)
@@ -192,8 +192,8 @@ afunclit(Addr *a)
 
 static int     resvd[] =
 {
-//     D_DI,   // for movstring
-//     D_SI,   // for movstring
+       D_DI,   // for movstring
+       D_SI,   // for movstring
 
        D_AX,   // for divide
        D_CX,   // for shift
similarity index 100%
rename from test/bugs/bug206.go
rename to test/fixedbugs/bug206.go
index f9bdb783786ce3d13e5afd7178f4f3554f198ad6..148471660a041261eb3748b2023113a1330160a4 100644 (file)
@@ -174,6 +174,3 @@ bugs/bug198.go:8: T is not a type
 bugs/bug198.go:8: too many arguments to return
 bugs/bug198.go:10: too many arguments to CALL
 BUG: errchk: compiler crashed
-
-=========== bugs/bug206.go
-BUG: bug206