diff options
author | Ken Thompson <ken@golang.org> | 2009-08-27 13:19:44 -0700 |
---|---|---|
committer | Ken Thompson <ken@golang.org> | 2009-08-27 13:19:44 -0700 |
commit | 0dabe43cdf56dce2192b29d1150bf83512330e11 (patch) | |
tree | fc84602f52231b16fc51243f0f54e59ec7c88370 | |
parent | a19a15019735ca35f0d84177846ce65bb65457a4 (diff) | |
download | go-0dabe43cdf56dce2192b29d1150bf83512330e11.tar.gz |
inline slicearray
R=rsc
OCL=33974
CL=33974
-rw-r--r-- | src/cmd/6g/cgen.c | 4 | ||||
-rw-r--r-- | src/cmd/6g/gg.h | 1 | ||||
-rw-r--r-- | src/cmd/6g/ggen.c | 168 | ||||
-rw-r--r-- | test/ken/slicearray.go | 127 |
4 files changed, 300 insertions, 0 deletions
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index fcdf7ead9..ab712e543 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -35,6 +35,10 @@ cgen(Node *n, Node *res) if(initflag && gen_as_init(n, res)) goto ret; + // inline slices + if(cgen_inline(n, res)) + goto ret; + if(n->ullman >= UINF) { if(n->op == OINDREG) fatal("cgen: this is going to misscompile"); diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index ca90762cf..a2896bb15 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -93,6 +93,7 @@ Prog* gins(int, Node*, Node*); int samaddr(Node*, Node*); void naddr(Node*, Addr*); void cgen_aret(Node*, Node*); +int cgen_inline(Node*, Node*); /* * gsubr.c 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; +} diff --git a/test/ken/slicearray.go b/test/ken/slicearray.go new file mode 100644 index 000000000..31faa9c78 --- /dev/null +++ b/test/ken/slicearray.go @@ -0,0 +1,127 @@ +// $G $D/$F.go && $L $F.$A && ./$A.out + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + + +package main + +var bx [10]byte +var by []byte; +var fx [10]float +var fy []float; +var lb,hb int +var t int + +func +main() +{ + // width 1 (byte) + lb = 0; hb = 10; + by = bx[lb:hb]; tstb(); + by = bx[lb:10]; tstb(); + by = bx[0:hb]; tstb(); + by = bx[0:10]; tstb(); + + lb = 2; hb = 10; + by = bx[lb:hb]; tstb(); + by = bx[lb:10]; tstb(); + by = bx[2:hb]; tstb(); + by = bx[2:10]; tstb(); + + lb = 0; hb = 8; + by = bx[lb:hb]; tstb(); + by = bx[lb:8]; tstb(); + by = bx[0:hb]; tstb(); + by = bx[0:8]; tstb(); + + lb = 2; hb = 8; + by = bx[lb:hb]; tstb(); + by = bx[lb:8]; tstb(); + by = bx[2:hb]; tstb(); + by = bx[2:8]; tstb(); + + // width 4 (float) + lb = 0; hb = 10; + fy = fx[lb:hb]; tstf(); + fy = fx[lb:10]; tstf(); + fy = fx[0:hb]; tstf(); + fy = fx[0:10]; tstf(); + + lb = 2; hb = 10; + fy = fx[lb:hb]; tstf(); + fy = fx[lb:10]; tstf(); + fy = fx[2:hb]; tstf(); + fy = fx[2:10]; tstf(); + + lb = 0; hb = 8; + fy = fx[lb:hb]; tstf(); + fy = fx[lb:8]; tstf(); + fy = fx[0:hb]; tstf(); + fy = fx[0:8]; tstf(); + + lb = 2; hb = 8; + fy = fx[lb:hb]; tstf(); + fy = fx[lb:8]; tstf(); + fy = fx[2:hb]; tstf(); + fy = fx[2:8]; tstf(); +} + +func +tstb() +{ + t++; + if len(by) != hb-lb { + panicln("t=", t, "lb=", lb, "hb=", hb, + "len=", len(by), "hb-lb=", hb-lb); + } + if cap(by) != len(bx)-lb { + panicln("t=", t, "lb=", lb, "hb=", hb, + "cap=", cap(by), "len(bx)-lb=", len(bx)-lb); + } + for i:=lb; i<hb; i++ { + if bx[i] != by[i-lb] { + panicln("t=", t, "lb=", lb, "hb=", hb, + "bx[", i, "]=", bx[i], + "by[", i-lb, "]=", by[i-lb]); + } + } + by = nil; +} + +func +tstf() +{ + t++; + if len(fy) != hb-lb { + panicln("t=", t, "lb=", lb, "hb=", hb, + "len=", len(fy), "hb-lb=", hb-lb); + } + if cap(fy) != len(fx)-lb { + panicln("t=", t, "lb=", lb, "hb=", hb, + "cap=", cap(fy), "len(fx)-lb=", len(fx)-lb); + } + for i:=lb; i<hb; i++ { + if fx[i] != fy[i-lb] { + panicln("t=", t, "lb=", lb, "hb=", hb, + "fx[", i, "]=", fx[i], + "fy[", i-lb, "]=", fy[i-lb]); + } + } + fy = nil; +} + +func +init() +{ + for i:=0; i<len(bx); i++ { + bx[i] = byte(i+20); + } + by = nil; + + for i:=0; i<len(fx); i++ { + fx[i] = float(i+20); + } + fy = nil; +} |