github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/gc/sinit.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6   * static initialization
     7   */
     8  
     9  #include	<u.h>
    10  #include	<libc.h>
    11  #include	"go.h"
    12  
    13  enum
    14  {
    15  	InitNotStarted = 0,
    16  	InitDone = 1,
    17  	InitPending = 2,
    18  };
    19  
    20  static int iszero(Node*);
    21  static void initplan(Node*);
    22  static NodeList *initlist;
    23  static void init2(Node*, NodeList**);
    24  static void init2list(NodeList*, NodeList**);
    25  static int staticinit(Node*, NodeList**);
    26  static Node *staticname(Type*, int);
    27  
    28  // init1 walks the AST starting at n, and accumulates in out
    29  // the list of definitions needing init code in dependency order.
    30  static void
    31  init1(Node *n, NodeList **out)
    32  {
    33  	NodeList *l;
    34  	Node *nv;
    35  
    36  	if(n == N)
    37  		return;
    38  	init1(n->left, out);
    39  	init1(n->right, out);
    40  	for(l=n->list; l; l=l->next)
    41  		init1(l->n, out);
    42  
    43  	if(n->left && n->type && n->left->op == OTYPE && n->class == PFUNC) {
    44  		// Methods called as Type.Method(receiver, ...).
    45  		// Definitions for method expressions are stored in type->nname.
    46  		init1(n->type->nname, out);
    47  	}
    48  
    49  	if(n->op != ONAME)
    50  		return;
    51  	switch(n->class) {
    52  	case PEXTERN:
    53  	case PFUNC:
    54  		break;
    55  	default:
    56  		if(isblank(n) && n->curfn == N && n->defn != N && n->defn->initorder == InitNotStarted) {
    57  			// blank names initialization is part of init() but not
    58  			// when they are inside a function.
    59  			break;
    60  		}
    61  		return;
    62  	}
    63  
    64  	if(n->initorder == InitDone)
    65  		return;
    66  	if(n->initorder == InitPending) {
    67  		// Since mutually recursive sets of functions are allowed,
    68  		// we don't necessarily raise an error if n depends on a node
    69  		// which is already waiting for its dependencies to be visited.
    70  		//
    71  		// initlist contains a cycle of identifiers referring to each other.
    72  		// If this cycle contains a variable, then this variable refers to itself.
    73  		// Conversely, if there exists an initialization cycle involving
    74  		// a variable in the program, the tree walk will reach a cycle
    75  		// involving that variable.
    76  		if(n->class != PFUNC) {
    77  			nv = n;
    78  			goto foundinitloop;
    79  		}
    80  		for(l=initlist; l->n!=n; l=l->next) {
    81  			if(l->n->class != PFUNC) {
    82  				nv = l->n;
    83  				goto foundinitloop;
    84  			}
    85  		}
    86  		// The loop involves only functions, ok.
    87  		return;
    88  
    89  	foundinitloop:
    90  		// if there have already been errors printed,
    91  		// those errors probably confused us and
    92  		// there might not be a loop.  let the user
    93  		// fix those first.
    94  		flusherrors();
    95  		if(nerrors > 0)
    96  			errorexit();
    97  
    98  		// There is a loop involving nv. We know about
    99  		// n and initlist = n1 <- ... <- nv <- ... <- n <- ...
   100  		print("%L: initialization loop:\n", nv->lineno);
   101  		// Build back pointers in initlist.
   102  		for(l=initlist; l; l=l->next)
   103  			if(l->next != nil)
   104  				l->next->end = l;
   105  		// Print nv -> ... -> n1 -> n.
   106  		for(l=initlist; l->n!=nv; l=l->next);
   107  		for(; l; l=l->end)
   108  			print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
   109  		// Print n -> ... -> nv.
   110  		for(l=initlist; l->n!=n; l=l->next);
   111  		for(; l->n != nv; l=l->end)
   112  			print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
   113  		print("\t%L %S\n", nv->lineno, nv->sym);
   114  		errorexit();
   115  	}
   116  
   117  	// reached a new unvisited node.
   118  	n->initorder = InitPending;
   119  	l = malloc(sizeof *l);
   120  	if(l == nil) {
   121  		flusherrors();
   122  		yyerror("out of memory");
   123  		errorexit();
   124  	}
   125  	l->next = initlist;
   126  	l->n = n;
   127  	l->end = nil;
   128  	initlist = l;
   129  
   130  	// make sure that everything n depends on is initialized.
   131  	// n->defn is an assignment to n
   132  	if(n->defn != N) {
   133  		switch(n->defn->op) {
   134  		default:
   135  			goto bad;
   136  
   137  		case ODCLFUNC:
   138  			init2list(n->defn->nbody, out);
   139  			break;
   140  
   141  		case OAS:
   142  			if(n->defn->left != n)
   143  				goto bad;
   144  			if(isblank(n->defn->left) && candiscard(n->defn->right)) {
   145  				n->defn->op = OEMPTY;
   146  				n->defn->left = N;
   147  				n->defn->right = N;
   148  				break;
   149  			}
   150  
   151  			init2(n->defn->right, out);
   152  			if(debug['j'])
   153  				print("%S\n", n->sym);
   154  			if(isblank(n) || !staticinit(n, out)) {
   155  				if(debug['%'])
   156  					dump("nonstatic", n->defn);
   157  				*out = list(*out, n->defn);
   158  			}
   159  			break;
   160  
   161  		case OAS2FUNC:
   162  		case OAS2MAPR:
   163  		case OAS2DOTTYPE:
   164  		case OAS2RECV:
   165  			if(n->defn->initorder != InitNotStarted)
   166  				break;
   167  			n->defn->initorder = InitDone;
   168  			for(l=n->defn->rlist; l; l=l->next)
   169  				init1(l->n, out);
   170  			if(debug['%']) dump("nonstatic", n->defn);
   171  			*out = list(*out, n->defn);
   172  			break;
   173  		}
   174  	}
   175  	l = initlist;
   176  	initlist = l->next;
   177  	if(l->n != n)
   178  		fatal("bad initlist");
   179  	free(l);
   180  	n->initorder = InitDone;
   181  	return;
   182  
   183  bad:
   184  	dump("defn", n->defn);
   185  	fatal("init1: bad defn");
   186  }
   187  
   188  // recurse over n, doing init1 everywhere.
   189  static void
   190  init2(Node *n, NodeList **out)
   191  {
   192  	if(n == N || n->initorder == InitDone)
   193  		return;
   194  
   195  	if(n->op == ONAME && n->ninit)
   196  		fatal("name %S with ninit: %+N\n", n->sym, n);
   197  
   198  	init1(n, out);
   199  	init2(n->left, out);
   200  	init2(n->right, out);
   201  	init2(n->ntest, out);
   202  	init2list(n->ninit, out);
   203  	init2list(n->list, out);
   204  	init2list(n->rlist, out);
   205  	init2list(n->nbody, out);
   206  	init2list(n->nelse, out);
   207  	
   208  	if(n->op == OCLOSURE)
   209  		init2list(n->closure->nbody, out);
   210  	if(n->op == ODOTMETH)
   211  		init2(n->type->nname, out);
   212  }
   213  
   214  static void
   215  init2list(NodeList *l, NodeList **out)
   216  {
   217  	for(; l; l=l->next)
   218  		init2(l->n, out);
   219  }
   220  
   221  static void
   222  initreorder(NodeList *l, NodeList **out)
   223  {
   224  	Node *n;
   225  
   226  	for(; l; l=l->next) {
   227  		n = l->n;
   228  		switch(n->op) {
   229  		case ODCLFUNC:
   230  		case ODCLCONST:
   231  		case ODCLTYPE:
   232  			continue;
   233  		}
   234  		initreorder(n->ninit, out);
   235  		n->ninit = nil;
   236  		init1(n, out);
   237  	}
   238  }
   239  
   240  // initfix computes initialization order for a list l of top-level
   241  // declarations and outputs the corresponding list of statements
   242  // to include in the init() function body.
   243  NodeList*
   244  initfix(NodeList *l)
   245  {
   246  	NodeList *lout;
   247  	int lno;
   248  
   249  	lout = nil;
   250  	lno = lineno;
   251  	initreorder(l, &lout);
   252  	lineno = lno;
   253  	return lout;
   254  }
   255  
   256  /*
   257   * compilation of top-level (static) assignments
   258   * into DATA statements if at all possible.
   259   */
   260  
   261  static int staticassign(Node*, Node*, NodeList**);
   262  
   263  static int
   264  staticinit(Node *n, NodeList **out)
   265  {
   266  	Node *l, *r;
   267  
   268  	if(n->op != ONAME || n->class != PEXTERN || n->defn == N || n->defn->op != OAS)
   269  		fatal("staticinit");
   270  
   271  	lineno = n->lineno;
   272  	l = n->defn->left;
   273  	r = n->defn->right;
   274  	return staticassign(l, r, out);
   275  }
   276  
   277  // like staticassign but we are copying an already
   278  // initialized value r.
   279  static int
   280  staticcopy(Node *l, Node *r, NodeList **out)
   281  {
   282  	int i;
   283  	InitEntry *e;
   284  	InitPlan *p;
   285  	Node *a, *ll, *rr, *orig, n1;
   286  
   287  	if(r->op != ONAME || r->class != PEXTERN || r->sym->pkg != localpkg)
   288  		return 0;
   289  	if(r->defn == N)	// probably zeroed but perhaps supplied externally and of unknown value
   290  		return 0;
   291  	if(r->defn->op != OAS)
   292  		return 0;
   293  	orig = r;
   294  	r = r->defn->right;
   295  	
   296  	switch(r->op) {
   297  	case ONAME:
   298  		if(staticcopy(l, r, out))
   299  			return 1;
   300  		*out = list(*out, nod(OAS, l, r));
   301  		return 1;
   302  	
   303  	case OLITERAL:
   304  		if(iszero(r))
   305  			return 1;
   306  		gdata(l, r, l->type->width);
   307  		return 1;
   308  
   309  	case OADDR:
   310  		switch(r->left->op) {
   311  		case ONAME:
   312  			gdata(l, r, l->type->width);
   313  			return 1;
   314  		}
   315  		break;
   316  	
   317  	case OPTRLIT:
   318  		switch(r->left->op) {
   319  		default:
   320  			//dump("not static addr", r);
   321  			break;
   322  		case OARRAYLIT:
   323  		case OSTRUCTLIT:
   324  		case OMAPLIT:
   325  			// copy pointer
   326  			gdata(l, nod(OADDR, r->nname, N), l->type->width);
   327  			return 1;
   328  		}
   329  		break;
   330  
   331  	case OARRAYLIT:
   332  		if(isslice(r->type)) {
   333  			// copy slice
   334  			a = r->nname;
   335  			n1 = *l;
   336  			n1.xoffset = l->xoffset + Array_array;
   337  			gdata(&n1, nod(OADDR, a, N), widthptr);
   338  			n1.xoffset = l->xoffset + Array_nel;
   339  			gdata(&n1, r->right, widthint);
   340  			n1.xoffset = l->xoffset + Array_cap;
   341  			gdata(&n1, r->right, widthint);
   342  			return 1;
   343  		}
   344  		// fall through
   345  	case OSTRUCTLIT:
   346  		p = r->initplan;
   347  		n1 = *l;
   348  		for(i=0; i<p->len; i++) {
   349  			e = &p->e[i];
   350  			n1.xoffset = l->xoffset + e->xoffset;
   351  			n1.type = e->expr->type;
   352  			if(e->expr->op == OLITERAL)
   353  				gdata(&n1, e->expr, n1.type->width);
   354  			else {
   355  				ll = nod(OXXX, N, N);
   356  				*ll = n1;
   357  				ll->orig = ll; // completely separate copy
   358  				if(!staticassign(ll, e->expr, out)) {
   359  					// Requires computation, but we're
   360  					// copying someone else's computation.
   361  					rr = nod(OXXX, N, N);
   362  					*rr = *orig;
   363  					rr->orig = rr; // completely separate copy
   364  					rr->type = ll->type;
   365  					rr->xoffset += e->xoffset;
   366  					*out = list(*out, nod(OAS, ll, rr));
   367  				}
   368  			}
   369  		}
   370  		return 1;
   371  	}
   372  	return 0;
   373  }
   374  
   375  static int
   376  staticassign(Node *l, Node *r, NodeList **out)
   377  {
   378  	Node *a, n1;
   379  	Type *ta;
   380  	InitPlan *p;
   381  	InitEntry *e;
   382  	int i;
   383  	Strlit *sval;
   384  	
   385  	switch(r->op) {
   386  	default:
   387  		//dump("not static", r);
   388  		break;
   389  	
   390  	case ONAME:
   391  		if(r->class == PEXTERN && r->sym->pkg == localpkg)
   392  			return staticcopy(l, r, out);
   393  		break;
   394  
   395  	case OLITERAL:
   396  		if(iszero(r))
   397  			return 1;
   398  		gdata(l, r, l->type->width);
   399  		return 1;
   400  
   401  	case OADDR:
   402  		switch(r->left->op) {
   403  		default:
   404  			//dump("not static addr", r);
   405  			break;
   406  
   407  		case ONAME:
   408  			gdata(l, r, l->type->width);
   409  			return 1;
   410  		}
   411  	
   412  	case OPTRLIT:
   413  		switch(r->left->op) {
   414  		default:
   415  			//dump("not static ptrlit", r);
   416  			break;
   417  
   418  		case OARRAYLIT:
   419  		case OMAPLIT:
   420  		case OSTRUCTLIT:
   421  			// Init pointer.
   422  			a = staticname(r->left->type, 1);
   423  			r->nname = a;
   424  			gdata(l, nod(OADDR, a, N), l->type->width);
   425  			// Init underlying literal.
   426  			if(!staticassign(a, r->left, out))
   427  				*out = list(*out, nod(OAS, a, r->left));
   428  			return 1;
   429  		}
   430  		break;
   431  
   432  	case OSTRARRAYBYTE:
   433  		if(l->class == PEXTERN && r->left->op == OLITERAL) {
   434  			sval = r->left->val.u.sval;
   435  			slicebytes(l, sval->s, sval->len);
   436  			return 1;
   437  		}
   438  		break;
   439  
   440  	case OARRAYLIT:
   441  		initplan(r);
   442  		if(isslice(r->type)) {
   443  			// Init slice.
   444  			ta = typ(TARRAY);
   445  			ta->type = r->type->type;
   446  			ta->bound = mpgetfix(r->right->val.u.xval);
   447  			a = staticname(ta, 1);
   448  			r->nname = a;
   449  			n1 = *l;
   450  			n1.xoffset = l->xoffset + Array_array;
   451  			gdata(&n1, nod(OADDR, a, N), widthptr);
   452  			n1.xoffset = l->xoffset + Array_nel;
   453  			gdata(&n1, r->right, widthint);
   454  			n1.xoffset = l->xoffset + Array_cap;
   455  			gdata(&n1, r->right, widthint);
   456  			// Fall through to init underlying array.
   457  			l = a;
   458  		}
   459  		// fall through
   460  	case OSTRUCTLIT:
   461  		initplan(r);
   462  		p = r->initplan;
   463  		n1 = *l;
   464  		for(i=0; i<p->len; i++) {
   465  			e = &p->e[i];
   466  			n1.xoffset = l->xoffset + e->xoffset;
   467  			n1.type = e->expr->type;
   468  			if(e->expr->op == OLITERAL)
   469  				gdata(&n1, e->expr, n1.type->width);
   470  			else {
   471  				a = nod(OXXX, N, N);
   472  				*a = n1;
   473  				a->orig = a; // completely separate copy
   474  				if(!staticassign(a, e->expr, out))
   475  					*out = list(*out, nod(OAS, a, e->expr));
   476  			}
   477  		}
   478  		return 1;
   479  
   480  	case OMAPLIT:
   481  		// TODO: Table-driven map insert.
   482  		break;
   483  	}
   484  	return 0;
   485  }
   486  
   487  /*
   488   * from here down is the walk analysis
   489   * of composite literals.
   490   * most of the work is to generate
   491   * data statements for the constant
   492   * part of the composite literal.
   493   */
   494  
   495  static	void	structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
   496  static	void	arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
   497  static	void	slicelit(int ctxt, Node *n, Node *var, NodeList **init);
   498  static	void	maplit(int ctxt, Node *n, Node *var, NodeList **init);
   499  
   500  static Node*
   501  staticname(Type *t, int ctxt)
   502  {
   503  	Node *n;
   504  
   505  	snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen);
   506  	statuniqgen++;
   507  	n = newname(lookup(namebuf));
   508  	if(!ctxt)
   509  		n->readonly = 1;
   510  	addvar(n, t, PEXTERN);
   511  	return n;
   512  }
   513  
   514  static int
   515  isliteral(Node *n)
   516  {
   517  	if(n->op == OLITERAL)
   518  		if(n->val.ctype != CTNIL)
   519  			return 1;
   520  	return 0;
   521  }
   522  
   523  static int
   524  simplename(Node *n)
   525  {
   526  	if(n->op != ONAME)
   527  		goto no;
   528  	if(!n->addable)
   529  		goto no;
   530  	if(n->class & PHEAP)
   531  		goto no;
   532  	if(n->class == PPARAMREF)
   533  		goto no;
   534  	return 1;
   535  
   536  no:
   537  	return 0;
   538  }
   539  
   540  static void
   541  litas(Node *l, Node *r, NodeList **init)
   542  {
   543  	Node *a;
   544  
   545  	a = nod(OAS, l, r);
   546  	typecheck(&a, Etop);
   547  	walkexpr(&a, init);
   548  	*init = list(*init, a);
   549  }
   550  
   551  enum
   552  {
   553  	MODEDYNAM	= 1,
   554  	MODECONST	= 2,
   555  };
   556  
   557  static int
   558  getdyn(Node *n, int top)
   559  {
   560  	NodeList *nl;
   561  	Node *value;
   562  	int mode;
   563  
   564  	mode = 0;
   565  	switch(n->op) {
   566  	default:
   567  		if(isliteral(n))
   568  			return MODECONST;
   569  		return MODEDYNAM;
   570  	case OARRAYLIT:
   571  		if(!top && n->type->bound < 0)
   572  			return MODEDYNAM;
   573  	case OSTRUCTLIT:
   574  		break;
   575  	}
   576  
   577  	for(nl=n->list; nl; nl=nl->next) {
   578  		value = nl->n->right;
   579  		mode |= getdyn(value, 0);
   580  		if(mode == (MODEDYNAM|MODECONST))
   581  			break;
   582  	}
   583  	return mode;
   584  }
   585  
   586  static void
   587  structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
   588  {
   589  	Node *r, *a;
   590  	NodeList *nl;
   591  	Node *index, *value;
   592  
   593  	for(nl=n->list; nl; nl=nl->next) {
   594  		r = nl->n;
   595  		if(r->op != OKEY)
   596  			fatal("structlit: rhs not OKEY: %N", r);
   597  		index = r->left;
   598  		value = r->right;
   599  
   600  		switch(value->op) {
   601  		case OARRAYLIT:
   602  			if(value->type->bound < 0) {
   603  				if(pass == 1 && ctxt != 0) {
   604  					a = nod(ODOT, var, newname(index->sym));
   605  					slicelit(ctxt, value, a, init);
   606  				} else
   607  				if(pass == 2 && ctxt == 0) {
   608  					a = nod(ODOT, var, newname(index->sym));
   609  					slicelit(ctxt, value, a, init);
   610  				} else
   611  				if(pass == 3)
   612  					break;
   613  				continue;
   614  			}
   615  			a = nod(ODOT, var, newname(index->sym));
   616  			arraylit(ctxt, pass, value, a, init);
   617  			continue;
   618  
   619  		case OSTRUCTLIT:
   620  			a = nod(ODOT, var, newname(index->sym));
   621  			structlit(ctxt, pass, value, a, init);
   622  			continue;
   623  		}
   624  
   625  		if(isliteral(value)) {
   626  			if(pass == 2)
   627  				continue;
   628  		} else
   629  			if(pass == 1)
   630  				continue;
   631  
   632  		// build list of var.field = expr
   633  		a = nod(ODOT, var, newname(index->sym));
   634  		a = nod(OAS, a, value);
   635  		typecheck(&a, Etop);
   636  		walkexpr(&a, init);
   637  		if(pass == 1) {
   638  			if(a->op != OAS)
   639  				fatal("structlit: not as");
   640  			a->dodata = 2;
   641  		}
   642  		*init = list(*init, a);
   643  	}
   644  }
   645  
   646  static void
   647  arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
   648  {
   649  	Node *r, *a;
   650  	NodeList *l;
   651  	Node *index, *value;
   652  
   653  	for(l=n->list; l; l=l->next) {
   654  		r = l->n;
   655  		if(r->op != OKEY)
   656  			fatal("arraylit: rhs not OKEY: %N", r);
   657  		index = r->left;
   658  		value = r->right;
   659  
   660  		switch(value->op) {
   661  		case OARRAYLIT:
   662  			if(value->type->bound < 0) {
   663  				if(pass == 1 && ctxt != 0) {
   664  					a = nod(OINDEX, var, index);
   665  					slicelit(ctxt, value, a, init);
   666  				} else
   667  				if(pass == 2 && ctxt == 0) {
   668  					a = nod(OINDEX, var, index);
   669  					slicelit(ctxt, value, a, init);
   670  				} else
   671  				if(pass == 3)
   672  					break;
   673  				continue;
   674  			}
   675  			a = nod(OINDEX, var, index);
   676  			arraylit(ctxt, pass, value, a, init);
   677  			continue;
   678  
   679  		case OSTRUCTLIT:
   680  			a = nod(OINDEX, var, index);
   681  			structlit(ctxt, pass, value, a, init);
   682  			continue;
   683  		}
   684  
   685  		if(isliteral(index) && isliteral(value)) {
   686  			if(pass == 2)
   687  				continue;
   688  		} else
   689  			if(pass == 1)
   690  				continue;
   691  
   692  		// build list of var[index] = value
   693  		a = nod(OINDEX, var, index);
   694  		a = nod(OAS, a, value);
   695  		typecheck(&a, Etop);
   696  		walkexpr(&a, init);	// add any assignments in r to top
   697  		if(pass == 1) {
   698  			if(a->op != OAS)
   699  				fatal("structlit: not as");
   700  			a->dodata = 2;
   701  		}
   702  		*init = list(*init, a);
   703  	}
   704  }
   705  
   706  static void
   707  slicelit(int ctxt, Node *n, Node *var, NodeList **init)
   708  {
   709  	Node *r, *a;
   710  	NodeList *l;
   711  	Type *t;
   712  	Node *vstat, *vauto;
   713  	Node *index, *value;
   714  	int mode;
   715  
   716  	// make an array type
   717  	t = shallow(n->type);
   718  	t->bound = mpgetfix(n->right->val.u.xval);
   719  	t->width = 0;
   720  	t->sym = nil;
   721  	t->haspointers = 0;
   722  	dowidth(t);
   723  
   724  	if(ctxt != 0) {
   725  		// put everything into static array
   726  		vstat = staticname(t, ctxt);
   727  		arraylit(ctxt, 1, n, vstat, init);
   728  		arraylit(ctxt, 2, n, vstat, init);
   729  
   730  		// copy static to slice
   731  		a = nod(OSLICE, vstat, nod(OKEY, N, N));
   732  		a = nod(OAS, var, a);
   733  		typecheck(&a, Etop);
   734  		a->dodata = 2;
   735  		*init = list(*init, a);
   736  		return;
   737  	}
   738  
   739  	// recipe for var = []t{...}
   740  	// 1. make a static array
   741  	//	var vstat [...]t
   742  	// 2. assign (data statements) the constant part
   743  	//	vstat = constpart{}
   744  	// 3. make an auto pointer to array and allocate heap to it
   745  	//	var vauto *[...]t = new([...]t)
   746  	// 4. copy the static array to the auto array
   747  	//	*vauto = vstat
   748  	// 5. assign slice of allocated heap to var
   749  	//	var = [0:]*auto
   750  	// 6. for each dynamic part assign to the slice
   751  	//	var[i] = dynamic part
   752  	//
   753  	// an optimization is done if there is no constant part
   754  	//	3. var vauto *[...]t = new([...]t)
   755  	//	5. var = [0:]*auto
   756  	//	6. var[i] = dynamic part
   757  
   758  	// if the literal contains constants,
   759  	// make static initialized array (1),(2)
   760  	vstat = N;
   761  	mode = getdyn(n, 1);
   762  	if(mode & MODECONST) {
   763  		vstat = staticname(t, ctxt);
   764  		arraylit(ctxt, 1, n, vstat, init);
   765  	}
   766  
   767  	// make new auto *array (3 declare)
   768  	vauto = temp(ptrto(t));
   769  
   770  	// set auto to point at new temp or heap (3 assign)
   771  	if(n->alloc != N) {
   772  		// temp allocated during order.c for dddarg
   773  		n->alloc->type = t;
   774  		if(vstat == N) {
   775  			a = nod(OAS, n->alloc, N);
   776  			typecheck(&a, Etop);
   777  			*init = list(*init, a);  // zero new temp
   778  		}
   779  		a = nod(OADDR, n->alloc, N);
   780  	} else if(n->esc == EscNone) {
   781  		a = temp(t);
   782  		if(vstat == N) {
   783  			a = nod(OAS, temp(t), N);
   784  			typecheck(&a, Etop);
   785  			*init = list(*init, a);  // zero new temp
   786  			a = a->left;
   787  		}
   788  		a = nod(OADDR, a, N);
   789  	} else {
   790  		a = nod(ONEW, N, N);
   791  		a->list = list1(typenod(t));
   792  	}
   793  	a = nod(OAS, vauto, a);
   794  	typecheck(&a, Etop);
   795  	walkexpr(&a, init);
   796  	*init = list(*init, a);
   797  
   798  	if(vstat != N) {
   799  		// copy static to heap (4)
   800  		a = nod(OIND, vauto, N);
   801  		a = nod(OAS, a, vstat);
   802  		typecheck(&a, Etop);
   803  		walkexpr(&a, init);
   804  		*init = list(*init, a);
   805  	}
   806  
   807  	// make slice out of heap (5)
   808  	a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
   809  	typecheck(&a, Etop);
   810  	walkexpr(&a, init);
   811  	*init = list(*init, a);
   812  
   813  	// put dynamics into slice (6)
   814  	for(l=n->list; l; l=l->next) {
   815  		r = l->n;
   816  		if(r->op != OKEY)
   817  			fatal("slicelit: rhs not OKEY: %N", r);
   818  		index = r->left;
   819  		value = r->right;
   820  		a = nod(OINDEX, var, index);
   821  		a->bounded = 1;
   822  		// TODO need to check bounds?
   823  
   824  		switch(value->op) {
   825  		case OARRAYLIT:
   826  			if(value->type->bound < 0)
   827  				break;
   828  			arraylit(ctxt, 2, value, a, init);
   829  			continue;
   830  
   831  		case OSTRUCTLIT:
   832  			structlit(ctxt, 2, value, a, init);
   833  			continue;
   834  		}
   835  
   836  		if(isliteral(index) && isliteral(value))
   837  			continue;
   838  
   839  		// build list of var[c] = expr
   840  		a = nod(OAS, a, value);
   841  		typecheck(&a, Etop);
   842  		walkexpr(&a, init);
   843  		*init = list(*init, a);
   844  	}
   845  }
   846  
   847  static void
   848  maplit(int ctxt, Node *n, Node *var, NodeList **init)
   849  {
   850  	Node *r, *a;
   851  	NodeList *l;
   852  	int nerr;
   853  	int64 b;
   854  	Type *t, *tk, *tv, *t1;
   855  	Node *vstat, *index, *value, *key, *val;
   856  	Sym *syma, *symb;
   857  
   858  USED(ctxt);
   859  ctxt = 0;
   860  
   861  	// make the map var
   862  	nerr = nerrors;
   863  
   864  	a = nod(OMAKE, N, N);
   865  	a->list = list1(typenod(n->type));
   866  	litas(var, a, init);
   867  
   868  	// count the initializers
   869  	b = 0;
   870  	for(l=n->list; l; l=l->next) {
   871  		r = l->n;
   872  
   873  		if(r->op != OKEY)
   874  			fatal("maplit: rhs not OKEY: %N", r);
   875  		index = r->left;
   876  		value = r->right;
   877  
   878  		if(isliteral(index) && isliteral(value))
   879  			b++;
   880  	}
   881  
   882  	if(b != 0) {
   883  		// build type [count]struct { a Tindex, b Tvalue }
   884  		t = n->type;
   885  		tk = t->down;
   886  		tv = t->type;
   887  
   888  		symb = lookup("b");
   889  		t = typ(TFIELD);
   890  		t->type = tv;
   891  		t->sym = symb;
   892  
   893  		syma = lookup("a");
   894  		t1 = t;
   895  		t = typ(TFIELD);
   896  		t->type = tk;
   897  		t->sym = syma;
   898  		t->down = t1;
   899  
   900  		t1 = t;
   901  		t = typ(TSTRUCT);
   902  		t->type = t1;
   903  
   904  		t1 = t;
   905  		t = typ(TARRAY);
   906  		t->bound = b;
   907  		t->type = t1;
   908  
   909  		dowidth(t);
   910  
   911  		// make and initialize static array
   912  		vstat = staticname(t, ctxt);
   913  		b = 0;
   914  		for(l=n->list; l; l=l->next) {
   915  			r = l->n;
   916  
   917  			if(r->op != OKEY)
   918  				fatal("maplit: rhs not OKEY: %N", r);
   919  			index = r->left;
   920  			value = r->right;
   921  
   922  			if(isliteral(index) && isliteral(value)) {
   923  				// build vstat[b].a = key;
   924  				a = nodintconst(b);
   925  				a = nod(OINDEX, vstat, a);
   926  				a = nod(ODOT, a, newname(syma));
   927  				a = nod(OAS, a, index);
   928  				typecheck(&a, Etop);
   929  				walkexpr(&a, init);
   930  				a->dodata = 2;
   931  				*init = list(*init, a);
   932  
   933  				// build vstat[b].b = value;
   934  				a = nodintconst(b);
   935  				a = nod(OINDEX, vstat, a);
   936  				a = nod(ODOT, a, newname(symb));
   937  				a = nod(OAS, a, value);
   938  				typecheck(&a, Etop);
   939  				walkexpr(&a, init);
   940  				a->dodata = 2;
   941  				*init = list(*init, a);
   942  
   943  				b++;
   944  			}
   945  		}
   946  
   947  		// loop adding structure elements to map
   948  		// for i = 0; i < len(vstat); i++ {
   949  		//	map[vstat[i].a] = vstat[i].b
   950  		// }
   951  		index = temp(types[TINT]);
   952  
   953  		a = nod(OINDEX, vstat, index);
   954  		a->bounded = 1;
   955  		a = nod(ODOT, a, newname(symb));
   956  
   957  		r = nod(OINDEX, vstat, index);
   958  		r->bounded = 1;
   959  		r = nod(ODOT, r, newname(syma));
   960  		r = nod(OINDEX, var, r);
   961  
   962  		r = nod(OAS, r, a);
   963  
   964  		a = nod(OFOR, N, N);
   965  		a->nbody = list1(r);
   966  
   967  		a->ninit = list1(nod(OAS, index, nodintconst(0)));
   968  		a->ntest = nod(OLT, index, nodintconst(t->bound));
   969  		a->nincr = nod(OAS, index, nod(OADD, index, nodintconst(1)));
   970  
   971  		typecheck(&a, Etop);
   972  		walkstmt(&a);
   973  		*init = list(*init, a);
   974  	}
   975  
   976  	// put in dynamic entries one-at-a-time
   977  	key = nil;
   978  	val = nil;
   979  	for(l=n->list; l; l=l->next) {
   980  		r = l->n;
   981  
   982  		if(r->op != OKEY)
   983  			fatal("maplit: rhs not OKEY: %N", r);
   984  		index = r->left;
   985  		value = r->right;
   986  
   987  		if(isliteral(index) && isliteral(value))
   988  			continue;
   989  			
   990  		// build list of var[c] = expr.
   991  		// use temporary so that mapassign1 can have addressable key, val.
   992  		if(key == nil) {
   993  			key = temp(var->type->down);
   994  			val = temp(var->type->type);
   995  		}
   996  		a = nod(OAS, key, r->left);
   997  		typecheck(&a, Etop);
   998  		walkstmt(&a);
   999  		*init = list(*init, a);
  1000  		a = nod(OAS, val, r->right);
  1001  		typecheck(&a, Etop);
  1002  		walkstmt(&a);
  1003  		*init = list(*init, a);
  1004  
  1005  		a = nod(OAS, nod(OINDEX, var, key), val);
  1006  		typecheck(&a, Etop);
  1007  		walkstmt(&a);
  1008  		*init = list(*init, a);
  1009  
  1010  		if(nerr != nerrors)
  1011  			break;
  1012  	}
  1013  	
  1014  	if(key != nil) {
  1015  		a = nod(OVARKILL, key, N);
  1016  		typecheck(&a, Etop);
  1017  		*init = list(*init, a);
  1018  		a = nod(OVARKILL, val, N);
  1019  		typecheck(&a, Etop);
  1020  		*init = list(*init, a);
  1021  	}
  1022  }
  1023  
  1024  void
  1025  anylit(int ctxt, Node *n, Node *var, NodeList **init)
  1026  {
  1027  	Type *t;
  1028  	Node *a, *vstat, *r;
  1029  
  1030  	t = n->type;
  1031  	switch(n->op) {
  1032  	default:
  1033  		fatal("anylit: not lit");
  1034  
  1035  	case OPTRLIT:
  1036  		if(!isptr[t->etype])
  1037  			fatal("anylit: not ptr");
  1038  
  1039  		if(n->right != N) {
  1040  			r = nod(OADDR, n->right, N);
  1041  			typecheck(&r, Erv);
  1042  		} else {
  1043  			r = nod(ONEW, N, N);
  1044  			r->typecheck = 1;
  1045  			r->type = t;
  1046  			r->esc = n->esc;
  1047  		}
  1048  		walkexpr(&r, init);
  1049  		a = nod(OAS, var, r);
  1050  
  1051  		typecheck(&a, Etop);
  1052  		*init = list(*init, a);
  1053  
  1054  		var = nod(OIND, var, N);
  1055  		typecheck(&var, Erv | Easgn);
  1056  		anylit(ctxt, n->left, var, init);
  1057  		break;
  1058  
  1059  	case OSTRUCTLIT:
  1060  		if(t->etype != TSTRUCT)
  1061  			fatal("anylit: not struct");
  1062  
  1063  		if(simplename(var)) {
  1064  
  1065  			if(ctxt == 0) {
  1066  				// lay out static data
  1067  				vstat = staticname(t, ctxt);
  1068  				structlit(ctxt, 1, n, vstat, init);
  1069  
  1070  				// copy static to var
  1071  				a = nod(OAS, var, vstat);
  1072  				typecheck(&a, Etop);
  1073  				walkexpr(&a, init);
  1074  				*init = list(*init, a);
  1075  
  1076  				// add expressions to automatic
  1077  				structlit(ctxt, 2, n, var, init);
  1078  				break;
  1079  			}
  1080  			structlit(ctxt, 1, n, var, init);
  1081  			structlit(ctxt, 2, n, var, init);
  1082  			break;
  1083  		}
  1084  
  1085  		// initialize of not completely specified
  1086  		if(count(n->list) < structcount(t)) {
  1087  			a = nod(OAS, var, N);
  1088  			typecheck(&a, Etop);
  1089  			walkexpr(&a, init);
  1090  			*init = list(*init, a);
  1091  		}
  1092  		structlit(ctxt, 3, n, var, init);
  1093  		break;
  1094  
  1095  	case OARRAYLIT:
  1096  		if(t->etype != TARRAY)
  1097  			fatal("anylit: not array");
  1098  		if(t->bound < 0) {
  1099  			slicelit(ctxt, n, var, init);
  1100  			break;
  1101  		}
  1102  
  1103  		if(simplename(var)) {
  1104  
  1105  			if(ctxt == 0) {
  1106  				// lay out static data
  1107  				vstat = staticname(t, ctxt);
  1108  				arraylit(1, 1, n, vstat, init);
  1109  
  1110  				// copy static to automatic
  1111  				a = nod(OAS, var, vstat);
  1112  				typecheck(&a, Etop);
  1113  				walkexpr(&a, init);
  1114  				*init = list(*init, a);
  1115  
  1116  				// add expressions to automatic
  1117  				arraylit(ctxt, 2, n, var, init);
  1118  				break;
  1119  			}
  1120  			arraylit(ctxt, 1, n, var, init);
  1121  			arraylit(ctxt, 2, n, var, init);
  1122  			break;
  1123  		}
  1124  
  1125  		// initialize of not completely specified
  1126  		if(count(n->list) < t->bound) {
  1127  			a = nod(OAS, var, N);
  1128  			typecheck(&a, Etop);
  1129  			walkexpr(&a, init);
  1130  			*init = list(*init, a);
  1131  		}
  1132  		arraylit(ctxt, 3, n, var, init);
  1133  		break;
  1134  
  1135  	case OMAPLIT:
  1136  		if(t->etype != TMAP)
  1137  			fatal("anylit: not map");
  1138  		maplit(ctxt, n, var, init);
  1139  		break;
  1140  	}
  1141  }
  1142  
  1143  int
  1144  oaslit(Node *n, NodeList **init)
  1145  {
  1146  	int ctxt;
  1147  
  1148  	if(n->left == N || n->right == N)
  1149  		goto no;
  1150  	if(n->left->type == T || n->right->type == T)
  1151  		goto no;
  1152  	if(!simplename(n->left))
  1153  		goto no;
  1154  	if(!eqtype(n->left->type, n->right->type))
  1155  		goto no;
  1156  
  1157  	// context is init() function.
  1158  	// implies generated data executed
  1159  	// exactly once and not subject to races.
  1160  	ctxt = 0;
  1161  //	if(n->dodata == 1)
  1162  //		ctxt = 1;
  1163  
  1164  	switch(n->right->op) {
  1165  	default:
  1166  		goto no;
  1167  
  1168  	case OSTRUCTLIT:
  1169  	case OARRAYLIT:
  1170  	case OMAPLIT:
  1171  		if(vmatch1(n->left, n->right))
  1172  			goto no;
  1173  		anylit(ctxt, n->right, n->left, init);
  1174  		break;
  1175  	}
  1176  	n->op = OEMPTY;
  1177  	return 1;
  1178  
  1179  no:
  1180  	// not a special composit literal assignment
  1181  	return 0;
  1182  }
  1183  
  1184  static int
  1185  getlit(Node *lit)
  1186  {
  1187  	if(smallintconst(lit))
  1188  		return mpgetfix(lit->val.u.xval);
  1189  	return -1;
  1190  }
  1191  
  1192  int
  1193  stataddr(Node *nam, Node *n)
  1194  {
  1195  	int l;
  1196  
  1197  	if(n == N)
  1198  		goto no;
  1199  
  1200  	switch(n->op) {
  1201  
  1202  	case ONAME:
  1203  		*nam = *n;
  1204  		return n->addable;
  1205  
  1206  	case ODOT:
  1207  		if(!stataddr(nam, n->left))
  1208  			break;
  1209  		nam->xoffset += n->xoffset;
  1210  		nam->type = n->type;
  1211  		return 1;
  1212  
  1213  	case OINDEX:
  1214  		if(n->left->type->bound < 0)
  1215  			break;
  1216  		if(!stataddr(nam, n->left))
  1217  			break;
  1218  		l = getlit(n->right);
  1219  		if(l < 0)
  1220  			break;
  1221  		// Check for overflow.
  1222  		if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
  1223  			break;
  1224   		nam->xoffset += l*n->type->width;
  1225  		nam->type = n->type;
  1226  		return 1;
  1227  	}
  1228  
  1229  no:
  1230  	return 0;
  1231  }
  1232  
  1233  int
  1234  gen_as_init(Node *n)
  1235  {
  1236  	Node *nr, *nl;
  1237  	Node nam, nod1;
  1238  
  1239  	if(n->dodata == 0)
  1240  		goto no;
  1241  
  1242  	nr = n->right;
  1243  	nl = n->left;
  1244  	if(nr == N) {
  1245  		if(!stataddr(&nam, nl))
  1246  			goto no;
  1247  		if(nam.class != PEXTERN)
  1248  			goto no;
  1249  		goto yes;
  1250  	}
  1251  
  1252  	if(nr->type == T || !eqtype(nl->type, nr->type))
  1253  		goto no;
  1254  
  1255  	if(!stataddr(&nam, nl))
  1256  		goto no;
  1257  
  1258  	if(nam.class != PEXTERN)
  1259  		goto no;
  1260  
  1261  	switch(nr->op) {
  1262  	default:
  1263  		goto no;
  1264  
  1265  	case OCONVNOP:
  1266  		nr = nr->left;
  1267  		if(nr == N || nr->op != OSLICEARR)
  1268  			goto no;
  1269  		// fall through
  1270  	
  1271  	case OSLICEARR:
  1272  		if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) {
  1273  			nr = nr->left;
  1274  			goto slice;
  1275  		}
  1276  		goto no;
  1277  
  1278  	case OLITERAL:
  1279  		break;
  1280  	}
  1281  
  1282  	switch(nr->type->etype) {
  1283  	default:
  1284  		goto no;
  1285  
  1286  	case TBOOL:
  1287  	case TINT8:
  1288  	case TUINT8:
  1289  	case TINT16:
  1290  	case TUINT16:
  1291  	case TINT32:
  1292  	case TUINT32:
  1293  	case TINT64:
  1294  	case TUINT64:
  1295  	case TINT:
  1296  	case TUINT:
  1297  	case TUINTPTR:
  1298  	case TPTR32:
  1299  	case TPTR64:
  1300  	case TFLOAT32:
  1301  	case TFLOAT64:
  1302  		gdata(&nam, nr, nr->type->width);
  1303  		break;
  1304  
  1305  	case TCOMPLEX64:
  1306  	case TCOMPLEX128:
  1307  		gdatacomplex(&nam, nr->val.u.cval);
  1308  		break;
  1309  
  1310  	case TSTRING:
  1311  		gdatastring(&nam, nr->val.u.sval);
  1312  		break;
  1313  	}
  1314  
  1315  yes:
  1316  	return 1;
  1317  
  1318  slice:
  1319  	gused(N); // in case the data is the dest of a goto
  1320  	nl = nr;
  1321  	if(nr == N || nr->op != OADDR)
  1322  		goto no;
  1323  	nr = nr->left;
  1324  	if(nr == N || nr->op != ONAME)
  1325  		goto no;
  1326  
  1327  	// nr is the array being converted to a slice
  1328  	if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0)
  1329  		goto no;
  1330  
  1331  	nam.xoffset += Array_array;
  1332  	gdata(&nam, nl, types[tptr]->width);
  1333  
  1334  	nam.xoffset += Array_nel-Array_array;
  1335  	nodconst(&nod1, types[TINT], nr->type->bound);
  1336  	gdata(&nam, &nod1, widthint);
  1337  
  1338  	nam.xoffset += Array_cap-Array_nel;
  1339  	gdata(&nam, &nod1, widthint);
  1340  
  1341  	goto yes;
  1342  
  1343  no:
  1344  	if(n->dodata == 2) {
  1345  		dump("\ngen_as_init", n);
  1346  		fatal("gen_as_init couldnt make data statement");
  1347  	}
  1348  	return 0;
  1349  }
  1350  
  1351  static int iszero(Node*);
  1352  static int isvaluelit(Node*);
  1353  static InitEntry* entry(InitPlan*);
  1354  static void addvalue(InitPlan*, vlong, Node*, Node*);
  1355  
  1356  static void
  1357  initplan(Node *n)
  1358  {
  1359  	InitPlan *p;
  1360  	Node *a;
  1361  	NodeList *l;
  1362  
  1363  	if(n->initplan != nil)
  1364  		return;
  1365  	p = mal(sizeof *p);
  1366  	n->initplan = p;
  1367  	switch(n->op) {
  1368  	default:
  1369  		fatal("initplan");
  1370  	case OARRAYLIT:
  1371  		for(l=n->list; l; l=l->next) {
  1372  			a = l->n;
  1373  			if(a->op != OKEY || !smallintconst(a->left))
  1374  				fatal("initplan arraylit");
  1375  			addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right);
  1376  		}
  1377  		break;
  1378  	case OSTRUCTLIT:
  1379  		for(l=n->list; l; l=l->next) {
  1380  			a = l->n;
  1381  			if(a->op != OKEY || a->left->type == T)
  1382  				fatal("initplan structlit");
  1383  			addvalue(p, a->left->type->width, N, a->right);
  1384  		}
  1385  		break;
  1386  	case OMAPLIT:
  1387  		for(l=n->list; l; l=l->next) {
  1388  			a = l->n;
  1389  			if(a->op != OKEY)
  1390  				fatal("initplan maplit");
  1391  			addvalue(p, -1, a->left, a->right);
  1392  		}
  1393  		break;
  1394  	}
  1395  }
  1396  
  1397  static void
  1398  addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n)
  1399  {
  1400  	int i;
  1401  	InitPlan *q;
  1402  	InitEntry *e;
  1403  
  1404  	USED(key);
  1405  
  1406  	// special case: zero can be dropped entirely
  1407  	if(iszero(n)) {
  1408  		p->zero += n->type->width;
  1409  		return;
  1410  	}
  1411  	
  1412  	// special case: inline struct and array (not slice) literals
  1413  	if(isvaluelit(n)) {
  1414  		initplan(n);
  1415  		q = n->initplan;
  1416  		for(i=0; i<q->len; i++) {
  1417  			e = entry(p);
  1418  			*e = q->e[i];
  1419  			e->xoffset += xoffset;
  1420  		}
  1421  		return;
  1422  	}
  1423  	
  1424  	// add to plan
  1425  	if(n->op == OLITERAL)
  1426  		p->lit += n->type->width;
  1427  	else
  1428  		p->expr += n->type->width;
  1429  
  1430  	e = entry(p);
  1431  	e->xoffset = xoffset;
  1432  	e->expr = n;
  1433  }
  1434  
  1435  static int
  1436  iszero(Node *n)
  1437  {
  1438  	NodeList *l;
  1439  
  1440  	switch(n->op) {
  1441  	case OLITERAL:
  1442  		switch(n->val.ctype) {
  1443  		default:
  1444  			dump("unexpected literal", n);
  1445  			fatal("iszero");
  1446  	
  1447  		case CTNIL:
  1448  			return 1;
  1449  		
  1450  		case CTSTR:
  1451  			return n->val.u.sval == nil || n->val.u.sval->len == 0;
  1452  	
  1453  		case CTBOOL:
  1454  			return n->val.u.bval == 0;
  1455  			
  1456  		case CTINT:
  1457  		case CTRUNE:
  1458  			return mpcmpfixc(n->val.u.xval, 0) == 0;
  1459  	
  1460  		case CTFLT:
  1461  			return mpcmpfltc(n->val.u.fval, 0) == 0;
  1462  	
  1463  		case CTCPLX:
  1464  			return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0;
  1465  		}
  1466  		break;
  1467  	case OARRAYLIT:
  1468  		if(isslice(n->type))
  1469  			break;
  1470  		// fall through
  1471  	case OSTRUCTLIT:
  1472  		for(l=n->list; l; l=l->next)
  1473  			if(!iszero(l->n->right))
  1474  				return 0;
  1475  		return 1;
  1476  	}
  1477  	return 0;
  1478  }
  1479  
  1480  static int
  1481  isvaluelit(Node *n)
  1482  {
  1483  	return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT;
  1484  }
  1485  
  1486  static InitEntry*
  1487  entry(InitPlan *p)
  1488  {
  1489  	if(p->len >= p->cap) {
  1490  		if(p->cap == 0)
  1491  			p->cap = 4;
  1492  		else
  1493  			p->cap *= 2;
  1494  		p->e = realloc(p->e, p->cap*sizeof p->e[0]);
  1495  		if(p->e == nil)
  1496  			fatal("out of memory");
  1497  	}
  1498  	return &p->e[p->len++];
  1499  }