summaryrefslogtreecommitdiff
path: root/src/cmd/6g/ggen.c
diff options
context:
space:
mode:
authorKen Thompson <ken@golang.org>2009-08-27 13:19:44 -0700
committerKen Thompson <ken@golang.org>2009-08-27 13:19:44 -0700
commit69bcd2b798c42d41464d869691f6741526e44746 (patch)
treefc84602f52231b16fc51243f0f54e59ec7c88370 /src/cmd/6g/ggen.c
parentaf0018ef7358503776416d3eb2b528b0f1d9e406 (diff)
downloadgolang-69bcd2b798c42d41464d869691f6741526e44746.tar.gz
inline slicearray
R=rsc OCL=33974 CL=33974
Diffstat (limited to 'src/cmd/6g/ggen.c')
-rw-r--r--src/cmd/6g/ggen.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 5c2a8953b..8bae94917 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -1172,3 +1172,171 @@ yes:
//print("%P\n", p);
return 1;
}
+
+void
+getargs(NodeList *nn, Node *reg, int n)
+{
+ NodeList *l;
+ int i;
+
+ l = nn;
+ for(i=0; i<n; i++) {
+ if(!smallintconst(l->n->right)) {
+ regalloc(reg+i, l->n->right->type, N);
+ cgen(l->n->right, reg+i);
+ } else
+ reg[i] = *l->n->right;
+ l = l->next;
+ }
+ // botch - need second pass to sort by offset
+}
+
+void
+cmpandthrow(Node *nodes, int l, int r)
+{
+ vlong cl, cr;
+ Prog *p1;
+ int op, c;
+
+ op = OLE;
+ if(smallintconst(nodes+l)) {
+ cl = mpgetfix((nodes+l)->val.u.xval);
+ if(cl == 0)
+ return;
+ if(smallintconst(nodes+r)) {
+ cr = mpgetfix((nodes+r)->val.u.xval);
+ if(cl > cr)
+ ginscall(throwindex, 0);
+ return;
+ }
+
+ // put the constant on the right
+ op = brrev(op);
+ c = l;
+ l = r;
+ r = c;
+ }
+
+ gins(optoas(OCMP, types[TUINT32]), nodes+l, nodes+r);
+ p1 = gbranch(optoas(op, types[TUINT32]), T);
+ ginscall(throwindex, 0);
+ patch(p1, pc);
+}
+
+// generate inline code for
+// slicearray
+// sliceslice
+// arraytoslice
+int
+cgen_inline(Node *n, Node *res)
+{
+ Node nodes[10];
+ Node n1, n2;
+ vlong v;
+ int i;
+
+ if(n->op != OCALLFUNC)
+ goto no;
+ if(n->left->op != ONAME)
+ goto no;
+ if(!res->addable)
+ goto no;
+ if(strcmp(n->left->sym->package, "sys") != 0)
+ goto no;
+ if(strcmp(n->left->sym->name, "slicearray") == 0)
+ goto slicearray;
+ if(strcmp(n->left->sym->name, "sliceslice") == 0)
+ goto sliceslice;
+ if(strcmp(n->left->sym->name, "arraytoslice") == 0)
+ goto arraytoslice;
+ goto no;
+
+slicearray:
+ getargs(n->list, nodes, 5);
+
+ // if(hb[3] > nel[1]) goto throw
+ cmpandthrow(nodes, 3, 1);
+
+ // if(lb[2] > hb[3]) goto throw
+ cmpandthrow(nodes, 2, 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);
+ 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);
+ gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
+ gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+ regfree(&n1);
+ }
+
+ // 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);
+ 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);
+
+ // ret.len = hb[3]-lb[2];
+ // ret.cap = nel[1]-lb[2];
+ // ret.array = old[0] + lb[3]*width[4];
+ for(i=0; i<5; i++) {
+ if(!smallintconst(nodes+i))
+ regfree(nodes+i);
+ }
+ return 1;
+
+sliceslice:
+ // if(hb > old.cap) goto throw;
+ // if(lb > hb) goto throw;
+ // ret.len = hb-lb;
+ // ret.cap = old.cap - lb;
+ // ret.array = old.array + lb*width;
+ goto no;
+
+arraytoslice:
+ // ret.len = nel;
+ // ret.cap = nel;
+ // ret.array = old;
+ goto no;
+
+no:
+ return 0;
+}