diff options
author | Ken Thompson <ken@golang.org> | 2009-05-21 13:46:07 -0700 |
---|---|---|
committer | Ken Thompson <ken@golang.org> | 2009-05-21 13:46:07 -0700 |
commit | 0a0ee63200f4986735c6c6cdc113e46ab952d362 (patch) | |
tree | 081f6345ece03bd3eb02b5e8567b65bba9a99403 /src/cmd/gc/sinit.c | |
parent | d848b4032c40985e350afb63dd31819855f940fe (diff) | |
download | golang-0a0ee63200f4986735c6c6cdc113e46ab952d362.tar.gz |
added key:val extension to
structure and array literals
R=r
OCL=29190
CL=29190
Diffstat (limited to 'src/cmd/gc/sinit.c')
-rw-r--r-- | src/cmd/gc/sinit.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c new file mode 100644 index 000000000..2567151f1 --- /dev/null +++ b/src/cmd/gc/sinit.c @@ -0,0 +1,346 @@ +// 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. + +#include "go.h" + +static struct +{ + Node* list; + Node* mapname; + Type* type; +} xxx; + +/* + * the init code (thru initfix) reformats the + * var = ... + * statements, rewriting the automatic + * variables with the static variables. + * this allows the code generator to + * generate DATA statements instead + * of assignment statements. + * it is quadradic, may need to change. + * it is extremely fragile knowing exactly + * how the code from (struct|array|map)lit + * will look. ideally the lit routines could + * write the code in this form, but ... + */ + +void +initlin(Node* n) +{ + if(n == N) + return; + initlin(n->ninit); + switch(n->op) { + default: + print("o = %O\n", n->op); + n->ninit = N; + xxx.list = list(xxx.list, n); + break; + + case OCALL: + // call to mapassign1 + if(n->left->op != ONAME || + n->right->op != OLIST || + n->right->left->op != OAS || + n->right->right->op != OLIST || + n->right->right->left->op != OAS || + n->right->right->right->op != OAS || + strcmp(n->left->sym->name, "mapassign1") != 0) + dump("o=call", n); + n->ninit = N; + xxx.list = list(xxx.list, n); + break; + + case OAS: + n->ninit = N; + xxx.list = list(xxx.list, n); + break; + + case OLIST: + initlin(n->left); + initlin(n->right); + break; + } +} + +int +inittmp(Node *n) +{ + if(n != N) + if(n->op == ONAME) + if(n->sym != S) + if(n->class == PAUTO) + if(strcmp(n->sym->name, "!tmpname!") == 0) + return 1; + return 0; +} + +int +sametmp(Node *n1, Node *n2) +{ + if(inittmp(n1)) + if(n1->xoffset == n2->xoffset) + return 1; + return 0; +} + +int +indsametmp(Node *n1, Node *n2) +{ + if(n1->op == OIND) + if(inittmp(n1->left)) + if(n1->left->xoffset == n2->xoffset) + return 1; + return 0; +} + +Node* +findarg(Node *n, char *arg, char *fn) +{ + Iter param; + Node *a; + + if(n == N || n->op != OCALL || + n->left == N || n->left->sym == S || + strcmp(n->left->sym->name, fn) != 0) + return N; + + a = listfirst(¶m, &n->right); + while(a != N) { + if(a->op == OAS && + a->left != N && a->right != N && + a->left->op == OINDREG && + a->left->sym != S) + if(strcmp(a->left->sym->name, arg) == 0) + return a->right; + a = listnext(¶m); + } + return N; +} + +Node* +slicerewrite(Node *n) +{ + Node *nel; + Type *t; + int b; + Node *a; + + // call to newarray - find nel argument + nel = findarg(n, "nel", "newarray"); + if(nel == N || !isslice(n->type)) + goto no; + + b = mpgetfix(nel->val.u.xval); + t = shallow(n->type); + t->bound = b; + + // special hack for zero-size array + // invent an l-value to point at + if(b == 0) + a = staticname(types[TBOOL]); + else + a = staticname(t); + + a = nod(OCOMPSLICE, a, N); + a->type = n->type; + return a; + +no: + return N; +} + +Node* +maprewrite(Node *n) +{ + Node *nel; + Type *ta, *tb; + Node *a; + + // call to newarray - find nel argument + nel = findarg(n, "hint", "newmap"); + if(nel == N) + goto no; + ta = n->type; + if(ta->etype != TMAP) + goto no; + + // create a new type from map[index]value + // [0]struct { a index; b value) } + + tb = typ(TFIELD); + tb->type = ta->down; + tb->sym = lookup("key"); + tb->nname = newname(tb->sym); + tb->down = typ(TFIELD); + tb->down->type = ta->type; + tb->down->sym = lookup("val"); + tb->down->nname = newname(tb->down->sym); + + ta = typ(TSTRUCT); + ta->type = tb; + + tb = typ(TARRAY); + tb->type = ta; + tb->bound = 0; + + dowidth(tb); + + a = staticname(tb); + a = nod(OCOMPMAP, a, N); + a->type = n->type; + + // save stuff for this iteration + xxx.mapname = a->left; + xxx.type = tb; + + return a; + +no: + return N; +} + +// convert the call to mapassign1 +// into static[i].key = k, static[i].val = v +Node* +mapindex(Node *n) +{ + Node *index, *val, *key, *a, *b; + + // pull all the primatives + key = findarg(n, "key", "mapassign1"); + val = findarg(n, "val", "mapassign1"); + index = nodintconst(xxx.type->bound); + xxx.type->bound++; + dowidth(xxx.type); + + // build tree + a = nod(OINDEX, xxx.mapname, index); + a = nod(ODOT, a, newname(lookup("key"))); + a = nod(OAS, a, key); + + b = nod(OINDEX, xxx.mapname, index); + b = nod(ODOT, b, newname(lookup("val"))); + b = nod(OAS, b, val); + + a = nod(OLIST, a, b); + walktype(a, Etop); + + return a; +} + +// for a copy out reference, A = B, +// look through the whole structure +// and substitute references of B to A. +// some rewrite goes on also. +int +initsub(Node *n, Node *nam) +{ + Iter iter; + Node *r, *w; + int any; + + any = 0; + r = listfirst(&iter, &xxx.list); + while(r != N) { + switch(r->op) { + case OAS: + case OEMPTY: + if(r->left != N) + switch(r->left->op) { + case ONAME: + if(sametmp(r->left, nam)) { + any = 1; + r->left = n; + + w = slicerewrite(r->right); + if(w != N) { + n = w->left; // from now on use fixed array + r->right = w; + break; + } + + w = maprewrite(r->right); + if(w != N) { + n = w->left; // from now on use fixed array + r->right = w; + break; + } + } + break; + case ODOT: + if(sametmp(r->left->left, nam)) { + any = 1; + r->left->left = n; + } + if(indsametmp(r->left->left, nam)) { + any = 1; + r->left->left->left = n; + } + break; + case OINDEX: + if(sametmp(r->left->left, nam)) { + any = 1; + r->left->left = n; + } + if(indsametmp(r->left->left, nam)) { + any = 1; + r->left->left->left = n; + } + break; + } + break; + case OCALL: + // call to mapassign1 + // look through the parameters + w = findarg(r, "hmap", "mapassign1"); + if(w == N) + break; + if(sametmp(w, nam)) { + any = 1; + *r = *mapindex(r); + } + if(indsametmp(w, nam)) { +fatal("indirect map index"); + any = 1; + w->right->left = n; + } + break; + } + r = listnext(&iter); + } + return any; +} + +Node* +initfix(Node* n) +{ + Iter iter; + Node *r; + +//dump("prelin", n); + + xxx.list = N; + initlin(n); + xxx.list = rev(xxx.list); + +return xxx.list; +if(debug['A']) +dump("preinitfix", xxx.list); + + // look for the copy-out reference + r = listfirst(&iter, &xxx.list); + while(r != N) { + if(r->op == OAS) + if(inittmp(r->right)) { + if(initsub(r->left, r->right)) + r->op = OEMPTY; + } + r = listnext(&iter); + } +if(debug['A']) +dump("postinitfix", xxx.list); + return xxx.list; +} |