]> Cypherpunks repositories - gostls13.git/commitdiff
fix fat copy of overlapping data
authorKen Thompson <ken@golang.org>
Fri, 22 Aug 2008 03:49:04 +0000 (20:49 -0700)
committerKen Thompson <ken@golang.org>
Fri, 22 Aug 2008 03:49:04 +0000 (20:49 -0700)
R=r
OCL=14417
CL=14417

src/cmd/6g/cgen.c
src/cmd/gc/go.y

index bbd904d499300c4be0f02e59b8f26003074e0f82..b4ae1dfb92889da24a56954373ac93ae34229143 100644 (file)
@@ -282,13 +282,6 @@ agen(Node *n, Node *res)
                fatal("agen: unknown op %N", n);
                break;
 
-//     case ONAME:
-//             regalloc(&n1, types[tptr], res);
-//             gins(optoas(OADDR, types[tptr]), n, &n1);
-//             gmove(&n1, res);
-//             regfree(&n1);
-//             break;
-
        case OCALLMETH:
                cgen_callmeth(n, 0);
                cgen_aret(n, res);
@@ -330,8 +323,6 @@ agen(Node *n, Node *res)
                agen_inter(n, res);
                break;
 
-//     case OINDREG:
-
        case OINDEX:
                w = n->type->width;
                if(nr->addable)
@@ -585,11 +576,27 @@ ret:
        ;
 }
 
+int32
+stkof(Node *n)
+{
+       switch(n->op) {
+       case OS2I:
+               return 2*widthptr;
+       case OI2I:
+               return 1*widthptr;
+       case OINDREG:
+               return n->xoffset;
+       }
+       // botch - probably failing to recognize address
+       // arithmetic on the above. eg INDEX and DOT
+       return -1;
+}
+
 void
 sgen(Node *n, Node *ns, uint32 w)
 {
        Node nodl, nodr;
-       int32 c;
+       int32 c, q, odst, osrc;
 
        if(debug['g']) {
                dump("\nsgen-res", ns);
@@ -601,6 +608,14 @@ sgen(Node *n, Node *ns, uint32 w)
                fatal("sgen UINF");
        }
 
+       // offset on the stack
+       odst = stkof(ns);
+       osrc = stkof(n);
+       if(osrc < 0)
+               odst = odst;
+       if(odst < 0)
+               osrc = odst;
+
        nodreg(&nodl, types[tptr], D_DI);
        nodreg(&nodr, types[tptr], D_SI);
 
@@ -611,20 +626,52 @@ sgen(Node *n, Node *ns, uint32 w)
                agen(ns, &nodl);
                agen(n, &nodr);
        }
-       gins(ACLD, N, N);       // clear direction flag
 
-       c = w / 8;
-       if(c > 0) {
-               gconreg(AMOVQ, c, D_CX);
-               gins(AREP, N, N);       // repeat
-               gins(AMOVSQ, N, N);     // MOVQ *(SI)+,*(DI)+
-       }
+       c = w % 8;      // bytes
+       q = w / 8;      // quads
+
+       // if we are copying forward on the stack and
+       // the src and dst overlap, then reverse direction
+       if(odst > osrc && odst-osrc < w) {
+               // reverse direction
+               gins(ASTD, N, N);               // set direction flag
+               if(c > 0) {
+                       gconreg(AADDQ, w-1, D_SI);
+                       gconreg(AADDQ, w-1, D_DI);
+
+                       gconreg(AMOVQ, c, D_CX);
+                       gins(AREP, N, N);       // repeat
+                       gins(AMOVSB, N, N);     // MOVB *(SI)-,*(DI)-
+               }
 
-       c = w % 8;
-       if(c > 0) {
-               gconreg(AMOVQ, c, D_CX);
-               gins(AREP, N, N);       // repeat
-               gins(AMOVSB, N, N);     // MOVB *(SI)+,*(DI)+
-       }
+               if(q > 0) {
+                       if(c > 0) {
+                               gconreg(AADDQ, -7, D_SI);
+                               gconreg(AADDQ, -7, D_DI);
+                       } else {
+                               gconreg(AADDQ, w-8, D_SI);
+                               gconreg(AADDQ, w-8, D_DI);
+                       }
+                       gconreg(AMOVQ, q, D_CX);
+                       gins(AREP, N, N);       // repeat
+                       gins(AMOVSQ, N, N);     // MOVQ *(SI)-,*(DI)-
+               }
+               // for future optimization
+               // we leave with the flag clear
+               gins(ACLD, N, N);
+       } else {
+               // normal direction
+               gins(ACLD, N, N);               // clear direction flag
+               if(q > 0) {
+                       gconreg(AMOVQ, q, D_CX);
+                       gins(AREP, N, N);       // repeat
+                       gins(AMOVSQ, N, N);     // MOVQ *(SI)+,*(DI)+
+               }
 
+               if(c > 0) {
+                       gconreg(AMOVQ, c, D_CX);
+                       gins(AREP, N, N);       // repeat
+                       gins(AMOVSB, N, N);     // MOVB *(SI)+,*(DI)+
+               }
+       }
 }
index 08c366422507f6d400f2f37837d341e18477e66c..8f1b71a16d0fdf3a749e35cfe439e8474bf69c08 100644 (file)
@@ -28,7 +28,7 @@
 %token                 LLSH LRSH LINC LDEC LSEND LRECV
 %token                 LIGNORE
 
-%type  <sym>           sym sym1 sym2 key1 key2 laconst lname latype
+%type  <sym>           sym sym1 sym2 key laconst lname latype
 %type  <lint>          chandir
 %type  <node>          xdcl xdcl_list_r oxdcl_list
 %type  <node>          common_dcl Acommon_dcl Bcommon_dcl
@@ -836,18 +836,17 @@ sym:
 
 sym1:
        sym
-|      key1
+|      key
 
 sym2:
        sym
-|      key1
-|      key2
+|      key
 
 /*
  * keywords that we can
  * use as variable/type names
  */
-key1:
+key:
        LNIL
 |      LTRUE
 |      LFALSE
@@ -858,38 +857,7 @@ key1:
 |      LNEW
 |      LBASETYPE
 |      LTYPEOF
-
-/*
- * keywords that we can
- * use as field names
- */
-key2:
-       LPACKAGE
-|      LIMPORT
-|      LEXPORT
-|      LMAP
-|      LCHAN
-|      LINTERFACE
-|      LFUNC
-|      LSTRUCT
-|      LFALL
-|      LRETURN
-|      LVAR
-|      LTYPE
-|      LCONST
 |      LCONVERT
-|      LSELECT
-|      LFOR
-|      LIF
-|      LELSE
-|      LSWITCH
-|      LCASE
-|      LDEFAULT
-|      LBREAK
-|      LCONTINUE
-|      LGO
-|      LGOTO
-|      LRANGE
 
 name:
        lname