diff options
author | Ken Thompson <ken@golang.org> | 2009-09-09 17:48:55 -0700 |
---|---|---|
committer | Ken Thompson <ken@golang.org> | 2009-09-09 17:48:55 -0700 |
commit | 5f8ec86b7feb48ef5046ab7e455df76fd2216b63 (patch) | |
tree | 9ef2359730f81dd7a234c78eb2e7bc8f40ef9bf1 /src/cmd/gc/sinit.c | |
parent | 377387c12837f06cc96b6ee3bf951efa2b024e60 (diff) | |
download | golang-5f8ec86b7feb48ef5046ab7e455df76fd2216b63.tar.gz |
composit literal under
init function context.
also moved composit literal
code from walk.c to sinit.c
R=rsc
OCL=34503
CL=34503
Diffstat (limited to 'src/cmd/gc/sinit.c')
-rw-r--r-- | src/cmd/gc/sinit.c | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index 07db731ef..4ae82ba2c 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -95,3 +95,542 @@ initfix(NodeList *l) initreorder(l, &lout); return lout; } + +/* + * from here down is the walk analysis + * of composit literals. + * most of the work is to generate + * data statements for the constant + * part of the composit literal. + */ + +static int +isliteral(Node *n) +{ + if(n->op == OLITERAL) + if(n->val.ctype != CTNIL) + return 1; + return 0; +} + +static int +simplename(Node *n) +{ + if(n->op != ONAME) + goto no; + if(!n->addable) + goto no; + if(n->class & PHEAP) + goto no; + if(n->class == PPARAMREF) + goto no; + return 1; + +no: + return 0; +} + +static void arraylit(Node *n, Node *var, int pass, NodeList **init); + +static void +structlit(Node *n, Node *var, int pass, NodeList **init) +{ + Node *r, *a; + NodeList *nl; + Node *index, *value; + + for(nl=n->list; nl; nl=nl->next) { + r = nl->n; + if(r->op != OKEY) + fatal("structlit: rhs not OKEY: %N", r); + index = r->left; + value = r->right; + + switch(value->op) { + case OARRAYLIT: + if(value->type->bound < 0) + break; + a = nod(ODOT, var, newname(index->sym)); + arraylit(value, a, pass, init); + continue; + + case OSTRUCTLIT: + a = nod(ODOT, var, newname(index->sym)); + structlit(value, a, pass, init); + continue; + } + + if(isliteral(value)) { + if(pass == 2) + continue; + } else + if(pass == 1) + continue; + + // build list of var.field = expr + a = nod(ODOT, var, newname(index->sym)); + a = nod(OAS, a, value); + typecheck(&a, Etop); + walkexpr(&a, init); + if(pass == 1) { + if(a->op != OAS) + fatal("structlit: not as"); + a->dodata = 2; + } + *init = list(*init, a); + } +} + +static void +arraylit(Node *n, Node *var, int pass, NodeList **init) +{ + Node *r, *a; + NodeList *l; + Node *index, *value; + + for(l=n->list; l; l=l->next) { + r = l->n; + if(r->op != OKEY) + fatal("arraylit: rhs not OKEY: %N", r); + index = r->left; + value = r->right; + + switch(value->op) { + case OARRAYLIT: + if(value->type->bound < 0) + break; + a = nod(OINDEX, var, index); + arraylit(value, a, pass, init); + continue; + + case OSTRUCTLIT: + a = nod(OINDEX, var, index); + structlit(value, a, pass, init); + continue; + } + + if(isliteral(index) && isliteral(value)) { + if(pass == 2) + continue; + } else + if(pass == 1) + continue; + + // build list of var[index] = value + a = nod(OINDEX, var, index); + a = nod(OAS, a, value); + typecheck(&a, Etop); + walkexpr(&a, init); // add any assignments in r to top + if(pass == 1) { + if(a->op != OAS) + fatal("structlit: not as"); + a->dodata = 2; + } + *init = list(*init, a); + } +} + +static void +slicelit(Node *n, Node *var, NodeList **init) +{ + Node *r, *a; + NodeList *l; + Type *t; + Node *vstat, *vheap; + Node *index, *value; + + // make an array type + t = shallow(n->type); + t->bound = mpgetfix(n->right->val.u.xval); + t->width = 0; + dowidth(t); + + // make static initialized array + vstat = staticname(t); + arraylit(n, vstat, 1, init); + + // make new *array heap + vheap = nod(OXXX, N, N); + tempname(vheap, ptrto(t)); + + a = nod(ONEW, N, N); + a->list = list1(typenod(t)); + a = nod(OAS, vheap, a); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + + // copy static to heap + a = nod(OIND, vheap, N); + a = nod(OAS, a, vstat); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + + // make slice out of heap + a = nod(OAS, var, vheap); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + + // put dynamics into slice + for(l=n->list; l; l=l->next) { + r = l->n; + if(r->op != OKEY) + fatal("slicelit: rhs not OKEY: %N", r); + index = r->left; + value = r->right; + + switch(value->op) { + case OARRAYLIT: + if(value->type->bound < 0) + break; + a = nod(OINDEX, var, index); + arraylit(value, a, 2, init); + continue; + + case OSTRUCTLIT: + a = nod(OINDEX, var, index); + structlit(value, a, 2, init); + continue; + } + + if(isliteral(index) && isliteral(value)) + continue; + + // build list of var[c] = expr + a = nod(OINDEX, var, index); + a = nod(OAS, a, value); + typecheck(&a, Etop); + walkexpr(&a, init); // add any assignments in r to top + *init = list(*init, a); + } +} + +static void +maplit(Node *n, Node *var, NodeList **init) +{ + Node *r, *a; + NodeList *l; + int nerr, b; + Type *t, *tk, *tv, *t1; + Node *vstat, *index, *value; + Sym *syma, *symb; + + // make the map var + nerr = nerrors; + + a = nod(OMAKE, N, N); + a->list = list1(typenod(n->type)); + a = nod(OAS, var, a); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + + // count the initializers + b = 0; + for(l=n->list; l; l=l->next) { + r = l->n; + + if(r->op != OKEY) + fatal("slicelit: rhs not OKEY: %N", r); + index = r->left; + value = r->right; + + if(isliteral(index) && isliteral(value)) + b++; + } + + t = T; + if(b != 0) { + // build type [count]struct { a Tindex, b Tvalue } + t = n->type; + tk = t->down; + tv = t->type; + + symb = lookup("b"); + t = typ(TFIELD); + t->type = tv; + t->sym = symb; + + syma = lookup("a"); + t1 = t; + t = typ(TFIELD); + t->type = tk; + t->sym = syma; + t->down = t1; + + t1 = t; + t = typ(TSTRUCT); + t->type = t1; + + t1 = t; + t = typ(TARRAY); + t->bound = b; + t->type = t1; + + dowidth(t); + + // make and initialize static array + vstat = staticname(t); + b = 0; + for(l=n->list; l; l=l->next) { + r = l->n; + + if(r->op != OKEY) + fatal("slicelit: rhs not OKEY: %N", r); + index = r->left; + value = r->right; + + if(isliteral(index) && isliteral(value)) { + // build vstat[b].a = key; + a = nodintconst(b); + a = nod(OINDEX, vstat, a); + a = nod(ODOT, a, newname(syma)); + a = nod(OAS, a, index); + typecheck(&a, Etop); + walkexpr(&a, init); + a->dodata = 2; + *init = list(*init, a); + + // build vstat[b].b = value; + a = nodintconst(b); + a = nod(OINDEX, vstat, a); + a = nod(ODOT, a, newname(symb)); + a = nod(OAS, a, value); + typecheck(&a, Etop); + walkexpr(&a, init); + a->dodata = 2; + *init = list(*init, a); + + b++; + } + } + + // loop adding structure elements to map + // for i = 0; i < len(vstat); i++ { + // map[vstat[i].a] = vstat[i].b + // } + index = nod(OXXX, N, N); + tempname(index, types[TINT]); + + a = nod(OINDEX, vstat, index); + a = nod(ODOT, a, newname(symb)); + + r = nod(OINDEX, vstat, index); + r = nod(ODOT, r, newname(syma)); + r = nod(OINDEX, var, r); + + r = nod(OAS, r, a); + + a = nod(OFOR, N, N); + a->nbody = list1(r); + + a->ninit = list1(nod(OAS, index, nodintconst(0))); + a->ntest = nod(OLT, index, nodintconst(t->bound)); + a->nincr = nod(OASOP, index, nodintconst(1)); + a->nincr->etype = OADD; + + typecheck(&a, Etop); + walkstmt(&a); + *init = list(*init, a); + } + + // put in dynamic entries one-at-a-time + for(l=n->list; l; l=l->next) { + r = l->n; + + if(r->op != OKEY) + fatal("slicelit: rhs not OKEY: %N", r); + index = r->left; + value = r->right; + + if(isliteral(index) && isliteral(value)) + continue; + + // build list of var[c] = expr + a = nod(OINDEX, var, r->left); + a = nod(OAS, a, r->right); + typecheck(&a, Etop); + walkexpr(&a, init); + if(nerr != nerrors) + break; + + *init = list(*init, a); + } +} + +void +anylit(Node *n, Node *var, NodeList **init) +{ + Type *t; + Node *a, *vstat; + + t = n->type; + switch(n->op) { + default: + fatal("anylit: not lit"); + + case OSTRUCTLIT: + if(t->etype != TSTRUCT) + fatal("anylit: not struct"); + + if(simplename(var)) { + + // lay out static data + vstat = staticname(t); + structlit(n, vstat, 1, init); + + // copy static to automatic + a = nod(OAS, var, vstat); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + + // add expressions to automatic + structlit(n, var, 2, init); + break; + } + + // initialize of not completely specified + if(count(n->list) < structcount(t)) { + a = nod(OAS, var, N); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + } + structlit(n, var, 3, init); + break; + + case OARRAYLIT: + if(t->etype != TARRAY) + fatal("anylit: not array"); + if(t->bound < 0) { + slicelit(n, var, init); + break; + } + + if(simplename(var)) { + + // lay out static data + vstat = staticname(t); + arraylit(n, vstat, 1, init); + + // copy static to automatic + a = nod(OAS, var, vstat); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + + // add expressions to automatic + arraylit(n, var, 2, init); + break; + } + + // initialize of not completely specified + if(count(n->list) < t->bound) { + a = nod(OAS, var, N); + typecheck(&a, Etop); + walkexpr(&a, init); + *init = list(*init, a); + } + arraylit(n, var, 3, init); + break; + + case OMAPLIT: + if(t->etype != TMAP) + fatal("anylit: not map"); + maplit(n, var, init); + break; + } +} + +int +oaslit(Node *n, NodeList **init) +{ + Type *t; + Node *vstat, *a; + + if(n->left == N || n->right == N) + goto no; + if(n->left->type == T || n->right->type == T) + goto no; + if(!simplename(n->left)) + goto no; + if(!eqtype(n->left->type, n->right->type)) + goto no; + if(n->dodata == 1) + goto initctxt; + + switch(n->right->op) { + default: + goto no; + + case OSTRUCTLIT: + case OARRAYLIT: + case OMAPLIT: + if(vmatch1(n->left, n->right)) + goto no; + anylit(n->right, n->left, init); + break; + } + n->op = OEMPTY; + return 1; + +no: + // not a special composit literal assignment + return 0; + +initctxt: + // in the initialization context + // we are trying to put data statements + // right into the initialized variables + switch(n->right->op) { + default: + goto no; + + case OSTRUCTLIT: + structlit(n->right, n->left, 1, init); + structlit(n->right, n->left, 2, init); + break; + + case OARRAYLIT: + t = n->right->type; + if(t == T) + goto no; + if(t->bound >= 0) { + arraylit(n->right, n->left, 1, init); + arraylit(n->right, n->left, 2, init); + break; + } + + // make a static slice + // make an array type + t = shallow(t); + t->bound = mpgetfix(n->right->right->val.u.xval); + t->width = 0; + dowidth(t); + + // make static initialized array + vstat = staticname(t); + arraylit(n->right, vstat, 1, init); + arraylit(n->right, vstat, 2, init); + + // copy static to slice + a = nod(OADDR, vstat, N); + a = nod(OAS, n->left, a); + typecheck(&a, Etop); +// turns into a function that is hard to parse +// in ggen where it is turned into DATA statements +// walkexpr(&a, init); + a->dodata = 2; + *init = list(*init, a); + break; + + case OMAPLIT: + maplit(n->right, n->left, init); + break; + } + n->op = OEMPTY; + return 1; +} |