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