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