]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: inline slice[arr,str] in the frontend (mostly).
authorLuuk van Dijk <lvd@golang.org>
Sun, 3 Jun 2012 02:50:57 +0000 (22:50 -0400)
committerRuss Cox <rsc@golang.org>
Sun, 3 Jun 2012 02:50:57 +0000 (22:50 -0400)
R=rsc, ality, rogpeppe, minux.ma, dave
CC=golang-dev
https://golang.org/cl/5966075

19 files changed:
src/cmd/5g/cgen.c
src/cmd/5g/gg.h
src/cmd/5g/ggen.c
src/cmd/5g/gsubr.c
src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
src/cmd/8g/cgen.c
src/cmd/8g/gg.h
src/cmd/8g/ggen.c
src/cmd/8g/gsubr.c
src/cmd/gc/builtin.c
src/cmd/gc/gen.c
src/cmd/gc/go.h
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/pkg/runtime/slice.c
src/pkg/runtime/string.goc

index a1732d232085f060e1cabd00297bcdc0491996ce..2e13f9a6c9997d68012eb9ee0712387235843d8e 100644 (file)
@@ -30,6 +30,19 @@ cgen(Node *n, Node *res)
        if(res == N || res->type == T)
                fatal("cgen: res nil");
 
+       switch(n->op) {
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+               if (res->op != ONAME || !res->addable) {
+                       tempname(&n1, n->type);
+                       cgen_slice(n, &n1);
+                       cgen(&n1, res);
+               } else
+                       cgen_slice(n, res);
+               return;
+       }
+
        while(n->op == OCONVNOP)
                n = n->left;
 
@@ -577,6 +590,14 @@ agen(Node *n, Node *res)
                cgen_aret(n, res);
                break;
 
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+               tempname(&n1, n->type);
+               cgen_slice(n, &n1);
+               agen(&n1, res);
+               break;
+
        case OINDEX:
                p2 = nil;  // to be patched to panicindex.
                w = n->type->width;
index a9e7ded68351ee27ea604a3957e42d26579cc40d..d579ac16ce2e79e7d0d90c50e616513dff98a16b 100644 (file)
@@ -78,7 +78,6 @@ 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 091ab77534623ffa61770afcba6980895c2df81d..85f63a2f7ade7d25af58ceed83ca3ca073ae0736 100644 (file)
@@ -68,8 +68,11 @@ ginscall(Node *f, int proc)
                break;
 
        case 0: // normal call
+       case -1:        // normal call but no return
                p = gins(ABL, N, f);
                afunclit(&p->to);
+               if(proc == -1 || noreturn(p))
+                       gins(AUNDEF, N, N);
                break;
 
        case 1: // call in new proc (go)
@@ -656,395 +659,3 @@ clearfat(Node *nl)
        regfree(&dst);
        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;
-
-// We're only going to bother inlining if we can
-// convert all the arguments to 32 bits safely.  Can we?
-static int
-fix64(NodeList *nn, int n)
-{
-       NodeList *l;
-       Node *r;
-       int i;
-       
-       l = nn;
-       for(i=0; i<n; i++) {
-               r = l->n->right;
-               if(is64(r->type) && !smallintconst(r)) {
-                       if(r->op == OCONV)
-                               r = r->left;
-                       if(is64(r->type))
-                               return 0;
-               }
-               l = l->next;
-       }
-       return 1;
-}
-
-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;
-       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))
-                       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, +1);
-               throwpc = pc;
-               ginscall(panicslice, 0);
-               patch(p1, pc);
-       } else {
-               op = brcom(op);
-               p1 = gbranch(optoas(op, types[TUINT32]), T, -1);
-               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, ntemp;
-       vlong v;
-       int i, narg;
-
-       if(n->op != OCALLFUNC)
-               goto no;
-       if(!n->left->addable)
-               goto no;
-       if(n->left->sym == S)
-               goto no;
-       if(n->left->sym->pkg != runtimepkg)
-               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;
-       if(!fix64(n->list, 5))
-               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:
-       if(!fix64(n->list, narg))
-               goto no;
-       ntemp.op = OXXX;
-       if(!sleasy(n->list->n->right)) {
-               Node *n0;
-               
-               n0 = n->list->n->right;
-               tempname(&ntemp, res->type);
-               cgen(n0, &ntemp);
-               n->list->n->right = &ntemp;
-               getargs(n->list, nodes, narg);
-               n->list->n->right = n0;
-       } else
-               getargs(n->list, nodes, narg);
-
-       nres = *res;            // result
-       if(!sleasy(res)) {
-               if(ntemp.op == OXXX)
-                       tempname(&ntemp, res->type);
-               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 = nodes[0];
-               n2.xoffset += Array_nel;
-               n2.type = types[TUINT32];
-               cmpandthrow(&nodes[1], &n2);
-
-               // ret.nel = old.nel[0]-lb[1];
-               n2 = nodes[0];
-               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 = nodes[0];
-               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 = nodes[0];
-       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 = nodes[0];
-       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 e4899fc91fbfcdb007adda4137f4a0069c14eb30..74266cb15f89359237f464acf9906a640b57dd43 100644 (file)
@@ -1141,6 +1141,27 @@ gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
        return p;
 }
 
+// Generate an instruction referencing *n
+// to force segv on nil pointer dereference.
+bsdvoid
+checkref(Node *n)
+{
+       Node m1, m2;
+
+       if(n->type->type->width < unmappedzero)
+               return;
+
+       regalloc(&m1, types[TUINTPTR], n);
+       regalloc(&m2, types[TUINT8], n);
+       cgen(n, &m1);
+       m1.xoffset = 0;
+       m1.op = OINDREG;
+       m1.type = types[TUINT8];
+       gins(AMOVBU, &m1, &m2);
+       regfree(&m2);
+       regfree(&m1);
+}
+
 static void
 checkoffset(Addr *a, int canemitcode)
 {
index 249fcd71a043909f537c0991b9eb3ca59be3ce21..e38fb86a32378d4812faeeb989794a6091213fb6 100644 (file)
@@ -33,9 +33,18 @@ cgen(Node *n, Node *res)
        while(n->op == OCONVNOP)
                n = n->left;
 
-       // inline slices
-       if(cgen_inline(n, res))
+       switch(n->op) {
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+               if (res->op != ONAME || !res->addable) {
+                       tempname(&n1, n->type);
+                       cgen_slice(n, &n1);
+                       cgen(&n1, res);
+               } else
+                       cgen_slice(n, res);
                goto ret;
+       }
 
        if(n->ullman >= UINF) {
                if(n->op == OINDREG)
@@ -532,6 +541,14 @@ agen(Node *n, Node *res)
                cgen_aret(n, res);
                break;
 
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+               tempname(&n1, n->type);
+               cgen_slice(n, &n1);
+               agen(&n1, res);
+               break;
+
        case OINDEX:
                w = n->type->width;
                if(nr->addable)
index 2e2ee498f3a31b5078c8d9b28dad7566dc888412..4073e228c69e2b44ab10eef0aa66e7944646b3c7 100644 (file)
@@ -92,7 +92,6 @@ Prog* gins(int, Node*, Node*);
 int    samaddr(Node*, Node*);
 void   naddr(Node*, Addr*, int);
 void   cgen_aret(Node*, Node*);
-int    cgen_inline(Node*, Node*);
 void   restx(Node*, Node*);
 void   savex(int, Node*, Node*, Node*, Type*);
 int    componentgen(Node*, Node*);
index de5e818429ababd0476cd7d7e63caae5ba5a5f0e..4d9fa4812fbbe493939803b8916f5c4d93dfef7a 100644 (file)
@@ -69,7 +69,7 @@ ginscall(Node *f, int proc)
        case -1:        // normal call but no return
                p = gins(ACALL, N, f);
                afunclit(&p->to);
-               if(proc == -1)
+               if(proc == -1 || noreturn(p))
                        gins(AUNDEF, N, N);
                break;
 
@@ -1068,366 +1068,3 @@ clearfat(Node *nl)
        restx(&n1, &oldn1);
        restx(&ax, &oldax);
 }
-
-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;
-       Prog *p1;
-       int op;
-       Node *c;
-       Type *t;
-       Node n1;
-       
-       if(nl->op == OCONV && is64(nl->type))
-               nl = nl->left;
-       if(nr->op == OCONV && is64(nr->type))
-               nr = nr->left;
-
-       op = OLE;
-       if(smallintconst(nl)) {
-               cl = mpgetfix(nl->val.u.xval);
-               if(cl == 0)
-                       return;
-               if(smallintconst(nr))
-                       return;
-               // put the constant on the right
-               op = brrev(op);
-               c = nl;
-               nl = nr;
-               nr = c;
-       }
-       if(is64(nr->type) && smallintconst(nr))
-               nr->type = types[TUINT32];
-
-       n1.op = OXXX;
-       t = types[TUINT32];
-       if(nl->type->width != t->width || nr->type->width != t->width) {
-               if((is64(nl->type) && nl->op != OLITERAL) || (is64(nr->type) && nr->op != OLITERAL))
-                       t = types[TUINT64];
-
-               // Check if we need to use a temporary.
-               // At least one of the arguments is 32 bits
-               // (the len or cap) so one temporary suffices.
-               if(nl->type->width != t->width && nl->op != OLITERAL) {
-                       regalloc(&n1, t, nl);
-                       gmove(nl, &n1);
-                       nl = &n1;
-               } else if(nr->type->width != t->width && nr->op != OLITERAL) {
-                       regalloc(&n1, t, nr);
-                       gmove(nr, &n1);
-                       nr = &n1;
-               }
-       }
-       gins(optoas(OCMP, t), nl, nr);
-       if(n1.op != OXXX)
-               regfree(&n1);
-       if(throwpc == nil) {
-               p1 = gbranch(optoas(op, t), T, +1);
-               throwpc = pc;
-               ginscall(panicslice, -1);
-               patch(p1, pc);
-       } else {
-               op = brcom(op);
-               p1 = gbranch(optoas(op, t), T, -1);
-               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, ntemp;
-       vlong v;
-       int i, narg, nochk;
-
-       if(n->op != OCALLFUNC)
-               goto no;
-       if(!n->left->addable)
-               goto no;
-       if(n->left->sym == S)
-               goto no;
-       if(n->left->sym->pkg != runtimepkg)
-               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;
-       n2.type = types[TUINT32];
-
-       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;
-       n2.type = types[TUINT32];
-
-       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;
-       n2.type = types[tptr];
-
-       if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
-               v = mpgetfix(nodes[2].val.u.xval) *
-                       mpgetfix(nodes[4].val.u.xval);
-               if(v != 0)
-                       ginscon(optoas(OADD, types[tptr]), v, &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:
-       nochk = n->etype;  // skip bounds checking
-       ntemp.op = OXXX;
-       if(!sleasy(n->list->n->right)) {
-               Node *n0;
-               
-               n0 = n->list->n->right;
-               tempname(&ntemp, res->type);
-               cgen(n0, &ntemp);
-               n->list->n->right = &ntemp;
-               getargs(n->list, nodes, narg);
-               n->list->n->right = n0;
-       } else
-               getargs(n->list, nodes, narg);
-
-       nres = *res;            // result
-       if(!sleasy(res)) {
-               if(ntemp.op == OXXX)
-                       tempname(&ntemp, res->type);
-               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 = nodes[0];
-               n2.xoffset += Array_nel;
-               n2.type = types[TUINT32];
-               if(!nochk)
-                       cmpandthrow(&nodes[1], &n2);
-
-               // ret.nel = old.nel[0]-lb[1];
-               n2 = nodes[0];
-               n2.xoffset += Array_nel;
-               n2.type = types[TUINT32];
-       
-               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;
-               n2.type = types[TUINT32];
-               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-               regfree(&n1);
-       } else {        // old[lb:hb]
-               n2 = nodes[0];
-               n2.xoffset += Array_cap;
-               n2.type = types[TUINT32];
-               if(!nochk) {
-                       // if(hb[2] > old.cap[0]) goto throw;
-                       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;
-               n2.type = types[TUINT32];
-
-               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;
-       n2.type = types[TUINT32];
-
-       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;
-       n2.type = types[TUINT32];
-
-       gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-       regfree(&n1);
-
-       // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
-       n2 = nodes[0];
-       n2.xoffset += Array_array;
-       n2.type = types[tptr];
-       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)
-                       ginscon(optoas(OADD, types[tptr]), v, &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;
-       n2.type = types[tptr];
-       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);
-       }
-       return 1;
-
-no:
-       return 0;
-}
index d286bca2fe71bd01e0ba7989e7e74ab576ca3a4f..8284bd3da50fee18e5fe1832157d73ba982f97af 100644 (file)
@@ -1029,6 +1029,25 @@ gins(int as, Node *f, Node *t)
        return p;
 }
 
+// Generate an instruction referencing *n
+// to force segv on nil pointer dereference.
+void
+checkref(Node *n)
+{
+       Node m;
+
+       if(n->type->type->width < unmappedzero)
+               return;
+
+       regalloc(&m, types[TUINTPTR], n);
+       cgen(n, &m);
+       m.xoffset = 0;
+       m.op = OINDREG;
+       m.type = types[TUINT8];
+       gins(ATESTB, nodintconst(0), &m);
+       regfree(&m);
+}
+
 static void
 checkoffset(Addr *a, int canemitcode)
 {
index 8f6bfc24d09476d9531f4d2cca68605a3ac362ad..860e8cb6c046f2f62ad4ae1a3a1045edc923683d 100644 (file)
@@ -63,9 +63,18 @@ cgen(Node *n, Node *res)
        if(res == N || res->type == T)
                fatal("cgen: res nil");
 
-       // inline slices
-       if(cgen_inline(n, res))
+       switch(n->op) {
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+               if (res->op != ONAME || !res->addable) {
+                       tempname(&n1, n->type);
+                       cgen_slice(n, &n1);
+                       cgen(&n1, res);
+               } else
+                       cgen_slice(n, res);
                return;
+       }
 
        while(n->op == OCONVNOP)
                n = n->left;
@@ -532,6 +541,14 @@ agen(Node *n, Node *res)
                cgen_aret(n, res);
                break;
 
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+               tempname(&n1, n->type);
+               cgen_slice(n, &n1);
+               agen(&n1, res);
+               break;
+
        case OINDEX:
                p2 = nil;  // to be patched to panicindex.
                w = n->type->width;
index 0edb54c178840c30c9b9c0038f0ca26b9e383535..12632f651c199da71c01432f5ec9e30f2f0b3783 100644 (file)
@@ -104,7 +104,6 @@ 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);
 void   mgen(Node*, Node*, Node*);
 void   mfree(Node*);
index b113788ef771c09cc555b70d585dcbc8b724fbd7..749f913ef5ee4548a52d1a4a8a3ae34546cdd731 100644 (file)
@@ -109,7 +109,7 @@ ginscall(Node *f, int proc)
        case -1:        // normal call but no return
                p = gins(ACALL, N, f);
                afunclit(&p->to);
-               if(proc == -1)
+               if(proc == -1 || noreturn(p))
                        gins(AUNDEF, N, N);
                break;
 
@@ -780,401 +780,3 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
        regfree(&n1b);
        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;
-
-// We're only going to bother inlining if we can
-// convert all the arguments to 32 bits safely.  Can we?
-static int
-fix64(NodeList *nn, int n)
-{
-       NodeList *l;
-       Node *r;
-       int i;
-       
-       l = nn;
-       for(i=0; i<n; i++) {
-               r = l->n->right;
-               if(is64(r->type) && !smallintconst(r)) {
-                       if(r->op == OCONV)
-                               r = r->left;
-                       if(is64(r->type))
-                               return 0;
-               }
-               l = l->next;
-       }
-       return 1;
-}
-
-void
-getargs(NodeList *nn, Node *reg, int n)
-{
-       NodeList *l;
-       Node *r;
-       int i;
-
-       throwpc = nil;
-
-       l = nn;
-       for(i=0; i<n; i++) {
-               r = l->n->right;
-               if(is64(r->type)) {
-                       if(r->op == OCONV)
-                               r = r->left;
-                       else if(smallintconst(r))
-                               r->type = types[TUINT32];
-                       if(is64(r->type))
-                               fatal("getargs");
-               }
-               if(!smallintconst(r) && !isslice(r->type)) {
-                       if(i < 3)       // AX CX DX
-                               nodreg(reg+i, r->type, D_AX+i);
-                       else
-                               reg[i].op = OXXX;
-                       regalloc(reg+i, r->type, reg+i);
-                       cgen(r, reg+i);
-               } else
-                       reg[i] = *r;
-               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;
-       Prog *p1;
-       int op;
-       Node *c, n1;
-       Type *t;
-
-       op = OLE;
-       if(smallintconst(nl)) {
-               cl = mpgetfix(nl->val.u.xval);
-               if(cl == 0)
-                       return;
-               if(smallintconst(nr))
-                       return;
-               // put the constant on the right
-               op = brrev(op);
-               c = nl;
-               nl = nr;
-               nr = c;
-       }
-       
-       // Arguments are known not to be 64-bit,
-       // but they might be smaller than 32 bits.
-       // Check if we need to use a temporary.
-       // At least one of the arguments is 32 bits
-       // (the len or cap) so one temporary suffices.
-       n1.op = OXXX;
-       t = types[TUINT32];
-       if(nl->type->width != t->width) {
-               regalloc(&n1, t, nl);
-               gmove(nl, &n1);
-               nl = &n1;
-       } else if(nr->type->width != t->width) {
-               regalloc(&n1, t, nr);
-               gmove(nr, &n1);
-               nr = &n1;
-       }
-       gins(optoas(OCMP, t), nl, nr);
-       if(n1.op != OXXX)
-               regfree(&n1);
-       if(throwpc == nil) {
-               p1 = gbranch(optoas(op, t), T, +1);
-               throwpc = pc;
-               ginscall(panicslice, -1);
-               patch(p1, pc);
-       } else {
-               op = brcom(op);
-               p1 = gbranch(optoas(op, t), T, -1);
-               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, ntemp;
-       vlong v;
-       int i, narg, nochk;
-
-       if(n->op != OCALLFUNC)
-               goto no;
-       if(!n->left->addable)
-               goto no;
-       if(n->left->sym == S)
-               goto no;
-       if(n->left->sym->pkg != runtimepkg)
-               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;
-       if(!fix64(n->list, 5))
-               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;
-       n2.type = types[TUINT32];
-
-       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;
-       n2.type = types[TUINT32];
-
-       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;
-       n2.type = types[tptr];
-
-       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:
-       if(!fix64(n->list, narg))
-               goto no;
-       nochk = n->etype;  // skip bounds checking
-       ntemp.op = OXXX;
-       if(!sleasy(n->list->n->right)) {
-               Node *n0;
-               
-               n0 = n->list->n->right;
-               tempname(&ntemp, res->type);
-               cgen(n0, &ntemp);
-               n->list->n->right = &ntemp;
-               getargs(n->list, nodes, narg);
-               n->list->n->right = n0;
-       } else
-               getargs(n->list, nodes, narg);
-
-       nres = *res;            // result
-       if(!sleasy(res)) {
-               if(ntemp.op == OXXX)
-                       tempname(&ntemp, res->type);
-               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 = nodes[0];
-               n2.xoffset += Array_nel;
-               n2.type = types[TUINT32];
-               if(!nochk)
-                       cmpandthrow(&nodes[1], &n2);
-
-               // ret.nel = old.nel[0]-lb[1];
-               n2 = nodes[0];
-               n2.xoffset += Array_nel;
-               n2.type = types[TUINT32];
-       
-               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;
-               n2.type = types[TUINT32];
-               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-               regfree(&n1);
-       } else {        // old[lb:hb]
-               n2 = nodes[0];
-               n2.xoffset += Array_cap;
-               n2.type = types[TUINT32];
-               if (!nochk) {
-                       // if(hb[2] > old.cap[0]) goto throw;
-                       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;
-               n2.type = types[TUINT32];
-
-               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;
-       n2.type = types[TUINT32];
-
-       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;
-       n2.type = types[TUINT32];
-       gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-       regfree(&n1);
-
-       // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
-       n2 = nodes[0];
-       n2.xoffset += Array_array;
-       n2.type = types[tptr];
-
-       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;
-       n2.type = types[tptr];
-       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);
-       }
-       return 1;
-
-no:
-       return 0;
-}
index 9d504c67916a207c5389c5f142e11cf81a5c10e8..4011fa5c59b1e0c2d8c3b790b6c1350321ae3336 100644 (file)
@@ -1768,6 +1768,25 @@ gins(int as, Node *f, Node *t)
        return p;
 }
 
+// Generate an instruction referencing *n
+// to force segv on nil pointer dereference.
+void
+checkref(Node *n)
+{
+       Node m;
+
+       if(n->type->type->width < unmappedzero)
+               return;
+
+       regalloc(&m, types[TUINTPTR], n);
+       cgen(n, &m);
+       m.xoffset = 0;
+       m.op = OINDREG;
+       m.type = types[TUINT8];
+       gins(ATESTB, nodintconst(0), &m);
+       regfree(&m);
+}
+
 static void
 checkoffset(Addr *a, int canemitcode)
 {
index ca3d6670d455d33f93092436e98dc97ffd272451..4aec0c04eae642cb82c8794691575d90afde82ed 100644 (file)
@@ -86,9 +86,6 @@ char *runtimeimport =
        "func @\"\".block()\n"
        "func @\"\".makeslice(@\"\".typ *byte, @\"\".nel int64, @\"\".cap int64) (@\"\".ary []any)\n"
        "func @\"\".growslice(@\"\".typ *byte, @\"\".old []any, @\"\".n int64) (@\"\".ary []any)\n"
-       "func @\"\".sliceslice1(@\"\".old []any, @\"\".lb uint64, @\"\".width uint64) (@\"\".ary []any)\n"
-       "func @\"\".sliceslice(@\"\".old []any, @\"\".lb uint64, @\"\".hb uint64, @\"\".width uint64) (@\"\".ary []any)\n"
-       "func @\"\".slicearray(@\"\".old *any, @\"\".nel uint64, @\"\".lb uint64, @\"\".hb uint64, @\"\".width uint64) (@\"\".ary []any)\n"
        "func @\"\".closure()\n"
        "func @\"\".memequal(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
        "func @\"\".memequal8(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
index 5012e4a52dee78cbd205661db0a2bf1bc3573742..98066002773e85188df77d48b0e090df4d3be43f 100644 (file)
@@ -734,6 +734,66 @@ ret:
        ;
 }
 
+
+/*
+ * generate:
+ *     res = s[lo, hi];
+ * n->left is s
+ * n->list is (cap(s)-lo(TUINT32), hi-lo(TUINT32)[, lo*width(TUINTPTR)])
+ * caller (cgen) guarantees res is an addable ONAME.
+ *
+ */
+void
+cgen_slice(Node *n, Node *res)
+{
+       Node src, dst, *cap, *len, *offs, *add;
+
+//     print("cgen_slice: %N = %+N\n", res, n);
+
+       cap = n->list->n;
+       len = n->list->next->n;
+       offs = N;
+       if(n->list->next->next)
+               offs = n->list->next->next->n;
+
+       // dst.len = hi [ - lo ]
+       dst = *res;
+       dst.xoffset += Array_nel;
+       dst.type = types[TUINT32];
+       cgen(len, &dst);
+
+       if(n->op != OSLICESTR) {
+               // dst.cap = cap [ - lo ]
+               dst = *res;
+               dst.xoffset += Array_cap;
+               dst.type = types[TUINT32];
+               cgen(cap, &dst);
+       }
+
+       // dst.array = src.array  [ + lo *width ]
+       dst = *res;
+       dst.xoffset += Array_array;
+       dst.type = types[TUINTPTR];
+
+       if(n->op == OSLICEARR) {
+               if(!isptr[n->left->type->etype])
+                       fatal("slicearr is supposed to work on pointer: %+N\n", n);
+               checkref(n->left);
+       }
+
+       src = *n->left;
+       src.xoffset += Array_array;
+       src.type = types[TUINTPTR];
+
+       if(offs == N) {
+               cgen(&src, &dst);
+       } else {
+               add = nod(OADD, &src, offs);
+               typecheck(&add, Erv);
+               cgen(add, &dst);
+       }
+}
+
 /*
  * gather series of offsets
  * >=0 is direct addressed field
index 71268aa6f7dd0082e39a84089e1ea312f0ec6be0..82fe05be5d571869d419f619e6aba740fd44ac36 100644 (file)
@@ -987,6 +987,7 @@ void        dumplist(char *s, NodeList *l);
 void   addrescapes(Node *n);
 void   cgen_as(Node *nl, Node *nr);
 void   cgen_callmeth(Node *n, int proc);
+void   cgen_slice(Node* n, Node* res);
 void   clearlabels(void);
 void   checklabels(void);
 int    dotoffset(Node *n, int *oary, Node **nn);
@@ -1305,6 +1306,7 @@ EXTERN    Node*   nodfp;
 int    anyregalloc(void);
 void   betypeinit(void);
 void   bgen(Node *n, int true, int likely, Prog *to);
+void   checkref(Node*);
 void   cgen(Node*, Node*);
 void   cgen_asop(Node *n);
 void   cgen_call(Node *n, int proc);
index 15a61d9ef62a243acc1497cbc87283525fc4fa66..d5cdb2a5ea14fc1689685272df9f8f93f1903d19 100644 (file)
@@ -117,9 +117,6 @@ func block()
 
 func makeslice(typ *byte, nel int64, cap int64) (ary []any)
 func growslice(typ *byte, old []any, n int64) (ary []any)
-func sliceslice1(old []any, lb uint64, width uint64) (ary []any)
-func sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
-func slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any)
 
 func closure() // has args, but compiler fills in
 
index 026db25eddbaebc775739ab23e9ae3e760cfbd11..262135bcbe546261aa3c5431d5defdeb2c224567 100644 (file)
@@ -21,6 +21,7 @@ static        NodeList*       reorder3(NodeList*);
 static Node*   addstr(Node*, NodeList**);
 static Node*   appendslice(Node*, NodeList**);
 static Node*   append(Node*, NodeList**);
+static Node*   sliceany(Node*, NodeList**);
 static void    walkcompare(Node**, NodeList**);
 static void    walkrotate(Node**);
 static int     bounded(Node*, int64);
@@ -371,7 +372,7 @@ walkexpr(Node **np, NodeList **init)
        NodeList *ll, *lr, *lpost;
        Type *t;
        int et;
-       int64 v, v1, v2, len;
+       int64 v;
        int32 lno;
        Node *n, *fn;
        char buf[100], *p;
@@ -916,95 +917,29 @@ walkexpr(Node **np, NodeList **init)
                goto ret;
 
        case OSLICE:
+               if(n->right != N && n->right->left == N && n->right->right == N) { // noop
+                       walkexpr(&n->left, init);
+                       n = n->left;
+                       goto ret;
+               }
+               // fallthrough
        case OSLICEARR:
+       case OSLICESTR:
+               if(n->right == N) // already processed
+                       goto ret;
+
                walkexpr(&n->left, init);
-               n->left = safeexpr(n->left, init);
+               // cgen_slice can't handle string literals as source
+               // TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
+               if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left->op == OINDEX))
+                       n->left = copyexpr(n->left, n->left->type, init);
+               else
+                       n->left = safeexpr(n->left, init);
                walkexpr(&n->right->left, init);
                n->right->left = safeexpr(n->right->left, init);
                walkexpr(&n->right->right, init);
                n->right->right = safeexpr(n->right->right, init);
-
-               len = 1LL<<60;
-               t = n->left->type;
-               if(t != T && isptr[t->etype])
-                       t = t->type;
-               if(isfixedarray(t))
-                       len = t->bound;
-
-               // check for static out of bounds
-               // NOTE: v > len not v >= len.
-               v1 = -1;
-               v2 = -1;
-               if(isconst(n->right->left, CTINT)) {
-                       v1 = mpgetfix(n->right->left->val.u.xval);
-                       if(v1 < 0 || v1 >= (1LL<<31) || v1 > len) {
-                               yyerror("slice index out of bounds");
-                               v1 = -1;
-                       }
-               }
-               if(isconst(n->right->right, CTINT)) {
-                       v2 = mpgetfix(n->right->right->val.u.xval);
-                       if(v2 < 0 || v2 >= (1LL<<31) || v2 > len) {
-                               yyerror("slice index out of bounds");
-                               v2 = -1;
-                       }
-               }
-               if(v1 >= 0 && v2 >= 0 && v1 > v2)
-                       yyerror("inverted slice range");
-
-               if(n->op == OSLICEARR)
-                       goto slicearray;
-
-               // dynamic slice
-               // sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
-               // sliceslice1(old []any, lb uint64, width uint64) (ary []any)
-               t = n->type;
-               et = n->bounded;
-               if(n->right->left == N)
-                       l = nodintconst(0);
-               else
-                       l = conv(n->right->left, types[TUINT64]);
-               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,
-                               l,
-                               conv(n->right->right, types[TUINT64]),
-                               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,
-                               l,
-                               nodintconst(t->type->width));
-               }
-               n->bounded = et;        // preserve flag from OSLICE to the slice* call.
-               goto ret;
-
-       slicearray:
-               // static slice
-               // slicearray(old *any, uint64 nel, lb uint64, hb uint64, width uint64) (ary []any)
-               t = n->type;
-               fn = syslook("slicearray", 1);
-               argtype(fn, n->left->type->type);       // any-1
-               argtype(fn, t->type);                   // any-2
-               if(n->right->left == N)
-                       l = nodintconst(0);
-               else
-                       l = conv(n->right->left, types[TUINT64]);
-               if(n->right->right == N)
-                       r = nodintconst(n->left->type->type->bound);
-               else
-                       r = conv(n->right->right, types[TUINT64]);
-               n = mkcall1(fn, t, init,
-                       n->left, nodintconst(n->left->type->type->bound),
-                       l,
-                       r,
-                       nodintconst(t->type->width));
+               n = sliceany(n, init);  // chops n->right, sets n->list
                goto ret;
 
        case OADDR:
@@ -1082,25 +1017,7 @@ walkexpr(Node **np, NodeList **init)
        case OADDSTR:
                n = addstr(n, init);
                goto ret;
-
-       case OSLICESTR:
-               // sys_slicestring(s, lb, hb)
-               if(n->right->left == N)
-                       l = nodintconst(0);
-               else
-                       l = conv(n->right->left, types[TINT]);
-               if(n->right->right) {
-                       n = mkcall("slicestring", n->type, init,
-                               conv(n->left, types[TSTRING]),
-                               l,
-                               conv(n->right->right, types[TINT]));
-               } else {
-                       n = mkcall("slicestring1", n->type, init,
-                               conv(n->left, types[TSTRING]),
-                               l);
-               }
-               goto ret;
-
+       
        case OAPPEND:
                if(n->isddd) {
                        if(istype(n->type->type, TUINT8) && istype(n->list->next->n->type, TSTRING))
@@ -2433,6 +2350,155 @@ append(Node *n, NodeList **init)
        return ns;
 }
 
+
+// Generate frontend part for OSLICE[ARR|STR]
+// 
+static Node*
+sliceany(Node* n, NodeList **init)
+{
+       int bounded;
+       Node *src, *lb, *hb, *bound, *chk, *chk1, *chk2;
+       int64 lbv, hbv, bv, w;
+       Type *bt;
+
+//     print("before sliceany: %+N\n", n);
+
+       src = n->left;
+       lb = n->right->left;
+       hb = n->right->right;
+
+       bounded = n->etype;
+       
+       if(n->op == OSLICESTR)
+               bound = nod(OLEN, src, N);
+       else
+               bound = nod(OCAP, src, N);
+
+       typecheck(&bound, Erv);
+       walkexpr(&bound, init);  // if src is an array, bound will be a const now.
+
+       // static checks if possible
+       bv = 1LL<<50;
+       if(isconst(bound, CTINT)) {
+               if(!smallintconst(bound))
+                       yyerror("array len too large");
+               else
+                       bv = mpgetfix(bound->val.u.xval);
+       }
+       lbv = -1;
+       hbv = -1;
+
+       if(isconst(hb, CTINT)) {
+               hbv = mpgetfix(hb->val.u.xval);
+               if(hbv < 0 || hbv > bv || !smallintconst(hb)) {
+                       yyerror("slice index out of bounds");
+                       hbv = -1;
+               }
+       }
+       if(isconst(lb, CTINT)) {
+               lbv = mpgetfix(lb->val.u.xval);
+               if(lbv < 0 || lbv > bv || !smallintconst(lb)) {
+                       yyerror("slice index out of bounds");
+                       lbv = -1;
+               }
+               if(lbv == 0)
+                       lb = N;
+       }
+       if(lbv >= 0 && hbv >= 0 && lbv > hbv)
+               yyerror("inverted slice range");
+
+       // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison
+       // generate
+       //     if hb > bound || lb > hb { panicslice() }
+       chk = N;
+       chk1 = N;
+       chk2 = N;
+
+       bt = types[TUINT32];
+       if(hb != N && hb->type->width > 4)
+               bt = types[TUINT64];
+       if(lb != N && lb->type->width > 4)
+               bt = types[TUINT64];
+
+       bound = cheapexpr(conv(bound, bt), init);
+
+       if(hb != N) {
+               hb = cheapexpr(conv(hb, bt), init);
+               if(!bounded)
+                       chk1 = nod(OLT, bound, hb);  
+       } else if(n->op == OSLICEARR) {
+               hb = bound;
+       } else {
+               hb = nod(OLEN, src, N);
+               typecheck(&hb, Erv);
+               walkexpr(&hb, init);
+               hb = cheapexpr(conv(hb, bt), init);
+       }
+
+       if(lb != N) {
+               lb = cheapexpr(conv(lb, bt), init);
+               if(!bounded)
+                       chk2 = nod(OLT, hb, lb);  
+       }
+
+       if(chk1 != N || chk2 != N) {
+               chk = nod(OIF, N, N);
+               chk->nbody = list1(mkcall("panicslice", T, init));
+               if(chk1 != N)
+                       chk->ntest = chk1;
+               if(chk2 != N) {
+                       if(chk->ntest == N)
+                               chk->ntest = chk2;
+                       else
+                               chk->ntest = nod(OOROR, chk->ntest, chk2);
+               }
+               typecheck(&chk, Etop);
+               walkstmt(&chk);
+               *init = concat(*init, chk->ninit);
+               chk->ninit = nil;
+               *init = list(*init, chk);
+       }
+       
+       // prepare new cap, len and offs for backend cgen_slice
+       // cap = bound [ - lo ]
+       n->right = N;
+       n->list = nil;
+       if(lb == N)
+               bound = conv(bound, types[TUINT32]);
+       else
+               bound = nod(OSUB, conv(bound, types[TUINT32]), conv(lb, types[TUINT32]));
+       typecheck(&bound, Erv);
+       walkexpr(&bound, init);
+       n->list = list(n->list, bound);
+
+       // len = hi [ - lo]
+       if(lb == N)
+               hb = conv(hb, types[TUINT32]);
+       else
+               hb = nod(OSUB, conv(hb, types[TUINT32]), conv(lb, types[TUINT32]));
+       typecheck(&hb, Erv);
+       walkexpr(&hb, init);
+       n->list = list(n->list, hb);
+
+       // offs = [width *] lo, but omit if zero
+       if(lb != N) {
+               if(n->op == OSLICESTR)
+                       w = 1;
+               else
+                       w = n->type->type->width;
+               lb = conv(lb, types[TUINTPTR]);
+               if(w > 1)
+                       lb = nod(OMUL, nodintconst(w), lb);
+               typecheck(&lb, Erv);
+               walkexpr(&lb, init);
+               n->list = list(n->list, lb);
+       }
+
+//     print("after sliceany: %+N\n", n);
+
+       return n;
+}
+
 static Node*
 eqfor(Type *t)
 {
index e5726c93b90be15fdec0574d521556dfcdaf477b..3c7c8be0e9a45888171bf56bc05c5398ac48ce77 100644 (file)
@@ -147,149 +147,6 @@ growslice1(SliceType *t, Slice x, int32 newcap, Slice *ret)
        runtime·memmove(ret->array, x.array, ret->len * t->elem->size);
 }
 
-// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
-void
-runtime·sliceslice(Slice old, uint64 lb, uint64 hb, uint64 width, Slice ret)
-{
-       if(hb > old.cap || lb > hb) {
-               if(debug) {
-                       runtime·prints("runtime.sliceslice: old=");
-                       runtime·printslice(old);
-                       runtime·prints("; lb=");
-                       runtime·printint(lb);
-                       runtime·prints("; hb=");
-                       runtime·printint(hb);
-                       runtime·prints("; width=");
-                       runtime·printint(width);
-                       runtime·prints("\n");
-
-                       runtime·prints("oldarray: nel=");
-                       runtime·printint(old.len);
-                       runtime·prints("; cap=");
-                       runtime·printint(old.cap);
-                       runtime·prints("\n");
-               }
-               runtime·panicslice();
-       }
-
-       // new array is inside old array
-       ret.len = hb - lb;
-       ret.cap = old.cap - lb;
-       ret.array = old.array + lb*width;
-
-       FLUSH(&ret);
-
-       if(debug) {
-               runtime·prints("runtime.sliceslice: old=");
-               runtime·printslice(old);
-               runtime·prints("; lb=");
-               runtime·printint(lb);
-               runtime·prints("; hb=");
-               runtime·printint(hb);
-               runtime·prints("; width=");
-               runtime·printint(width);
-               runtime·prints("; ret=");
-               runtime·printslice(ret);
-               runtime·prints("\n");
-       }
-}
-
-// sliceslice1(old []any, lb uint64, width uint64) (ary []any);
-void
-runtime·sliceslice1(Slice old, uint64 lb, uint64 width, Slice ret)
-{
-       if(lb > old.len) {
-               if(debug) {
-                       runtime·prints("runtime.sliceslice: old=");
-                       runtime·printslice(old);
-                       runtime·prints("; lb=");
-                       runtime·printint(lb);
-                       runtime·prints("; width=");
-                       runtime·printint(width);
-                       runtime·prints("\n");
-
-                       runtime·prints("oldarray: nel=");
-                       runtime·printint(old.len);
-                       runtime·prints("; cap=");
-                       runtime·printint(old.cap);
-                       runtime·prints("\n");
-               }
-               runtime·panicslice();
-       }
-
-       // 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) {
-               runtime·prints("runtime.sliceslice: old=");
-               runtime·printslice(old);
-               runtime·prints("; lb=");
-               runtime·printint(lb);
-               runtime·prints("; width=");
-               runtime·printint(width);
-               runtime·prints("; ret=");
-               runtime·printslice(ret);
-               runtime·prints("\n");
-       }
-}
-
-// slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any);
-void
-runtime·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, 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;
-       }
-
-       if(hb > nel || lb > hb) {
-               if(debug) {
-                       runtime·prints("runtime.slicearray: old=");
-                       runtime·printpointer(old);
-                       runtime·prints("; nel=");
-                       runtime·printint(nel);
-                       runtime·prints("; lb=");
-                       runtime·printint(lb);
-                       runtime·prints("; hb=");
-                       runtime·printint(hb);
-                       runtime·prints("; width=");
-                       runtime·printint(width);
-                       runtime·prints("\n");
-               }
-               runtime·panicslice();
-       }
-
-       // new array is inside old array
-       ret.len = hb-lb;
-       ret.cap = nel-lb;
-       ret.array = old + lb*width;
-
-       FLUSH(&ret);
-
-       if(debug) {
-               runtime·prints("runtime.slicearray: old=");
-               runtime·printpointer(old);
-               runtime·prints("; nel=");
-               runtime·printint(nel);
-               runtime·prints("; lb=");
-               runtime·printint(lb);
-               runtime·prints("; hb=");
-               runtime·printint(hb);
-               runtime·prints("; width=");
-               runtime·printint(width);
-               runtime·prints("; ret=");
-               runtime·printslice(ret);
-               runtime·prints("\n");
-       }
-}
-
 // copy(to any, fr any, wid uint32) int
 void
 runtime·copy(Slice to, Slice fm, uintptr width, int32 ret)
index 7e1f8a1e8bf908caf1a514769cca38659b94e2cb..090c4cd20e1b8790be4e007265b4f8c3057e2ef5 100644 (file)
@@ -235,31 +235,6 @@ runtime·strstr(byte *s1, byte *s2)
        return nil;
 }
 
-func slicestring(si String, lindex int32, hindex int32) (so String) {
-       int32 l;
-
-       if(lindex < 0 || lindex > si.len ||
-          hindex < lindex || hindex > si.len) {
-               runtime·panicslice();
-       }
-
-       l = hindex-lindex;
-       so.str = si.str + lindex;
-       so.len = l;
-}
-
-func slicestring1(si String, lindex int32) (so String) {
-       int32 l;
-
-       if(lindex < 0 || lindex > si.len) {
-               runtime·panicslice();
-       }
-
-       l = si.len-lindex;
-       so.str = si.str + lindex;
-       so.len = l;
-}
-
 func intstring(v int64) (s String) {
        s = gostringsize(8);
        s.len = runtime·runetochar(s.str, v);