github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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)	// zeroed
   290  		return 1;
   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  				if(!staticassign(ll, e->expr, out)) {
   358  					// Requires computation, but we're
   359  					// copying someone else's computation.
   360  					rr = nod(OXXX, N, N);
   361  					*rr = *orig;
   362  					rr->type = ll->type;
   363  					rr->xoffset += e->xoffset;
   364  					*out = list(*out, nod(OAS, ll, rr));
   365  				}
   366  			}
   367  		}
   368  		return 1;
   369  	}
   370  	return 0;
   371  }
   372  
   373  static int
   374  staticassign(Node *l, Node *r, NodeList **out)
   375  {
   376  	Node *a, n1;
   377  	Type *ta;
   378  	InitPlan *p;
   379  	InitEntry *e;
   380  	int i;
   381  	
   382  	switch(r->op) {
   383  	default:
   384  		//dump("not static", r);
   385  		break;
   386  	
   387  	case ONAME:
   388  		if(r->class == PEXTERN && r->sym->pkg == localpkg)
   389  			return staticcopy(l, r, out);
   390  		break;
   391  
   392  	case OLITERAL:
   393  		if(iszero(r))
   394  			return 1;
   395  		gdata(l, r, l->type->width);
   396  		return 1;
   397  
   398  	case OADDR:
   399  		switch(r->left->op) {
   400  		default:
   401  			//dump("not static addr", r);
   402  			break;
   403  
   404  		case ONAME:
   405  			gdata(l, r, l->type->width);
   406  			return 1;
   407  		}
   408  	
   409  	case OPTRLIT:
   410  		switch(r->left->op) {
   411  		default:
   412  			//dump("not static ptrlit", r);
   413  			break;
   414  
   415  		case OARRAYLIT:
   416  		case OMAPLIT:
   417  		case OSTRUCTLIT:
   418  			// Init pointer.
   419  			a = staticname(r->left->type, 1);
   420  			r->nname = a;
   421  			gdata(l, nod(OADDR, a, N), l->type->width);
   422  			// Init underlying literal.
   423  			if(!staticassign(a, r->left, out))
   424  				*out = list(*out, nod(OAS, a, r->left));
   425  			return 1;
   426  		}
   427  		break;
   428  
   429  	case OARRAYLIT:
   430  		initplan(r);
   431  		if(isslice(r->type)) {
   432  			// Init slice.
   433  			ta = typ(TARRAY);
   434  			ta->type = r->type->type;
   435  			ta->bound = mpgetfix(r->right->val.u.xval);
   436  			a = staticname(ta, 1);
   437  			r->nname = a;
   438  			n1 = *l;
   439  			n1.xoffset = l->xoffset + Array_array;
   440  			gdata(&n1, nod(OADDR, a, N), widthptr);
   441  			n1.xoffset = l->xoffset + Array_nel;
   442  			gdata(&n1, r->right, widthint);
   443  			n1.xoffset = l->xoffset + Array_cap;
   444  			gdata(&n1, r->right, widthint);
   445  			// Fall through to init underlying array.
   446  			l = a;
   447  		}
   448  		// fall through
   449  	case OSTRUCTLIT:
   450  		initplan(r);
   451  		p = r->initplan;
   452  		n1 = *l;
   453  		for(i=0; i<p->len; i++) {
   454  			e = &p->e[i];
   455  			n1.xoffset = l->xoffset + e->xoffset;
   456  			n1.type = e->expr->type;
   457  			if(e->expr->op == OLITERAL)
   458  				gdata(&n1, e->expr, n1.type->width);
   459  			else {
   460  				a = nod(OXXX, N, N);
   461  				*a = n1;
   462  				if(!staticassign(a, e->expr, out))
   463  					*out = list(*out, nod(OAS, a, e->expr));
   464  			}
   465  		}
   466  		return 1;
   467  
   468  	case OMAPLIT:
   469  		// TODO: Table-driven map insert.
   470  		break;
   471  	}
   472  	return 0;
   473  }
   474  
   475  /*
   476   * from here down is the walk analysis
   477   * of composite literals.
   478   * most of the work is to generate
   479   * data statements for the constant
   480   * part of the composite literal.
   481   */
   482  
   483  static	void	structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
   484  static	void	arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
   485  static	void	slicelit(int ctxt, Node *n, Node *var, NodeList **init);
   486  static	void	maplit(int ctxt, Node *n, Node *var, NodeList **init);
   487  
   488  static Node*
   489  staticname(Type *t, int ctxt)
   490  {
   491  	Node *n;
   492  
   493  	snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen);
   494  	statuniqgen++;
   495  	n = newname(lookup(namebuf));
   496  	if(!ctxt)
   497  		n->readonly = 1;
   498  	addvar(n, t, PEXTERN);
   499  	return n;
   500  }
   501  
   502  static int
   503  isliteral(Node *n)
   504  {
   505  	if(n->op == OLITERAL)
   506  		if(n->val.ctype != CTNIL)
   507  			return 1;
   508  	return 0;
   509  }
   510  
   511  static int
   512  simplename(Node *n)
   513  {
   514  	if(n->op != ONAME)
   515  		goto no;
   516  	if(!n->addable)
   517  		goto no;
   518  	if(n->class & PHEAP)
   519  		goto no;
   520  	if(n->class == PPARAMREF)
   521  		goto no;
   522  	return 1;
   523  
   524  no:
   525  	return 0;
   526  }
   527  
   528  static void
   529  litas(Node *l, Node *r, NodeList **init)
   530  {
   531  	Node *a;
   532  
   533  	a = nod(OAS, l, r);
   534  	typecheck(&a, Etop);
   535  	walkexpr(&a, init);
   536  	*init = list(*init, a);
   537  }
   538  
   539  enum
   540  {
   541  	MODEDYNAM	= 1,
   542  	MODECONST	= 2,
   543  };
   544  
   545  static int
   546  getdyn(Node *n, int top)
   547  {
   548  	NodeList *nl;
   549  	Node *value;
   550  	int mode;
   551  
   552  	mode = 0;
   553  	switch(n->op) {
   554  	default:
   555  		if(isliteral(n))
   556  			return MODECONST;
   557  		return MODEDYNAM;
   558  	case OARRAYLIT:
   559  		if(!top && n->type->bound < 0)
   560  			return MODEDYNAM;
   561  	case OSTRUCTLIT:
   562  		break;
   563  	}
   564  
   565  	for(nl=n->list; nl; nl=nl->next) {
   566  		value = nl->n->right;
   567  		mode |= getdyn(value, 0);
   568  		if(mode == (MODEDYNAM|MODECONST))
   569  			break;
   570  	}
   571  	return mode;
   572  }
   573  
   574  static void
   575  structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
   576  {
   577  	Node *r, *a;
   578  	NodeList *nl;
   579  	Node *index, *value;
   580  
   581  	for(nl=n->list; nl; nl=nl->next) {
   582  		r = nl->n;
   583  		if(r->op != OKEY)
   584  			fatal("structlit: rhs not OKEY: %N", r);
   585  		index = r->left;
   586  		value = r->right;
   587  
   588  		switch(value->op) {
   589  		case OARRAYLIT:
   590  			if(value->type->bound < 0) {
   591  				if(pass == 1 && ctxt != 0) {
   592  					a = nod(ODOT, var, newname(index->sym));
   593  					slicelit(ctxt, value, a, init);
   594  				} else
   595  				if(pass == 2 && ctxt == 0) {
   596  					a = nod(ODOT, var, newname(index->sym));
   597  					slicelit(ctxt, value, a, init);
   598  				} else
   599  				if(pass == 3)
   600  					break;
   601  				continue;
   602  			}
   603  			a = nod(ODOT, var, newname(index->sym));
   604  			arraylit(ctxt, pass, value, a, init);
   605  			continue;
   606  
   607  		case OSTRUCTLIT:
   608  			a = nod(ODOT, var, newname(index->sym));
   609  			structlit(ctxt, pass, value, a, init);
   610  			continue;
   611  		}
   612  
   613  		if(isliteral(value)) {
   614  			if(pass == 2)
   615  				continue;
   616  		} else
   617  			if(pass == 1)
   618  				continue;
   619  
   620  		// build list of var.field = expr
   621  		a = nod(ODOT, var, newname(index->sym));
   622  		a = nod(OAS, a, value);
   623  		typecheck(&a, Etop);
   624  		walkexpr(&a, init);
   625  		if(pass == 1) {
   626  			if(a->op != OAS)
   627  				fatal("structlit: not as");
   628  			a->dodata = 2;
   629  		}
   630  		*init = list(*init, a);
   631  	}
   632  }
   633  
   634  static void
   635  arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
   636  {
   637  	Node *r, *a;
   638  	NodeList *l;
   639  	Node *index, *value;
   640  
   641  	for(l=n->list; l; l=l->next) {
   642  		r = l->n;
   643  		if(r->op != OKEY)
   644  			fatal("arraylit: rhs not OKEY: %N", r);
   645  		index = r->left;
   646  		value = r->right;
   647  
   648  		switch(value->op) {
   649  		case OARRAYLIT:
   650  			if(value->type->bound < 0) {
   651  				if(pass == 1 && ctxt != 0) {
   652  					a = nod(OINDEX, var, index);
   653  					slicelit(ctxt, value, a, init);
   654  				} else
   655  				if(pass == 2 && ctxt == 0) {
   656  					a = nod(OINDEX, var, index);
   657  					slicelit(ctxt, value, a, init);
   658  				} else
   659  				if(pass == 3)
   660  					break;
   661  				continue;
   662  			}
   663  			a = nod(OINDEX, var, index);
   664  			arraylit(ctxt, pass, value, a, init);
   665  			continue;
   666  
   667  		case OSTRUCTLIT:
   668  			a = nod(OINDEX, var, index);
   669  			structlit(ctxt, pass, value, a, init);
   670  			continue;
   671  		}
   672  
   673  		if(isliteral(index) && isliteral(value)) {
   674  			if(pass == 2)
   675  				continue;
   676  		} else
   677  			if(pass == 1)
   678  				continue;
   679  
   680  		// build list of var[index] = value
   681  		a = nod(OINDEX, var, index);
   682  		a = nod(OAS, a, value);
   683  		typecheck(&a, Etop);
   684  		walkexpr(&a, init);	// add any assignments in r to top
   685  		if(pass == 1) {
   686  			if(a->op != OAS)
   687  				fatal("structlit: not as");
   688  			a->dodata = 2;
   689  		}
   690  		*init = list(*init, a);
   691  	}
   692  }
   693  
   694  static void
   695  slicelit(int ctxt, Node *n, Node *var, NodeList **init)
   696  {
   697  	Node *r, *a;
   698  	NodeList *l;
   699  	Type *t;
   700  	Node *vstat, *vauto;
   701  	Node *index, *value;
   702  	int mode;
   703  
   704  	// make an array type
   705  	t = shallow(n->type);
   706  	t->bound = mpgetfix(n->right->val.u.xval);
   707  	t->width = 0;
   708  	t->sym = nil;
   709  	t->haspointers = 0;
   710  	dowidth(t);
   711  
   712  	if(ctxt != 0) {
   713  		// put everything into static array
   714  		vstat = staticname(t, ctxt);
   715  		arraylit(ctxt, 1, n, vstat, init);
   716  		arraylit(ctxt, 2, n, vstat, init);
   717  
   718  		// copy static to slice
   719  		a = nod(OSLICE, vstat, nod(OKEY, N, N));
   720  		a = nod(OAS, var, a);
   721  		typecheck(&a, Etop);
   722  		a->dodata = 2;
   723  		*init = list(*init, a);
   724  		return;
   725  	}
   726  
   727  	// recipe for var = []t{...}
   728  	// 1. make a static array
   729  	//	var vstat [...]t
   730  	// 2. assign (data statements) the constant part
   731  	//	vstat = constpart{}
   732  	// 3. make an auto pointer to array and allocate heap to it
   733  	//	var vauto *[...]t = new([...]t)
   734  	// 4. copy the static array to the auto array
   735  	//	*vauto = vstat
   736  	// 5. assign slice of allocated heap to var
   737  	//	var = [0:]*auto
   738  	// 6. for each dynamic part assign to the slice
   739  	//	var[i] = dynamic part
   740  	//
   741  	// an optimization is done if there is no constant part
   742  	//	3. var vauto *[...]t = new([...]t)
   743  	//	5. var = [0:]*auto
   744  	//	6. var[i] = dynamic part
   745  
   746  	// if the literal contains constants,
   747  	// make static initialized array (1),(2)
   748  	vstat = N;
   749  	mode = getdyn(n, 1);
   750  	if(mode & MODECONST) {
   751  		vstat = staticname(t, ctxt);
   752  		arraylit(ctxt, 1, n, vstat, init);
   753  	}
   754  
   755  	// make new auto *array (3 declare)
   756  	vauto = temp(ptrto(t));
   757  
   758  	// set auto to point at new temp or heap (3 assign)
   759  	if(n->esc == EscNone) {
   760  		a = nod(OAS, temp(t), N);
   761  		typecheck(&a, Etop);
   762  		*init = list(*init, a);  // zero new temp
   763  		a = nod(OADDR, a->left, N);
   764  	} else {
   765  		a = nod(ONEW, N, N);
   766  		a->list = list1(typenod(t));
   767  	}
   768  	a = nod(OAS, vauto, a);
   769  	typecheck(&a, Etop);
   770  	walkexpr(&a, init);
   771  	*init = list(*init, a);
   772  
   773  	if(vstat != N) {
   774  		// copy static to heap (4)
   775  		a = nod(OIND, vauto, N);
   776  		a = nod(OAS, a, vstat);
   777  		typecheck(&a, Etop);
   778  		walkexpr(&a, init);
   779  		*init = list(*init, a);
   780  	}
   781  
   782  	// make slice out of heap (5)
   783  	a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
   784  	typecheck(&a, Etop);
   785  	walkexpr(&a, init);
   786  	*init = list(*init, a);
   787  
   788  	// put dynamics into slice (6)
   789  	for(l=n->list; l; l=l->next) {
   790  		r = l->n;
   791  		if(r->op != OKEY)
   792  			fatal("slicelit: rhs not OKEY: %N", r);
   793  		index = r->left;
   794  		value = r->right;
   795  		a = nod(OINDEX, var, index);
   796  		a->bounded = 1;
   797  		// TODO need to check bounds?
   798  
   799  		switch(value->op) {
   800  		case OARRAYLIT:
   801  			if(value->type->bound < 0)
   802  				break;
   803  			arraylit(ctxt, 2, value, a, init);
   804  			continue;
   805  
   806  		case OSTRUCTLIT:
   807  			structlit(ctxt, 2, value, a, init);
   808  			continue;
   809  		}
   810  
   811  		if(isliteral(index) && isliteral(value))
   812  			continue;
   813  
   814  		// build list of var[c] = expr
   815  		a = nod(OAS, a, value);
   816  		typecheck(&a, Etop);
   817  		walkexpr(&a, init);
   818  		*init = list(*init, a);
   819  	}
   820  }
   821  
   822  static void
   823  maplit(int ctxt, Node *n, Node *var, NodeList **init)
   824  {
   825  	Node *r, *a;
   826  	NodeList *l;
   827  	int nerr;
   828  	int64 b;
   829  	Type *t, *tk, *tv, *t1;
   830  	Node *vstat, *index, *value;
   831  	Sym *syma, *symb;
   832  
   833  USED(ctxt);
   834  ctxt = 0;
   835  
   836  	// make the map var
   837  	nerr = nerrors;
   838  
   839  	a = nod(OMAKE, N, N);
   840  	a->list = list1(typenod(n->type));
   841  	litas(var, a, init);
   842  
   843  	// count the initializers
   844  	b = 0;
   845  	for(l=n->list; l; l=l->next) {
   846  		r = l->n;
   847  
   848  		if(r->op != OKEY)
   849  			fatal("slicelit: rhs not OKEY: %N", r);
   850  		index = r->left;
   851  		value = r->right;
   852  
   853  		if(isliteral(index) && isliteral(value))
   854  			b++;
   855  	}
   856  
   857  	if(b != 0) {
   858  		// build type [count]struct { a Tindex, b Tvalue }
   859  		t = n->type;
   860  		tk = t->down;
   861  		tv = t->type;
   862  
   863  		symb = lookup("b");
   864  		t = typ(TFIELD);
   865  		t->type = tv;
   866  		t->sym = symb;
   867  
   868  		syma = lookup("a");
   869  		t1 = t;
   870  		t = typ(TFIELD);
   871  		t->type = tk;
   872  		t->sym = syma;
   873  		t->down = t1;
   874  
   875  		t1 = t;
   876  		t = typ(TSTRUCT);
   877  		t->type = t1;
   878  
   879  		t1 = t;
   880  		t = typ(TARRAY);
   881  		t->bound = b;
   882  		t->type = t1;
   883  
   884  		dowidth(t);
   885  
   886  		// make and initialize static array
   887  		vstat = staticname(t, ctxt);
   888  		b = 0;
   889  		for(l=n->list; l; l=l->next) {
   890  			r = l->n;
   891  
   892  			if(r->op != OKEY)
   893  				fatal("slicelit: rhs not OKEY: %N", r);
   894  			index = r->left;
   895  			value = r->right;
   896  
   897  			if(isliteral(index) && isliteral(value)) {
   898  				// build vstat[b].a = key;
   899  				a = nodintconst(b);
   900  				a = nod(OINDEX, vstat, a);
   901  				a = nod(ODOT, a, newname(syma));
   902  				a = nod(OAS, a, index);
   903  				typecheck(&a, Etop);
   904  				walkexpr(&a, init);
   905  				a->dodata = 2;
   906  				*init = list(*init, a);
   907  
   908  				// build vstat[b].b = value;
   909  				a = nodintconst(b);
   910  				a = nod(OINDEX, vstat, a);
   911  				a = nod(ODOT, a, newname(symb));
   912  				a = nod(OAS, a, value);
   913  				typecheck(&a, Etop);
   914  				walkexpr(&a, init);
   915  				a->dodata = 2;
   916  				*init = list(*init, a);
   917  
   918  				b++;
   919  			}
   920  		}
   921  
   922  		// loop adding structure elements to map
   923  		// for i = 0; i < len(vstat); i++ {
   924  		//	map[vstat[i].a] = vstat[i].b
   925  		// }
   926  		index = temp(types[TINT]);
   927  
   928  		a = nod(OINDEX, vstat, index);
   929  		a->bounded = 1;
   930  		a = nod(ODOT, a, newname(symb));
   931  
   932  		r = nod(OINDEX, vstat, index);
   933  		r->bounded = 1;
   934  		r = nod(ODOT, r, newname(syma));
   935  		r = nod(OINDEX, var, r);
   936  
   937  		r = nod(OAS, r, a);
   938  
   939  		a = nod(OFOR, N, N);
   940  		a->nbody = list1(r);
   941  
   942  		a->ninit = list1(nod(OAS, index, nodintconst(0)));
   943  		a->ntest = nod(OLT, index, nodintconst(t->bound));
   944  		a->nincr = nod(OASOP, index, nodintconst(1));
   945  		a->nincr->etype = OADD;
   946  
   947  		typecheck(&a, Etop);
   948  		walkstmt(&a);
   949  		*init = list(*init, a);
   950  	}
   951  
   952  	// put in dynamic entries one-at-a-time
   953  	for(l=n->list; l; l=l->next) {
   954  		r = l->n;
   955  
   956  		if(r->op != OKEY)
   957  			fatal("slicelit: rhs not OKEY: %N", r);
   958  		index = r->left;
   959  		value = r->right;
   960  
   961  		if(isliteral(index) && isliteral(value))
   962  			continue;
   963  
   964  		// build list of var[c] = expr
   965  		a = nod(OINDEX, var, r->left);
   966  		a = nod(OAS, a, r->right);
   967  		typecheck(&a, Etop);
   968  		walkexpr(&a, init);
   969  		if(nerr != nerrors)
   970  			break;
   971  
   972  		*init = list(*init, a);
   973  	}
   974  }
   975  
   976  void
   977  anylit(int ctxt, Node *n, Node *var, NodeList **init)
   978  {
   979  	Type *t;
   980  	Node *a, *vstat, *r;
   981  
   982  	t = n->type;
   983  	switch(n->op) {
   984  	default:
   985  		fatal("anylit: not lit");
   986  
   987  	case OPTRLIT:
   988  		if(!isptr[t->etype])
   989  			fatal("anylit: not ptr");
   990  
   991  		r = nod(ONEW, N, N);
   992  		r->typecheck = 1;
   993  		r->type = t;
   994  		r->esc = n->esc;
   995  		walkexpr(&r, init);
   996  
   997  		a = nod(OAS, var, r);
   998  
   999  		typecheck(&a, Etop);
  1000  		*init = list(*init, a);
  1001  
  1002  		var = nod(OIND, var, N);
  1003  		typecheck(&var, Erv | Easgn);
  1004  		anylit(ctxt, n->left, var, init);
  1005  		break;
  1006  
  1007  	case OSTRUCTLIT:
  1008  		if(t->etype != TSTRUCT)
  1009  			fatal("anylit: not struct");
  1010  
  1011  		if(simplename(var)) {
  1012  
  1013  			if(ctxt == 0) {
  1014  				// lay out static data
  1015  				vstat = staticname(t, ctxt);
  1016  				structlit(ctxt, 1, n, vstat, init);
  1017  
  1018  				// copy static to var
  1019  				a = nod(OAS, var, vstat);
  1020  				typecheck(&a, Etop);
  1021  				walkexpr(&a, init);
  1022  				*init = list(*init, a);
  1023  
  1024  				// add expressions to automatic
  1025  				structlit(ctxt, 2, n, var, init);
  1026  				break;
  1027  			}
  1028  			structlit(ctxt, 1, n, var, init);
  1029  			structlit(ctxt, 2, n, var, init);
  1030  			break;
  1031  		}
  1032  
  1033  		// initialize of not completely specified
  1034  		if(count(n->list) < structcount(t)) {
  1035  			a = nod(OAS, var, N);
  1036  			typecheck(&a, Etop);
  1037  			walkexpr(&a, init);
  1038  			*init = list(*init, a);
  1039  		}
  1040  		structlit(ctxt, 3, n, var, init);
  1041  		break;
  1042  
  1043  	case OARRAYLIT:
  1044  		if(t->etype != TARRAY)
  1045  			fatal("anylit: not array");
  1046  		if(t->bound < 0) {
  1047  			slicelit(ctxt, n, var, init);
  1048  			break;
  1049  		}
  1050  
  1051  		if(simplename(var)) {
  1052  
  1053  			if(ctxt == 0) {
  1054  				// lay out static data
  1055  				vstat = staticname(t, ctxt);
  1056  				arraylit(1, 1, n, vstat, init);
  1057  
  1058  				// copy static to automatic
  1059  				a = nod(OAS, var, vstat);
  1060  				typecheck(&a, Etop);
  1061  				walkexpr(&a, init);
  1062  				*init = list(*init, a);
  1063  
  1064  				// add expressions to automatic
  1065  				arraylit(ctxt, 2, n, var, init);
  1066  				break;
  1067  			}
  1068  			arraylit(ctxt, 1, n, var, init);
  1069  			arraylit(ctxt, 2, n, var, init);
  1070  			break;
  1071  		}
  1072  
  1073  		// initialize of not completely specified
  1074  		if(count(n->list) < t->bound) {
  1075  			a = nod(OAS, var, N);
  1076  			typecheck(&a, Etop);
  1077  			walkexpr(&a, init);
  1078  			*init = list(*init, a);
  1079  		}
  1080  		arraylit(ctxt, 3, n, var, init);
  1081  		break;
  1082  
  1083  	case OMAPLIT:
  1084  		if(t->etype != TMAP)
  1085  			fatal("anylit: not map");
  1086  		maplit(ctxt, n, var, init);
  1087  		break;
  1088  	}
  1089  }
  1090  
  1091  int
  1092  oaslit(Node *n, NodeList **init)
  1093  {
  1094  	int ctxt;
  1095  
  1096  	if(n->left == N || n->right == N)
  1097  		goto no;
  1098  	if(n->left->type == T || n->right->type == T)
  1099  		goto no;
  1100  	if(!simplename(n->left))
  1101  		goto no;
  1102  	if(!eqtype(n->left->type, n->right->type))
  1103  		goto no;
  1104  
  1105  	// context is init() function.
  1106  	// implies generated data executed
  1107  	// exactly once and not subject to races.
  1108  	ctxt = 0;
  1109  //	if(n->dodata == 1)
  1110  //		ctxt = 1;
  1111  
  1112  	switch(n->right->op) {
  1113  	default:
  1114  		goto no;
  1115  
  1116  	case OSTRUCTLIT:
  1117  	case OARRAYLIT:
  1118  	case OMAPLIT:
  1119  		if(vmatch1(n->left, n->right))
  1120  			goto no;
  1121  		anylit(ctxt, n->right, n->left, init);
  1122  		break;
  1123  	}
  1124  	n->op = OEMPTY;
  1125  	return 1;
  1126  
  1127  no:
  1128  	// not a special composit literal assignment
  1129  	return 0;
  1130  }
  1131  
  1132  static int
  1133  getlit(Node *lit)
  1134  {
  1135  	if(smallintconst(lit))
  1136  		return mpgetfix(lit->val.u.xval);
  1137  	return -1;
  1138  }
  1139  
  1140  int
  1141  stataddr(Node *nam, Node *n)
  1142  {
  1143  	int l;
  1144  
  1145  	if(n == N)
  1146  		goto no;
  1147  
  1148  	switch(n->op) {
  1149  
  1150  	case ONAME:
  1151  		*nam = *n;
  1152  		return n->addable;
  1153  
  1154  	case ODOT:
  1155  		if(!stataddr(nam, n->left))
  1156  			break;
  1157  		nam->xoffset += n->xoffset;
  1158  		nam->type = n->type;
  1159  		return 1;
  1160  
  1161  	case OINDEX:
  1162  		if(n->left->type->bound < 0)
  1163  			break;
  1164  		if(!stataddr(nam, n->left))
  1165  			break;
  1166  		l = getlit(n->right);
  1167  		if(l < 0)
  1168  			break;
  1169  		// Check for overflow.
  1170  		if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
  1171  			break;
  1172   		nam->xoffset += l*n->type->width;
  1173  		nam->type = n->type;
  1174  		return 1;
  1175  	}
  1176  
  1177  no:
  1178  	return 0;
  1179  }
  1180  
  1181  int
  1182  gen_as_init(Node *n)
  1183  {
  1184  	Node *nr, *nl;
  1185  	Node nam, nod1;
  1186  
  1187  	if(n->dodata == 0)
  1188  		goto no;
  1189  
  1190  	nr = n->right;
  1191  	nl = n->left;
  1192  	if(nr == N) {
  1193  		if(!stataddr(&nam, nl))
  1194  			goto no;
  1195  		if(nam.class != PEXTERN)
  1196  			goto no;
  1197  		goto yes;
  1198  	}
  1199  
  1200  	if(nr->type == T || !eqtype(nl->type, nr->type))
  1201  		goto no;
  1202  
  1203  	if(!stataddr(&nam, nl))
  1204  		goto no;
  1205  
  1206  	if(nam.class != PEXTERN)
  1207  		goto no;
  1208  
  1209  	switch(nr->op) {
  1210  	default:
  1211  		goto no;
  1212  
  1213  	case OCONVNOP:
  1214  		nr = nr->left;
  1215  		if(nr == N || nr->op != OSLICEARR)
  1216  			goto no;
  1217  		// fall through
  1218  	
  1219  	case OSLICEARR:
  1220  		if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) {
  1221  			nr = nr->left;
  1222  			goto slice;
  1223  		}
  1224  		goto no;
  1225  
  1226  	case OLITERAL:
  1227  		break;
  1228  	}
  1229  
  1230  	switch(nr->type->etype) {
  1231  	default:
  1232  		goto no;
  1233  
  1234  	case TBOOL:
  1235  	case TINT8:
  1236  	case TUINT8:
  1237  	case TINT16:
  1238  	case TUINT16:
  1239  	case TINT32:
  1240  	case TUINT32:
  1241  	case TINT64:
  1242  	case TUINT64:
  1243  	case TINT:
  1244  	case TUINT:
  1245  	case TUINTPTR:
  1246  	case TPTR32:
  1247  	case TPTR64:
  1248  	case TFLOAT32:
  1249  	case TFLOAT64:
  1250  		gdata(&nam, nr, nr->type->width);
  1251  		break;
  1252  
  1253  	case TCOMPLEX64:
  1254  	case TCOMPLEX128:
  1255  		gdatacomplex(&nam, nr->val.u.cval);
  1256  		break;
  1257  
  1258  	case TSTRING:
  1259  		gdatastring(&nam, nr->val.u.sval);
  1260  		break;
  1261  	}
  1262  
  1263  yes:
  1264  	return 1;
  1265  
  1266  slice:
  1267  	gused(N); // in case the data is the dest of a goto
  1268  	nl = nr;
  1269  	if(nr == N || nr->op != OADDR)
  1270  		goto no;
  1271  	nr = nr->left;
  1272  	if(nr == N || nr->op != ONAME)
  1273  		goto no;
  1274  
  1275  	// nr is the array being converted to a slice
  1276  	if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0)
  1277  		goto no;
  1278  
  1279  	nam.xoffset += Array_array;
  1280  	gdata(&nam, nl, types[tptr]->width);
  1281  
  1282  	nam.xoffset += Array_nel-Array_array;
  1283  	nodconst(&nod1, types[TINT], nr->type->bound);
  1284  	gdata(&nam, &nod1, widthint);
  1285  
  1286  	nam.xoffset += Array_cap-Array_nel;
  1287  	gdata(&nam, &nod1, widthint);
  1288  
  1289  	goto yes;
  1290  
  1291  no:
  1292  	if(n->dodata == 2) {
  1293  		dump("\ngen_as_init", n);
  1294  		fatal("gen_as_init couldnt make data statement");
  1295  	}
  1296  	return 0;
  1297  }
  1298  
  1299  static int iszero(Node*);
  1300  static int isvaluelit(Node*);
  1301  static InitEntry* entry(InitPlan*);
  1302  static void addvalue(InitPlan*, vlong, Node*, Node*);
  1303  
  1304  static void
  1305  initplan(Node *n)
  1306  {
  1307  	InitPlan *p;
  1308  	Node *a;
  1309  	NodeList *l;
  1310  
  1311  	if(n->initplan != nil)
  1312  		return;
  1313  	p = mal(sizeof *p);
  1314  	n->initplan = p;
  1315  	switch(n->op) {
  1316  	default:
  1317  		fatal("initplan");
  1318  	case OARRAYLIT:
  1319  		for(l=n->list; l; l=l->next) {
  1320  			a = l->n;
  1321  			if(a->op != OKEY || !smallintconst(a->left))
  1322  				fatal("initplan arraylit");
  1323  			addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right);
  1324  		}
  1325  		break;
  1326  	case OSTRUCTLIT:
  1327  		for(l=n->list; l; l=l->next) {
  1328  			a = l->n;
  1329  			if(a->op != OKEY || a->left->type == T)
  1330  				fatal("initplan structlit");
  1331  			addvalue(p, a->left->type->width, N, a->right);
  1332  		}
  1333  		break;
  1334  	case OMAPLIT:
  1335  		for(l=n->list; l; l=l->next) {
  1336  			a = l->n;
  1337  			if(a->op != OKEY)
  1338  				fatal("initplan maplit");
  1339  			addvalue(p, -1, a->left, a->right);
  1340  		}
  1341  		break;
  1342  	}
  1343  }
  1344  
  1345  static void
  1346  addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n)
  1347  {
  1348  	int i;
  1349  	InitPlan *q;
  1350  	InitEntry *e;
  1351  
  1352  	USED(key);
  1353  
  1354  	// special case: zero can be dropped entirely
  1355  	if(iszero(n)) {
  1356  		p->zero += n->type->width;
  1357  		return;
  1358  	}
  1359  	
  1360  	// special case: inline struct and array (not slice) literals
  1361  	if(isvaluelit(n)) {
  1362  		initplan(n);
  1363  		q = n->initplan;
  1364  		for(i=0; i<q->len; i++) {
  1365  			e = entry(p);
  1366  			*e = q->e[i];
  1367  			e->xoffset += xoffset;
  1368  		}
  1369  		return;
  1370  	}
  1371  	
  1372  	// add to plan
  1373  	if(n->op == OLITERAL)
  1374  		p->lit += n->type->width;
  1375  	else
  1376  		p->expr += n->type->width;
  1377  
  1378  	e = entry(p);
  1379  	e->xoffset = xoffset;
  1380  	e->expr = n;
  1381  }
  1382  
  1383  static int
  1384  iszero(Node *n)
  1385  {
  1386  	NodeList *l;
  1387  
  1388  	switch(n->op) {
  1389  	case OLITERAL:
  1390  		switch(n->val.ctype) {
  1391  		default:
  1392  			dump("unexpected literal", n);
  1393  			fatal("iszero");
  1394  	
  1395  		case CTNIL:
  1396  			return 1;
  1397  		
  1398  		case CTSTR:
  1399  			return n->val.u.sval == nil || n->val.u.sval->len == 0;
  1400  	
  1401  		case CTBOOL:
  1402  			return n->val.u.bval == 0;
  1403  			
  1404  		case CTINT:
  1405  		case CTRUNE:
  1406  			return mpcmpfixc(n->val.u.xval, 0) == 0;
  1407  	
  1408  		case CTFLT:
  1409  			return mpcmpfltc(n->val.u.fval, 0) == 0;
  1410  	
  1411  		case CTCPLX:
  1412  			return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0;
  1413  		}
  1414  		break;
  1415  	case OARRAYLIT:
  1416  		if(isslice(n->type))
  1417  			break;
  1418  		// fall through
  1419  	case OSTRUCTLIT:
  1420  		for(l=n->list; l; l=l->next)
  1421  			if(!iszero(l->n->right))
  1422  				return 0;
  1423  		return 1;
  1424  	}
  1425  	return 0;
  1426  }
  1427  
  1428  static int
  1429  isvaluelit(Node *n)
  1430  {
  1431  	return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT;
  1432  }
  1433  
  1434  static InitEntry*
  1435  entry(InitPlan *p)
  1436  {
  1437  	if(p->len >= p->cap) {
  1438  		if(p->cap == 0)
  1439  			p->cap = 4;
  1440  		else
  1441  			p->cap *= 2;
  1442  		p->e = realloc(p->e, p->cap*sizeof p->e[0]);
  1443  		if(p->e == nil)
  1444  			fatal("out of memory");
  1445  	}
  1446  	return &p->e[p->len++];
  1447  }