]> Cypherpunks repositories - gostls13.git/commitdiff
sliceslice inline
authorKen Thompson <ken@golang.org>
Fri, 28 Aug 2009 19:37:39 +0000 (12:37 -0700)
committerKen Thompson <ken@golang.org>
Fri, 28 Aug 2009 19:37:39 +0000 (12:37 -0700)
R=rsc
OCL=34041
CL=34041

src/cmd/6g/gg.h
src/cmd/6g/ggen.c
src/cmd/6g/reg.c
src/pkg/runtime/runtime.c
test/ken/sliceslice.go [new file with mode: 0644]

index a2896bb153e82274607517ca292e0342ee9c41d9..39b56d04abffcc695430202c32019d8c4862645c 100644 (file)
@@ -55,6 +55,7 @@ EXTERN        Node*   newproc;
 EXTERN Node*   deferproc;
 EXTERN Node*   deferreturn;
 EXTERN Node*   throwindex;
+EXTERN Node*   throwslice;
 EXTERN Node*   throwreturn;
 
 /*
index 8b94e69bd7e5e47bc6d67bb5d2c9f7b549a5f0b9..3048f911600fed00583e326dfcedec007165861c 100644 (file)
@@ -22,6 +22,7 @@ compile(Node *fn)
                deferproc = sysfunc("deferproc");
                deferreturn = sysfunc("deferreturn");
                throwindex = sysfunc("throwindex");
+               throwslice = sysfunc("throwslice");
                throwreturn = sysfunc("throwreturn");
        }
 
@@ -1176,7 +1177,7 @@ yes:
 static int
 regcmp(Node *ra, Node *rb)
 {
-       return ra->xoffset - rb->xoffset;
+       return ra->local - rb->local;
 }
 
 void
@@ -1192,12 +1193,14 @@ getargs(NodeList *nn, Node *reg, int n)
                        cgen(l->n->right, reg+i);
                } else
                        reg[i] = *l->n->right;
-               reg[i].xoffset = l->n->left->xoffset;
+               if(reg[i].local != 0)
+                       yyerror("local used");
+               reg[i].local = l->n->left->xoffset;
                l = l->next;
        }
-       qsort(reg, n, sizeof(*reg), regcmp);
+       qsort((void*)reg, n, sizeof(*reg), regcmp);
        for(i=0; i<n; i++)
-               reg[i].xoffset = 0;
+               reg[i].local = 0;
 }
 
 void
@@ -1216,7 +1219,7 @@ cmpandthrow(Node *nl, Node *nr)
                if(smallintconst(nr)) {
                        cr = mpgetfix(nr->val.u.xval);
                        if(cl > cr)
-                               ginscall(throwindex, 0);
+                               ginscall(throwslice, 0);
                        return;
                }
 
@@ -1229,7 +1232,7 @@ cmpandthrow(Node *nl, Node *nr)
 
        gins(optoas(OCMP, types[TUINT32]), nl, nr);
        p1 = gbranch(optoas(op, types[TUINT32]), T);
-       ginscall(throwindex, 0);
+       ginscall(throwslice, 0);
        patch(p1, pc);
 }
 
@@ -1247,7 +1250,7 @@ cgen_inline(Node *n, Node *res)
 
        if(n->op != OCALLFUNC)
                goto no;
-       if(n->left->op != ONAME)
+       if(!n->left->addable)
                goto no;
        if(!res->addable)
                goto no;
@@ -1270,7 +1273,6 @@ slicearray:
        // if(lb[2] > hb[3]) goto throw
        cmpandthrow(nodes+2, nodes+3);
 
-
        // len = hb[3] - lb[2] (destroys hb)
        n2 = *res;
        n2.xoffset += Array_nel;
@@ -1283,7 +1285,8 @@ slicearray:
        } else {
                regalloc(&n1, types[TUINT32], nodes+3);
                gmove(nodes+3, &n1);
-               gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
+               if(!smallintconst(nodes+2) || mpgetfix((nodes+2)->val.u.xval) != 0)
+                       gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
                regfree(&n1);
        }
@@ -1300,7 +1303,8 @@ slicearray:
        } else {
                regalloc(&n1, types[TUINT32], nodes+1);
                gmove(nodes+1, &n1);
-               gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
+               if(!smallintconst(nodes+2) || mpgetfix((nodes+2)->val.u.xval) != 0)
+                       gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
                regfree(&n1);
        }
@@ -1312,8 +1316,10 @@ slicearray:
        if(smallintconst(nodes+2) && smallintconst(nodes+4)) {
                v = mpgetfix((nodes+2)->val.u.xval) *
                        mpgetfix((nodes+4)->val.u.xval);
-               nodconst(&n1, types[tptr], v);
-               gins(optoas(OADD, types[tptr]), &n1, nodes+0);
+               if(v != 0) {
+                       nodconst(&n1, types[tptr], v);
+                       gins(optoas(OADD, types[tptr]), &n1, nodes+0);
+               }
        } else {
                regalloc(&n1, types[tptr], nodes+2);
                gmove(nodes+2, &n1);
@@ -1331,14 +1337,79 @@ slicearray:
        return 1;
 
 sliceslice:
-goto no;
        getargs(n->list, nodes, 4);
+       if(!(nodes+0)->addable) {
+               for(i=0; i<4; i++) {
+                       if((nodes+i)->op == OREGISTER)
+                               regfree(nodes+i);
+               }
+               goto no;
+       }
+
+       // if(hb[2] > old.cap[0]) goto throw;
+       n2 = *(nodes+0);
+       n2.xoffset += Array_cap;
+       cmpandthrow(nodes+2, &n2);
 
-       // if(hb > old.cap) goto throw;
-       // if(lb > hb) goto throw;
-       // ret.len = hb-lb;
-       // ret.cap = old.cap - lb;
-       // ret.array = old.array + lb*width;
+       // if(lb[1] > hb[2]) goto throw;
+       cmpandthrow(nodes+1, nodes+2);
+
+       // ret.len = hb[2]-lb[1]; (destroys hb[2])
+       n2 = *res;
+       n2.xoffset += Array_nel;
+
+       if(smallintconst(nodes+2) && smallintconst(nodes+1)) {
+               v = mpgetfix((nodes+2)->val.u.xval) -
+                       mpgetfix((nodes+1)->val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], nodes+2);
+               gmove(nodes+2, &n1);
+               if(!smallintconst(nodes+1) || mpgetfix((nodes+1)->val.u.xval) != 0)
+                       gins(optoas(OSUB, types[TUINT32]), nodes+1, &n1);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+               regfree(&n1);
+       }
+
+       // ret.cap = old.cap[0]-lb[1]; (uses hb[2])
+       n2 = *(nodes+0);
+       n2.xoffset += Array_cap;
+
+       regalloc(&n1, types[TUINT32], nodes+2);
+       gins(optoas(OAS, types[TUINT32]), &n2, &n1);
+       if(!smallintconst(nodes+1) || mpgetfix((nodes+1)->val.u.xval) != 0)
+               gins(optoas(OSUB, types[TUINT32]), nodes+1, &n1);
+
+       n2 = *res;
+       n2.xoffset += Array_cap;
+       gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       regfree(&n1);
+
+       // ret.array = old.array[0]+lb[1]*width[3]; (uses lb)
+       n2 = *(nodes+0);
+       n2.xoffset += Array_array;
+
+       regalloc(&n1, types[tptr], nodes+1);
+       if(smallintconst(nodes+1) && smallintconst(nodes+3)) {
+               gins(optoas(OAS, types[TUINT32]), &n2, &n1);
+               v = mpgetfix((nodes+1)->val.u.xval) *
+                       mpgetfix((nodes+3)->val.u.xval);
+               if(v != 0) {
+                       nodconst(&n2, types[tptr], v);
+                       gins(optoas(OADD, types[tptr]), &n2, &n1);
+               }
+       } else {
+               gmove(nodes+1, &n1);
+               if(!smallintconst(nodes+3) || mpgetfix((nodes+3)->val.u.xval) != 1)
+                       gins(optoas(OMUL, types[tptr]), nodes+3, &n1);
+               gins(optoas(OADD, types[tptr]), &n2, &n1);
+       }
+
+       n2 = *res;
+       n2.xoffset += Array_array;
+       gins(optoas(OAS, types[tptr]), &n1, &n2);
+       regfree(&n1);
 
        for(i=0; i<4; i++) {
                if((nodes+i)->op == OREGISTER)
index d017c62ab3a827b0f4f0a384ffe33273c911b0d5..6503ba9db14d748fba1c66fe8dd22ef9e2af5fb9 100644 (file)
@@ -1534,6 +1534,7 @@ noreturn(Prog *p)
 
        if(symlist[0] == S) {
                symlist[0] = pkglookup("throwindex", "sys");
+               symlist[0] = pkglookup("throwslice", "sys");
                symlist[1] = pkglookup("panicl", "sys");
        }
 
index 50a94ec92109d6f39ef0a3d1bdfcc9f18d953a88..6f359e1846760ef4aab18a97337d8bcce50bdaf8 100644 (file)
@@ -45,6 +45,12 @@ sys·throwindex(void)
        throw("index out of range");
 }
 
+void
+sys·throwslice(void)
+{
+       throw("slice out of range");
+}
+
 void
 sys·throwreturn(void)
 {
diff --git a/test/ken/sliceslice.go b/test/ken/sliceslice.go
new file mode 100644 (file)
index 0000000..3a8d522
--- /dev/null
@@ -0,0 +1,129 @@
+// $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
+
+var    bx      []byte
+var    by      []byte;
+var    fx      []float
+var    fy      []float;
+var    lb,hb   int
+var    t       int
+
+func
+main()
+{
+
+       // width 1 (byte)
+       lb = 0; hb = 10;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:10]; tstb();
+       by = bx[0:hb]; tstb();
+       by = bx[0:10]; tstb();
+
+       lb = 2; hb = 10;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:10]; tstb();
+       by = bx[2:hb]; tstb();
+       by = bx[2:10]; tstb();
+
+       lb = 0; hb = 8;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:8]; tstb();
+       by = bx[0:hb]; tstb();
+       by = bx[0:8]; tstb();
+
+       lb = 2; hb = 8;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:8]; tstb();
+       by = bx[2:hb]; tstb();
+       by = bx[2:8]; tstb();
+
+       // width 4 (float)
+       lb = 0; hb = 10;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:10]; tstf();
+       fy = fx[0:hb]; tstf();
+       fy = fx[0:10]; tstf();
+
+       lb = 2; hb = 10;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:10]; tstf();
+       fy = fx[2:hb]; tstf();
+       fy = fx[2:10]; tstf();
+
+       lb = 0; hb = 8;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:8]; tstf();
+       fy = fx[0:hb]; tstf();
+       fy = fx[0:8]; tstf();
+
+       lb = 2; hb = 8;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:8]; tstf();
+       fy = fx[2:hb]; tstf();
+       fy = fx[2:8]; tstf();
+}
+
+func
+tstb()
+{
+       t++;
+       if len(by) != hb-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "len=", len(by), "hb-lb=", hb-lb);
+       }
+       if cap(by) != len(bx)-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "cap=", cap(by), "len(bx)-lb=", len(bx)-lb);
+       }
+       for i:=lb; i<hb; i++ {
+               if bx[i] != by[i-lb] {
+                       panicln("t=", t, "lb=", lb, "hb=", hb,
+                               "bx[", i, "]=", bx[i],
+                               "by[", i-lb, "]=", by[i-lb]);
+               }
+       }
+       by = nil;
+}
+
+func
+tstf()
+{
+       t++;
+       if len(fy) != hb-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "len=", len(fy), "hb-lb=", hb-lb);
+       }
+       if cap(fy) != len(fx)-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "cap=", cap(fy), "len(fx)-lb=", len(fx)-lb);
+       }
+       for i:=lb; i<hb; i++ {
+               if fx[i] != fy[i-lb] {
+                       panicln("t=", t, "lb=", lb, "hb=", hb,
+                               "fx[", i, "]=", fx[i],
+                               "fy[", i-lb, "]=", fy[i-lb]);
+               }
+       }
+       fy = nil;
+}
+
+func
+init()
+{
+       bx = make([]byte, 10);
+       for i:=0; i<len(bx); i++ {
+               bx[i] = byte(i+20);
+       }
+       by = nil;
+
+       fx = make([]float, 10);
+       for i:=0; i<len(fx); i++ {
+               fx[i] = float(i+20);
+       }
+       fy = nil;
+}