summaryrefslogtreecommitdiff
path: root/src/cmd/gc/sinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/sinit.c')
-rw-r--r--src/cmd/gc/sinit.c971
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;
-}
-