github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/cmd/gc/walk.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  #include	<u.h>
     6  #include	<libc.h>
     7  #include	"go.h"
     8  #include	"../ld/textflag.h"
     9  #include	"../../runtime/mgc0.h"
    10  
    11  static	Node*	walkprint(Node*, NodeList**);
    12  static	Node*	writebarrierfn(char*, Type*, Type*);
    13  static	Node*	applywritebarrier(Node*, NodeList**);
    14  static	Node*	mapfn(char*, Type*);
    15  static	Node*	mapfndel(char*, Type*);
    16  static	Node*	ascompatee1(int, Node*, Node*, NodeList**);
    17  static	NodeList*	ascompatee(int, NodeList*, NodeList*, NodeList**);
    18  static	NodeList*	ascompatet(int, NodeList*, Type**, int, NodeList**);
    19  static	NodeList*	ascompatte(int, Node*, int, Type**, NodeList*, int, NodeList**);
    20  static	Node*	convas(Node*, NodeList**);
    21  static	void	heapmoves(void);
    22  static	NodeList*	paramstoheap(Type **argin, int out);
    23  static	NodeList*	reorder1(NodeList*);
    24  static	NodeList*	reorder3(NodeList*);
    25  static	Node*	addstr(Node*, NodeList**);
    26  static	Node*	appendslice(Node*, NodeList**);
    27  static	Node*	append(Node*, NodeList**);
    28  static	Node*	copyany(Node*, NodeList**, int);
    29  static	Node*	sliceany(Node*, NodeList**);
    30  static	void	walkcompare(Node**, NodeList**);
    31  static	void	walkrotate(Node**);
    32  static	void	walkmul(Node**, NodeList**);
    33  static	void	walkdiv(Node**, NodeList**);
    34  static	int	bounded(Node*, int64);
    35  static	Mpint	mpzero;
    36  static	void	walkprintfunc(Node**, NodeList**);
    37  
    38  void
    39  walk(Node *fn)
    40  {
    41  	char s[50];
    42  	NodeList *l;
    43  	int lno;
    44  
    45  	curfn = fn;
    46  
    47  	if(debug['W']) {
    48  		snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
    49  		dumplist(s, curfn->nbody);
    50  	}
    51  
    52  	lno = lineno;
    53  
    54  	// Final typecheck for any unused variables.
    55  	// It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
    56  	for(l=fn->dcl; l; l=l->next)
    57  		if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO)
    58  			typecheck(&l->n, Erv | Easgn);
    59  
    60  	// Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
    61  	for(l=fn->dcl; l; l=l->next)
    62  		if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO && l->n->defn && l->n->defn->op == OTYPESW && l->n->used)
    63  			l->n->defn->left->used++;
    64  	
    65  	for(l=fn->dcl; l; l=l->next) {
    66  		if(l->n->op != ONAME || (l->n->class&~PHEAP) != PAUTO || l->n->sym->name[0] == '&' || l->n->used)
    67  			continue;
    68  		if(l->n->defn && l->n->defn->op == OTYPESW) {
    69  			if(l->n->defn->left->used)
    70  				continue;
    71  			lineno = l->n->defn->left->lineno;
    72  			yyerror("%S declared and not used", l->n->sym);
    73  			l->n->defn->left->used = 1; // suppress repeats
    74  		} else {
    75  			lineno = l->n->lineno;
    76  			yyerror("%S declared and not used", l->n->sym);
    77  		}
    78  	}	
    79  
    80  	lineno = lno;
    81  	if(nerrors != 0)
    82  		return;
    83  	walkstmtlist(curfn->nbody);
    84  	if(debug['W']) {
    85  		snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
    86  		dumplist(s, curfn->nbody);
    87  	}
    88  	heapmoves();
    89  	if(debug['W'] && curfn->enter != nil) {
    90  		snprint(s, sizeof(s), "enter %S", curfn->nname->sym);
    91  		dumplist(s, curfn->enter);
    92  	}
    93  }
    94  
    95  
    96  void
    97  walkstmtlist(NodeList *l)
    98  {
    99  	for(; l; l=l->next)
   100  		walkstmt(&l->n);
   101  }
   102  
   103  static int
   104  samelist(NodeList *a, NodeList *b)
   105  {
   106  	for(; a && b; a=a->next, b=b->next)
   107  		if(a->n != b->n)
   108  			return 0;
   109  	return a == b;
   110  }
   111  
   112  static int
   113  paramoutheap(Node *fn)
   114  {
   115  	NodeList *l;
   116  
   117  	for(l=fn->dcl; l; l=l->next) {
   118  		switch(l->n->class) {
   119  		case PPARAMOUT:
   120  		case PPARAMOUT|PHEAP:
   121  			return l->n->addrtaken;
   122  		case PAUTO:
   123  		case PAUTO|PHEAP:
   124  			// stop early - parameters are over
   125  			return 0;
   126  		}
   127  	}
   128  	return 0;
   129  }
   130  
   131  void
   132  walkstmt(Node **np)
   133  {
   134  	NodeList *init;
   135  	NodeList *ll, *rl;
   136  	int cl;
   137  	Node *n, *f;
   138  
   139  	n = *np;
   140  	if(n == N)
   141  		return;
   142  	if(n->dodata == 2) // don't walk, generated by anylit.
   143  		return;
   144  
   145  	setlineno(n);
   146  
   147  	walkstmtlist(n->ninit);
   148  
   149  	switch(n->op) {
   150  	default:
   151  		if(n->op == ONAME)
   152  			yyerror("%S is not a top level statement", n->sym);
   153  		else
   154  			yyerror("%O is not a top level statement", n->op);
   155  		dump("nottop", n);
   156  		break;
   157  
   158  	case OAS:
   159  	case OASOP:
   160  	case OAS2:
   161  	case OAS2DOTTYPE:
   162  	case OAS2RECV:
   163  	case OAS2FUNC:
   164  	case OAS2MAPR:
   165  	case OCLOSE:
   166  	case OCOPY:
   167  	case OCALLMETH:
   168  	case OCALLINTER:
   169  	case OCALL:
   170  	case OCALLFUNC:
   171  	case ODELETE:
   172  	case OSEND:
   173  	case OPRINT:
   174  	case OPRINTN:
   175  	case OPANIC:
   176  	case OEMPTY:
   177  	case ORECOVER:
   178  		if(n->typecheck == 0)
   179  			fatal("missing typecheck: %+N", n);
   180  		init = n->ninit;
   181  		n->ninit = nil;
   182  		walkexpr(&n, &init);
   183  		addinit(&n, init);
   184  		if((*np)->op == OCOPY && n->op == OCONVNOP)
   185  			n->op = OEMPTY; // don't leave plain values as statements.
   186  		break;
   187  
   188  	case ORECV:
   189  		// special case for a receive where we throw away
   190  		// the value received.
   191  		if(n->typecheck == 0)
   192  			fatal("missing typecheck: %+N", n);
   193  		init = n->ninit;
   194  		n->ninit = nil;
   195  
   196  		walkexpr(&n->left, &init);
   197  		n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, &init, typename(n->left->type), n->left, nodnil());
   198  		walkexpr(&n, &init);
   199  
   200  		addinit(&n, init);
   201  		break;
   202  
   203  	case OBREAK:
   204  	case ODCL:
   205  	case OCONTINUE:
   206  	case OFALL:
   207  	case OGOTO:
   208  	case OLABEL:
   209  	case ODCLCONST:
   210  	case ODCLTYPE:
   211  	case OCHECKNIL:
   212  	case OVARKILL:
   213  		break;
   214  
   215  	case OBLOCK:
   216  		walkstmtlist(n->list);
   217  		break;
   218  
   219  	case OXCASE:
   220  		yyerror("case statement out of place");
   221  		n->op = OCASE;
   222  	case OCASE:
   223  		walkstmt(&n->right);
   224  		break;
   225  
   226  	case ODEFER:
   227  		hasdefer = 1;
   228  		switch(n->left->op) {
   229  		case OPRINT:
   230  		case OPRINTN:
   231  			walkprintfunc(&n->left, &n->ninit);
   232  			break;
   233  		case OCOPY:
   234  			n->left = copyany(n->left, &n->ninit, 1);
   235  			break;
   236  		default:
   237  			walkexpr(&n->left, &n->ninit);
   238  			break;
   239  		}
   240  		break;
   241  
   242  	case OFOR:
   243  		if(n->ntest != N) {
   244  			walkstmtlist(n->ntest->ninit);
   245  			init = n->ntest->ninit;
   246  			n->ntest->ninit = nil;
   247  			walkexpr(&n->ntest, &init);
   248  			addinit(&n->ntest, init);
   249  		}
   250  		walkstmt(&n->nincr);
   251  		walkstmtlist(n->nbody);
   252  		break;
   253  
   254  	case OIF:
   255  		walkexpr(&n->ntest, &n->ninit);
   256  		walkstmtlist(n->nbody);
   257  		walkstmtlist(n->nelse);
   258  		break;
   259  
   260  	case OPROC:
   261  		switch(n->left->op) {
   262  		case OPRINT:
   263  		case OPRINTN:
   264  			walkprintfunc(&n->left, &n->ninit);
   265  			break;
   266  		case OCOPY:
   267  			n->left = copyany(n->left, &n->ninit, 1);
   268  			break;
   269  		default:
   270  			walkexpr(&n->left, &n->ninit);
   271  			break;
   272  		}
   273  		break;
   274  
   275  	case ORETURN:
   276  		walkexprlist(n->list, &n->ninit);
   277  		if(n->list == nil)
   278  			break;
   279  		if((curfn->type->outnamed && count(n->list) > 1) || paramoutheap(curfn)) {
   280  			// assign to the function out parameters,
   281  			// so that reorder3 can fix up conflicts
   282  			rl = nil;
   283  			for(ll=curfn->dcl; ll != nil; ll=ll->next) {
   284  				cl = ll->n->class & ~PHEAP;
   285  				if(cl == PAUTO)
   286  					break;
   287  				if(cl == PPARAMOUT)
   288  					rl = list(rl, ll->n);
   289  			}
   290  			if(samelist(rl, n->list)) {
   291  				// special return in disguise
   292  				n->list = nil;
   293  				break;
   294  			}
   295  			if(count(n->list) == 1 && count(rl) > 1) {
   296  				// OAS2FUNC in disguise
   297  				f = n->list->n;
   298  				if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
   299  					fatal("expected return of call, have %N", f);
   300  				n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
   301  				break;
   302  			}
   303  
   304  			// move function calls out, to make reorder3's job easier.
   305  			walkexprlistsafe(n->list, &n->ninit);
   306  			ll = ascompatee(n->op, rl, n->list, &n->ninit);
   307  			n->list = reorder3(ll);
   308  			break;
   309  		}
   310  		ll = ascompatte(n->op, nil, 0, getoutarg(curfn->type), n->list, 1, &n->ninit);
   311  		n->list = ll;
   312  		break;
   313  
   314  	case ORETJMP:
   315  		break;
   316  
   317  	case OSELECT:
   318  		walkselect(n);
   319  		break;
   320  
   321  	case OSWITCH:
   322  		walkswitch(n);
   323  		break;
   324  
   325  	case ORANGE:
   326  		walkrange(n);
   327  		break;
   328  
   329  	case OXFALL:
   330  		yyerror("fallthrough statement out of place");
   331  		n->op = OFALL;
   332  		break;
   333  	}
   334  
   335  	if(n->op == ONAME)
   336  		fatal("walkstmt ended up with name: %+N", n);
   337  	
   338  	*np = n;
   339  }
   340  
   341  
   342  /*
   343   * walk the whole tree of the body of an
   344   * expression or simple statement.
   345   * the types expressions are calculated.
   346   * compile-time constants are evaluated.
   347   * complex side effects like statements are appended to init
   348   */
   349  
   350  void
   351  walkexprlist(NodeList *l, NodeList **init)
   352  {
   353  	for(; l; l=l->next)
   354  		walkexpr(&l->n, init);
   355  }
   356  
   357  void
   358  walkexprlistsafe(NodeList *l, NodeList **init)
   359  {
   360  	for(; l; l=l->next) {
   361  		l->n = safeexpr(l->n, init);
   362  		walkexpr(&l->n, init);
   363  	}
   364  }
   365  
   366  void
   367  walkexprlistcheap(NodeList *l, NodeList **init)
   368  {
   369  	for(; l; l=l->next) {
   370  		l->n = cheapexpr(l->n, init);
   371  		walkexpr(&l->n, init);
   372  	}
   373  }
   374  
   375  void
   376  walkexpr(Node **np, NodeList **init)
   377  {
   378  	Node *r, *l, *var, *a;
   379  	Node *map, *key;
   380  	NodeList *ll, *lr;
   381  	Type *t;
   382  	int et, old_safemode;
   383  	int64 v;
   384  	int32 lno;
   385  	Node *n, *fn, *n1, *n2;
   386  	Sym *sym;
   387  	char buf[100], *p;
   388  
   389  	n = *np;
   390  
   391  	if(n == N)
   392  		return;
   393  
   394  	if(init == &n->ninit) {
   395  		// not okay to use n->ninit when walking n,
   396  		// because we might replace n with some other node
   397  		// and would lose the init list.
   398  		fatal("walkexpr init == &n->ninit");
   399  	}
   400  
   401  	if(n->ninit != nil) {
   402  		walkstmtlist(n->ninit);
   403  		*init = concat(*init, n->ninit);
   404  		n->ninit = nil;
   405  	}
   406  
   407  	// annoying case - not typechecked
   408  	if(n->op == OKEY) {
   409  		walkexpr(&n->left, init);
   410  		walkexpr(&n->right, init);
   411  		return;
   412  	}
   413  
   414  	lno = setlineno(n);
   415  
   416  	if(debug['w'] > 1)
   417  		dump("walk-before", n);
   418  
   419  	if(n->typecheck != 1)
   420  		fatal("missed typecheck: %+N\n", n);
   421  
   422  	switch(n->op) {
   423  	default:
   424  		dump("walk", n);
   425  		fatal("walkexpr: switch 1 unknown op %+hN", n);
   426  		break;
   427  
   428  	case OTYPE:
   429  	case ONONAME:
   430  	case OINDREG:
   431  	case OEMPTY:
   432  		goto ret;
   433  
   434  	case ONOT:
   435  	case OMINUS:
   436  	case OPLUS:
   437  	case OCOM:
   438  	case OREAL:
   439  	case OIMAG:
   440  	case ODOTMETH:
   441  	case ODOTINTER:
   442  		walkexpr(&n->left, init);
   443  		goto ret;
   444  
   445  	case OIND:
   446  		walkexpr(&n->left, init);
   447  		goto ret;
   448  
   449  	case ODOT:
   450  		usefield(n);
   451  		walkexpr(&n->left, init);
   452  		goto ret;
   453  
   454  	case ODOTPTR:
   455  		usefield(n);
   456  		if(n->op == ODOTPTR && n->left->type->type->width == 0) {
   457  			// No actual copy will be generated, so emit an explicit nil check.
   458  			n->left = cheapexpr(n->left, init);
   459  			checknil(n->left, init);
   460  		}
   461  		walkexpr(&n->left, init);
   462  		goto ret;
   463  
   464  	case OEFACE:
   465  		walkexpr(&n->left, init);
   466  		walkexpr(&n->right, init);
   467  		goto ret;
   468  
   469  	case OSPTR:
   470  	case OITAB:
   471  		walkexpr(&n->left, init);
   472  		goto ret;
   473  
   474  	case OLEN:
   475  	case OCAP:
   476  		walkexpr(&n->left, init);
   477  
   478  		// replace len(*[10]int) with 10.
   479  		// delayed until now to preserve side effects.
   480  		t = n->left->type;
   481  		if(isptr[t->etype])
   482  			t = t->type;
   483  		if(isfixedarray(t)) {
   484  			safeexpr(n->left, init);
   485  			nodconst(n, n->type, t->bound);
   486  			n->typecheck = 1;
   487  		}
   488  		goto ret;
   489  
   490  	case OLSH:
   491  	case ORSH:
   492  		walkexpr(&n->left, init);
   493  		walkexpr(&n->right, init);
   494  		t = n->left->type;
   495  		n->bounded = bounded(n->right, 8*t->width);
   496  		if(debug['m'] && n->etype && !isconst(n->right, CTINT))
   497  			warn("shift bounds check elided");
   498  		goto ret;
   499  
   500  	case OAND:
   501  	case OSUB:
   502  	case OHMUL:
   503  	case OLT:
   504  	case OLE:
   505  	case OGE:
   506  	case OGT:
   507  	case OADD:
   508  	case OCOMPLEX:
   509  	case OLROT:
   510  		// Use results from call expression as arguments for complex.
   511  		if(n->op == OCOMPLEX && n->left == N && n->right == N) {
   512  			n->left = n->list->n;
   513  			n->right = n->list->next->n;
   514  		}
   515  		walkexpr(&n->left, init);
   516  		walkexpr(&n->right, init);
   517  		goto ret;
   518  
   519  	case OOR:
   520  	case OXOR:
   521  		walkexpr(&n->left, init);
   522  		walkexpr(&n->right, init);
   523  		walkrotate(&n);
   524  		goto ret;
   525  
   526  	case OEQ:
   527  	case ONE:
   528  		walkexpr(&n->left, init);
   529  		walkexpr(&n->right, init);
   530  		// Disable safemode while compiling this code: the code we
   531  		// generate internally can refer to unsafe.Pointer.
   532  		// In this case it can happen if we need to generate an ==
   533  		// for a struct containing a reflect.Value, which itself has
   534  		// an unexported field of type unsafe.Pointer.
   535  		old_safemode = safemode;
   536  		safemode = 0;
   537  		walkcompare(&n, init);
   538  		safemode = old_safemode;
   539  		goto ret;
   540  
   541  	case OANDAND:
   542  	case OOROR:
   543  		walkexpr(&n->left, init);
   544  		// cannot put side effects from n->right on init,
   545  		// because they cannot run before n->left is checked.
   546  		// save elsewhere and store on the eventual n->right.
   547  		ll = nil;
   548  		walkexpr(&n->right, &ll);
   549  		addinit(&n->right, ll);
   550  		goto ret;
   551  
   552  	case OPRINT:
   553  	case OPRINTN:
   554  		walkexprlist(n->list, init);
   555  		n = walkprint(n, init);
   556  		goto ret;
   557  
   558  	case OPANIC:
   559  		n = mkcall("gopanic", T, init, n->left);
   560  		goto ret;
   561  
   562  	case ORECOVER:
   563  		n = mkcall("gorecover", n->type, init, nod(OADDR, nodfp, N));
   564  		goto ret;
   565  
   566  	case OLITERAL:
   567  		n->addable = 1;
   568  		goto ret;
   569  
   570  	case OCLOSUREVAR:
   571  	case OCFUNC:
   572  		n->addable = 1;
   573  		goto ret;
   574  
   575  	case ONAME:
   576  		if(!(n->class & PHEAP) && n->class != PPARAMREF)
   577  			n->addable = 1;
   578  		goto ret;
   579  
   580  	case OCALLINTER:
   581  		t = n->left->type;
   582  		if(n->list && n->list->n->op == OAS)
   583  			goto ret;
   584  		walkexpr(&n->left, init);
   585  		walkexprlist(n->list, init);
   586  		ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
   587  		n->list = reorder1(ll);
   588  		goto ret;
   589  
   590  	case OCALLFUNC:
   591  		t = n->left->type;
   592  		if(n->list && n->list->n->op == OAS)
   593  			goto ret;
   594  
   595  		walkexpr(&n->left, init);
   596  		walkexprlist(n->list, init);
   597  
   598  		ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
   599  		n->list = reorder1(ll);
   600  		goto ret;
   601  
   602  	case OCALLMETH:
   603  		t = n->left->type;
   604  		if(n->list && n->list->n->op == OAS)
   605  			goto ret;
   606  		walkexpr(&n->left, init);
   607  		walkexprlist(n->list, init);
   608  		ll = ascompatte(n->op, n, 0, getthis(t), list1(n->left->left), 0, init);
   609  		lr = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
   610  		ll = concat(ll, lr);
   611  		n->left->left = N;
   612  		ullmancalc(n->left);
   613  		n->list = reorder1(ll);
   614  		goto ret;
   615  
   616  	case OAS:
   617  		*init = concat(*init, n->ninit);
   618  		n->ninit = nil;
   619  
   620  		walkexpr(&n->left, init);
   621  		n->left = safeexpr(n->left, init);
   622  
   623  		if(oaslit(n, init))
   624  			goto ret;
   625  
   626  		if(n->right == N || iszero(n->right) && !flag_race)
   627  			goto ret;
   628  
   629  		switch(n->right->op) {
   630  		default:
   631  			walkexpr(&n->right, init);
   632  			break;
   633  		
   634  		case ORECV:
   635  			// x = <-c; n->left is x, n->right->left is c.
   636  			// orderstmt made sure x is addressable.
   637  			walkexpr(&n->right->left, init);
   638  			n1 = nod(OADDR, n->left, N);
   639  			r = n->right->left; // the channel
   640  			n = mkcall1(chanfn("chanrecv1", 2, r->type), T, init, typename(r->type), r, n1);
   641  			walkexpr(&n, init);
   642  			goto ret;
   643  		}
   644  
   645  		if(n->left != N && n->right != N) {
   646  			r = convas(nod(OAS, n->left, n->right), init);
   647  			r->dodata = n->dodata;
   648  			n = r;
   649  			n = applywritebarrier(n, init);
   650  		}
   651  
   652  		goto ret;
   653  
   654  	case OAS2:
   655  		*init = concat(*init, n->ninit);
   656  		n->ninit = nil;
   657  		walkexprlistsafe(n->list, init);
   658  		walkexprlistsafe(n->rlist, init);
   659  		ll = ascompatee(OAS, n->list, n->rlist, init);
   660  		ll = reorder3(ll);
   661  		for(lr = ll; lr != nil; lr = lr->next)
   662  			lr->n = applywritebarrier(lr->n, init);
   663  		n = liststmt(ll);
   664  		goto ret;
   665  
   666  	case OAS2FUNC:
   667  		// a,b,... = fn()
   668  		*init = concat(*init, n->ninit);
   669  		n->ninit = nil;
   670  		r = n->rlist->n;
   671  		walkexprlistsafe(n->list, init);
   672  		walkexpr(&r, init);
   673  
   674  		ll = ascompatet(n->op, n->list, &r->type, 0, init);
   675  		for(lr = ll; lr != nil; lr = lr->next)
   676  			lr->n = applywritebarrier(lr->n, init);
   677  		n = liststmt(concat(list1(r), ll));
   678  		goto ret;
   679  
   680  	case OAS2RECV:
   681  		// x, y = <-c
   682  		// orderstmt made sure x is addressable.
   683  		*init = concat(*init, n->ninit);
   684  		n->ninit = nil;
   685  		r = n->rlist->n;
   686  		walkexprlistsafe(n->list, init);
   687  		walkexpr(&r->left, init);
   688  		if(isblank(n->list->n))
   689  			n1 = nodnil();
   690  		else
   691  			n1 = nod(OADDR, n->list->n, N);
   692  		n1->etype = 1; // addr does not escape
   693  		fn = chanfn("chanrecv2", 2, r->left->type);
   694  		r = mkcall1(fn, n->list->next->n->type, init, typename(r->left->type), r->left, n1);
   695  		n = nod(OAS, n->list->next->n, r);
   696  		typecheck(&n, Etop);
   697  		goto ret;
   698  
   699  	case OAS2MAPR:
   700  		// a,b = m[i];
   701  		*init = concat(*init, n->ninit);
   702  		n->ninit = nil;
   703  		r = n->rlist->n;
   704  		walkexprlistsafe(n->list, init);
   705  		walkexpr(&r->left, init);
   706  		walkexpr(&r->right, init);
   707  		t = r->left->type;
   708  		p = nil;
   709  		if(t->type->width <= 128) { // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing.
   710  			switch(simsimtype(t->down)) {
   711  			case TINT32:
   712  			case TUINT32:
   713  				p = "mapaccess2_fast32";
   714  				break;
   715  			case TINT64:
   716  			case TUINT64:
   717  				p = "mapaccess2_fast64";
   718  				break;
   719  			case TSTRING:
   720  				p = "mapaccess2_faststr";
   721  				break;
   722  			}
   723  		}
   724  		if(p != nil) {
   725  			// fast versions take key by value
   726  			key = r->right;
   727  		} else {
   728  			// standard version takes key by reference
   729  			// orderexpr made sure key is addressable.
   730  			key = nod(OADDR, r->right, N);
   731  			p = "mapaccess2";
   732  		}
   733  
   734  		// from:
   735  		//   a,b = m[i]
   736  		// to:
   737  		//   var,b = mapaccess2*(t, m, i)
   738  		//   a = *var
   739  		a = n->list->n;
   740  		var = temp(ptrto(t->type));
   741  		var->typecheck = 1;
   742  		fn = mapfn(p, t);
   743  		r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key);
   744  
   745  		// mapaccess2* returns a typed bool, but due to spec changes,
   746  		// the boolean result of i.(T) is now untyped so we make it the
   747  		// same type as the variable on the lhs.
   748  		if(!isblank(n->list->next->n))
   749  			r->type->type->down->type = n->list->next->n->type;
   750  		n->rlist = list1(r);
   751  		n->op = OAS2FUNC;
   752  		n->list->n = var;
   753  		walkexpr(&n, init);
   754  		*init = list(*init, n);
   755  		n = nod(OAS, a, nod(OIND, var, N));
   756  		typecheck(&n, Etop);
   757  		walkexpr(&n, init);
   758  		// mapaccess needs a zero value to be at least this big.
   759  		if(zerosize < t->type->width)
   760  			zerosize = t->type->width;
   761  		// TODO: ptr is always non-nil, so disable nil check for this OIND op.
   762  		goto ret;
   763  
   764  	case ODELETE:
   765  		*init = concat(*init, n->ninit);
   766  		n->ninit = nil;
   767  		map = n->list->n;
   768  		key = n->list->next->n;
   769  		walkexpr(&map, init);
   770  		walkexpr(&key, init);
   771  		// orderstmt made sure key is addressable.
   772  		key = nod(OADDR, key, N);
   773  		t = map->type;
   774  		n = mkcall1(mapfndel("mapdelete", t), T, init, typename(t), map, key);
   775  		goto ret;
   776  
   777  	case OAS2DOTTYPE:
   778  		// a,b = i.(T)
   779  		*init = concat(*init, n->ninit);
   780  		n->ninit = nil;
   781  		r = n->rlist->n;
   782  		walkexprlistsafe(n->list, init);
   783  		if(isblank(n->list->n) && !isinter(r->type)) {
   784  			strcpy(buf, "assert");
   785  			p = buf+strlen(buf);
   786  			if(isnilinter(r->left->type))
   787  				*p++ = 'E';
   788  			else
   789  				*p++ = 'I';
   790  			*p++ = '2';
   791  			*p++ = 'T';
   792  			*p++ = 'O';
   793  			*p++ = 'K';
   794  			*p = '\0';
   795  			
   796  			fn = syslook(buf, 1);
   797  
   798  			// runtime.assert(E|I)2TOK returns a typed bool, but due
   799  			// to spec changes, the boolean result of i.(T) is now untyped
   800  			// so we make it the same type as the variable on the lhs.
   801  			if(!isblank(n->list->next->n))
   802  				fn->type->type->down->type->type = n->list->next->n->type;
   803  			ll = list1(typename(r->type));
   804  			ll = list(ll, r->left);
   805  			argtype(fn, r->left->type);
   806  			n1 = nod(OCALL, fn, N);
   807  			n1->list = ll;
   808  			n = nod(OAS, n->list->next->n, n1);
   809  			typecheck(&n, Etop);
   810  			walkexpr(&n, init);
   811  			goto ret;
   812  		}
   813  
   814  		r->op = ODOTTYPE2;
   815  		walkexpr(&r, init);
   816  		ll = ascompatet(n->op, n->list, &r->type, 0, init);
   817  		n = liststmt(concat(list1(r), ll));
   818  		goto ret;
   819  
   820  	case ODOTTYPE:
   821  	case ODOTTYPE2:
   822  		// Build name of function: assertI2E2 etc.
   823  		strcpy(buf, "assert");
   824  		p = buf+strlen(buf);
   825  		if(isnilinter(n->left->type))
   826  			*p++ = 'E';
   827  		else
   828  			*p++ = 'I';
   829  		*p++ = '2';
   830  		if(isnilinter(n->type))
   831  			*p++ = 'E';
   832  		else if(isinter(n->type))
   833  			*p++ = 'I';
   834  		else
   835  			*p++ = 'T';
   836  		if(n->op == ODOTTYPE2)
   837  			*p++ = '2';
   838  		*p = '\0';
   839  
   840  		fn = syslook(buf, 1);
   841  		ll = list1(typename(n->type));
   842  		ll = list(ll, n->left);
   843  		argtype(fn, n->left->type);
   844  		argtype(fn, n->type);
   845  		n = nod(OCALL, fn, N);
   846  		n->list = ll;
   847  		typecheck(&n, Erv | Efnstruct);
   848  		walkexpr(&n, init);
   849  		goto ret;
   850  
   851  	case OCONVIFACE:
   852  		walkexpr(&n->left, init);
   853  
   854  		// Optimize convT2E as a two-word copy when T is uintptr-shaped.
   855  		if(isnilinter(n->type) && isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
   856  			l = nod(OEFACE, typename(n->left->type), n->left);
   857  			l->type = n->type;
   858  			l->typecheck = n->typecheck;
   859  			n = l;
   860  			goto ret;
   861  		}
   862  
   863  		// Build name of function: convI2E etc.
   864  		// Not all names are possible
   865  		// (e.g., we'll never generate convE2E or convE2I).
   866  		strcpy(buf, "conv");
   867  		p = buf+strlen(buf);
   868  		if(isnilinter(n->left->type))
   869  			*p++ = 'E';
   870  		else if(isinter(n->left->type))
   871  			*p++ = 'I';
   872  		else
   873  			*p++ = 'T';
   874  		*p++ = '2';
   875  		if(isnilinter(n->type))
   876  			*p++ = 'E';
   877  		else
   878  			*p++ = 'I';
   879  		*p = '\0';
   880  
   881  		fn = syslook(buf, 1);
   882  		ll = nil;
   883  		if(!isinter(n->left->type))
   884  			ll = list(ll, typename(n->left->type));
   885  		if(!isnilinter(n->type))
   886  			ll = list(ll, typename(n->type));
   887  		if(!isinter(n->left->type) && !isnilinter(n->type)){
   888  			sym = pkglookup(smprint("%-T.%-T", n->left->type, n->type), itabpkg);
   889  			if(sym->def == N) {
   890  				l = nod(ONAME, N, N);
   891  				l->sym = sym;
   892  				l->type = ptrto(types[TUINT8]);
   893  				l->addable = 1;
   894  				l->class = PEXTERN;
   895  				l->xoffset = 0;
   896  				sym->def = l;
   897  				ggloblsym(sym, widthptr, DUPOK|NOPTR);
   898  			}
   899  			l = nod(OADDR, sym->def, N);
   900  			l->addable = 1;
   901  			ll = list(ll, l);
   902  
   903  			if(isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
   904  				/* For pointer types, we can make a special form of optimization
   905  				 *
   906  				 * These statements are put onto the expression init list:
   907  				 * 	Itab *tab = atomicloadtype(&cache);
   908  				 * 	if(tab == nil)
   909  				 * 		tab = typ2Itab(type, itype, &cache);
   910  				 *
   911  				 * The CONVIFACE expression is replaced with this:
   912  				 * 	OEFACE{tab, ptr};
   913  				 */
   914  				l = temp(ptrto(types[TUINT8]));
   915  
   916  				n1 = nod(OAS, l, sym->def);
   917  				typecheck(&n1, Etop);
   918  				*init = list(*init, n1);
   919  
   920  				fn = syslook("typ2Itab", 1);
   921  				n1 = nod(OCALL, fn, N);
   922  				n1->list = ll;
   923  				typecheck(&n1, Erv);
   924  				walkexpr(&n1, init);
   925  
   926  				n2 = nod(OIF, N, N);
   927  				n2->ntest = nod(OEQ, l, nodnil());
   928  				n2->nbody = list1(nod(OAS, l, n1));
   929  				n2->likely = -1;
   930  				typecheck(&n2, Etop);
   931  				*init = list(*init, n2);
   932  
   933  				l = nod(OEFACE, l, n->left);
   934  				l->typecheck = n->typecheck; 
   935  				l->type = n->type;
   936  				n = l;
   937  				goto ret;
   938  			}
   939  		}
   940  		if(isinter(n->left->type)) {
   941  			ll = list(ll, n->left);
   942  		} else {
   943  			// regular types are passed by reference to avoid C vararg calls
   944  			// orderexpr arranged for n->left to be a temporary for all
   945  			// the conversions it could see. comparison of an interface
   946  			// with a non-interface, especially in a switch on interface value
   947  			// with non-interface cases, is not visible to orderstmt, so we
   948  			// have to fall back on allocating a temp here.
   949  			if(islvalue(n->left))
   950  				ll = list(ll, nod(OADDR, n->left, N));
   951  			else
   952  				ll = list(ll, nod(OADDR, copyexpr(n->left, n->left->type, init), N));
   953  		}
   954  		argtype(fn, n->left->type);
   955  		argtype(fn, n->type);
   956  		dowidth(fn->type);
   957  		n = nod(OCALL, fn, N);
   958  		n->list = ll;
   959  		typecheck(&n, Erv);
   960  		walkexpr(&n, init);
   961  		goto ret;
   962  
   963  	case OCONV:
   964  	case OCONVNOP:
   965  		if(thechar == '5') {
   966  			if(isfloat[n->left->type->etype]) {
   967  				if(n->type->etype == TINT64) {
   968  					n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
   969  					goto ret;
   970  				}
   971  				if(n->type->etype == TUINT64) {
   972  					n = mkcall("float64touint64", n->type, init, conv(n->left, types[TFLOAT64]));
   973  					goto ret;
   974  				}
   975  			}
   976  			if(isfloat[n->type->etype]) {
   977  				if(n->left->type->etype == TINT64) {
   978  					n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
   979  					goto ret;
   980  				}
   981  				if(n->left->type->etype == TUINT64) {
   982  					n = mkcall("uint64tofloat64", n->type, init, conv(n->left, types[TUINT64]));
   983  					goto ret;
   984  				}
   985  			}
   986  		}
   987  		walkexpr(&n->left, init);
   988  		goto ret;
   989  
   990  	case OANDNOT:
   991  		walkexpr(&n->left, init);
   992  		n->op = OAND;
   993  		n->right = nod(OCOM, n->right, N);
   994  		typecheck(&n->right, Erv);
   995  		walkexpr(&n->right, init);
   996  		goto ret;
   997  
   998  	case OMUL:
   999  		walkexpr(&n->left, init);
  1000  		walkexpr(&n->right, init);
  1001  		walkmul(&n, init);
  1002  		goto ret;
  1003  
  1004  	case ODIV:
  1005  	case OMOD:
  1006  		walkexpr(&n->left, init);
  1007  		walkexpr(&n->right, init);
  1008  		/*
  1009  		 * rewrite complex div into function call.
  1010  		 */
  1011  		et = n->left->type->etype;
  1012  		if(iscomplex[et] && n->op == ODIV) {
  1013  			t = n->type;
  1014  			n = mkcall("complex128div", types[TCOMPLEX128], init,
  1015  				conv(n->left, types[TCOMPLEX128]),
  1016  				conv(n->right, types[TCOMPLEX128]));
  1017  			n = conv(n, t);
  1018  			goto ret;
  1019  		}
  1020  		// Nothing to do for float divisions.
  1021  		if(isfloat[et])
  1022  			goto ret;
  1023  
  1024  		// Try rewriting as shifts or magic multiplies.
  1025  		walkdiv(&n, init);
  1026  
  1027  		/*
  1028  		 * rewrite 64-bit div and mod into function calls
  1029  		 * on 32-bit architectures.
  1030  		 */
  1031  		switch(n->op) {
  1032  		case OMOD:
  1033  		case ODIV:
  1034  			if(widthreg >= 8 || (et != TUINT64 && et != TINT64))
  1035  				goto ret;
  1036  			if(et == TINT64)
  1037  				strcpy(namebuf, "int64");
  1038  			else
  1039  				strcpy(namebuf, "uint64");
  1040  			if(n->op == ODIV)
  1041  				strcat(namebuf, "div");
  1042  			else
  1043  				strcat(namebuf, "mod");
  1044  			n = mkcall(namebuf, n->type, init,
  1045  				conv(n->left, types[et]), conv(n->right, types[et]));
  1046  			break;
  1047  		default:
  1048  			break;
  1049  		}
  1050  		goto ret;
  1051  
  1052  	case OINDEX:
  1053  		walkexpr(&n->left, init);
  1054  		// save the original node for bounds checking elision.
  1055  		// If it was a ODIV/OMOD walk might rewrite it.
  1056  		r = n->right;
  1057  		walkexpr(&n->right, init);
  1058  
  1059  		// if range of type cannot exceed static array bound,
  1060  		// disable bounds check.
  1061  		if(n->bounded)
  1062  			goto ret;
  1063  		t = n->left->type;
  1064  		if(t != T && isptr[t->etype])
  1065  			t = t->type;
  1066  		if(isfixedarray(t)) {
  1067  			n->bounded = bounded(r, t->bound);
  1068  			if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
  1069  				warn("index bounds check elided");
  1070  			if(smallintconst(n->right) && !n->bounded)
  1071  				yyerror("index out of bounds");
  1072  		} else if(isconst(n->left, CTSTR)) {
  1073  			n->bounded = bounded(r, n->left->val.u.sval->len);
  1074  			if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
  1075  				warn("index bounds check elided");
  1076  			if(smallintconst(n->right)) {
  1077  				if(!n->bounded)
  1078  					yyerror("index out of bounds");
  1079  				else {
  1080  					// replace "abc"[1] with 'b'.
  1081  					// delayed until now because "abc"[1] is not
  1082  					// an ideal constant.
  1083  					v = mpgetfix(n->right->val.u.xval);
  1084  					nodconst(n, n->type, n->left->val.u.sval->s[v]);
  1085  					n->typecheck = 1;
  1086  				}
  1087  			}
  1088  		}
  1089  
  1090  		if(isconst(n->right, CTINT))
  1091  		if(mpcmpfixfix(n->right->val.u.xval, &mpzero) < 0 ||
  1092  		   mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0)
  1093  			yyerror("index out of bounds");
  1094  		goto ret;
  1095  
  1096  	case OINDEXMAP:
  1097  		if(n->etype == 1)
  1098  			goto ret;
  1099  		walkexpr(&n->left, init);
  1100  		walkexpr(&n->right, init);
  1101  
  1102  		t = n->left->type;
  1103  		p = nil;
  1104  		if(t->type->width <= 128) {  // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing.
  1105  			switch(simsimtype(t->down)) {
  1106  			case TINT32:
  1107  			case TUINT32:
  1108  				p = "mapaccess1_fast32";
  1109  				break;
  1110  			case TINT64:
  1111  			case TUINT64:
  1112  				p = "mapaccess1_fast64";
  1113  				break;
  1114  			case TSTRING:
  1115  				p = "mapaccess1_faststr";
  1116  				break;
  1117  			}
  1118  		}
  1119  		if(p != nil) {
  1120  			// fast versions take key by value
  1121  			key = n->right;
  1122  		} else {
  1123  			// standard version takes key by reference.
  1124  			// orderexpr made sure key is addressable.
  1125  			key = nod(OADDR, n->right, N);
  1126  			p = "mapaccess1";
  1127  		}
  1128  		n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, key);
  1129  		n = nod(OIND, n, N);
  1130  		n->type = t->type;
  1131  		n->typecheck = 1;
  1132  		// mapaccess needs a zero value to be at least this big.
  1133  		if(zerosize < t->type->width)
  1134  			zerosize = t->type->width;
  1135  		goto ret;
  1136  
  1137  	case ORECV:
  1138  		fatal("walkexpr ORECV"); // should see inside OAS only
  1139  
  1140  	case OSLICE:
  1141  		if(n->right != N && n->right->left == N && n->right->right == N) { // noop
  1142  			walkexpr(&n->left, init);
  1143  			n = n->left;
  1144  			goto ret;
  1145  		}
  1146  		// fallthrough
  1147  	case OSLICEARR:
  1148  	case OSLICESTR:
  1149  		if(n->right == N) // already processed
  1150  			goto ret;
  1151  
  1152  		walkexpr(&n->left, init);
  1153  		// cgen_slice can't handle string literals as source
  1154  		// TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
  1155  		if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left->op == OINDEX))
  1156  			n->left = copyexpr(n->left, n->left->type, init);
  1157  		else
  1158  			n->left = safeexpr(n->left, init);
  1159  		walkexpr(&n->right->left, init);
  1160  		n->right->left = safeexpr(n->right->left, init);
  1161  		walkexpr(&n->right->right, init);
  1162  		n->right->right = safeexpr(n->right->right, init);
  1163  		n = sliceany(n, init);  // chops n->right, sets n->list
  1164  		goto ret;
  1165  	
  1166  	case OSLICE3:
  1167  	case OSLICE3ARR:
  1168  		if(n->right == N) // already processed
  1169  			goto ret;
  1170  
  1171  		walkexpr(&n->left, init);
  1172  		// TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
  1173  		// TODO the comment on the previous line was copied from case OSLICE. it might not even be true.
  1174  		if(n->left->op == OINDEX)
  1175  			n->left = copyexpr(n->left, n->left->type, init);
  1176  		else
  1177  			n->left = safeexpr(n->left, init);
  1178  		walkexpr(&n->right->left, init);
  1179  		n->right->left = safeexpr(n->right->left, init);
  1180  		walkexpr(&n->right->right->left, init);
  1181  		n->right->right->left = safeexpr(n->right->right->left, init);
  1182  		walkexpr(&n->right->right->right, init);
  1183  		n->right->right->right = safeexpr(n->right->right->right, init);
  1184  		n = sliceany(n, init);  // chops n->right, sets n->list
  1185  		goto ret;
  1186  
  1187  	case OADDR:
  1188  		walkexpr(&n->left, init);
  1189  		goto ret;
  1190  
  1191  	case ONEW:
  1192  		if(n->esc == EscNone && n->type->type->width < (1<<16)) {
  1193  			r = temp(n->type->type);
  1194  			r = nod(OAS, r, N);  // zero temp
  1195  			typecheck(&r, Etop);
  1196  			*init = list(*init, r);
  1197  			r = nod(OADDR, r->left, N);
  1198  			typecheck(&r, Erv);
  1199  			n = r;
  1200  		} else {
  1201  			n = callnew(n->type->type);
  1202  		}
  1203  		goto ret;
  1204  
  1205  	case OCMPSTR:
  1206  		// If one argument to the comparison is an empty string,
  1207  		// comparing the lengths instead will yield the same result
  1208  		// without the function call.
  1209  		if((isconst(n->left, CTSTR) && n->left->val.u.sval->len == 0) ||
  1210  		   (isconst(n->right, CTSTR) && n->right->val.u.sval->len == 0)) {
  1211  			r = nod(n->etype, nod(OLEN, n->left, N), nod(OLEN, n->right, N));
  1212  			typecheck(&r, Erv);
  1213  			walkexpr(&r, init);
  1214  			r->type = n->type;
  1215  			n = r;
  1216  			goto ret;
  1217  		}
  1218  
  1219  		// s + "badgerbadgerbadger" == "badgerbadgerbadger"
  1220  		if((n->etype == OEQ || n->etype == ONE) &&
  1221  		   isconst(n->right, CTSTR) &&
  1222  		   n->left->op == OADDSTR && count(n->left->list) == 2 &&
  1223  		   isconst(n->left->list->next->n, CTSTR) &&
  1224  		   cmpslit(n->right, n->left->list->next->n) == 0) {
  1225  			r = nod(n->etype, nod(OLEN, n->left->list->n, N), nodintconst(0));
  1226  			typecheck(&r, Erv);
  1227  			walkexpr(&r, init);
  1228  			r->type = n->type;
  1229  			n = r;
  1230  			goto ret;
  1231  		}
  1232  
  1233  		if(n->etype == OEQ || n->etype == ONE) {
  1234  			// prepare for rewrite below
  1235  			n->left = cheapexpr(n->left, init);
  1236  			n->right = cheapexpr(n->right, init);
  1237  
  1238  			r = mkcall("eqstring", types[TBOOL], init,
  1239  				conv(n->left, types[TSTRING]),
  1240  				conv(n->right, types[TSTRING]));
  1241  
  1242  			// quick check of len before full compare for == or !=
  1243  			if(n->etype == OEQ) {
  1244  				// len(left) == len(right) && eqstring(left, right)
  1245  				r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
  1246  			} else {
  1247  				// len(left) != len(right) || !eqstring(left, right)
  1248  				r = nod(ONOT, r, N);
  1249  				r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
  1250  			}
  1251  			typecheck(&r, Erv);
  1252  			walkexpr(&r, nil);
  1253  		} else {
  1254  			// sys_cmpstring(s1, s2) :: 0
  1255  			r = mkcall("cmpstring", types[TINT], init,
  1256  				conv(n->left, types[TSTRING]),
  1257  				conv(n->right, types[TSTRING]));
  1258  			r = nod(n->etype, r, nodintconst(0));
  1259  		}
  1260  
  1261  		typecheck(&r, Erv);
  1262  		if(n->type->etype != TBOOL) fatal("cmp %T", n->type);
  1263  		r->type = n->type;
  1264  		n = r;
  1265  		goto ret;
  1266  
  1267  	case OADDSTR:
  1268  		n = addstr(n, init);
  1269  		goto ret;
  1270  	
  1271  	case OAPPEND:
  1272  		if(n->isddd)
  1273  			n = appendslice(n, init); // also works for append(slice, string).
  1274  		else
  1275  			n = append(n, init);
  1276  		goto ret;
  1277  
  1278  	case OCOPY:
  1279  		n = copyany(n, init, flag_race);
  1280  		goto ret;
  1281  
  1282  	case OCLOSE:
  1283  		// cannot use chanfn - closechan takes any, not chan any
  1284  		fn = syslook("closechan", 1);
  1285  		argtype(fn, n->left->type);
  1286  		n = mkcall1(fn, T, init, n->left);
  1287  		goto ret;
  1288  
  1289  	case OMAKECHAN:
  1290  		n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
  1291  			typename(n->type),
  1292  			conv(n->left, types[TINT64]));
  1293  		goto ret;
  1294  
  1295  	case OMAKEMAP:
  1296  		t = n->type;
  1297  
  1298  		fn = syslook("makemap", 1);
  1299  		argtype(fn, t->down);	// any-1
  1300  		argtype(fn, t->type);	// any-2
  1301  
  1302  		n = mkcall1(fn, n->type, init,
  1303  			typename(n->type),
  1304  			conv(n->left, types[TINT64]));
  1305  		goto ret;
  1306  
  1307  	case OMAKESLICE:
  1308  		l = n->left;
  1309  		r = n->right;
  1310  		if(r == nil)
  1311  			l = r = safeexpr(l, init);
  1312  		t = n->type;
  1313  		if(n->esc == EscNone
  1314  			&& smallintconst(l) && smallintconst(r)
  1315  			&& (t->type->width == 0 || mpgetfix(r->val.u.xval) < (1ULL<<16) / t->type->width)) {
  1316  			// var arr [r]T
  1317  			// n = arr[:l]
  1318  			t = aindex(r, t->type); // [r]T
  1319  			var = temp(t);
  1320  			a = nod(OAS, var, N); // zero temp
  1321  			typecheck(&a, Etop);
  1322  			*init = list(*init, a);
  1323  			r = nod(OSLICE, var, nod(OKEY, N, l)); // arr[:l]
  1324  			r = conv(r, n->type); // in case n->type is named.
  1325  			typecheck(&r, Erv);
  1326  			walkexpr(&r, init);
  1327  			n = r;
  1328  		} else {
  1329  			// makeslice(t *Type, nel int64, max int64) (ary []any)
  1330  			fn = syslook("makeslice", 1);
  1331  			argtype(fn, t->type);			// any-1
  1332  			n = mkcall1(fn, n->type, init,
  1333  				typename(n->type),
  1334  				conv(l, types[TINT64]),
  1335  				conv(r, types[TINT64]));
  1336  		}
  1337  		goto ret;
  1338  
  1339  	case ORUNESTR:
  1340  		// sys_intstring(v)
  1341  		n = mkcall("intstring", n->type, init,
  1342  			conv(n->left, types[TINT64]));
  1343  		goto ret;
  1344  
  1345  	case OARRAYBYTESTR:
  1346  		// slicebytetostring([]byte) string;
  1347  		n = mkcall("slicebytetostring", n->type, init, n->left);
  1348  		goto ret;
  1349  
  1350  	case OARRAYBYTESTRTMP:
  1351  		// slicebytetostringtmp([]byte) string;
  1352  		n = mkcall("slicebytetostringtmp", n->type, init, n->left);
  1353  		goto ret;
  1354  
  1355  	case OARRAYRUNESTR:
  1356  		// slicerunetostring([]rune) string;
  1357  		n = mkcall("slicerunetostring", n->type, init, n->left);
  1358  		goto ret;
  1359  
  1360  	case OSTRARRAYBYTE:
  1361  		// stringtoslicebyte(string) []byte;
  1362  		n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
  1363  		goto ret;
  1364  
  1365  	case OSTRARRAYRUNE:
  1366  		// stringtoslicerune(string) []rune
  1367  		n = mkcall("stringtoslicerune", n->type, init, n->left);
  1368  		goto ret;
  1369  
  1370  	case OCMPIFACE:
  1371  		// ifaceeq(i1 any-1, i2 any-2) (ret bool);
  1372  		if(!eqtype(n->left->type, n->right->type))
  1373  			fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type);
  1374  		if(isnilinter(n->left->type))
  1375  			fn = syslook("efaceeq", 1);
  1376  		else
  1377  			fn = syslook("ifaceeq", 1);
  1378  
  1379  		n->right = cheapexpr(n->right, init);
  1380  		n->left = cheapexpr(n->left, init);
  1381  		argtype(fn, n->right->type);
  1382  		argtype(fn, n->left->type);
  1383  		r = mkcall1(fn, n->type, init, n->left, n->right);
  1384  		if(n->etype == ONE)
  1385  			r = nod(ONOT, r, N);
  1386  		
  1387  		// check itable/type before full compare.
  1388  		if(n->etype == OEQ)
  1389  			r = nod(OANDAND, nod(OEQ, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
  1390  		else
  1391  			r = nod(OOROR, nod(ONE, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
  1392  		typecheck(&r, Erv);
  1393  		walkexpr(&r, init);
  1394  		r->type = n->type;
  1395  		n = r;
  1396  		goto ret;
  1397  
  1398  	case OARRAYLIT:
  1399  	case OMAPLIT:
  1400  	case OSTRUCTLIT:
  1401  	case OPTRLIT:
  1402  		var = temp(n->type);
  1403  		anylit(0, n, var, init);
  1404  		n = var;
  1405  		goto ret;
  1406  
  1407  	case OSEND:
  1408  		n1 = n->right;
  1409  		n1 = assignconv(n1, n->left->type->type, "chan send");
  1410  		walkexpr(&n1, init);
  1411  		n1 = nod(OADDR, n1, N);
  1412  		n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
  1413  		goto ret;
  1414  
  1415  	case OCLOSURE:
  1416  		n = walkclosure(n, init);
  1417  		goto ret;
  1418  	
  1419  	case OCALLPART:
  1420  		n = walkpartialcall(n, init);
  1421  		goto ret;
  1422  	}
  1423  	fatal("missing switch %O", n->op);
  1424  
  1425  ret:
  1426  	// Expressions that are constant at run time but not
  1427  	// considered const by the language spec are not turned into
  1428  	// constants until walk. For example, if n is y%1 == 0, the
  1429  	// walk of y%1 may have replaced it by 0.
  1430  	// Check whether n with its updated args is itself now a constant.
  1431  	t = n->type;
  1432  	evconst(n);
  1433  	n->type = t;
  1434  	if(n->op == OLITERAL)
  1435  		typecheck(&n, Erv);
  1436  
  1437  	ullmancalc(n);
  1438  
  1439  	if(debug['w'] && n != N)
  1440  		dump("walk", n);
  1441  
  1442  	lineno = lno;
  1443  	*np = n;
  1444  }
  1445  
  1446  static Node*
  1447  ascompatee1(int op, Node *l, Node *r, NodeList **init)
  1448  {
  1449  	Node *n;
  1450  	USED(op);
  1451  	
  1452  	// convas will turn map assigns into function calls,
  1453  	// making it impossible for reorder3 to work.
  1454  	n = nod(OAS, l, r);
  1455  	if(l->op == OINDEXMAP)
  1456  		return n;
  1457  
  1458  	return convas(n, init);
  1459  }
  1460  
  1461  static NodeList*
  1462  ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
  1463  {
  1464  	NodeList *ll, *lr, *nn;
  1465  
  1466  	/*
  1467  	 * check assign expression list to
  1468  	 * a expression list. called in
  1469  	 *	expr-list = expr-list
  1470  	 */
  1471  
  1472  	// ensure order of evaluation for function calls
  1473  	for(ll=nl; ll; ll=ll->next)
  1474  		ll->n = safeexpr(ll->n, init);
  1475  	for(lr=nr; lr; lr=lr->next)
  1476  		lr->n = safeexpr(lr->n, init);
  1477  
  1478  	nn = nil;
  1479  	for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next) {
  1480  		// Do not generate 'x = x' during return. See issue 4014.
  1481  		if(op == ORETURN && ll->n == lr->n)
  1482  			continue;
  1483  		nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
  1484  	}
  1485  
  1486  	// cannot happen: caller checked that lists had same length
  1487  	if(ll || lr)
  1488  		yyerror("error in shape across %+H %O %+H / %d %d [%s]", nl, op, nr, count(nl), count(nr), curfn->nname->sym->name);
  1489  	return nn;
  1490  }
  1491  
  1492  /*
  1493   * l is an lv and rt is the type of an rv
  1494   * return 1 if this implies a function call
  1495   * evaluating the lv or a function call
  1496   * in the conversion of the types
  1497   */
  1498  static int
  1499  fncall(Node *l, Type *rt)
  1500  {
  1501  	Node r;
  1502  
  1503  	if(l->ullman >= UINF || l->op == OINDEXMAP)
  1504  		return 1;
  1505  	memset(&r, 0, sizeof r);
  1506  	if(needwritebarrier(l, &r))
  1507  		return 1;
  1508  	if(eqtype(l->type, rt))
  1509  		return 0;
  1510  	return 1;
  1511  }
  1512  
  1513  static NodeList*
  1514  ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
  1515  {
  1516  	Node *l, *tmp, *a;
  1517  	NodeList *ll;
  1518  	Type *r;
  1519  	Iter saver;
  1520  	int ucount;
  1521  	NodeList *nn, *mm;
  1522  
  1523  	USED(op);
  1524  
  1525  	/*
  1526  	 * check assign type list to
  1527  	 * a expression list. called in
  1528  	 *	expr-list = func()
  1529  	 */
  1530  	r = structfirst(&saver, nr);
  1531  	nn = nil;
  1532  	mm = nil;
  1533  	ucount = 0;
  1534  	for(ll=nl; ll; ll=ll->next) {
  1535  		if(r == T)
  1536  			break;
  1537  		l = ll->n;
  1538  		if(isblank(l)) {
  1539  			r = structnext(&saver);
  1540  			continue;
  1541  		}
  1542  
  1543  		// any lv that causes a fn call must be
  1544  		// deferred until all the return arguments
  1545  		// have been pulled from the output arguments
  1546  		if(fncall(l, r->type)) {
  1547  			tmp = temp(r->type);
  1548  			typecheck(&tmp, Erv);
  1549  			a = nod(OAS, l, tmp);
  1550  			a = convas(a, init);
  1551  			mm = list(mm, a);
  1552  			l = tmp;
  1553  		}
  1554  
  1555  		a = nod(OAS, l, nodarg(r, fp));
  1556  		a = convas(a, init);
  1557  		ullmancalc(a);
  1558  		if(a->ullman >= UINF) {
  1559  			dump("ascompatet ucount", a);
  1560  			ucount++;
  1561  		}
  1562  		nn = list(nn, a);
  1563  		r = structnext(&saver);
  1564  	}
  1565  
  1566  	if(ll != nil || r != T)
  1567  		yyerror("ascompatet: assignment count mismatch: %d = %d",
  1568  			count(nl), structcount(*nr));
  1569  
  1570  	if(ucount)
  1571  		fatal("ascompatet: too many function calls evaluating parameters");
  1572  	return concat(nn, mm);
  1573  }
  1574  
  1575   /*
  1576   * package all the arguments that match a ... T parameter into a []T.
  1577   */
  1578  static NodeList*
  1579  mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, Node *ddd)
  1580  {
  1581  	Node *a, *n;
  1582  	Type *tslice;
  1583  	int esc;
  1584  	
  1585  	esc = EscUnknown;
  1586  	if(ddd != nil)
  1587  		esc = ddd->esc;
  1588  	
  1589  	tslice = typ(TARRAY);
  1590  	tslice->type = l->type->type;
  1591  	tslice->bound = -1;
  1592  
  1593  	if(count(lr0) == 0) {
  1594  		n = nodnil();
  1595  		n->type = tslice;
  1596  	} else {
  1597  		n = nod(OCOMPLIT, N, typenod(tslice));
  1598  		if(ddd != nil)
  1599  			n->alloc = ddd->alloc; // temporary to use
  1600  		n->list = lr0;
  1601  		n->esc = esc;
  1602  		typecheck(&n, Erv);
  1603  		if(n->type == T)
  1604  			fatal("mkdotargslice: typecheck failed");
  1605  		walkexpr(&n, init);
  1606  	}
  1607  
  1608  	a = nod(OAS, nodarg(l, fp), n);
  1609  	nn = list(nn, convas(a, init));
  1610  	return nn;
  1611  }
  1612  
  1613  /*
  1614   * helpers for shape errors
  1615   */
  1616  static char*
  1617  dumptypes(Type **nl, char *what)
  1618  {
  1619  	int first;
  1620  	Type *l;
  1621  	Iter savel;
  1622  	Fmt fmt;
  1623  
  1624  	fmtstrinit(&fmt);
  1625  	fmtprint(&fmt, "\t");
  1626  	first = 1;
  1627  	for(l = structfirst(&savel, nl); l != T; l = structnext(&savel)) {
  1628  		if(first)
  1629  			first = 0;
  1630  		else
  1631  			fmtprint(&fmt, ", ");
  1632  		fmtprint(&fmt, "%T", l);
  1633  	}
  1634  	if(first)
  1635  		fmtprint(&fmt, "[no arguments %s]", what);
  1636  	return fmtstrflush(&fmt);
  1637  }
  1638  
  1639  static char*
  1640  dumpnodetypes(NodeList *l, char *what)
  1641  {
  1642  	int first;
  1643  	Node *r;
  1644  	Fmt fmt;
  1645  
  1646  	fmtstrinit(&fmt);
  1647  	fmtprint(&fmt, "\t");
  1648  	first = 1;
  1649  	for(; l; l=l->next) {
  1650  		r = l->n;
  1651  		if(first)
  1652  			first = 0;
  1653  		else
  1654  			fmtprint(&fmt, ", ");
  1655  		fmtprint(&fmt, "%T", r->type);
  1656  	}
  1657  	if(first)
  1658  		fmtprint(&fmt, "[no arguments %s]", what);
  1659  	return fmtstrflush(&fmt);
  1660  }
  1661  
  1662  /*
  1663   * check assign expression list to
  1664   * a type list. called in
  1665   *	return expr-list
  1666   *	func(expr-list)
  1667   */
  1668  static NodeList*
  1669  ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init)
  1670  {
  1671  	Type *l, *ll;
  1672  	Node *r, *a;
  1673  	NodeList *nn, *lr0, *alist;
  1674  	Iter savel;
  1675  	char *l1, *l2;
  1676  
  1677  	lr0 = lr;
  1678  	l = structfirst(&savel, nl);
  1679  	r = N;
  1680  	if(lr)
  1681  		r = lr->n;
  1682  	nn = nil;
  1683  
  1684  	// f(g()) where g has multiple return values
  1685  	if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
  1686  		// optimization - can do block copy
  1687  		if(eqtypenoname(r->type, *nl)) {
  1688  			a = nodarg(*nl, fp);
  1689  			r = nod(OCONVNOP, r, N);
  1690  			r->type = a->type;
  1691  			nn = list1(convas(nod(OAS, a, r), init));
  1692  			goto ret;
  1693  		}
  1694  
  1695  		// conversions involved.
  1696  		// copy into temporaries.
  1697  		alist = nil;
  1698  		for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
  1699  			a = temp(l->type);
  1700  			alist = list(alist, a);
  1701  		}
  1702  		a = nod(OAS2, N, N);
  1703  		a->list = alist;
  1704  		a->rlist = lr;
  1705  		typecheck(&a, Etop);
  1706  		walkstmt(&a);
  1707  		*init = list(*init, a);
  1708  		lr = alist;
  1709  		r = lr->n;
  1710  		l = structfirst(&savel, nl);
  1711  	}
  1712  
  1713  loop:
  1714  	if(l != T && l->isddd) {
  1715  		// the ddd parameter must be last
  1716  		ll = structnext(&savel);
  1717  		if(ll != T)
  1718  			yyerror("... must be last argument");
  1719  
  1720  		// special case --
  1721  		// only if we are assigning a single ddd
  1722  		// argument to a ddd parameter then it is
  1723  		// passed thru unencapsulated
  1724  		if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
  1725  			a = nod(OAS, nodarg(l, fp), r);
  1726  			a = convas(a, init);
  1727  			nn = list(nn, a);
  1728  			goto ret;
  1729  		}
  1730  
  1731  		// normal case -- make a slice of all
  1732  		// remaining arguments and pass it to
  1733  		// the ddd parameter.
  1734  		nn = mkdotargslice(lr, nn, l, fp, init, call->right);
  1735  		goto ret;
  1736  	}
  1737  
  1738  	if(l == T || r == N) {
  1739  		if(l != T || r != N) {
  1740  			l1 = dumptypes(nl, "expected");
  1741  			l2 = dumpnodetypes(lr0, "given");
  1742  			if(l != T)
  1743  				yyerror("not enough arguments to %O\n%s\n%s", op, l1, l2);
  1744  			else
  1745  				yyerror("too many arguments to %O\n%s\n%s", op, l1, l2);
  1746  		}
  1747  		goto ret;
  1748  	}
  1749  
  1750  	a = nod(OAS, nodarg(l, fp), r);
  1751  	a = convas(a, init);
  1752  	nn = list(nn, a);
  1753  
  1754  	l = structnext(&savel);
  1755  	r = N;
  1756  	lr = lr->next;
  1757  	if(lr != nil)
  1758  		r = lr->n;
  1759  	goto loop;
  1760  
  1761  ret:
  1762  	for(lr=nn; lr; lr=lr->next)
  1763  		lr->n->typecheck = 1;
  1764  	return nn;
  1765  }
  1766  
  1767  // generate code for print
  1768  static Node*
  1769  walkprint(Node *nn, NodeList **init)
  1770  {
  1771  	Node *r;
  1772  	Node *n;
  1773  	NodeList *l, *all;
  1774  	Node *on;
  1775  	Type *t;
  1776  	int notfirst, et, op;
  1777  	NodeList *calls;
  1778  
  1779  	op = nn->op;
  1780  	all = nn->list;
  1781  	calls = nil;
  1782  	notfirst = 0;
  1783  
  1784  	// Hoist all the argument evaluation up before the lock.
  1785  	walkexprlistcheap(all, init);
  1786  
  1787  	calls = list(calls, mkcall("printlock", T, init));
  1788  
  1789  	for(l=all; l; l=l->next) {
  1790  		if(notfirst) {
  1791  			calls = list(calls, mkcall("printsp", T, init));
  1792  		}
  1793  		notfirst = op == OPRINTN;
  1794  
  1795  		n = l->n;
  1796  		if(n->op == OLITERAL) {
  1797  			switch(n->val.ctype) {
  1798  			case CTRUNE:
  1799  				defaultlit(&n, runetype);
  1800  				break;
  1801  			case CTINT:
  1802  				defaultlit(&n, types[TINT64]);
  1803  				break;
  1804  			case CTFLT:
  1805  				defaultlit(&n, types[TFLOAT64]);
  1806  				break;
  1807  			}
  1808  		}
  1809  		if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL)
  1810  			defaultlit(&n, types[TINT64]);
  1811  		defaultlit(&n, nil);
  1812  		l->n = n;
  1813  		if(n->type == T || n->type->etype == TFORW)
  1814  			continue;
  1815  
  1816  		t = n->type;
  1817  		et = n->type->etype;
  1818  		if(isinter(n->type)) {
  1819  			if(isnilinter(n->type))
  1820  				on = syslook("printeface", 1);
  1821  			else
  1822  				on = syslook("printiface", 1);
  1823  			argtype(on, n->type);		// any-1
  1824  		} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
  1825  			on = syslook("printpointer", 1);
  1826  			argtype(on, n->type);	// any-1
  1827  		} else if(isslice(n->type)) {
  1828  			on = syslook("printslice", 1);
  1829  			argtype(on, n->type);	// any-1
  1830  		} else if(isint[et]) {
  1831  			if(et == TUINT64) {
  1832  				if((t->sym->pkg == runtimepkg || compiling_runtime) && strcmp(t->sym->name, "hex") == 0)
  1833  					on = syslook("printhex", 0);
  1834  				else
  1835  					on = syslook("printuint", 0);
  1836  			} else
  1837  				on = syslook("printint", 0);
  1838  		} else if(isfloat[et]) {
  1839  			on = syslook("printfloat", 0);
  1840  		} else if(iscomplex[et]) {
  1841  			on = syslook("printcomplex", 0);
  1842  		} else if(et == TBOOL) {
  1843  			on = syslook("printbool", 0);
  1844  		} else if(et == TSTRING) {
  1845  			on = syslook("printstring", 0);
  1846  		} else {
  1847  			badtype(OPRINT, n->type, T);
  1848  			continue;
  1849  		}
  1850  
  1851  		t = *getinarg(on->type);
  1852  		if(t != nil)
  1853  			t = t->type;
  1854  		if(t != nil)
  1855  			t = t->type;
  1856  
  1857  		if(!eqtype(t, n->type)) {
  1858  			n = nod(OCONV, n, N);
  1859  			n->type = t;
  1860  		}
  1861  
  1862  		r = nod(OCALL, on, N);
  1863  		r->list = list1(n);
  1864  		calls = list(calls, r);
  1865  	}
  1866  
  1867  	if(op == OPRINTN)
  1868  		calls = list(calls, mkcall("printnl", T, nil));
  1869  
  1870  	calls = list(calls, mkcall("printunlock", T, init));
  1871  
  1872  	typechecklist(calls, Etop);
  1873  	walkexprlist(calls, init);
  1874  
  1875  	r = nod(OEMPTY, N, N);
  1876  	typecheck(&r, Etop);
  1877  	walkexpr(&r, init);
  1878  	r->ninit = calls;
  1879  	return r;
  1880  }
  1881  
  1882  Node*
  1883  callnew(Type *t)
  1884  {
  1885  	Node *fn;
  1886  
  1887  	dowidth(t);
  1888  	fn = syslook("newobject", 1);
  1889  	argtype(fn, t);
  1890  	return mkcall1(fn, ptrto(t), nil, typename(t));
  1891  }
  1892  
  1893  static int
  1894  isstack(Node *n)
  1895  {
  1896  	while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
  1897  		n = n->left;
  1898  	
  1899  	switch(n->op) {
  1900  	case OINDREG:
  1901  		// OINDREG only ends up in walk if it's indirect of SP.
  1902  		return 1;
  1903  
  1904  	case ONAME:
  1905  		switch(n->class) {
  1906  		case PAUTO:
  1907  		case PPARAM:
  1908  		case PPARAMOUT:
  1909  			return 1;
  1910  		}
  1911  		break;
  1912  	}
  1913  	
  1914  	return 0;
  1915  }
  1916  
  1917  static int
  1918  isglobal(Node *n)
  1919  {
  1920  	while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
  1921  		n = n->left;
  1922  	
  1923  	switch(n->op) {
  1924  	case ONAME:
  1925  		switch(n->class) {
  1926  		case PEXTERN:
  1927  			return 1;
  1928  		}
  1929  		break;
  1930  	}
  1931  	
  1932  	return 0;
  1933  }
  1934  
  1935  // Do we need a write barrier for the assignment l = r?
  1936  int
  1937  needwritebarrier(Node *l, Node *r)
  1938  {
  1939  	if(!use_writebarrier)
  1940  		return 0;
  1941  
  1942  	if(l == N || isblank(l))
  1943  		return 0;
  1944  
  1945  	// No write barrier for write of non-pointers.
  1946  	dowidth(l->type);
  1947  	if(!haspointers(l->type))
  1948  		return 0;
  1949  
  1950  	// No write barrier for write to stack.
  1951  	if(isstack(l))
  1952  		return 0;
  1953  
  1954  	// No write barrier for implicit or explicit zeroing.
  1955  	if(r == N || iszero(r))
  1956  		return 0;
  1957  
  1958  	// No write barrier for initialization to constant.
  1959  	if(r->op == OLITERAL)
  1960  		return 0;
  1961  
  1962  	// No write barrier for storing static (read-only) data.
  1963  	if(r->op == ONAME && strncmp(r->sym->name, "statictmp_", 10) == 0)
  1964  		return 0;
  1965  
  1966  	// No write barrier for storing address of stack values,
  1967  	// which are guaranteed only to be written to the stack.
  1968  	if(r->op == OADDR && isstack(r->left))
  1969  		return 0;
  1970  
  1971  	// No write barrier for storing address of global, which
  1972  	// is live no matter what.
  1973  	if(r->op == OADDR && isglobal(r->left))
  1974  		return 0;
  1975  
  1976  	// No write barrier for reslice: x = x[0:y] or x = append(x, ...).
  1977  	// Both are compiled to modify x directly.
  1978  	// In the case of append, a write barrier may still be needed
  1979  	// if the underlying array grows, but the append code can
  1980  	// generate the write barrier directly in that case.
  1981  	// (It does not yet, but the cost of the write barrier will be
  1982  	// small compared to the cost of the allocation.)
  1983  	if(r->reslice) {
  1984  		switch(r->op) {
  1985  		case OSLICE:
  1986  		case OSLICE3:
  1987  		case OSLICESTR:
  1988  		case OAPPEND:
  1989  			break;
  1990  		default:
  1991  			dump("bad reslice-l", l);
  1992  			dump("bad reslice-r", r);
  1993  			break;
  1994  		}
  1995  		return 0;
  1996  	}
  1997  
  1998  	// Otherwise, be conservative and use write barrier.
  1999  	return 1;
  2000  }
  2001  
  2002  // TODO(rsc): Perhaps componentgen should run before this.
  2003  static Node*
  2004  applywritebarrier(Node *n, NodeList **init)
  2005  {
  2006  	Node *l, *r;
  2007  	Type *t;
  2008  	vlong x;
  2009  	static Bvec *bv;
  2010  	char name[32];
  2011  
  2012  	if(n->left && n->right && needwritebarrier(n->left, n->right)) {
  2013  		t = n->left->type;
  2014  		l = nod(OADDR, n->left, N);
  2015  		l->etype = 1; // addr does not escape
  2016  		if(t->width == widthptr) {
  2017  			n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init,
  2018  				l, n->right);
  2019  		} else if(t->etype == TSTRING) {
  2020  			n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init,
  2021  				l, n->right);
  2022  		} else if(isslice(t)) {
  2023  			n = mkcall1(writebarrierfn("writebarrierslice", t, n->right->type), T, init,
  2024  				l, n->right);
  2025  		} else if(isinter(t)) {
  2026  			n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init,
  2027  				l, n->right);
  2028  		} else if(t->width <= 4*widthptr) {
  2029  			x = 0;
  2030  			if(bv == nil)
  2031  				bv = bvalloc(BitsPerPointer*4);
  2032  			bvresetall(bv);
  2033  			twobitwalktype1(t, &x, bv);
  2034  			// The bvgets are looking for BitsPointer in successive slots.
  2035  			enum {
  2036  				PtrBit = 1,
  2037  			};
  2038  			if(BitsPointer != (1<<PtrBit))
  2039  				fatal("wrong PtrBit");
  2040  			switch(t->width/widthptr) {
  2041  			default:
  2042  				fatal("found writebarrierfat for %d-byte object of type %T", (int)t->width, t);
  2043  			case 2:
  2044  				snprint(name, sizeof name, "writebarrierfat%d%d",
  2045  					bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit));
  2046  				break;
  2047  			case 3:
  2048  				snprint(name, sizeof name, "writebarrierfat%d%d%d",
  2049  					bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit));
  2050  				break;
  2051  			case 4:
  2052  				snprint(name, sizeof name, "writebarrierfat%d%d%d%d",
  2053  					bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit), bvget(bv, 3*BitsPerPointer+PtrBit));
  2054  				break;
  2055  			}
  2056  			n = mkcall1(writebarrierfn(name, t, n->right->type), T, init,
  2057  				l, nodnil(), n->right);
  2058  		} else {
  2059  			r = n->right;
  2060  			while(r->op == OCONVNOP)
  2061  				r = r->left;
  2062  			r = nod(OADDR, r, N);
  2063  			r->etype = 1; // addr does not escape
  2064  			//warnl(n->lineno, "writebarrierfat %T %N", t, r);
  2065  			n = mkcall1(writebarrierfn("writebarrierfat", t, r->left->type), T, init,
  2066  				typename(t), l, r);
  2067  		}
  2068  	}
  2069  	return n;
  2070  }
  2071  
  2072  static Node*
  2073  convas(Node *n, NodeList **init)
  2074  {
  2075  	Type *lt, *rt;
  2076  	Node *map, *key, *val;
  2077  
  2078  	if(n->op != OAS)
  2079  		fatal("convas: not OAS %O", n->op);
  2080  
  2081  	n->typecheck = 1;
  2082  
  2083  	if(n->left == N || n->right == N)
  2084  		goto out;
  2085  
  2086  	lt = n->left->type;
  2087  	rt = n->right->type;
  2088  	if(lt == T || rt == T)
  2089  		goto out;
  2090  
  2091  	if(isblank(n->left)) {
  2092  		defaultlit(&n->right, T);
  2093  		goto out;
  2094  	}
  2095  
  2096  	if(n->left->op == OINDEXMAP) {
  2097  		map = n->left->left;
  2098  		key = n->left->right;
  2099  		val = n->right;
  2100  		walkexpr(&map, init);
  2101  		walkexpr(&key, init);
  2102  		walkexpr(&val, init);
  2103  		// orderexpr made sure key and val are addressable.
  2104  		key = nod(OADDR, key, N);
  2105  		val = nod(OADDR, val, N);
  2106  		n = mkcall1(mapfn("mapassign1", map->type), T, init,
  2107  			typename(map->type), map, key, val);
  2108  		goto out;
  2109  	}
  2110  
  2111  	if(!eqtype(lt, rt)) {
  2112  		n->right = assignconv(n->right, lt, "assignment");
  2113  		walkexpr(&n->right, init);
  2114  	}
  2115  
  2116  out:
  2117  	ullmancalc(n);
  2118  	return n;
  2119  }
  2120  
  2121  /*
  2122   * from ascompat[te]
  2123   * evaluating actual function arguments.
  2124   *	f(a,b)
  2125   * if there is exactly one function expr,
  2126   * then it is done first. otherwise must
  2127   * make temp variables
  2128   */
  2129  static NodeList*
  2130  reorder1(NodeList *all)
  2131  {
  2132  	Node *f, *a, *n;
  2133  	NodeList *l, *r, *g;
  2134  	int c, d, t;
  2135  
  2136  	c = 0;	// function calls
  2137  	t = 0;	// total parameters
  2138  
  2139  	for(l=all; l; l=l->next) {
  2140  		n = l->n;
  2141  		t++;
  2142  		ullmancalc(n);
  2143  		if(n->ullman >= UINF)
  2144  			c++;
  2145  	}
  2146  	if(c == 0 || t == 1)
  2147  		return all;
  2148  
  2149  	g = nil;	// fncalls assigned to tempnames
  2150  	f = N;	// last fncall assigned to stack
  2151  	r = nil;	// non fncalls and tempnames assigned to stack
  2152  	d = 0;
  2153  	for(l=all; l; l=l->next) {
  2154  		n = l->n;
  2155  		if(n->ullman < UINF) {
  2156  			r = list(r, n);
  2157  			continue;
  2158  		}
  2159  		d++;
  2160  		if(d == c) {
  2161  			f = n;
  2162  			continue;
  2163  		}
  2164  
  2165  		// make assignment of fncall to tempname
  2166  		a = temp(n->right->type);
  2167  		a = nod(OAS, a, n->right);
  2168  		g = list(g, a);
  2169  
  2170  		// put normal arg assignment on list
  2171  		// with fncall replaced by tempname
  2172  		n->right = a->left;
  2173  		r = list(r, n);
  2174  	}
  2175  
  2176  	if(f != N)
  2177  		g = list(g, f);
  2178  	return concat(g, r);
  2179  }
  2180  
  2181  static void reorder3save(Node**, NodeList*, NodeList*, NodeList**);
  2182  static int aliased(Node*, NodeList*, NodeList*);
  2183  
  2184  /*
  2185   * from ascompat[ee]
  2186   *	a,b = c,d
  2187   * simultaneous assignment. there cannot
  2188   * be later use of an earlier lvalue.
  2189   *
  2190   * function calls have been removed.
  2191   */
  2192  static NodeList*
  2193  reorder3(NodeList *all)
  2194  {
  2195  	NodeList *list, *early, *mapinit;
  2196  	Node *l;
  2197  
  2198  	// If a needed expression may be affected by an
  2199  	// earlier assignment, make an early copy of that
  2200  	// expression and use the copy instead.
  2201  	early = nil;
  2202  	mapinit = nil;
  2203  	for(list=all; list; list=list->next) {
  2204  		l = list->n->left;
  2205  
  2206  		// Save subexpressions needed on left side.
  2207  		// Drill through non-dereferences.
  2208  		for(;;) {
  2209  			if(l->op == ODOT || l->op == OPAREN) {
  2210  				l = l->left;
  2211  				continue;
  2212  			}
  2213  			if(l->op == OINDEX && isfixedarray(l->left->type)) {
  2214  				reorder3save(&l->right, all, list, &early);
  2215  				l = l->left;
  2216  				continue;
  2217  			}
  2218  			break;
  2219  		}
  2220  		switch(l->op) {
  2221  		default:
  2222  			fatal("reorder3 unexpected lvalue %#O", l->op);
  2223  		case ONAME:
  2224  			break;
  2225  		case OINDEX:
  2226  		case OINDEXMAP:
  2227  			reorder3save(&l->left, all, list, &early);
  2228  			reorder3save(&l->right, all, list, &early);
  2229  			if(l->op == OINDEXMAP)
  2230  				list->n = convas(list->n, &mapinit);
  2231  			break;
  2232  		case OIND:
  2233  		case ODOTPTR:
  2234  			reorder3save(&l->left, all, list, &early);
  2235  		}
  2236  
  2237  		// Save expression on right side.
  2238  		reorder3save(&list->n->right, all, list, &early);
  2239  	}
  2240  
  2241  	early = concat(mapinit, early);
  2242  	return concat(early, all);
  2243  }
  2244  
  2245  static int vmatch2(Node*, Node*);
  2246  static int varexpr(Node*);
  2247  
  2248  /*
  2249   * if the evaluation of *np would be affected by the 
  2250   * assignments in all up to but not including stop,
  2251   * copy into a temporary during *early and
  2252   * replace *np with that temp.
  2253   */
  2254  static void
  2255  reorder3save(Node **np, NodeList *all, NodeList *stop, NodeList **early)
  2256  {
  2257  	Node *n, *q;
  2258  
  2259  	n = *np;
  2260  	if(!aliased(n, all, stop))
  2261  		return;
  2262  	
  2263  	q = temp(n->type);
  2264  	q = nod(OAS, q, n);
  2265  	typecheck(&q, Etop);
  2266  	*early = list(*early, q);
  2267  	*np = q->left;
  2268  }
  2269  
  2270  /*
  2271   * what's the outer value that a write to n affects?
  2272   * outer value means containing struct or array.
  2273   */
  2274  Node*
  2275  outervalue(Node *n)
  2276  {	
  2277  	for(;;) {
  2278  		if(n->op == ODOT || n->op == OPAREN) {
  2279  			n = n->left;
  2280  			continue;
  2281  		}
  2282  		if(n->op == OINDEX && isfixedarray(n->left->type)) {
  2283  			n = n->left;
  2284  			continue;
  2285  		}
  2286  		break;
  2287  	}
  2288  	return n;
  2289  }
  2290  
  2291  /*
  2292   * Is it possible that the computation of n might be
  2293   * affected by writes in as up to but not including stop?
  2294   */
  2295  static int
  2296  aliased(Node *n, NodeList *all, NodeList *stop)
  2297  {
  2298  	int memwrite, varwrite;
  2299  	Node *a;
  2300  	NodeList *l;
  2301  
  2302  	if(n == N)
  2303  		return 0;
  2304  
  2305  	// Look for obvious aliasing: a variable being assigned
  2306  	// during the all list and appearing in n.
  2307  	// Also record whether there are any writes to main memory.
  2308  	// Also record whether there are any writes to variables
  2309  	// whose addresses have been taken.
  2310  	memwrite = 0;
  2311  	varwrite = 0;
  2312  	for(l=all; l!=stop; l=l->next) {
  2313  		a = outervalue(l->n->left);
  2314  		if(a->op != ONAME) {
  2315  			memwrite = 1;
  2316  			continue;
  2317  		}
  2318  		switch(n->class) {
  2319  		default:
  2320  			varwrite = 1;
  2321  			continue;
  2322  		case PAUTO:
  2323  		case PPARAM:
  2324  		case PPARAMOUT:
  2325  			if(n->addrtaken) {
  2326  				varwrite = 1;
  2327  				continue;
  2328  			}
  2329  			if(vmatch2(a, n)) {
  2330  				// Direct hit.
  2331  				return 1;
  2332  			}
  2333  		}
  2334  	}
  2335  
  2336  	// The variables being written do not appear in n.
  2337  	// However, n might refer to computed addresses
  2338  	// that are being written.
  2339  	
  2340  	// If no computed addresses are affected by the writes, no aliasing.
  2341  	if(!memwrite && !varwrite)
  2342  		return 0;
  2343  
  2344  	// If n does not refer to computed addresses
  2345  	// (that is, if n only refers to variables whose addresses
  2346  	// have not been taken), no aliasing.
  2347  	if(varexpr(n))
  2348  		return 0;
  2349  
  2350  	// Otherwise, both the writes and n refer to computed memory addresses.
  2351  	// Assume that they might conflict.
  2352  	return 1;
  2353  }
  2354  
  2355  /*
  2356   * does the evaluation of n only refer to variables
  2357   * whose addresses have not been taken?
  2358   * (and no other memory)
  2359   */
  2360  static int
  2361  varexpr(Node *n)
  2362  {
  2363  	if(n == N)
  2364  		return 1;
  2365  
  2366  	switch(n->op) {
  2367  	case OLITERAL:	
  2368  		return 1;
  2369  	case ONAME:
  2370  		switch(n->class) {
  2371  		case PAUTO:
  2372  		case PPARAM:
  2373  		case PPARAMOUT:
  2374  			if(!n->addrtaken)
  2375  				return 1;
  2376  		}
  2377  		return 0;
  2378  
  2379  	case OADD:
  2380  	case OSUB:
  2381  	case OOR:
  2382  	case OXOR:
  2383  	case OMUL:
  2384  	case ODIV:
  2385  	case OMOD:
  2386  	case OLSH:
  2387  	case ORSH:
  2388  	case OAND:
  2389  	case OANDNOT:
  2390  	case OPLUS:
  2391  	case OMINUS:
  2392  	case OCOM:
  2393  	case OPAREN:
  2394  	case OANDAND:
  2395  	case OOROR:
  2396  	case ODOT:  // but not ODOTPTR
  2397  	case OCONV:
  2398  	case OCONVNOP:
  2399  	case OCONVIFACE:
  2400  	case ODOTTYPE:
  2401  		return varexpr(n->left) && varexpr(n->right);
  2402  	}
  2403  
  2404  	// Be conservative.
  2405  	return 0;
  2406  }
  2407  
  2408  /*
  2409   * is the name l mentioned in r?
  2410   */
  2411  static int
  2412  vmatch2(Node *l, Node *r)
  2413  {
  2414  	NodeList *ll;
  2415  
  2416  	if(r == N)
  2417  		return 0;
  2418  	switch(r->op) {
  2419  	case ONAME:
  2420  		// match each right given left
  2421  		return l == r;
  2422  	case OLITERAL:
  2423  		return 0;
  2424  	}
  2425  	if(vmatch2(l, r->left))
  2426  		return 1;
  2427  	if(vmatch2(l, r->right))
  2428  		return 1;
  2429  	for(ll=r->list; ll; ll=ll->next)
  2430  		if(vmatch2(l, ll->n))
  2431  			return 1;
  2432  	return 0;
  2433  }
  2434  
  2435  /*
  2436   * is any name mentioned in l also mentioned in r?
  2437   * called by sinit.c
  2438   */
  2439  int
  2440  vmatch1(Node *l, Node *r)
  2441  {
  2442  	NodeList *ll;
  2443  
  2444  	/*
  2445  	 * isolate all left sides
  2446  	 */
  2447  	if(l == N || r == N)
  2448  		return 0;
  2449  	switch(l->op) {
  2450  	case ONAME:
  2451  		switch(l->class) {
  2452  		case PPARAM:
  2453  		case PPARAMREF:
  2454  		case PAUTO:
  2455  			break;
  2456  		default:
  2457  			// assignment to non-stack variable
  2458  			// must be delayed if right has function calls.
  2459  			if(r->ullman >= UINF)
  2460  				return 1;
  2461  			break;
  2462  		}
  2463  		return vmatch2(l, r);
  2464  	case OLITERAL:
  2465  		return 0;
  2466  	}
  2467  	if(vmatch1(l->left, r))
  2468  		return 1;
  2469  	if(vmatch1(l->right, r))
  2470  		return 1;
  2471  	for(ll=l->list; ll; ll=ll->next)
  2472  		if(vmatch1(ll->n, r))
  2473  			return 1;
  2474  	return 0;
  2475  }
  2476  
  2477  /*
  2478   * walk through argin parameters.
  2479   * generate and return code to allocate
  2480   * copies of escaped parameters to the heap.
  2481   */
  2482  static NodeList*
  2483  paramstoheap(Type **argin, int out)
  2484  {
  2485  	Type *t;
  2486  	Iter savet;
  2487  	Node *v;
  2488  	NodeList *nn;
  2489  
  2490  	nn = nil;
  2491  	for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
  2492  		v = t->nname;
  2493  		if(v && v->sym && v->sym->name[0] == '~' && v->sym->name[1] == 'r') // unnamed result
  2494  			v = N;
  2495  		// In precisestack mode, the garbage collector assumes results
  2496  		// are always live, so zero them always.
  2497  		if(out && (precisestack_enabled || (v == N && hasdefer))) {
  2498  			// Defer might stop a panic and show the
  2499  			// return values as they exist at the time of panic.
  2500  			// Make sure to zero them on entry to the function.
  2501  			nn = list(nn, nod(OAS, nodarg(t, 1), N));
  2502  		}
  2503  		if(v == N || !(v->class & PHEAP))
  2504  			continue;
  2505  
  2506  		// generate allocation & copying code
  2507  		if(compiling_runtime)
  2508  			yyerror("%N escapes to heap, not allowed in runtime.", v);
  2509  		if(v->alloc == nil)
  2510  			v->alloc = callnew(v->type);
  2511  		nn = list(nn, nod(OAS, v->heapaddr, v->alloc));
  2512  		if((v->class & ~PHEAP) != PPARAMOUT)
  2513  			nn = list(nn, nod(OAS, v, v->stackparam));
  2514  	}
  2515  	return nn;
  2516  }
  2517  
  2518  /*
  2519   * walk through argout parameters copying back to stack
  2520   */
  2521  static NodeList*
  2522  returnsfromheap(Type **argin)
  2523  {
  2524  	Type *t;
  2525  	Iter savet;
  2526  	Node *v;
  2527  	NodeList *nn;
  2528  
  2529  	nn = nil;
  2530  	for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
  2531  		v = t->nname;
  2532  		if(v == N || v->class != (PHEAP|PPARAMOUT))
  2533  			continue;
  2534  		nn = list(nn, nod(OAS, v->stackparam, v));
  2535  	}
  2536  	return nn;
  2537  }
  2538  
  2539  /*
  2540   * take care of migrating any function in/out args
  2541   * between the stack and the heap.  adds code to
  2542   * curfn's before and after lists.
  2543   */
  2544  static void
  2545  heapmoves(void)
  2546  {
  2547  	NodeList *nn;
  2548  	int32 lno;
  2549  
  2550  	lno = lineno;
  2551  	lineno = curfn->lineno;
  2552  	nn = paramstoheap(getthis(curfn->type), 0);
  2553  	nn = concat(nn, paramstoheap(getinarg(curfn->type), 0));
  2554  	nn = concat(nn, paramstoheap(getoutarg(curfn->type), 1));
  2555  	curfn->enter = concat(curfn->enter, nn);
  2556  	lineno = curfn->endlineno;
  2557  	curfn->exit = returnsfromheap(getoutarg(curfn->type));
  2558  	lineno = lno;
  2559  }
  2560  
  2561  static Node*
  2562  vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
  2563  {
  2564  	int i, n;
  2565  	Node *r;
  2566  	NodeList *args;
  2567  
  2568  	if(fn->type == T || fn->type->etype != TFUNC)
  2569  		fatal("mkcall %N %T", fn, fn->type);
  2570  
  2571  	args = nil;
  2572  	n = fn->type->intuple;
  2573  	for(i=0; i<n; i++)
  2574  		args = list(args, va_arg(va, Node*));
  2575  
  2576  	r = nod(OCALL, fn, N);
  2577  	r->list = args;
  2578  	if(fn->type->outtuple > 0)
  2579  		typecheck(&r, Erv | Efnstruct);
  2580  	else
  2581  		typecheck(&r, Etop);
  2582  	walkexpr(&r, init);
  2583  	r->type = t;
  2584  	return r;
  2585  }
  2586  
  2587  Node*
  2588  mkcall(char *name, Type *t, NodeList **init, ...)
  2589  {
  2590  	Node *r;
  2591  	va_list va;
  2592  
  2593  	va_start(va, init);
  2594  	r = vmkcall(syslook(name, 0), t, init, va);
  2595  	va_end(va);
  2596  	return r;
  2597  }
  2598  
  2599  Node*
  2600  mkcall1(Node *fn, Type *t, NodeList **init, ...)
  2601  {
  2602  	Node *r;
  2603  	va_list va;
  2604  
  2605  	va_start(va, init);
  2606  	r = vmkcall(fn, t, init, va);
  2607  	va_end(va);
  2608  	return r;
  2609  }
  2610  
  2611  Node*
  2612  conv(Node *n, Type *t)
  2613  {
  2614  	if(eqtype(n->type, t))
  2615  		return n;
  2616  	n = nod(OCONV, n, N);
  2617  	n->type = t;
  2618  	typecheck(&n, Erv);
  2619  	return n;
  2620  }
  2621  
  2622  Node*
  2623  chanfn(char *name, int n, Type *t)
  2624  {
  2625  	Node *fn;
  2626  	int i;
  2627  
  2628  	if(t->etype != TCHAN)
  2629  		fatal("chanfn %T", t);
  2630  	fn = syslook(name, 1);
  2631  	for(i=0; i<n; i++)
  2632  		argtype(fn, t->type);
  2633  	return fn;
  2634  }
  2635  
  2636  static Node*
  2637  mapfn(char *name, Type *t)
  2638  {
  2639  	Node *fn;
  2640  
  2641  	if(t->etype != TMAP)
  2642  		fatal("mapfn %T", t);
  2643  	fn = syslook(name, 1);
  2644  	argtype(fn, t->down);
  2645  	argtype(fn, t->type);
  2646  	argtype(fn, t->down);
  2647  	argtype(fn, t->type);
  2648  	return fn;
  2649  }
  2650  
  2651  static Node*
  2652  mapfndel(char *name, Type *t)
  2653  {
  2654  	Node *fn;
  2655  
  2656  	if(t->etype != TMAP)
  2657  		fatal("mapfn %T", t);
  2658  	fn = syslook(name, 1);
  2659  	argtype(fn, t->down);
  2660  	argtype(fn, t->type);
  2661  	argtype(fn, t->down);
  2662  	return fn;
  2663  }
  2664  
  2665  static Node*
  2666  writebarrierfn(char *name, Type *l, Type *r)
  2667  {
  2668  	Node *fn;
  2669  
  2670  	fn = syslook(name, 1);
  2671  	argtype(fn, l);
  2672  	argtype(fn, r);
  2673  	return fn;
  2674  }
  2675  
  2676  static Node*
  2677  addstr(Node *n, NodeList **init)
  2678  {
  2679  	Node *r, *cat, *slice;
  2680  	NodeList *args, *l;
  2681  	int c;
  2682  	Type *t;
  2683  
  2684  	// orderexpr rewrote OADDSTR to have a list of strings.
  2685  	c = count(n->list);
  2686  	if(c < 2)
  2687  		yyerror("addstr count %d too small", c);
  2688  
  2689  	// build list of string arguments
  2690  	args = nil;
  2691  	for(l=n->list; l != nil; l=l->next)
  2692  		args = list(args, conv(l->n, types[TSTRING]));
  2693  
  2694  	if(c <= 5) {
  2695  		// small numbers of strings use direct runtime helpers.
  2696  		// note: orderexpr knows this cutoff too.
  2697  		snprint(namebuf, sizeof(namebuf), "concatstring%d", c);
  2698  	} else {
  2699  		// large numbers of strings are passed to the runtime as a slice.
  2700  		strcpy(namebuf, "concatstrings");
  2701  		t = typ(TARRAY);
  2702  		t->type = types[TSTRING];
  2703  		t->bound = -1;
  2704  		slice = nod(OCOMPLIT, N, typenod(t));
  2705  		slice->alloc = n->alloc;
  2706  		slice->list = args;
  2707  		slice->esc = EscNone;
  2708  		args = list1(slice);
  2709  	}
  2710  	cat = syslook(namebuf, 1);
  2711  	r = nod(OCALL, cat, N);
  2712  	r->list = args;
  2713  	typecheck(&r, Erv);
  2714  	walkexpr(&r, init);
  2715  	r->type = n->type;
  2716  
  2717  	return r;
  2718  }
  2719  
  2720  // expand append(l1, l2...) to
  2721  //   init {
  2722  //     s := l1
  2723  //     if n := len(l1) + len(l2) - cap(s); n > 0 {
  2724  //       s = growslice(s, n)
  2725  //     }
  2726  //     s = s[:len(l1)+len(l2)]
  2727  //     memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
  2728  //   }
  2729  //   s
  2730  //
  2731  // l2 is allowed to be a string.
  2732  static Node*
  2733  appendslice(Node *n, NodeList **init)
  2734  {
  2735  	NodeList *l;
  2736  	Node *l1, *l2, *nt, *nif, *fn;
  2737  	Node *nptr1, *nptr2, *nwid;
  2738  	Node *s;
  2739  
  2740  	walkexprlistsafe(n->list, init);
  2741  
  2742  	// walkexprlistsafe will leave OINDEX (s[n]) alone if both s
  2743  	// and n are name or literal, but those may index the slice we're
  2744  	// modifying here.  Fix explicitly.
  2745  	for(l=n->list; l; l=l->next)
  2746  		l->n = cheapexpr(l->n, init);
  2747  
  2748  	l1 = n->list->n;
  2749  	l2 = n->list->next->n;
  2750  
  2751  	s = temp(l1->type); // var s []T
  2752  	l = nil;
  2753  	l = list(l, nod(OAS, s, l1)); // s = l1
  2754  
  2755  	nt = temp(types[TINT]);
  2756  	nif = nod(OIF, N, N);
  2757  	// n := len(s) + len(l2) - cap(s)
  2758  	nif->ninit = list1(nod(OAS, nt,
  2759  		nod(OSUB, nod(OADD, nod(OLEN, s, N), nod(OLEN, l2, N)), nod(OCAP, s, N))));
  2760  	nif->ntest = nod(OGT, nt, nodintconst(0));
  2761  	// instantiate growslice(Type*, []any, int64) []any
  2762  	fn = syslook("growslice", 1);
  2763  	argtype(fn, s->type->type);
  2764  	argtype(fn, s->type->type);
  2765  
  2766  	// s = growslice(T, s, n)
  2767  	nif->nbody = list1(nod(OAS, s, mkcall1(fn, s->type, &nif->ninit,
  2768  					       typename(s->type),
  2769  					       s,
  2770  					       conv(nt, types[TINT64]))));
  2771  
  2772  	l = list(l, nif);
  2773  
  2774  	if(flag_race) {
  2775  		// rely on runtime to instrument copy.
  2776  		// copy(s[len(l1):len(l1)+len(l2)], l2)
  2777  		nptr1 = nod(OSLICE, s, nod(OKEY,
  2778  			nod(OLEN, l1, N),
  2779  			nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N))));
  2780  		nptr1->etype = 1;
  2781  		nptr2 = l2;
  2782  		if(l2->type->etype == TSTRING)
  2783  			fn = syslook("slicestringcopy", 1);
  2784  		else
  2785  			fn = syslook("slicecopy", 1);
  2786  		argtype(fn, l1->type);
  2787  		argtype(fn, l2->type);
  2788  		nt = mkcall1(fn, types[TINT], &l,
  2789  				nptr1, nptr2,
  2790  				nodintconst(s->type->type->width));
  2791  		l = list(l, nt);
  2792  	} else {
  2793  		// memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
  2794  		nptr1 = nod(OINDEX, s, nod(OLEN, l1, N));
  2795  		nptr1->bounded = 1;
  2796  		nptr1 = nod(OADDR, nptr1, N);
  2797  
  2798  		nptr2 = nod(OSPTR, l2, N);
  2799  
  2800  		fn = syslook("memmove", 1);
  2801  		argtype(fn, s->type->type);	// 1 old []any
  2802  		argtype(fn, s->type->type);	// 2 ret []any
  2803  
  2804  		nwid = cheapexpr(conv(nod(OLEN, l2, N), types[TUINTPTR]), &l);
  2805  		nwid = nod(OMUL, nwid, nodintconst(s->type->type->width));
  2806  		nt = mkcall1(fn, T, &l, nptr1, nptr2, nwid);
  2807  		l = list(l, nt);
  2808  	}
  2809  
  2810  	// s = s[:len(l1)+len(l2)]
  2811  	nt = nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N));
  2812  	nt = nod(OSLICE, s, nod(OKEY, N, nt));
  2813  	nt->etype = 1;
  2814  	l = list(l, nod(OAS, s, nt));
  2815  
  2816  	typechecklist(l, Etop);
  2817  	walkstmtlist(l);
  2818  	*init = concat(*init, l);
  2819  	return s;
  2820  }
  2821  
  2822  // expand append(src, a [, b]* ) to
  2823  //
  2824  //   init {
  2825  //     s := src
  2826  //     const argc = len(args) - 1
  2827  //     if cap(s) - len(s) < argc {
  2828  //	    s = growslice(s, argc)
  2829  //     }
  2830  //     n := len(s)
  2831  //     s = s[:n+argc]
  2832  //     s[n] = a
  2833  //     s[n+1] = b
  2834  //     ...
  2835  //   }
  2836  //   s
  2837  static Node*
  2838  append(Node *n, NodeList **init)
  2839  {
  2840  	NodeList *l, *a;
  2841  	Node *nsrc, *ns, *nn, *na, *nx, *fn;
  2842  	int argc;
  2843  
  2844  	walkexprlistsafe(n->list, init);
  2845  
  2846  	// walkexprlistsafe will leave OINDEX (s[n]) alone if both s
  2847  	// and n are name or literal, but those may index the slice we're
  2848  	// modifying here.  Fix explicitly.
  2849  	for(l=n->list; l; l=l->next)
  2850  		l->n = cheapexpr(l->n, init);
  2851  
  2852  	nsrc = n->list->n;
  2853  
  2854  	// Resolve slice type of multi-valued return.
  2855  	if(istype(nsrc->type, TSTRUCT))
  2856  		nsrc->type = nsrc->type->type->type;
  2857  	argc = count(n->list) - 1;
  2858  	if (argc < 1) {
  2859  		return nsrc;
  2860  	}
  2861  
  2862  	l = nil;
  2863  
  2864  	ns = temp(nsrc->type);
  2865  	l = list(l, nod(OAS, ns, nsrc));  // s = src
  2866  
  2867  	na = nodintconst(argc);		// const argc
  2868  	nx = nod(OIF, N, N);		// if cap(s) - len(s) < argc
  2869  	nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
  2870  
  2871  	fn = syslook("growslice", 1);	//   growslice(<type>, old []T, n int64) (ret []T)
  2872  	argtype(fn, ns->type->type);	// 1 old []any
  2873  	argtype(fn, ns->type->type);	// 2 ret []any
  2874  
  2875  	nx->nbody = list1(nod(OAS, ns, mkcall1(fn,  ns->type, &nx->ninit,
  2876  					       typename(ns->type),
  2877  					       ns,
  2878  					       conv(na, types[TINT64]))));
  2879  	l = list(l, nx);
  2880  
  2881  	nn = temp(types[TINT]);
  2882  	l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));	 // n = len(s)
  2883  
  2884  	nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));	 // ...s[:n+argc]
  2885  	nx->etype = 1;
  2886  	l = list(l, nod(OAS, ns, nx));			// s = s[:n+argc]
  2887  
  2888  	for (a = n->list->next;	 a != nil; a = a->next) {
  2889  		nx = nod(OINDEX, ns, nn);		// s[n] ...
  2890  		nx->bounded = 1;
  2891  		l = list(l, nod(OAS, nx, a->n));	// s[n] = arg
  2892  		if (a->next != nil)
  2893  			l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1))));  // n = n + 1
  2894  	}
  2895  
  2896  	typechecklist(l, Etop);
  2897  	walkstmtlist(l);
  2898  	*init = concat(*init, l);
  2899  	return ns;
  2900  }
  2901  
  2902  // Lower copy(a, b) to a memmove call or a runtime call.
  2903  //
  2904  // init {
  2905  //   n := len(a)
  2906  //   if n > len(b) { n = len(b) }
  2907  //   memmove(a.ptr, b.ptr, n*sizeof(elem(a)))
  2908  // }
  2909  // n;
  2910  //
  2911  // Also works if b is a string.
  2912  //
  2913  static Node*
  2914  copyany(Node *n, NodeList **init, int runtimecall)
  2915  {
  2916  	Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn;
  2917  	NodeList *l;
  2918  	
  2919  	if(haspointers(n->left->type->type)) {
  2920  		fn = writebarrierfn("writebarriercopy", n->left->type, n->right->type);
  2921  		return mkcall1(fn, n->type, init, typename(n->left->type->type), n->left, n->right);
  2922  	}
  2923  
  2924  	if(runtimecall) {
  2925  		if(n->right->type->etype == TSTRING)
  2926  			fn = syslook("slicestringcopy", 1);
  2927  		else
  2928  			fn = syslook("slicecopy", 1);
  2929  		argtype(fn, n->left->type);
  2930  		argtype(fn, n->right->type);
  2931  		return mkcall1(fn, n->type, init,
  2932  				n->left, n->right,
  2933  				nodintconst(n->left->type->type->width));
  2934  	}
  2935  	walkexpr(&n->left, init);
  2936  	walkexpr(&n->right, init);
  2937  	nl = temp(n->left->type);
  2938  	nr = temp(n->right->type);
  2939  	l = nil;
  2940  	l = list(l, nod(OAS, nl, n->left));
  2941  	l = list(l, nod(OAS, nr, n->right));
  2942  
  2943  	nfrm = nod(OSPTR, nr, N);
  2944  	nto = nod(OSPTR, nl, N);
  2945  
  2946  	nlen = temp(types[TINT]);
  2947  	// n = len(to)
  2948  	l = list(l, nod(OAS, nlen, nod(OLEN, nl, N)));
  2949  	// if n > len(frm) { n = len(frm) }
  2950  	nif = nod(OIF, N, N);
  2951  	nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N));
  2952  	nif->nbody = list(nif->nbody,
  2953  		nod(OAS, nlen, nod(OLEN, nr, N)));
  2954  	l = list(l, nif);
  2955  
  2956  	// Call memmove.
  2957  	fn = syslook("memmove", 1);
  2958  	argtype(fn, nl->type->type);
  2959  	argtype(fn, nl->type->type);
  2960  	nwid = temp(types[TUINTPTR]);
  2961  	l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR])));
  2962  	nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width));
  2963  	l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid));
  2964  
  2965  	typechecklist(l, Etop);
  2966  	walkstmtlist(l);
  2967  	*init = concat(*init, l);
  2968  	return nlen;
  2969  }
  2970  
  2971  // Generate frontend part for OSLICE[3][ARR|STR]
  2972  // 
  2973  static	Node*
  2974  sliceany(Node* n, NodeList **init)
  2975  {
  2976  	int bounded, slice3;
  2977  	Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2;
  2978  	int64 lbv, hbv, cbv, bv, w;
  2979  	Type *bt;
  2980  
  2981  //	print("before sliceany: %+N\n", n);
  2982  
  2983  	src = n->left;
  2984  	lb = n->right->left;
  2985  	slice3 = n->op == OSLICE3 || n->op == OSLICE3ARR;
  2986  	if(slice3) {
  2987  		hb = n->right->right->left;
  2988  		cb = n->right->right->right;
  2989  	} else {
  2990  		hb = n->right->right;
  2991  		cb = N;
  2992  	}
  2993  
  2994  	bounded = n->etype;
  2995  	
  2996  	if(n->op == OSLICESTR)
  2997  		bound = nod(OLEN, src, N);
  2998  	else
  2999  		bound = nod(OCAP, src, N);
  3000  
  3001  	typecheck(&bound, Erv);
  3002  	walkexpr(&bound, init);  // if src is an array, bound will be a const now.
  3003  
  3004  	// static checks if possible
  3005  	bv = 1LL<<50;
  3006  	if(isconst(bound, CTINT)) {
  3007  		if(!smallintconst(bound))
  3008  			yyerror("array len too large");
  3009  		else
  3010  			bv = mpgetfix(bound->val.u.xval);
  3011  	}
  3012  
  3013  	if(isconst(cb, CTINT)) {
  3014  		cbv = mpgetfix(cb->val.u.xval);
  3015  		if(cbv < 0 || cbv > bv)
  3016  			yyerror("slice index out of bounds");
  3017  	}
  3018  	if(isconst(hb, CTINT)) {
  3019  		hbv = mpgetfix(hb->val.u.xval);
  3020  		if(hbv < 0 || hbv > bv)
  3021  			yyerror("slice index out of bounds");
  3022  	}
  3023  	if(isconst(lb, CTINT)) {
  3024  		lbv = mpgetfix(lb->val.u.xval);
  3025  		if(lbv < 0 || lbv > bv) {
  3026  			yyerror("slice index out of bounds");
  3027  			lbv = -1;
  3028  		}
  3029  		if(lbv == 0)
  3030  			lb = N;
  3031  	}
  3032  
  3033  	// Checking src[lb:hb:cb] or src[lb:hb].
  3034  	// if chk0 || chk1 || chk2 { panicslice() }
  3035  	chk = N;
  3036  	chk0 = N; // cap(src) < cb
  3037  	chk1 = N; // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
  3038  	chk2 = N; // hb < lb
  3039  
  3040  	// All comparisons are unsigned to avoid testing < 0.
  3041  	bt = types[simtype[TUINT]];
  3042  	if(cb != N && cb->type->width > 4)
  3043  		bt = types[TUINT64];
  3044  	if(hb != N && hb->type->width > 4)
  3045  		bt = types[TUINT64];
  3046  	if(lb != N && lb->type->width > 4)
  3047  		bt = types[TUINT64];
  3048  
  3049  	bound = cheapexpr(conv(bound, bt), init);
  3050  
  3051  	if(cb != N) {
  3052  		cb = cheapexpr(conv(cb, bt), init);
  3053  		if(!bounded)
  3054  			chk0 = nod(OLT, bound, cb);
  3055  	} else if(slice3) {
  3056  		// When we figure out what this means, implement it.
  3057  		fatal("slice3 with cb == N"); // rejected by parser
  3058  	}
  3059  		
  3060  	if(hb != N) {
  3061  		hb = cheapexpr(conv(hb, bt), init);
  3062  		if(!bounded) {
  3063  			if(cb != N)
  3064  				chk1 = nod(OLT, cb, hb);
  3065  			else
  3066  				chk1 = nod(OLT, bound, hb);
  3067  		}
  3068  	} else if(slice3) {
  3069  		// When we figure out what this means, implement it.
  3070  		fatal("slice3 with hb == N"); // rejected by parser
  3071  	} else if(n->op == OSLICEARR) {
  3072  		hb = bound;
  3073  	} else {
  3074  		hb = nod(OLEN, src, N);
  3075  		typecheck(&hb, Erv);
  3076  		walkexpr(&hb, init);
  3077  		hb = cheapexpr(conv(hb, bt), init);
  3078  	}
  3079  
  3080  	if(lb != N) {
  3081  		lb = cheapexpr(conv(lb, bt), init);
  3082  		if(!bounded)
  3083  			chk2 = nod(OLT, hb, lb);  
  3084  	}
  3085  
  3086  	if(chk0 != N || chk1 != N || chk2 != N) {
  3087  		chk = nod(OIF, N, N);
  3088  		chk->nbody = list1(mkcall("panicslice", T, init));
  3089  		chk->likely = -1;
  3090  		if(chk0 != N)
  3091  			chk->ntest = chk0;
  3092  		if(chk1 != N) {
  3093  			if(chk->ntest == N)
  3094  				chk->ntest = chk1;
  3095  			else
  3096  				chk->ntest = nod(OOROR, chk->ntest, chk1);
  3097  		}
  3098  		if(chk2 != N) {
  3099  			if(chk->ntest == N)
  3100  				chk->ntest = chk2;
  3101  			else
  3102  				chk->ntest = nod(OOROR, chk->ntest, chk2);
  3103  		}
  3104  		typecheck(&chk, Etop);
  3105  		walkstmt(&chk);
  3106  		*init = concat(*init, chk->ninit);
  3107  		chk->ninit = nil;
  3108  		*init = list(*init, chk);
  3109  	}
  3110  	
  3111  	// prepare new cap, len and offs for backend cgen_slice
  3112  	// cap = bound [ - lo ]
  3113  	n->right = N;
  3114  	n->list = nil;
  3115  	if(!slice3)
  3116  		cb = bound;
  3117  	if(lb == N)
  3118  		bound = conv(cb, types[simtype[TUINT]]);
  3119  	else
  3120  		bound = nod(OSUB, conv(cb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
  3121  	typecheck(&bound, Erv);
  3122  	walkexpr(&bound, init);
  3123  	n->list = list(n->list, bound);
  3124  
  3125  	// len = hi [ - lo]
  3126  	if(lb == N)
  3127  		hb = conv(hb, types[simtype[TUINT]]);
  3128  	else
  3129  		hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
  3130  	typecheck(&hb, Erv);
  3131  	walkexpr(&hb, init);
  3132  	n->list = list(n->list, hb);
  3133  
  3134  	// offs = [width *] lo, but omit if zero
  3135  	if(lb != N) {
  3136  		if(n->op == OSLICESTR)
  3137  			w = 1;
  3138  		else
  3139  			w = n->type->type->width;
  3140  		lb = conv(lb, types[TUINTPTR]);
  3141  		if(w > 1)
  3142  			lb = nod(OMUL, nodintconst(w), lb);
  3143  		typecheck(&lb, Erv);
  3144  		walkexpr(&lb, init);
  3145  		n->list = list(n->list, lb);
  3146  	}
  3147  
  3148  //	print("after sliceany: %+N\n", n);
  3149  
  3150  	return n;
  3151  }
  3152  
  3153  static Node*
  3154  eqfor(Type *t)
  3155  {
  3156  	int a;
  3157  	Node *n;
  3158  	Node *ntype;
  3159  	Sym *sym;
  3160  
  3161  	// Should only arrive here with large memory or
  3162  	// a struct/array containing a non-memory field/element.
  3163  	// Small memory is handled inline, and single non-memory
  3164  	// is handled during type check (OCMPSTR etc).
  3165  	a = algtype1(t, nil);
  3166  	if(a != AMEM && a != -1)
  3167  		fatal("eqfor %T", t);
  3168  
  3169  	if(a == AMEM) {
  3170  		n = syslook("memequal", 1);
  3171  		argtype(n, t);
  3172  		argtype(n, t);
  3173  		return n;
  3174  	}
  3175  
  3176  	sym = typesymprefix(".eq", t);
  3177  	n = newname(sym);
  3178  	n->class = PFUNC;
  3179  	ntype = nod(OTFUNC, N, N);
  3180  	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
  3181  	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
  3182  	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
  3183  	ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, N, typenod(types[TBOOL])));
  3184  	typecheck(&ntype, Etype);
  3185  	n->type = ntype->type;
  3186  	return n;
  3187  }
  3188  
  3189  static int
  3190  countfield(Type *t)
  3191  {
  3192  	Type *t1;
  3193  	int n;
  3194  	
  3195  	n = 0;
  3196  	for(t1=t->type; t1!=T; t1=t1->down)
  3197  		n++;
  3198  	return n;
  3199  }
  3200  
  3201  static void
  3202  walkcompare(Node **np, NodeList **init)
  3203  {
  3204  	Node *n, *l, *r, *call, *a, *li, *ri, *expr, *cmpl, *cmpr;
  3205  	int andor, i;
  3206  	Type *t, *t1;
  3207  	
  3208  	n = *np;
  3209  	
  3210  	// Must be comparison of array or struct.
  3211  	// Otherwise back end handles it.
  3212  	t = n->left->type;
  3213  	switch(t->etype) {
  3214  	default:
  3215  		return;
  3216  	case TARRAY:
  3217  		if(isslice(t))
  3218  			return;
  3219  		break;
  3220  	case TSTRUCT:
  3221  		break;
  3222  	}
  3223  	
  3224  	cmpl = n->left;
  3225  	while(cmpl != N && cmpl->op == OCONVNOP)
  3226  		cmpl = cmpl->left;
  3227  	cmpr = n->right;
  3228  	while(cmpr != N && cmpr->op == OCONVNOP)
  3229  		cmpr = cmpr->left;
  3230  	
  3231  	if(!islvalue(cmpl) || !islvalue(cmpr)) {
  3232  		fatal("arguments of comparison must be lvalues - %N %N", cmpl, cmpr);
  3233  	}
  3234  
  3235  	l = temp(ptrto(t));
  3236  	a = nod(OAS, l, nod(OADDR, cmpl, N));
  3237  	a->right->etype = 1;  // addr does not escape
  3238  	typecheck(&a, Etop);
  3239  	*init = list(*init, a);
  3240  
  3241  	r = temp(ptrto(t));
  3242  	a = nod(OAS, r, nod(OADDR, cmpr, N));
  3243  	a->right->etype = 1;  // addr does not escape
  3244  	typecheck(&a, Etop);
  3245  	*init = list(*init, a);
  3246  
  3247  	expr = N;
  3248  	andor = OANDAND;
  3249  	if(n->op == ONE)
  3250  		andor = OOROR;
  3251  
  3252  	if(t->etype == TARRAY &&
  3253  		t->bound <= 4 &&
  3254  		issimple[t->type->etype]) {
  3255  		// Four or fewer elements of a basic type.
  3256  		// Unroll comparisons.
  3257  		for(i=0; i<t->bound; i++) {
  3258  			li = nod(OINDEX, l, nodintconst(i));
  3259  			ri = nod(OINDEX, r, nodintconst(i));
  3260  			a = nod(n->op, li, ri);
  3261  			if(expr == N)
  3262  				expr = a;
  3263  			else
  3264  				expr = nod(andor, expr, a);
  3265  		}
  3266  		if(expr == N)
  3267  			expr = nodbool(n->op == OEQ);
  3268  		r = expr;
  3269  		goto ret;
  3270  	}
  3271  
  3272  	if(t->etype == TSTRUCT && countfield(t) <= 4) {
  3273  		// Struct of four or fewer fields.
  3274  		// Inline comparisons.
  3275  		for(t1=t->type; t1; t1=t1->down) {
  3276  			if(isblanksym(t1->sym))
  3277  				continue;
  3278  			li = nod(OXDOT, l, newname(t1->sym));
  3279  			ri = nod(OXDOT, r, newname(t1->sym));
  3280  			a = nod(n->op, li, ri);
  3281  			if(expr == N)
  3282  				expr = a;
  3283  			else
  3284  				expr = nod(andor, expr, a);
  3285  		}
  3286  		if(expr == N)
  3287  			expr = nodbool(n->op == OEQ);
  3288  		r = expr;
  3289  		goto ret;
  3290  	}
  3291  
  3292  	// Chose not to inline.  Call equality function directly.
  3293  	call = nod(OCALL, eqfor(t), N);
  3294  	call->list = list(call->list, l);
  3295  	call->list = list(call->list, r);
  3296  	call->list = list(call->list, nodintconst(t->width));
  3297  	r = call;
  3298  	if(n->op != OEQ)
  3299  		r = nod(ONOT, r, N);
  3300  	goto ret;
  3301  
  3302  ret:
  3303  	typecheck(&r, Erv);
  3304  	walkexpr(&r, init);
  3305  	if(r->type != n->type) {
  3306  		r = nod(OCONVNOP, r, N);
  3307  		r->type = n->type;
  3308  		r->typecheck = 1;
  3309  	}
  3310  	*np = r;
  3311  	return;
  3312  }
  3313  
  3314  static int
  3315  samecheap(Node *a, Node *b)
  3316  {
  3317  	Node *ar, *br;
  3318  	while(a != N && b != N && a->op == b->op) {
  3319  		switch(a->op) {
  3320  		default:
  3321  			return 0;
  3322  		case ONAME:
  3323  			return a == b;
  3324  		case ODOT:
  3325  		case ODOTPTR:
  3326  			ar = a->right;
  3327  			br = b->right;
  3328  			if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym)
  3329  				return 0;
  3330  			break;
  3331  		case OINDEX:
  3332  			ar = a->right;
  3333  			br = b->right;
  3334  			if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0)
  3335  				return 0;
  3336  			break;
  3337  		}
  3338  		a = a->left;
  3339  		b = b->left;
  3340  	}
  3341  	return 0;
  3342  }
  3343  
  3344  static void
  3345  walkrotate(Node **np)
  3346  {
  3347  	int w, sl, sr, s;
  3348  	Node *l, *r;
  3349  	Node *n;
  3350  
  3351  	if(thechar == '9')
  3352  		return;
  3353  	
  3354  	n = *np;
  3355  
  3356  	// Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
  3357  	l = n->left;
  3358  	r = n->right;
  3359  	if((n->op != OOR && n->op != OXOR) ||
  3360  	   (l->op != OLSH && l->op != ORSH) ||
  3361  	   (r->op != OLSH && r->op != ORSH) ||
  3362  	   n->type == T || issigned[n->type->etype] ||
  3363  	   l->op == r->op) {
  3364  		return;
  3365  	}
  3366  
  3367  	// Want same, side effect-free expression on lhs of both shifts.
  3368  	if(!samecheap(l->left, r->left))
  3369  		return;
  3370  	
  3371  	// Constants adding to width?
  3372  	w = l->type->width * 8;
  3373  	if(smallintconst(l->right) && smallintconst(r->right)) {
  3374  		if((sl=mpgetfix(l->right->val.u.xval)) >= 0 && (sr=mpgetfix(r->right->val.u.xval)) >= 0 && sl+sr == w)
  3375  			goto yes;
  3376  		return;
  3377  	}
  3378  	
  3379  	// TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
  3380  	return;
  3381  	
  3382  yes:
  3383  	// Rewrite left shift half to left rotate.
  3384  	if(l->op == OLSH)
  3385  		n = l;
  3386  	else
  3387  		n = r;
  3388  	n->op = OLROT;
  3389  	
  3390  	// Remove rotate 0 and rotate w.
  3391  	s = mpgetfix(n->right->val.u.xval);
  3392  	if(s == 0 || s == w)
  3393  		n = n->left;
  3394  
  3395  	*np = n;
  3396  	return;
  3397  }
  3398  
  3399  /*
  3400   * walkmul rewrites integer multiplication by powers of two as shifts.
  3401   */
  3402  static void
  3403  walkmul(Node **np, NodeList **init)
  3404  {
  3405  	Node *n, *nl, *nr;
  3406  	int pow, neg, w;
  3407  	
  3408  	n = *np;
  3409  	if(!isint[n->type->etype])
  3410  		return;
  3411  
  3412  	if(n->right->op == OLITERAL) {
  3413  		nl = n->left;
  3414  		nr = n->right;
  3415  	} else if(n->left->op == OLITERAL) {
  3416  		nl = n->right;
  3417  		nr = n->left;
  3418  	} else
  3419  		return;
  3420  
  3421  	neg = 0;
  3422  
  3423  	// x*0 is 0 (and side effects of x).
  3424  	if(mpgetfix(nr->val.u.xval) == 0) {
  3425  		cheapexpr(nl, init);
  3426  		nodconst(n, n->type, 0);
  3427  		goto ret;
  3428  	}
  3429  
  3430  	// nr is a constant.
  3431  	pow = powtwo(nr);
  3432  	if(pow < 0)
  3433  		return;
  3434  	if(pow >= 1000) {
  3435  		// negative power of 2, like -16
  3436  		neg = 1;
  3437  		pow -= 1000;
  3438  	}
  3439  
  3440  	w = nl->type->width*8;
  3441  	if(pow+1 >= w)// too big, shouldn't happen
  3442  		return;
  3443  
  3444  	nl = cheapexpr(nl, init);
  3445  
  3446  	if(pow == 0) {
  3447  		// x*1 is x
  3448  		n = nl;
  3449  		goto ret;
  3450  	}
  3451  	
  3452  	n = nod(OLSH, nl, nodintconst(pow));
  3453  
  3454  ret:
  3455  	if(neg)
  3456  		n = nod(OMINUS, n, N);
  3457  
  3458  	typecheck(&n, Erv);
  3459  	walkexpr(&n, init);
  3460  	*np = n;
  3461  }
  3462  
  3463  /*
  3464   * walkdiv rewrites division by a constant as less expensive
  3465   * operations.
  3466   */
  3467  static void
  3468  walkdiv(Node **np, NodeList **init)
  3469  {
  3470  	Node *n, *nl, *nr, *nc;
  3471  	Node *n1, *n2, *n3, *n4;
  3472  	int pow; // if >= 0, nr is 1<<pow
  3473  	int s; // 1 if nr is negative.
  3474  	int w;
  3475  	Type *twide;
  3476  	Magic m;
  3477  
  3478  	// TODO(minux)
  3479  	if(thechar == '9')
  3480  		return;
  3481  
  3482  	n = *np;
  3483  	if(n->right->op != OLITERAL)
  3484  		return;
  3485  	// nr is a constant.
  3486  	nl = cheapexpr(n->left, init);
  3487  	nr = n->right;
  3488  
  3489  	// special cases of mod/div
  3490  	// by a constant
  3491  	w = nl->type->width*8;
  3492  	s = 0;
  3493  	pow = powtwo(nr);
  3494  	if(pow >= 1000) {
  3495  		// negative power of 2
  3496  		s = 1;
  3497  		pow -= 1000;
  3498  	}
  3499  
  3500  	if(pow+1 >= w) {
  3501  		// divisor too large.
  3502  		return;
  3503  	}
  3504  	if(pow < 0) {
  3505  		goto divbymul;
  3506  	}
  3507  
  3508  	switch(pow) {
  3509  	case 0:
  3510  		if(n->op == OMOD) {
  3511  			// nl % 1 is zero.
  3512  			nodconst(n, n->type, 0);
  3513  		} else if(s) {
  3514  			// divide by -1
  3515  			n->op = OMINUS;
  3516  			n->right = N;
  3517  		} else {
  3518  			// divide by 1
  3519  			n = nl;
  3520  		}
  3521  		break;
  3522  	default:
  3523  		if(issigned[n->type->etype]) {
  3524  			if(n->op == OMOD) {
  3525  				// signed modulo 2^pow is like ANDing
  3526  				// with the last pow bits, but if nl < 0,
  3527  				// nl & (2^pow-1) is (nl+1)%2^pow - 1.
  3528  				nc = nod(OXXX, N, N);
  3529  				nodconst(nc, types[simtype[TUINT]], w-1);
  3530  				n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
  3531  				if(pow == 1) {
  3532  					typecheck(&n1, Erv);
  3533  					n1 = cheapexpr(n1, init);
  3534  					// n = (nl+ε)&1 -ε where ε=1 iff nl<0.
  3535  					n2 = nod(OSUB, nl, n1);
  3536  					nc = nod(OXXX, N, N);
  3537  					nodconst(nc, nl->type, 1);
  3538  					n3 = nod(OAND, n2, nc);
  3539  					n = nod(OADD, n3, n1);
  3540  				} else {
  3541  					// n = (nl+ε)&(nr-1) - ε where ε=2^pow-1 iff nl<0.
  3542  					nc = nod(OXXX, N, N);
  3543  					nodconst(nc, nl->type, (1LL<<pow)-1);
  3544  					n2 = nod(OAND, n1, nc); // n2 = 2^pow-1 iff nl<0.
  3545  					typecheck(&n2, Erv);
  3546  					n2 = cheapexpr(n2, init);
  3547  
  3548  					n3 = nod(OADD, nl, n2);
  3549  					n4 = nod(OAND, n3, nc);
  3550  					n = nod(OSUB, n4, n2);
  3551  				}
  3552  				break;
  3553  			} else {
  3554  				// arithmetic right shift does not give the correct rounding.
  3555  				// if nl >= 0, nl >> n == nl / nr
  3556  				// if nl < 0, we want to add 2^n-1 first.
  3557  				nc = nod(OXXX, N, N);
  3558  				nodconst(nc, types[simtype[TUINT]], w-1);
  3559  				n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
  3560  				if(pow == 1) {
  3561  					// nl+1 is nl-(-1)
  3562  					n->left = nod(OSUB, nl, n1);
  3563  				} else {
  3564  					// Do a logical right right on -1 to keep pow bits.
  3565  					nc = nod(OXXX, N, N);
  3566  					nodconst(nc, types[simtype[TUINT]], w-pow);
  3567  					n2 = nod(ORSH, conv(n1, tounsigned(nl->type)), nc);
  3568  					n->left = nod(OADD, nl, conv(n2, nl->type));
  3569  				}
  3570  				// n = (nl + 2^pow-1) >> pow
  3571  				n->op = ORSH;
  3572  				nc = nod(OXXX, N, N);
  3573  				nodconst(nc, types[simtype[TUINT]], pow);
  3574  				n->right = nc;
  3575  				n->typecheck = 0;
  3576  			}
  3577  			if(s)
  3578  				n = nod(OMINUS, n, N);
  3579  			break;
  3580  		}
  3581  		nc = nod(OXXX, N, N);
  3582  		if(n->op == OMOD) {
  3583  			// n = nl & (nr-1)
  3584  			n->op = OAND;
  3585  			nodconst(nc, nl->type, mpgetfix(nr->val.u.xval)-1);
  3586  		} else {
  3587  			// n = nl >> pow
  3588  			n->op = ORSH;
  3589  			nodconst(nc, types[simtype[TUINT]], pow);
  3590  		}
  3591  		n->typecheck = 0;
  3592  		n->right = nc;
  3593  		break;
  3594  	}
  3595  	goto ret;
  3596  
  3597  divbymul:
  3598  	// try to do division by multiply by (2^w)/d
  3599  	// see hacker's delight chapter 10
  3600  	// TODO: support 64-bit magic multiply here.
  3601  	m.w = w;
  3602  	if(issigned[nl->type->etype]) {
  3603  		m.sd = mpgetfix(nr->val.u.xval);
  3604  		smagic(&m);
  3605  	} else {
  3606  		m.ud = mpgetfix(nr->val.u.xval);
  3607  		umagic(&m);
  3608  	}
  3609  	if(m.bad)
  3610  		return;
  3611  
  3612  	// We have a quick division method so use it
  3613  	// for modulo too.
  3614  	if(n->op == OMOD)
  3615  		goto longmod;
  3616  
  3617  	switch(simtype[nl->type->etype]) {
  3618  	default:
  3619  		return;
  3620  
  3621  	case TUINT8:
  3622  	case TUINT16:
  3623  	case TUINT32:
  3624  		// n1 = nl * magic >> w (HMUL)
  3625  		nc = nod(OXXX, N, N);
  3626  		nodconst(nc, nl->type, m.um);
  3627  		n1 = nod(OMUL, nl, nc);
  3628  		typecheck(&n1, Erv);
  3629  		n1->op = OHMUL;
  3630  		if(m.ua) {
  3631  			// Select a Go type with (at least) twice the width.
  3632  			switch(simtype[nl->type->etype]) {
  3633  			default:
  3634  				return;
  3635  			case TUINT8:
  3636  			case TUINT16:
  3637  				twide = types[TUINT32];
  3638  				break;
  3639  			case TUINT32:
  3640  				twide = types[TUINT64];
  3641  				break;
  3642  			case TINT8:
  3643  			case TINT16:
  3644  				twide = types[TINT32];
  3645  				break;
  3646  			case TINT32:
  3647  				twide = types[TINT64];
  3648  				break;
  3649  			}
  3650  
  3651  			// add numerator (might overflow).
  3652  			// n2 = (n1 + nl)
  3653  			n2 = nod(OADD, conv(n1, twide), conv(nl, twide));
  3654  
  3655  			// shift by m.s
  3656  			nc = nod(OXXX, N, N);
  3657  			nodconst(nc, types[TUINT], m.s);
  3658  			n = conv(nod(ORSH, n2, nc), nl->type);
  3659  		} else {
  3660  			// n = n1 >> m.s
  3661  			nc = nod(OXXX, N, N);
  3662  			nodconst(nc, types[TUINT], m.s);
  3663  			n = nod(ORSH, n1, nc);
  3664  		}
  3665  		break;
  3666  
  3667  	case TINT8:
  3668  	case TINT16:
  3669  	case TINT32:
  3670  		// n1 = nl * magic >> w
  3671  		nc = nod(OXXX, N, N);
  3672  		nodconst(nc, nl->type, m.sm);
  3673  		n1 = nod(OMUL, nl, nc);
  3674  		typecheck(&n1, Erv);
  3675  		n1->op = OHMUL;
  3676  		if(m.sm < 0) {
  3677  			// add the numerator.
  3678  			n1 = nod(OADD, n1, nl);
  3679  		}
  3680  		// shift by m.s
  3681  		nc = nod(OXXX, N, N);
  3682  		nodconst(nc, types[TUINT], m.s);
  3683  		n2 = conv(nod(ORSH, n1, nc), nl->type);
  3684  		// add 1 iff n1 is negative.
  3685  		nc = nod(OXXX, N, N);
  3686  		nodconst(nc, types[TUINT], w-1);
  3687  		n3 = nod(ORSH, nl, nc); // n4 = -1 iff n1 is negative.
  3688  		n = nod(OSUB, n2, n3);
  3689  		// apply sign.
  3690  		if(m.sd < 0)
  3691  			n = nod(OMINUS, n, N);
  3692  		break;
  3693  	}
  3694  	goto ret;
  3695  
  3696  longmod:
  3697  	// rewrite as A%B = A - (A/B*B).
  3698  	n1 = nod(ODIV, nl, nr);
  3699  	n2 = nod(OMUL, n1, nr);
  3700  	n = nod(OSUB, nl, n2);
  3701  	goto ret;
  3702  
  3703  ret:
  3704  	typecheck(&n, Erv);
  3705  	walkexpr(&n, init);
  3706  	*np = n;
  3707  }
  3708  
  3709  // return 1 if integer n must be in range [0, max), 0 otherwise
  3710  static int
  3711  bounded(Node *n, int64 max)
  3712  {
  3713  	int64 v;
  3714  	int32 bits;
  3715  	int sign;
  3716  
  3717  	if(n->type == T || !isint[n->type->etype])
  3718  		return 0;
  3719  
  3720  	sign = issigned[n->type->etype];
  3721  	bits = 8*n->type->width;
  3722  
  3723  	if(smallintconst(n)) {
  3724  		v = mpgetfix(n->val.u.xval);
  3725  		return 0 <= v && v < max;
  3726  	}
  3727  
  3728  	switch(n->op) {
  3729  	case OAND:
  3730  		v = -1;
  3731  		if(smallintconst(n->left)) {
  3732  			v = mpgetfix(n->left->val.u.xval);
  3733  		} else if(smallintconst(n->right)) {
  3734  			v = mpgetfix(n->right->val.u.xval);
  3735  		}
  3736  		if(0 <= v && v < max)
  3737  			return 1;
  3738  		break;
  3739  
  3740  	case OMOD:
  3741  		if(!sign && smallintconst(n->right)) {
  3742  			v = mpgetfix(n->right->val.u.xval);
  3743  			if(0 <= v && v <= max)
  3744  				return 1;
  3745  		}
  3746  		break;
  3747  	
  3748  	case ODIV:
  3749  		if(!sign && smallintconst(n->right)) {
  3750  			v = mpgetfix(n->right->val.u.xval);
  3751  			while(bits > 0 && v >= 2) {
  3752  				bits--;
  3753  				v >>= 1;
  3754  			}
  3755  		}
  3756  		break;
  3757  	
  3758  	case ORSH:
  3759  		if(!sign && smallintconst(n->right)) {
  3760  			v = mpgetfix(n->right->val.u.xval);
  3761  			if(v > bits)
  3762  				return 1;
  3763  			bits -= v;
  3764  		}
  3765  		break;
  3766  	}
  3767  	
  3768  	if(!sign && bits <= 62 && (1LL<<bits) <= max)
  3769  		return 1;
  3770  	
  3771  	return 0;
  3772  }
  3773  
  3774  void
  3775  usefield(Node *n)
  3776  {
  3777  	Type *field, *l;
  3778  
  3779  	if(!fieldtrack_enabled)
  3780  		return;
  3781  
  3782  	switch(n->op) {
  3783  	default:
  3784  		fatal("usefield %O", n->op);
  3785  	case ODOT:
  3786  	case ODOTPTR:
  3787  		break;
  3788  	}
  3789  	
  3790  	field = n->paramfld;
  3791  	if(field == T)
  3792  		fatal("usefield %T %S without paramfld", n->left->type, n->right->sym);
  3793  	if(field->note == nil || strstr(field->note->s, "go:\"track\"") == nil)
  3794  		return;
  3795  
  3796  	// dedup on list
  3797  	if(field->lastfn == curfn)
  3798  		return;
  3799  	field->lastfn = curfn;
  3800  	field->outer = n->left->type;
  3801  	if(isptr[field->outer->etype])
  3802  		field->outer = field->outer->type;
  3803  	if(field->outer->sym == S)
  3804  		yyerror("tracked field must be in named struct type");
  3805  	if(!exportname(field->sym->name))
  3806  		yyerror("tracked field must be exported (upper case)");
  3807  
  3808  	l = typ(0);
  3809  	l->type = field;
  3810  	l->down = curfn->paramfld;
  3811  	curfn->paramfld = l;
  3812  }
  3813  
  3814  static int
  3815  candiscardlist(NodeList *l)
  3816  {
  3817  	for(; l; l=l->next)
  3818  		if(!candiscard(l->n))
  3819  			return 0;
  3820  	return 1;
  3821  }
  3822  
  3823  int
  3824  candiscard(Node *n)
  3825  {
  3826  	if(n == N)
  3827  		return 1;
  3828  	
  3829  	switch(n->op) {
  3830  	default:
  3831  		return 0;
  3832  
  3833  	case ONAME:
  3834  	case ONONAME:
  3835  	case OTYPE:
  3836  	case OPACK:
  3837  	case OLITERAL:
  3838  	case OADD:
  3839  	case OSUB:
  3840  	case OOR:
  3841  	case OXOR:
  3842  	case OADDSTR:
  3843  	case OADDR:
  3844  	case OANDAND:
  3845  	case OARRAYBYTESTR:
  3846  	case OARRAYRUNESTR:
  3847  	case OSTRARRAYBYTE:
  3848  	case OSTRARRAYRUNE:
  3849  	case OCAP:
  3850  	case OCMPIFACE:
  3851  	case OCMPSTR:
  3852  	case OCOMPLIT:
  3853  	case OMAPLIT:
  3854  	case OSTRUCTLIT:
  3855  	case OARRAYLIT:
  3856  	case OPTRLIT:
  3857  	case OCONV:
  3858  	case OCONVIFACE:
  3859  	case OCONVNOP:
  3860  	case ODOT:
  3861  	case OEQ:
  3862  	case ONE:
  3863  	case OLT:
  3864  	case OLE:
  3865  	case OGT:
  3866  	case OGE:
  3867  	case OKEY:
  3868  	case OLEN:
  3869  	case OMUL:
  3870  	case OLSH:
  3871  	case ORSH:
  3872  	case OAND:
  3873  	case OANDNOT:
  3874  	case ONEW:
  3875  	case ONOT:
  3876  	case OCOM:
  3877  	case OPLUS:
  3878  	case OMINUS:
  3879  	case OOROR:
  3880  	case OPAREN:
  3881  	case ORUNESTR:
  3882  	case OREAL:
  3883  	case OIMAG:
  3884  	case OCOMPLEX:
  3885  		// Discardable as long as the subpieces are.
  3886  		break;
  3887  
  3888  	case ODIV:
  3889  	case OMOD:
  3890  		// Discardable as long as we know it's not division by zero.
  3891  		if(isconst(n->right, CTINT) && mpcmpfixc(n->right->val.u.xval, 0) != 0)
  3892  			break;
  3893  		if(isconst(n->right, CTFLT) && mpcmpfltc(n->right->val.u.fval, 0) != 0)
  3894  			break;
  3895  		return 0;
  3896  
  3897  	case OMAKECHAN:
  3898  	case OMAKEMAP:
  3899  		// Discardable as long as we know it won't fail because of a bad size.
  3900  		if(isconst(n->left, CTINT) && mpcmpfixc(n->left->val.u.xval, 0) == 0)
  3901  			break;
  3902  		return 0;
  3903  	
  3904  	case OMAKESLICE:
  3905  		// Difficult to tell what sizes are okay.
  3906  		return 0;		
  3907  	}
  3908  	
  3909  	if(!candiscard(n->left) ||
  3910  	   !candiscard(n->right) ||
  3911  	   !candiscard(n->ntest) ||
  3912  	   !candiscard(n->nincr) ||
  3913  	   !candiscardlist(n->ninit) ||
  3914  	   !candiscardlist(n->nbody) ||
  3915  	   !candiscardlist(n->nelse) ||
  3916  	   !candiscardlist(n->list) ||
  3917  	   !candiscardlist(n->rlist)) {
  3918  		return 0;
  3919  	}
  3920  	
  3921  	return 1;
  3922  }
  3923  
  3924  // rewrite
  3925  //	print(x, y, z)
  3926  // into
  3927  //	func(a1, a2, a3) {
  3928  //		print(a1, a2, a3)
  3929  //	}(x, y, z)
  3930  // and same for println.
  3931  static void
  3932  walkprintfunc(Node **np, NodeList **init)
  3933  {
  3934  	Node *n;
  3935  	Node *a, *fn, *t, *oldfn;
  3936  	NodeList *l, *printargs;
  3937  	int num;
  3938  	char buf[100];
  3939  	static int prgen;
  3940  	
  3941  	n = *np;
  3942  
  3943  	if(n->ninit != nil) {
  3944  		walkstmtlist(n->ninit);
  3945  		*init = concat(*init, n->ninit);
  3946  		n->ninit = nil;
  3947  	}
  3948  
  3949  	t = nod(OTFUNC, N, N);
  3950  	num = 0;
  3951  	printargs = nil;
  3952  	for(l=n->list; l != nil; l=l->next) {
  3953  		snprint(buf, sizeof buf, "a%d", num++);
  3954  		a = nod(ODCLFIELD, newname(lookup(buf)), typenod(l->n->type));
  3955  		t->list = list(t->list, a);
  3956  		printargs = list(printargs, a->left);
  3957  	}
  3958  
  3959  	fn = nod(ODCLFUNC, N, N);
  3960  	snprint(buf, sizeof buf, "print·%d", ++prgen);
  3961  	fn->nname = newname(lookup(buf));
  3962  	fn->nname->defn = fn;
  3963  	fn->nname->ntype = t;
  3964  	declare(fn->nname, PFUNC);
  3965  
  3966  	oldfn = curfn;
  3967  	curfn = nil;
  3968  	funchdr(fn);
  3969  	
  3970  	a = nod(n->op, N, N);
  3971  	a->list = printargs;
  3972  	typecheck(&a, Etop);
  3973  	walkstmt(&a);
  3974  	
  3975  	fn->nbody = list1(a);
  3976  
  3977  	funcbody(fn);
  3978  	
  3979  	typecheck(&fn, Etop);
  3980  	typechecklist(fn->nbody, Etop);
  3981  	xtop = list(xtop, fn);
  3982  	curfn = oldfn;
  3983  
  3984  	a = nod(OCALL, N, N);
  3985  	a->left = fn->nname;
  3986  	a->list = n->list;
  3987  	typecheck(&a, Etop);
  3988  	walkexpr(&a, init);
  3989  	*np = a;
  3990  }