]> Cypherpunks repositories - gostls13.git/commitdiff
x[lo:] - gc and runtime.
authorRuss Cox <rsc@golang.org>
Fri, 20 Nov 2009 17:11:46 +0000 (09:11 -0800)
committerRuss Cox <rsc@golang.org>
Fri, 20 Nov 2009 17:11:46 +0000 (09:11 -0800)
  * add runtime sliceslice1 for x[lo:]
  * remove runtime arraytoslice, rewriting &arr into arr[0:len(arr)].
  * port cgen_inline into 8g, 5g.
  * use native memmove in maps

R=ken2
https://golang.org/cl/157106

17 files changed:
src/cmd/5g/gg.h
src/cmd/5g/ggen.c
src/cmd/6g/ggen.c
src/cmd/8g/cgen.c
src/cmd/8g/gg.h
src/cmd/8g/ggen.c
src/cmd/gc/builtin.c.boot
src/cmd/gc/go.y
src/cmd/gc/runtime.go
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c
src/pkg/runtime/hashmap.h
src/pkg/runtime/runtime.c
src/pkg/runtime/runtime.h
src/pkg/runtime/slice.c
test/ken/slicearray.go
test/ken/sliceslice.go

index 98e52788f180494b5f8e064bb11fc7691c8f07e1..6477452b92f1e4eb07a52203dae4a37fbaef956e 100644 (file)
@@ -61,6 +61,7 @@ EXTERN        Node*   newproc;
 EXTERN Node*   deferproc;
 EXTERN Node*   deferreturn;
 EXTERN Node*   throwindex;
+EXTERN Node*   throwslice;
 EXTERN Node*   throwreturn;
 EXTERN long    unmappedzero;
 EXTERN int     maxstksize;
@@ -78,6 +79,7 @@ void  cgen_callinter(Node*, Node*, int);
 void   cgen_proc(Node*, int);
 void   cgen_callret(Node*, Node*);
 void   cgen_dcl(Node*);
+int    cgen_inline(Node*, Node*);
 int    needconvert(Type*, Type*);
 void   genconv(Type*, Type*);
 void   allocparams(void);
index a22432009aa092a162a9449c03ab1bf88f2bc55a..e859f0578c38ea13469c000993adb580a526621e 100644 (file)
@@ -22,6 +22,7 @@ compile(Node *fn)
                deferproc = sysfunc("deferproc");
                deferreturn = sysfunc("deferreturn");
                throwindex = sysfunc("throwindex");
+               throwslice = sysfunc("throwslice");
                throwreturn = sysfunc("throwreturn");
        }
 
@@ -685,3 +686,382 @@ clearfat(Node *nl)
        regfree(&nz);
 }
 
+static int
+regcmp(const void *va, const void *vb)
+{
+       Node *ra, *rb;
+
+       ra = (Node*)va;
+       rb = (Node*)vb;
+       return ra->local - rb->local;
+}
+
+static Prog*   throwpc;
+
+void
+getargs(NodeList *nn, Node *reg, int n)
+{
+       NodeList *l;
+       int i;
+
+       throwpc = nil;
+
+       l = nn;
+       for(i=0; i<n; i++) {
+               if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
+                       regalloc(reg+i, l->n->right->type, N);
+                       cgen(l->n->right, reg+i);
+               } else
+                       reg[i] = *l->n->right;
+               if(reg[i].local != 0)
+                       yyerror("local used");
+               reg[i].local = l->n->left->xoffset;
+               l = l->next;
+       }
+       qsort((void*)reg, n, sizeof(*reg), regcmp);
+       for(i=0; i<n; i++)
+               reg[i].local = 0;
+}
+
+void
+cmpandthrow(Node *nl, Node *nr)
+{
+       vlong cl, cr;
+       Prog *p1;
+       int op;
+       Node *c, n1, n2;
+
+       op = OLE;
+       if(smallintconst(nl)) {
+               cl = mpgetfix(nl->val.u.xval);
+               if(cl == 0)
+                       return;
+               if(smallintconst(nr)) {
+                       cr = mpgetfix(nr->val.u.xval);
+                       if(cl > cr) {
+                               if(throwpc == nil) {
+                                       throwpc = pc;
+                                       ginscall(throwslice, 0);
+                               } else
+                                       patch(gbranch(AB, T), throwpc);
+                       }
+                       return;
+               }
+
+               // put the constant on the right
+               op = brrev(op);
+               c = nl;
+               nl = nr;
+               nr = c;
+       }
+
+       n1.op = OXXX;
+       if(nr->op != OREGISTER) {
+               regalloc(&n1, types[TUINT32], N);
+               gmove(nr, &n1);
+               nr = &n1;
+       }
+       n2.op = OXXX;
+       if(nl->op != OREGISTER) {
+               regalloc(&n2, types[TUINT32], N);
+               gmove(nl, &n2);
+               nl = &n2;
+       }
+       gcmp(optoas(OCMP, types[TUINT32]), nl, nr);
+       if(nr == &n1)
+               regfree(&n1);
+       if(nl == &n2)
+               regfree(&n2);
+       if(throwpc == nil) {
+               p1 = gbranch(optoas(op, types[TUINT32]), T);
+               throwpc = pc;
+               ginscall(throwslice, 0);
+               patch(p1, pc);
+       } else {
+               op = brcom(op);
+               p1 = gbranch(optoas(op, types[TUINT32]), T);
+               patch(p1, throwpc);
+       }
+}
+
+int
+sleasy(Node *n)
+{
+       if(n->op != ONAME)
+               return 0;
+       if(!n->addable)
+               return 0;
+       return 1;
+}
+
+// generate inline code for
+//     slicearray
+//     sliceslice
+//     arraytoslice
+int
+cgen_inline(Node *n, Node *res)
+{
+       Node nodes[5];
+       Node n1, n2, n3, nres, nnode0, ntemp;
+       vlong v;
+       int i, narg, bad;
+
+       if(n->op != OCALLFUNC)
+               goto no;
+       if(!n->left->addable)
+               goto no;
+       if(strcmp(n->left->sym->package, "runtime") != 0)
+               goto no;
+       if(strcmp(n->left->sym->name, "slicearray") == 0)
+               goto slicearray;
+       if(strcmp(n->left->sym->name, "sliceslice") == 0) {
+               narg = 4;
+               goto sliceslice;
+       }
+       if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
+               narg = 3;
+               goto sliceslice;
+       }
+       goto no;
+
+slicearray:
+       if(!sleasy(res))
+               goto no;
+       getargs(n->list, nodes, 5);
+
+       // if(hb[3] > nel[1]) goto throw
+       cmpandthrow(&nodes[3], &nodes[1]);
+
+       // if(lb[2] > hb[3]) goto throw
+       cmpandthrow(&nodes[2], &nodes[3]);
+
+       // len = hb[3] - lb[2] (destroys hb)
+       n2 = *res;
+       n2.type = types[TUINT32];
+       n2.xoffset += Array_nel;
+
+       if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
+               v = mpgetfix(nodes[3].val.u.xval) -
+                       mpgetfix(nodes[2].val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gmove(&n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], &nodes[3]);
+               gmove(&nodes[3], &n1);
+               if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
+                       gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
+               gmove(&n1, &n2);
+               regfree(&n1);
+       }
+
+       // cap = nel[1] - lb[2] (destroys nel)
+       n2 = *res;
+       n2.type = types[TUINT32];
+       n2.xoffset += Array_cap;
+
+       if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
+               v = mpgetfix(nodes[1].val.u.xval) -
+                       mpgetfix(nodes[2].val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gmove(&n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], &nodes[1]);
+               gmove(&nodes[1], &n1);
+               if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
+                       gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
+               gmove(&n1, &n2);
+               regfree(&n1);
+       }
+
+       // if slice could be too big, dereference to
+       // catch nil array pointer.
+       if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
+               n2 = nodes[0];
+               n2.xoffset = 0;
+               n2.op = OINDREG;
+               n2.type = types[TUINT8];
+               regalloc(&n1, types[TUINT32], N);
+               gins(AMOVB, &n2, &n1);
+               regfree(&n1);
+       }
+
+       // ary = old[0] + (lb[2] * width[4]) (destroys old)
+       n2 = *res;
+       n2.type = types[tptr];
+       n2.xoffset += Array_array;
+
+       if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
+               v = mpgetfix(nodes[2].val.u.xval) *
+                       mpgetfix(nodes[4].val.u.xval);
+               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);
+               if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1) {
+                       regalloc(&n3, types[tptr], N);
+                       gmove(&nodes[4], &n3);
+                       gins(optoas(OMUL, types[tptr]), &n3, &n1);
+                       regfree(&n3);
+               }
+               gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
+               regfree(&n1);
+       }
+       gmove(&nodes[0], &n2);
+
+       for(i=0; i<5; i++) {
+               if(nodes[i].op == OREGISTER)
+                       regfree(&nodes[i]);
+       }
+       return 1;
+
+sliceslice:
+       getargs(n->list, nodes, narg);
+
+       nres = *res;            // result
+       nnode0 = nodes[0];      // input slice
+       if(!sleasy(res) || !sleasy(&nodes[0])) {
+               bad = 0;
+               if(res->ullman >= UINF)
+                       bad = 1;
+               for(i=0; i<narg; i++) {
+                       if(nodes[i].ullman >= UINF)
+                               bad = 1;
+                       if(nodes[i].op == OREGISTER)
+                               regfree(&nodes[i]);
+               }
+
+               if(bad)
+                       goto no;
+
+               tempname(&ntemp, res->type);
+               if(!sleasy(&nodes[0])) {
+                       cgen(&nodes[0], &ntemp);
+                       nnode0 = ntemp;
+               }
+               getargs(n->list, nodes, narg);
+               if(!sleasy(res))
+                       nres = ntemp;
+       }
+       
+       if(narg == 3) { // old[lb:]
+               // move width to where it would be for old[lb:hb]
+               nodes[3] = nodes[2];
+               nodes[2].op = OXXX;
+               
+               // if(lb[1] > old.nel[0]) goto throw;
+               n2 = nnode0;
+               n2.xoffset += Array_nel;
+               n2.type = types[TUINT32];
+               cmpandthrow(&nodes[1], &n2);
+
+               // ret.nel = old.nel[0]-lb[1];
+               n2 = nnode0;
+               n2.type = types[TUINT32];
+               n2.xoffset += Array_nel;
+       
+               regalloc(&n1, types[TUINT32], N);
+               gmove(&n2, &n1);
+               if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
+                       gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
+       
+               n2 = nres;
+               n2.type = types[TUINT32];
+               n2.xoffset += Array_nel;
+               gmove(&n1, &n2);
+               regfree(&n1);
+       } else {        // old[lb:hb]
+               // if(hb[2] > old.cap[0]) goto throw;
+               n2 = nnode0;
+               n2.xoffset += Array_cap;
+               n2.type = types[TUINT32];
+               cmpandthrow(&nodes[2], &n2);
+
+               // if(lb[1] > hb[2]) goto throw;
+               cmpandthrow(&nodes[1], &nodes[2]);
+
+               // ret.len = hb[2]-lb[1]; (destroys hb[2])
+               n2 = nres;
+               n2.type = types[TUINT32];
+               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);
+                       gmove(&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);
+                       gmove(&n1, &n2);
+                       regfree(&n1);
+               }
+       }
+
+       // ret.cap = old.cap[0]-lb[1]; (uses hb[2])
+       n2 = nnode0;
+       n2.type = types[TUINT32];
+       n2.xoffset += Array_cap;
+
+       regalloc(&n1, types[TUINT32], &nodes[2]);
+       gmove(&n2, &n1);
+       if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
+               gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
+
+       n2 = nres;
+       n2.type = types[TUINT32];
+       n2.xoffset += Array_cap;
+       gmove(&n1, &n2);
+       regfree(&n1);
+
+       // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
+       n2 = nnode0;
+       n2.type = types[tptr];
+       n2.xoffset += Array_array;
+       regalloc(&n3, types[tptr], N);
+       gmove(&n2, &n3);
+
+       regalloc(&n1, types[tptr], &nodes[1]);
+       if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
+               gmove(&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]), &n3, &n1);
+               }
+       } else {
+               gmove(&nodes[1], &n1);
+               if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1) {
+                       regalloc(&n2, types[tptr], N);
+                       gmove(&nodes[3], &n2);
+                       gins(optoas(OMUL, types[tptr]), &n2, &n1);
+                       regfree(&n2);
+               }
+               gins(optoas(OADD, types[tptr]), &n3, &n1);
+       }
+       regfree(&n3);
+
+       n2 = nres;
+       n2.type = types[tptr];
+       n2.xoffset += Array_array;
+       gmove(&n1, &n2);
+       regfree(&n1);
+
+       for(i=0; i<4; i++) {
+               if(nodes[i].op == OREGISTER)
+                       regfree(&nodes[i]);
+       }
+
+       if(!sleasy(res)) {
+               cgen(&nres, res);
+       }
+       return 1;
+
+no:
+       return 0;
+}
index 5c0a22114f89ff50fc529883c9daa87819e15255..cf5614861675d60f124d109d9517ebbc625a19ec 100644 (file)
@@ -1131,7 +1131,7 @@ cgen_inline(Node *n, Node *res)
        Node nodes[5];
        Node n1, n2, nres, nnode0, ntemp;
        vlong v;
-       int i, bad;
+       int i, narg, bad;
 
        if(n->op != OCALLFUNC)
                goto no;
@@ -1141,10 +1141,14 @@ cgen_inline(Node *n, Node *res)
                goto no;
        if(strcmp(n->left->sym->name, "slicearray") == 0)
                goto slicearray;
-       if(strcmp(n->left->sym->name, "sliceslice") == 0)
+       if(strcmp(n->left->sym->name, "sliceslice") == 0) {
+               narg = 4;
                goto sliceslice;
-       if(strcmp(n->left->sym->name, "arraytoslice") == 0)
-               goto arraytoslice;
+       }
+       if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
+               narg = 3;
+               goto sliceslice;
+       }
        goto no;
 
 slicearray:
@@ -1231,44 +1235,8 @@ slicearray:
        }
        return 1;
 
-arraytoslice:
-       if(!sleasy(res))
-               goto no;
-       getargs(n->list, nodes, 2);
-
-       // ret.len = nel[1];
-       n2 = *res;
-       n2.xoffset += Array_nel;
-       gins(optoas(OAS, types[TUINT32]), &nodes[1], &n2);
-
-       // ret.cap = nel[1];
-       n2 = *res;
-       n2.xoffset += Array_cap;
-       gins(optoas(OAS, types[TUINT32]), &nodes[1], &n2);
-
-       // ret.array = old[0];
-       n2 = *res;
-       n2.xoffset += Array_array;
-       gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
-
-       // if slice could be too big, dereference to
-       // catch nil array pointer.
-       if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
-               n2 = nodes[0];
-               n2.xoffset = 0;
-               n2.op = OINDREG;
-               n2.type = types[TUINT8];
-               gins(ATESTB, nodintconst(0), &n2);
-       }
-
-       for(i=0; i<2; i++) {
-               if(nodes[i].op == OREGISTER)
-                       regfree(&nodes[i]);
-       }
-       return 1;
-
 sliceslice:
-       getargs(n->list, nodes, 4);
+       getargs(n->list, nodes, narg);
 
        nres = *res;            // result
        nnode0 = nodes[0];      // input slice
@@ -1276,7 +1244,7 @@ sliceslice:
                bad = 0;
                if(res->ullman >= UINF)
                        bad = 1;
-               for(i=0; i<4; i++) {
+               for(i=0; i<narg; i++) {
                        if(nodes[i].ullman >= UINF)
                                bad = 1;
                        if(nodes[i].op == OREGISTER)
@@ -1291,35 +1259,60 @@ sliceslice:
                        cgen(&nodes[0], &ntemp);
                        nnode0 = ntemp;
                }
-               getargs(n->list, nodes, 4);
+               getargs(n->list, nodes, narg);
                if(!sleasy(res))
                        nres = ntemp;
        }
-
-       // if(hb[2] > old.cap[0]) goto throw;
-       n2 = nnode0;
-       n2.xoffset += Array_cap;
-       cmpandthrow(&nodes[2], &n2);
-
-       // if(lb[1] > hb[2]) goto throw;
-       cmpandthrow(&nodes[1], &nodes[2]);
-
-       // ret.len = hb[2]-lb[1]; (destroys hb[2])
-       n2 = nres;
-       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(narg == 3) { // old[lb:]
+               // move width to where it would be for old[lb:hb]
+               nodes[3] = nodes[2];
+               nodes[2].op = OXXX;
+               
+               // if(lb[1] > old.nel[0]) goto throw;
+               n2 = nnode0;
+               n2.xoffset += Array_nel;
+               cmpandthrow(&nodes[1], &n2);
+
+               // ret.nel = old.nel[0]-lb[1];
+               n2 = nnode0;
+               n2.xoffset += Array_nel;
+       
+               regalloc(&n1, types[TUINT32], N);
+               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 = nres;
+               n2.xoffset += Array_nel;
                gins(optoas(OAS, types[TUINT32]), &n1, &n2);
                regfree(&n1);
+       } else {        // old[lb:hb]
+               // if(hb[2] > old.cap[0]) goto throw;
+               n2 = nnode0;
+               n2.xoffset += Array_cap;
+               cmpandthrow(&nodes[2], &n2);
+
+               // if(lb[1] > hb[2]) goto throw;
+               cmpandthrow(&nodes[1], &nodes[2]);
+
+               // ret.len = hb[2]-lb[1]; (destroys hb[2])
+               n2 = nres;
+               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])
index ee4df870a136c7a95fe908dc69469eb1a2eb40d0..b6b855de8bb7764ef9387733d565d81d03943374 100644 (file)
@@ -61,6 +61,10 @@ cgen(Node *n, Node *res)
        if(res == N || res->type == T)
                fatal("cgen: res nil");
 
+       // inline slices
+       if(cgen_inline(n, res))
+               return;
+
        while(n->op == OCONVNOP)
                n = n->left;
 
index b36d0730b7a173b6df4083f6cfaf6bdfe70c7d4f..3c0292cca82a5180d440a2d84c792da96b6d9ae7 100644 (file)
@@ -65,6 +65,7 @@ EXTERN        Node*   newproc;
 EXTERN Node*   deferproc;
 EXTERN Node*   deferreturn;
 EXTERN Node*   throwindex;
+EXTERN Node*   throwslice;
 EXTERN Node*   throwreturn;
 EXTERN int     maxstksize;
 extern uint32  unmappedzero;
@@ -106,6 +107,7 @@ Prog*       gins(int, Node*, Node*);
 int    samaddr(Node*, Node*);
 void   naddr(Node*, Addr*, int);
 void   cgen_aret(Node*, Node*);
+int    cgen_inline(Node*, Node*);
 Node*  ncon(uint32);
 
 /*
index 7fc0aab70fe5724ebf637d3e3cea44d712a78315..c0a917be29cc4deaecc735e7b0106acb7a7ab287 100644 (file)
@@ -22,6 +22,7 @@ compile(Node *fn)
                deferproc = sysfunc("deferproc");
                deferreturn = sysfunc("deferreturn");
                throwindex = sysfunc("throwindex");
+               throwslice = sysfunc("throwslice");
                throwreturn = sysfunc("throwreturn");
        }
 
@@ -740,4 +741,348 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
        regfree(&n2b);
 }
 
+static int
+regcmp(const void *va, const void *vb)
+{
+       Node *ra, *rb;
+
+       ra = (Node*)va;
+       rb = (Node*)vb;
+       return ra->local - rb->local;
+}
+
+static Prog*   throwpc;
+
+void
+getargs(NodeList *nn, Node *reg, int n)
+{
+       NodeList *l;
+       int i;
+
+       throwpc = nil;
+
+       l = nn;
+       for(i=0; i<n; i++) {
+               if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
+                       if(i < 3)       // AX CX DX
+                               nodreg(reg+i, l->n->right->type, D_AX+i);
+                       else
+                               reg[i].op = OXXX;
+                       regalloc(reg+i, l->n->right->type, reg+i);
+                       cgen(l->n->right, reg+i);
+               } else
+                       reg[i] = *l->n->right;
+               if(reg[i].local != 0)
+                       yyerror("local used");
+               reg[i].local = l->n->left->xoffset;
+               l = l->next;
+       }
+       qsort((void*)reg, n, sizeof(*reg), regcmp);
+       for(i=0; i<n; i++)
+               reg[i].local = 0;
+}
+
+void
+cmpandthrow(Node *nl, Node *nr)
+{
+       vlong cl, cr;
+       Prog *p1;
+       int op;
+       Node *c;
+
+       op = OLE;
+       if(smallintconst(nl)) {
+               cl = mpgetfix(nl->val.u.xval);
+               if(cl == 0)
+                       return;
+               if(smallintconst(nr)) {
+                       cr = mpgetfix(nr->val.u.xval);
+                       if(cl > cr) {
+                               if(throwpc == nil) {
+                                       throwpc = pc;
+                                       ginscall(throwslice, 0);
+                               } else
+                                       patch(gbranch(AJMP, T), throwpc);
+                       }
+                       return;
+               }
+
+               // put the constant on the right
+               op = brrev(op);
+               c = nl;
+               nl = nr;
+               nr = c;
+       }
+
+       gins(optoas(OCMP, types[TUINT32]), nl, nr);
+       if(throwpc == nil) {
+               p1 = gbranch(optoas(op, types[TUINT32]), T);
+               throwpc = pc;
+               ginscall(throwslice, 0);
+               patch(p1, pc);
+       } else {
+               op = brcom(op);
+               p1 = gbranch(optoas(op, types[TUINT32]), T);
+               patch(p1, throwpc);
+       }
+}
+
+int
+sleasy(Node *n)
+{
+       if(n->op != ONAME)
+               return 0;
+       if(!n->addable)
+               return 0;
+       return 1;
+}
+
+// generate inline code for
+//     slicearray
+//     sliceslice
+//     arraytoslice
+int
+cgen_inline(Node *n, Node *res)
+{
+       Node nodes[5];
+       Node n1, n2, nres, nnode0, ntemp;
+       vlong v;
+       int i, narg, bad;
+
+       if(n->op != OCALLFUNC)
+               goto no;
+       if(!n->left->addable)
+               goto no;
+       if(strcmp(n->left->sym->package, "runtime") != 0)
+               goto no;
+       if(strcmp(n->left->sym->name, "slicearray") == 0)
+               goto slicearray;
+       if(strcmp(n->left->sym->name, "sliceslice") == 0) {
+               narg = 4;
+               goto sliceslice;
+       }
+       if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
+               narg = 3;
+               goto sliceslice;
+       }
+       goto no;
+
+slicearray:
+       if(!sleasy(res))
+               goto no;
+       getargs(n->list, nodes, 5);
+
+       // if(hb[3] > nel[1]) goto throw
+       cmpandthrow(&nodes[3], &nodes[1]);
+
+       // 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;
+
+       if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
+               v = mpgetfix(nodes[3].val.u.xval) -
+                       mpgetfix(nodes[2].val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], &nodes[3]);
+               gmove(&nodes[3], &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);
+       }
 
+       // cap = nel[1] - lb[2] (destroys nel)
+       n2 = *res;
+       n2.xoffset += Array_cap;
+
+       if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
+               v = mpgetfix(nodes[1].val.u.xval) -
+                       mpgetfix(nodes[2].val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], &nodes[1]);
+               gmove(&nodes[1], &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);
+       }
+
+       // if slice could be too big, dereference to
+       // catch nil array pointer.
+       if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
+               n2 = nodes[0];
+               n2.xoffset = 0;
+               n2.op = OINDREG;
+               n2.type = types[TUINT8];
+               gins(ATESTB, nodintconst(0), &n2);
+       }
+
+       // ary = old[0] + (lb[2] * width[4]) (destroys old)
+       n2 = *res;
+       n2.xoffset += Array_array;
+
+       if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
+               v = mpgetfix(nodes[2].val.u.xval) *
+                       mpgetfix(nodes[4].val.u.xval);
+               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);
+               if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1)
+                       gins(optoas(OMUL, types[tptr]), &nodes[4], &n1);
+               gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
+               regfree(&n1);
+       }
+       gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
+
+       for(i=0; i<5; i++) {
+               if(nodes[i].op == OREGISTER)
+                       regfree(&nodes[i]);
+       }
+       return 1;
+
+sliceslice:
+       getargs(n->list, nodes, narg);
+
+       nres = *res;            // result
+       nnode0 = nodes[0];      // input slice
+       ntemp.op = OXXX;
+       if(!sleasy(res) || !sleasy(&nodes[0])) {
+               bad = 0;
+               if(res->ullman >= UINF)
+                       bad = 1;
+               for(i=0; i<narg; i++) {
+                       if(nodes[i].ullman >= UINF)
+                               bad = 1;
+                       if(nodes[i].op == OREGISTER)
+                               regfree(&nodes[i]);
+               }
+
+               if(bad)
+                       goto no;
+
+               tempalloc(&ntemp, res->type);
+               if(!sleasy(&nodes[0])) {
+                       cgen(&nodes[0], &ntemp);
+                       nnode0 = ntemp;
+               }
+               getargs(n->list, nodes, narg);
+               if(!sleasy(res))
+                       nres = ntemp;
+       }
+       
+       if(narg == 3) { // old[lb:]
+               // move width to where it would be for old[lb:hb]
+               nodes[3] = nodes[2];
+               nodes[2].op = OXXX;
+               
+               // if(lb[1] > old.nel[0]) goto throw;
+               n2 = nnode0;
+               n2.xoffset += Array_nel;
+               cmpandthrow(&nodes[1], &n2);
+
+               // ret.nel = old.nel[0]-lb[1];
+               n2 = nnode0;
+               n2.xoffset += Array_nel;
+       
+               regalloc(&n1, types[TUINT32], N);
+               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 = nres;
+               n2.xoffset += Array_nel;
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+               regfree(&n1);
+       } else {        // old[lb:hb]
+               // if(hb[2] > old.cap[0]) goto throw;
+               n2 = nnode0;
+               n2.xoffset += Array_cap;
+               cmpandthrow(&nodes[2], &n2);
+
+               // if(lb[1] > hb[2]) goto throw;
+               cmpandthrow(&nodes[1], &nodes[2]);
+
+               // ret.len = hb[2]-lb[1]; (destroys hb[2])
+               n2 = nres;
+               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 = nnode0;
+       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 = nres;
+       n2.xoffset += Array_cap;
+       gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       regfree(&n1);
+
+       // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
+       n2 = nnode0;
+       n2.xoffset += Array_array;
+
+       regalloc(&n1, types[tptr], &nodes[1]);
+       if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
+               gins(optoas(OAS, types[tptr]), &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 = nres;
+       n2.xoffset += Array_array;
+       gins(optoas(OAS, types[tptr]), &n1, &n2);
+       regfree(&n1);
+
+       for(i=0; i<4; i++) {
+               if(nodes[i].op == OREGISTER)
+                       regfree(&nodes[i]);
+       }
+
+       if(!sleasy(res)) {
+               cgen(&nres, res);
+       }
+       if(ntemp.op != OXXX)
+               tempfree(&ntemp);
+       return 1;
+
+no:
+       return 0;
+}
index 8b794efdb82bb1f5fd26baab7ad335e7ee0ad05a..58d6f9e82858450375848e85ac2762f43d9d2ab7 100644 (file)
@@ -64,9 +64,9 @@ char *runtimeimport =
        "func runtime.selectdefault (sel *uint8) (selected bool)\n"
        "func runtime.selectgo (sel *uint8)\n"
        "func runtime.makeslice (nel int, cap int, width int) (ary []any)\n"
+       "func runtime.sliceslice1 (old []any, lb int, width int) (ary []any)\n"
        "func runtime.sliceslice (old []any, lb int, hb int, width int) (ary []any)\n"
        "func runtime.slicearray (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
-       "func runtime.arraytoslice (old *any, nel int) (ary []any)\n"
        "func runtime.closure ()\n"
        "func runtime.int64div (? int64, ? int64) (? int64)\n"
        "func runtime.uint64div (? uint64, ? uint64) (? uint64)\n"
index 921ff1ed46a5444dd8d5874dd91217414293fbeb..8413df64fc3ef4c877f3eb04cf3e09685f9559b5 100644 (file)
@@ -831,9 +831,13 @@ pexpr:
        {
                $$ = nod(OINDEX, $1, $3);
        }
-|      pexpr '[' keyval ']'
+|      pexpr '[' expr ':' ']'
        {
-               $$ = nod(OSLICE, $1, $3);
+               $$ = nod(OSLICE, $1, nod(OKEY, $3, N));
+       }
+|      pexpr '[' expr ':' expr ']'
+       {
+               $$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
        }
 |      pseudocall
 |      convtype '(' expr ')'
index 1f078f2da814cd53505e321a5162e67ff73ff143..ea4084012c75688bf1655060b5843c4337936327 100644 (file)
@@ -79,9 +79,9 @@ func selectdefault(sel *byte) (selected bool)
 func selectgo(sel *byte)
 
 func makeslice(nel int, cap int, width int) (ary []any)
+func sliceslice1(old []any, lb int, width int) (ary []any)
 func sliceslice(old []any, lb int, hb int, width int) (ary []any)
 func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
-func arraytoslice(old *any, nel int) (ary []any)
 
 func closure() // has args, but compiler fills in
 
index 6dab9d7614bd036275537e8785f61bcb17478ff4..fb96221bd65e15bf7c0de20f1a4b73a780f5e4c8 100644 (file)
@@ -587,7 +587,7 @@ reswitch:
                defaultlit(&n->right->left, types[TUINT]);
                defaultlit(&n->right->right, types[TUINT]);
                implicitstar(&n->left);
-               if(n->right->left == N || n->right->right == N) {
+               if(n->right->left == N) {
                        yyerror("missing slice bounds?");
                        goto error;
                }
@@ -597,11 +597,13 @@ reswitch:
                        yyerror("invalid slice index %#N (type %T)", n->right->left, t);
                        goto error;
                }
-               if((t = n->right->right->type) == T)
-                       goto error;
-               if(!isint[t->etype]) {
-                       yyerror("invalid slice index %#N (type %T)", n->right->right, t);
-                       goto error;
+               if(n->right->right != N) {
+                       if((t = n->right->right->type) == T)
+                               goto error;
+                       if(!isint[t->etype]) {
+                               yyerror("invalid slice index %#N (type %T)", n->right->right, t);
+                               goto error;
+                       }
                }
                l = n->left;
                if((t = l->type) == T)
index 9f3c81e194f15a356cd83bba172c20cc1396428e..bf35b38917fa5c608d7cb96d5dcf46e889f0042b 100644 (file)
@@ -808,15 +808,26 @@ walkexpr(Node **np, NodeList **init)
                walkexpr(&n->right->right, init);
                // dynamic slice
                // sliceslice(old []any, lb int, hb int, width int) (ary []any)
+               // sliceslice1(old []any, lb int, width int) (ary []any)
                t = n->type;
-               fn = syslook("sliceslice", 1);
-               argtype(fn, t->type);                   // any-1
-               argtype(fn, t->type);                   // any-2
-               n = mkcall1(fn, t, init,
-                       n->left,
-                       conv(n->right->left, types[TINT]),
-                       conv(n->right->right, types[TINT]),
-                       nodintconst(t->type->width));
+               if(n->right->right != N) {
+                       fn = syslook("sliceslice", 1);
+                       argtype(fn, t->type);                   // any-1
+                       argtype(fn, t->type);                   // any-2
+                       n = mkcall1(fn, t, init,
+                               n->left,
+                               conv(n->right->left, types[TINT]),
+                               conv(n->right->right, types[TINT]),
+                               nodintconst(t->type->width));
+               } else {
+                       fn = syslook("sliceslice1", 1);
+                       argtype(fn, t->type);                   // any-1
+                       argtype(fn, t->type);                   // any-2
+                       n = mkcall1(fn, t, init,
+                               n->left,
+                               conv(n->right->left, types[TINT]),
+                               nodintconst(t->type->width));
+               }
                goto ret;
 
        case OSLICEARR:
@@ -829,13 +840,29 @@ walkexpr(Node **np, NodeList **init)
                fn = syslook("slicearray", 1);
                argtype(fn, n->left->type);     // any-1
                argtype(fn, t->type);                   // any-2
+               if(n->right->right == N)
+                       r = nodintconst(n->left->type->bound);
+               else
+                       r = conv(n->right->right, types[TINT]);
                n = mkcall1(fn, t, init,
                        nod(OADDR, n->left, N), nodintconst(n->left->type->bound),
                        conv(n->right->left, types[TINT]),
-                       conv(n->right->right, types[TINT]),
+                       r,
                        nodintconst(t->type->width));
                goto ret;
 
+       case OCONVSLICE:
+               // slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
+               fn = syslook("slicearray", 1);
+               argtype(fn, n->left->type->type);               // any-1
+               argtype(fn, n->type->type);                     // any-2
+               n = mkcall1(fn, n->type, init, n->left,
+                       nodintconst(n->left->type->type->bound),
+                       nodintconst(0),
+                       nodintconst(n->left->type->type->bound),
+                       nodintconst(n->type->type->width));
+               goto ret;
+
        case OADDR:;
                Node *nvar, *nstar;
 
@@ -1014,14 +1041,6 @@ walkexpr(Node **np, NodeList **init)
                n = ifacecvt(n->type, n->left, n->etype, init);
                goto ret;
 
-       case OCONVSLICE:
-               // arraytoslice(old *any, nel int) (ary []any)
-               fn = syslook("arraytoslice", 1);
-               argtype(fn, n->left->type->type);               // any-1
-               argtype(fn, n->type->type);                     // any-2
-               n = mkcall1(fn, n->type, init, n->left, nodintconst(n->left->type->type->bound));
-               goto ret;
-
        case OCLOSURE:
                n = walkclosure(n, init);
                goto ret;
index 984b80cbd636d7c5bbe2e0cc34d77b264ce9007d..9d821da6c51c3d3bdca1bf82a9efc1a18dab7ac5 100644 (file)
@@ -67,7 +67,6 @@
 #define        free(a)         USED(a)
 #define        offsetof(s,m)   (uint32)(&(((s*)0)->m))
 #define        memset(a,b,c)   runtime·memclr((byte*)(a), (uint32)(c))
-#define        memmove(a,b,c)  mmov((byte*)(a),(byte*)(b),(uint32)(c))
 #define        memcpy(a,b,c)   mcpy((byte*)(a),(byte*)(b),(uint32)(c))
 #define        assert(a)       if(!(a)) throw("assert")
 
index 39fda98283d11d9565df319f5aa392c44ac74f4a..4a0309e0c7e608c9c180a3edf67dc5d17437ea6b 100644 (file)
@@ -104,28 +104,6 @@ mcmp(byte *s1, byte *s2, uint32 n)
 }
 
 
-void
-mmov(byte *t, byte *f, uint32 n)
-{
-       if(t < f) {
-               while(n > 0) {
-                       *t = *f;
-                       t++;
-                       f++;
-                       n--;
-               }
-       } else {
-               t += n;
-               f += n;
-               while(n > 0) {
-                       t--;
-                       f--;
-                       *t = *f;
-                       n--;
-               }
-       }
-}
-
 byte*
 mchr(byte *p, byte c, byte *ep)
 {
index df1c45ae1f77a57522a720f92b6a0e64faeab684..11dc489f2bd29d8cf00e4bc5eaaca6d931dcdd98 100644 (file)
@@ -342,7 +342,7 @@ void        printf(int8*, ...);
 byte*  mchr(byte*, byte, byte*);
 void   mcpy(byte*, byte*, uint32);
 int32  mcmp(byte*, byte*, uint32);
-void   mmov(byte*, byte*, uint32);
+void   memmove(void*, void*, uint32);
 void*  mal(uint32);
 uint32 cmpstring(String, String);
 String gostring(byte*);
index 02839e27cc8dc60461b06b30efb29a654538ef15..17762ae269901d1cb339b9d8342c3564a2420985 100644 (file)
@@ -52,7 +52,6 @@ throwslice(uint32 lb, uint32 hb, uint32 n)
 void
 runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
 {
-
        if(hb > old.cap || lb > hb) {
                if(debug) {
                        prints("runtime·sliceslice: old=");
@@ -75,7 +74,7 @@ runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
        }
 
        // new array is inside old array
-       ret.len = hb-lb;
+       ret.len = hb - lb;
        ret.cap = old.cap - lb;
        ret.array = old.array + lb*width;
 
@@ -96,6 +95,49 @@ runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
        }
 }
 
+// sliceslice1(old []any, lb int, width int) (ary []any);
+void
+runtime·sliceslice1(Slice old, uint32 lb, uint32 width, Slice ret)
+{
+       if(lb > old.len) {
+               if(debug) {
+                       prints("runtime·sliceslice: old=");
+                       runtime·printslice(old);
+                       prints("; lb=");
+                       runtime·printint(lb);
+                       prints("; width=");
+                       runtime·printint(width);
+                       prints("\n");
+
+                       prints("oldarray: nel=");
+                       runtime·printint(old.len);
+                       prints("; cap=");
+                       runtime·printint(old.cap);
+                       prints("\n");
+               }
+               throwslice(lb, old.len, old.cap);
+       }
+
+       // new array is inside old array
+       ret.len = old.len - lb;
+       ret.cap = old.cap - lb;
+       ret.array = old.array + lb*width;
+
+       FLUSH(&ret);
+
+       if(debug) {
+               prints("runtime·sliceslice: old=");
+               runtime·printslice(old);
+               prints("; lb=");
+               runtime·printint(lb);
+               prints("; width=");
+               runtime·printint(width);
+               prints("; ret=");
+               runtime·printslice(ret);
+               prints("\n");
+       }
+}
+
 // slicearray(old *any, nel int, lb int, hb int, width int) (ary []any);
 void
 runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Slice ret)
@@ -149,34 +191,6 @@ runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, S
        }
 }
 
-// arraytoslice(old *any, nel int) (ary []any)
-void
-runtime·arraytoslice(byte* old, uint32 nel, Slice ret)
-{
-       if(nel > 0 && old == nil) {
-               // crash if old == nil.
-               // could give a better message
-               // but this is consistent with all the in-line checks
-               // that the compiler inserts for other uses.
-               *old = 0;
-       }
-
-       // new dope to old array
-       ret.len = nel;
-       ret.cap = nel;
-       ret.array = old;
-
-       FLUSH(&ret);
-
-       if(debug) {
-               prints("runtime·slicearrayp: old=");
-               runtime·printpointer(old);
-               prints("; ret=");
-               runtime·printslice(ret);
-               prints("\n");
-       }
-}
-
 // slicecopy(to any, fr any, wid uint32) int
 void
 runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret)
index 8e03cb3f40b79472a0253cf123d5a7c38829bd5e..a8f5ad928dc44e7ed92a9cdb3355eef61b453ae2 100644 (file)
@@ -26,14 +26,18 @@ main()
        lb = 0; hb = 10;
        by = bx[lb:hb]; tstb();
        by = bx[lb:10]; tstb();
+       by = bx[lb:]; tstb();
        by = bx[0:hb]; tstb();
        by = bx[0:10]; tstb();
+       by = bx[0:]; tstb();
 
        lb = 2; hb = 10;
        by = bx[lb:hb]; tstb();
        by = bx[lb:10]; tstb();
+       by = bx[lb:]; tstb();
        by = bx[2:hb]; tstb();
        by = bx[2:10]; tstb();
+       by = bx[2:]; tstb();
 
        lb = 0; hb = 8;
        by = bx[lb:hb]; tstb();
@@ -51,14 +55,18 @@ main()
        lb = 0; hb = 10;
        fy = fx[lb:hb]; tstf();
        fy = fx[lb:10]; tstf();
+       fy = fx[lb:]; tstf();
        fy = fx[0:hb]; tstf();
        fy = fx[0:10]; tstf();
+       fy = fx[0:]; tstf();
 
        lb = 2; hb = 10;
        fy = fx[lb:hb]; tstf();
        fy = fx[lb:10]; tstf();
+       fy = fx[lb:]; tstf();
        fy = fx[2:hb]; tstf();
        fy = fx[2:10]; tstf();
+       fy = fx[2:]; tstf();
 
        lb = 0; hb = 8;
        fy = fx[lb:hb]; tstf();
index 3a8d5226c05d1e5462d150598fc6cfe726f070f2..9c37dedbe41550395d767e224b9b003d362280e4 100644 (file)
@@ -21,14 +21,18 @@ main()
        lb = 0; hb = 10;
        by = bx[lb:hb]; tstb();
        by = bx[lb:10]; tstb();
+       by = bx[lb:]; tstb();
        by = bx[0:hb]; tstb();
        by = bx[0:10]; tstb();
+       by = bx[0:]; tstb();
 
        lb = 2; hb = 10;
        by = bx[lb:hb]; tstb();
        by = bx[lb:10]; tstb();
+       by = bx[lb:]; tstb();
        by = bx[2:hb]; tstb();
        by = bx[2:10]; tstb();
+       by = bx[2:]; tstb();
 
        lb = 0; hb = 8;
        by = bx[lb:hb]; tstb();
@@ -46,14 +50,18 @@ main()
        lb = 0; hb = 10;
        fy = fx[lb:hb]; tstf();
        fy = fx[lb:10]; tstf();
+       fy = fx[lb:]; tstf();
        fy = fx[0:hb]; tstf();
        fy = fx[0:10]; tstf();
+       fy = fx[0:]; tstf();
 
        lb = 2; hb = 10;
        fy = fx[lb:hb]; tstf();
        fy = fx[lb:10]; tstf();
+       fy = fx[lb:]; tstf();
        fy = fx[2:hb]; tstf();
        fy = fx[2:10]; tstf();
+       fy = fx[2:]; tstf();
 
        lb = 0; hb = 8;
        fy = fx[lb:hb]; tstf();