diff options
Diffstat (limited to 'src/cmd/gc/sinit.c')
| -rw-r--r-- | src/cmd/gc/sinit.c | 971 |
1 files changed, 0 insertions, 971 deletions
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c deleted file mode 100644 index eb7ef31ec..000000000 --- a/src/cmd/gc/sinit.c +++ /dev/null @@ -1,971 +0,0 @@ -// 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. - -/* - * static initialization - */ - -#include "go.h" - -static NodeList *initlist; -static void init2(Node*, NodeList**); -static void init2list(NodeList*, NodeList**); - -static void -init1(Node *n, NodeList **out) -{ - NodeList *l; - - if(n == N) - return; - init1(n->left, out); - init1(n->right, out); - for(l=n->list; l; l=l->next) - init1(l->n, out); - - if(n->op != ONAME) - return; - switch(n->class) { - case PEXTERN: - case PFUNC: - break; - default: - if(isblank(n) && n->defn != N && !n->defn->initorder) { - n->defn->initorder = 1; - *out = list(*out, n->defn); - } - return; - } - - if(n->initorder == 1) - return; - if(n->initorder == 2) { - if(n->class == PFUNC) - return; - - // if there have already been errors printed, - // those errors probably confused us and - // there might not be a loop. let the user - // fix those first. - flusherrors(); - if(nerrors > 0) - errorexit(); - - print("initialization loop:\n"); - for(l=initlist;; l=l->next) { - if(l->next == nil) - break; - l->next->end = l; - } - for(; l; l=l->end) - print("\t%L %S refers to\n", l->n->lineno, l->n->sym); - print("\t%L %S\n", n->lineno, n->sym); - errorexit(); - } - n->initorder = 2; - l = malloc(sizeof *l); - l->next = initlist; - l->n = n; - l->end = nil; - initlist = l; - - // make sure that everything n depends on is initialized. - // n->defn is an assignment to n - if(n->defn != N) { - switch(n->defn->op) { - default: - goto bad; - - case ODCLFUNC: - init2list(n->defn->nbody, out); - break; - - case OAS: - if(n->defn->left != n) - goto bad; - n->defn->dodata = 1; - init1(n->defn->right, out); - if(debug['j']) - print("%S\n", n->sym); - *out = list(*out, n->defn); - break; - - case OAS2FUNC: - case OAS2MAPR: - case OAS2DOTTYPE: - case OAS2RECV: - if(n->defn->initorder) - break; - n->defn->initorder = 1; - for(l=n->defn->rlist; l; l=l->next) - init1(l->n, out); - *out = list(*out, n->defn); - break; - } - } - l = initlist; - initlist = l->next; - if(l->n != n) - fatal("bad initlist"); - free(l); - n->initorder = 1; - return; - -bad: - dump("defn", n->defn); - fatal("init1: bad defn"); -} - -// recurse over n, doing init1 everywhere. -static void -init2(Node *n, NodeList **out) -{ - if(n == N || n->initorder == 1) - return; - init1(n, out); - init2(n->left, out); - init2(n->right, out); - init2(n->ntest, out); - init2list(n->ninit, out); - init2list(n->list, out); - init2list(n->rlist, out); - init2list(n->nbody, out); - init2list(n->nelse, out); -} - -static void -init2list(NodeList *l, NodeList **out) -{ - for(; l; l=l->next) - init2(l->n, out); -} - - -static void -initreorder(NodeList *l, NodeList **out) -{ - Node *n; - - for(; l; l=l->next) { - n = l->n; - switch(n->op) { - case ODCLFUNC: - case ODCLCONST: - case ODCLTYPE: - continue; - } - initreorder(n->ninit, out); - n->ninit = nil; - init1(n, out); - } -} - -NodeList* -initfix(NodeList *l) -{ - NodeList *lout; - - lout = nil; - initreorder(l, &lout); - return lout; -} - -/* - * from here down is the walk analysis - * of composite literals. - * most of the work is to generate - * data statements for the constant - * part of the composite literal. - */ - -static void structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init); -static void arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init); -static void slicelit(int ctxt, Node *n, Node *var, NodeList **init); -static void maplit(int ctxt, Node *n, Node *var, NodeList **init); - -static Node* -staticname(Type *t, int ctxt) -{ - Node *n; - - snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen); - statuniqgen++; - n = newname(lookup(namebuf)); - if(!ctxt) - n->readonly = 1; - addvar(n, t, PEXTERN); - return n; -} - -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 -litas(Node *l, Node *r, NodeList **init) -{ - Node *a; - - a = nod(OAS, l, r); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); -} - -enum -{ - MODEDYNAM = 1, - MODECONST = 2, -}; - -static int -getdyn(Node *n, int top) -{ - NodeList *nl; - Node *value; - int mode; - - mode = 0; - switch(n->op) { - default: - if(isliteral(n)) - return MODECONST; - return MODEDYNAM; - case OARRAYLIT: - if(!top && n->type->bound < 0) - return MODEDYNAM; - case OSTRUCTLIT: - break; - } - - for(nl=n->list; nl; nl=nl->next) { - value = nl->n->right; - mode |= getdyn(value, 0); - if(mode == (MODEDYNAM|MODECONST)) - break; - } - return mode; -} - -static void -structlit(int ctxt, int pass, Node *n, Node *var, 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) { - if(pass == 1 && ctxt != 0) { - a = nod(ODOT, var, newname(index->sym)); - slicelit(ctxt, value, a, init); - } else - if(pass == 2 && ctxt == 0) { - a = nod(ODOT, var, newname(index->sym)); - slicelit(ctxt, value, a, init); - } else - if(pass == 3) - break; - continue; - } - a = nod(ODOT, var, newname(index->sym)); - arraylit(ctxt, pass, value, a, init); - continue; - - case OSTRUCTLIT: - a = nod(ODOT, var, newname(index->sym)); - structlit(ctxt, pass, value, a, 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(int ctxt, int pass, Node *n, Node *var, 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) { - if(pass == 1 && ctxt != 0) { - a = nod(OINDEX, var, index); - slicelit(ctxt, value, a, init); - } else - if(pass == 2 && ctxt == 0) { - a = nod(OINDEX, var, index); - slicelit(ctxt, value, a, init); - } else - if(pass == 3) - break; - continue; - } - a = nod(OINDEX, var, index); - arraylit(ctxt, pass, value, a, init); - continue; - - case OSTRUCTLIT: - a = nod(OINDEX, var, index); - structlit(ctxt, pass, value, a, 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(int ctxt, Node *n, Node *var, NodeList **init) -{ - Node *r, *a; - NodeList *l; - Type *t; - Node *vstat, *vauto; - Node *index, *value; - int mode; - - // make an array type - t = shallow(n->type); - t->bound = mpgetfix(n->right->val.u.xval); - t->width = 0; - t->sym = nil; - dowidth(t); - - if(ctxt != 0) { - - // put everything into static array - vstat = staticname(t, ctxt); - arraylit(ctxt, 1, n, vstat, init); - arraylit(ctxt, 2, n, vstat, init); - - // copy static to slice - a = nod(OSLICE, vstat, nod(OKEY, N, N)); - a = nod(OAS, var, a); - typecheck(&a, Etop); - a->dodata = 2; - *init = list(*init, a); - return; - } - - // recipe for var = []t{...} - // 1. make a static array - // var vstat [...]t - // 2. assign (data statements) the constant part - // vstat = constpart{} - // 3. make an auto pointer to array and allocate heap to it - // var vauto *[...]t = new([...]t) - // 4. copy the static array to the auto array - // *vauto = vstat - // 5. assign slice of allocated heap to var - // var = [0:]*auto - // 6. for each dynamic part assign to the slice - // var[i] = dynamic part - // - // an optimization is done if there is no constant part - // 3. var vauto *[...]t = new([...]t) - // 5. var = [0:]*auto - // 6. var[i] = dynamic part - - // if the literal contains constants, - // make static initialized array (1),(2) - vstat = N; - mode = getdyn(n, 1); - if(mode & MODECONST) { - vstat = staticname(t, ctxt); - arraylit(ctxt, 1, n, vstat, init); - } - - // make new auto *array (3 declare) - vauto = nod(OXXX, N, N); - tempname(vauto, ptrto(t)); - - // set auto to point at new heap (3 assign) - a = nod(ONEW, N, N); - a->list = list1(typenod(t)); - a = nod(OAS, vauto, a); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); - - if(vstat != N) { - // copy static to heap (4) - a = nod(OIND, vauto, N); - a = nod(OAS, a, vstat); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); - } - - // make slice out of heap (5) - a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N))); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); - - // put dynamics into slice (6) - 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; - a = nod(OINDEX, var, index); - a->etype = 1; // no bounds checking - // TODO need to check bounds? - - switch(value->op) { - case OARRAYLIT: - if(value->type->bound < 0) - break; - arraylit(ctxt, 2, value, a, init); - continue; - - case OSTRUCTLIT: - structlit(ctxt, 2, value, a, init); - continue; - } - - if(isliteral(index) && isliteral(value)) - continue; - - // build list of var[c] = expr - a = nod(OAS, a, value); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); - } -} - -static void -maplit(int ctxt, 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; - -ctxt = 0; - - // make the map var - nerr = nerrors; - - a = nod(OMAKE, N, N); - a->list = list1(typenod(n->type)); - litas(var, a, init); - - // 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, ctxt); - 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->etype = 1; // no bounds checking - a = nod(ODOT, a, newname(symb)); - - r = nod(OINDEX, vstat, index); - r->etype = 1; // no bounds checking - 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(int ctxt, 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)) { - - if(ctxt == 0) { - // lay out static data - vstat = staticname(t, ctxt); - structlit(1, 1, n, vstat, init); - - // copy static to var - a = nod(OAS, var, vstat); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); - - // add expressions to automatic - structlit(ctxt, 2, n, var, init); - break; - } - structlit(ctxt, 1, n, var, init); - structlit(ctxt, 2, n, var, 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(ctxt, 3, n, var, init); - break; - - case OARRAYLIT: - if(t->etype != TARRAY) - fatal("anylit: not array"); - if(t->bound < 0) { - slicelit(ctxt, n, var, init); - break; - } - - if(simplename(var)) { - - if(ctxt == 0) { - // lay out static data - vstat = staticname(t, ctxt); - arraylit(1, 1, n, vstat, 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(ctxt, 2, n, var, init); - break; - } - arraylit(ctxt, 1, n, var, init); - arraylit(ctxt, 2, n, var, 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(ctxt, 3, n, var, init); - break; - - case OMAPLIT: - if(t->etype != TMAP) - fatal("anylit: not map"); - maplit(ctxt, n, var, init); - break; - } -} - -int -oaslit(Node *n, NodeList **init) -{ - int ctxt; - - 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; - - // context is init() function. - // implies generated data executed - // exactly once and not subject to races. - ctxt = 0; -// if(n->dodata == 1) -// ctxt = 1; - - switch(n->right->op) { - default: - goto no; - - case OSTRUCTLIT: - case OARRAYLIT: - case OMAPLIT: - if(vmatch1(n->left, n->right)) - goto no; - anylit(ctxt, n->right, n->left, init); - break; - } - n->op = OEMPTY; - return 1; - -no: - // not a special composit literal assignment - return 0; -} - -static int -getlit(Node *lit) -{ - if(smallintconst(lit)) - return mpgetfix(lit->val.u.xval); - return -1; -} - -int -stataddr(Node *nam, Node *n) -{ - int l; - - if(n == N) - goto no; - - switch(n->op) { - - case ONAME: - *nam = *n; - return n->addable; - - case ODOT: - if(!stataddr(nam, n->left)) - break; - nam->xoffset += n->xoffset; - nam->type = n->type; - return 1; - - case OINDEX: - if(n->left->type->bound < 0) - break; - if(!stataddr(nam, n->left)) - break; - l = getlit(n->right); - if(l < 0) - break; - nam->xoffset += l*n->type->width; - nam->type = n->type; - return 1; - } - -no: - return 0; -} - -int -gen_as_init(Node *n) -{ - Node *nr, *nl; - Node nam, nod1; - - if(n->dodata == 0) - goto no; - - nr = n->right; - nl = n->left; - if(nr == N) { - if(!stataddr(&nam, nl)) - goto no; - if(nam.class != PEXTERN) - goto no; - goto yes; - } - - if(nr->type == T || !eqtype(nl->type, nr->type)) - goto no; - - if(!stataddr(&nam, nl)) - goto no; - - if(nam.class != PEXTERN) - goto no; - - switch(nr->op) { - default: - goto no; - - case OCONVNOP: - nr = nr->left; - if(nr == N || nr->op != OSLICEARR) - goto no; - // fall through - - case OSLICEARR: - if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) { - nr = nr->left; - goto slice; - } - goto no; - - case OLITERAL: - break; - } - - switch(nr->type->etype) { - default: - goto no; - - case TBOOL: - case TINT8: - case TUINT8: - case TINT16: - case TUINT16: - case TINT32: - case TUINT32: - case TINT64: - case TUINT64: - case TINT: - case TUINT: - case TUINTPTR: - case TPTR32: - case TPTR64: - case TFLOAT32: - case TFLOAT64: - gused(N); // in case the data is the dest of a goto - gdata(&nam, nr, nr->type->width); - break; - - case TCOMPLEX64: - case TCOMPLEX128: - gused(N); // in case the data is the dest of a goto - gdatacomplex(&nam, nr->val.u.cval); - break; - - case TSTRING: - gused(N); // in case the data is the dest of a goto - gdatastring(&nam, nr->val.u.sval); - break; - } - -yes: - return 1; - -slice: - gused(N); // in case the data is the dest of a goto - nl = nr; - if(nr == N || nr->op != OADDR) - goto no; - nr = nr->left; - if(nr == N || nr->op != ONAME) - goto no; - - // nr is the array being converted to a slice - if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0) - goto no; - - nam.xoffset += Array_array; - gdata(&nam, nl, types[tptr]->width); - - nam.xoffset += Array_nel-Array_array; - nodconst(&nod1, types[TINT32], nr->type->bound); - gdata(&nam, &nod1, types[TINT32]->width); - - nam.xoffset += Array_cap-Array_nel; - gdata(&nam, &nod1, types[TINT32]->width); - - goto yes; - -no: - if(n->dodata == 2) { - dump("\ngen_as_init", n); - fatal("gen_as_init couldnt make data statement"); - } - return 0; -} - |
