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