The Go Programming Language

Text file src/cmd/gc/walk.c

     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	"go.h"
     6	
     7	static	Node*	walkprint(Node*, NodeList**, int);
     8	static	Node*	conv(Node*, Type*);
     9	static	Node*	mapfn(char*, Type*);
    10	static	Node*	makenewvar(Type*, NodeList**, Node**);
    11	static	Node*	ascompatee1(int, Node*, Node*, NodeList**);
    12	static	NodeList*	ascompatee(int, NodeList*, NodeList*, NodeList**);
    13	static	NodeList*	ascompatet(int, NodeList*, Type**, int, NodeList**);
    14	static	NodeList*	ascompatte(int, int, Type**, NodeList*, int, NodeList**);
    15	static	Node*	convas(Node*, NodeList**);
    16	static	void	heapmoves(void);
    17	static	NodeList*	paramstoheap(Type **argin, int out);
    18	static	NodeList*	reorder1(NodeList*);
    19	static	NodeList*	reorder3(NodeList*);
    20	static	Node*	addstr(Node*, NodeList**);
    21	static	Node*	appendslice(Node*, NodeList**);
    22	static	Node*	append(Node*, NodeList**);
    23	
    24	// can this code branch reach the end
    25	// without an unconditional RETURN
    26	// this is hard, so it is conservative
    27	static int
    28	walkret(NodeList *l)
    29	{
    30		Node *n;
    31	
    32	loop:
    33		while(l && l->next)
    34			l = l->next;
    35		if(l == nil)
    36			return 1;
    37	
    38		// at this point, we have the last
    39		// statement of the function
    40		n = l->n;
    41		switch(n->op) {
    42		case OBLOCK:
    43			l = n->list;
    44			goto loop;
    45	
    46		case OGOTO:
    47		case ORETURN:
    48		case OPANIC:
    49			return 0;
    50			break;
    51		}
    52	
    53		// all other statements
    54		// will flow to the end
    55		return 1;
    56	}
    57	
    58	void
    59	walk(Node *fn)
    60	{
    61		char s[50];
    62		NodeList *l;
    63		Node *n;
    64		int lno;
    65	
    66		curfn = fn;
    67	
    68		if(debug['W']) {
    69			snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
    70			dumplist(s, curfn->nbody);
    71		}
    72		if(curfn->type->outtuple)
    73			if(walkret(curfn->nbody))
    74				yyerror("function ends without a return statement");
    75	
    76		lno = lineno;
    77		for(l=fn->dcl; l; l=l->next) {
    78			n = l->n;
    79			if(n->op != ONAME || n->class != PAUTO)
    80				continue;
    81			lineno = n->lineno;
    82			typecheck(&n, Erv | Easgn);	// only needed for unused variables
    83			if(!n->used && n->sym->name[0] != '&' && !nsyntaxerrors)
    84				yyerror("%S declared and not used", n->sym);
    85		}
    86		lineno = lno;
    87		if(nerrors != 0)
    88			return;
    89		walkstmtlist(curfn->nbody);
    90		if(debug['W']) {
    91			snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
    92			dumplist(s, curfn->nbody);
    93		}
    94		heapmoves();
    95		if(debug['W'] && curfn->enter != nil) {
    96			snprint(s, sizeof(s), "enter %S", curfn->nname->sym);
    97			dumplist(s, curfn->enter);
    98		}
    99	}
   100	
   101	
   102	void
   103	walkstmtlist(NodeList *l)
   104	{
   105		for(; l; l=l->next)
   106			walkstmt(&l->n);
   107	}
   108	
   109	static int
   110	samelist(NodeList *a, NodeList *b)
   111	{
   112		for(; a && b; a=a->next, b=b->next)
   113			if(a->n != b->n)
   114				return 0;
   115		return a == b;
   116	}
   117	
   118	static int
   119	paramoutheap(Node *fn)
   120	{
   121		NodeList *l;
   122		
   123		for(l=fn->dcl; l; l=l->next) {
   124			switch(l->n->class) {
   125			case PPARAMOUT|PHEAP:
   126				return 1;
   127			case PAUTO:
   128			case PAUTO|PHEAP:
   129				// stop early - parameters are over
   130				return 0;
   131			}
   132		}
   133		return 0;
   134	}
   135	
   136	void
   137	walkstmt(Node **np)
   138	{
   139		NodeList *init;
   140		NodeList *ll, *rl;
   141		int cl;
   142		Node *n, *f;
   143	
   144		n = *np;
   145		if(n == N)
   146			return;
   147	
   148		setlineno(n);
   149	
   150		switch(n->op) {
   151		default:
   152			if(n->op == ONAME)
   153				yyerror("%S is not a top level statement", n->sym);
   154			else
   155				yyerror("%O is not a top level statement", n->op);
   156			dump("nottop", n);
   157			break;
   158	
   159		case OASOP:
   160		case OAS:
   161		case OAS2:
   162		case OAS2DOTTYPE:
   163		case OAS2RECV:
   164		case OAS2FUNC:
   165		case OAS2MAPW:
   166		case OAS2MAPR:
   167		case OCLOSE:
   168		case OCOPY:
   169		case OCALLMETH:
   170		case OCALLINTER:
   171		case OCALL:
   172		case OCALLFUNC:
   173		case OSEND:
   174		case ORECV:
   175		case OPRINT:
   176		case OPRINTN:
   177		case OPANIC:
   178		case OEMPTY:
   179		case ORECOVER:
   180			if(n->typecheck == 0) {
   181				dump("missing typecheck:", n);
   182				fatal("missing typecheck");
   183			}
   184			init = n->ninit;
   185			n->ninit = nil;
   186			walkexpr(&n, &init);
   187			n->ninit = concat(init, n->ninit);
   188			break;
   189	
   190		case OBREAK:
   191		case ODCL:
   192		case OCONTINUE:
   193		case OFALL:
   194		case OGOTO:
   195		case OLABEL:
   196		case ODCLCONST:
   197		case ODCLTYPE:
   198			break;
   199	
   200		case OBLOCK:
   201			walkstmtlist(n->list);
   202			break;
   203	
   204		case OXCASE:
   205			yyerror("case statement out of place");
   206			n->op = OCASE;
   207		case OCASE:
   208			walkstmt(&n->right);
   209			break;
   210	
   211		case ODEFER:
   212			hasdefer = 1;
   213			switch(n->left->op) {
   214			case OPRINT:
   215			case OPRINTN:
   216				walkexprlist(n->left->list, &n->ninit);
   217				n->left = walkprint(n->left, &n->ninit, 1);
   218				break;
   219			default:
   220				walkexpr(&n->left, &n->ninit);
   221				break;
   222			}
   223			break;
   224	
   225		case OFOR:
   226			walkstmtlist(n->ninit);
   227			if(n->ntest != N) {
   228				walkstmtlist(n->ntest->ninit);
   229				init = n->ntest->ninit;
   230				n->ntest->ninit = nil;
   231				walkexpr(&n->ntest, &init);
   232				n->ntest->ninit = concat(init, n->ntest->ninit);
   233			}
   234			walkstmt(&n->nincr);
   235			walkstmtlist(n->nbody);
   236			break;
   237	
   238		case OIF:
   239			walkstmtlist(n->ninit);
   240			walkexpr(&n->ntest, &n->ninit);
   241			walkstmtlist(n->nbody);
   242			walkstmtlist(n->nelse);
   243			break;
   244	
   245		case OPROC:
   246			switch(n->left->op) {
   247			case OPRINT:
   248			case OPRINTN:
   249				walkexprlist(n->left->list, &n->ninit);
   250				n->left = walkprint(n->left, &n->ninit, 1);
   251				break;
   252			default:
   253				walkexpr(&n->left, &n->ninit);
   254				break;
   255			}
   256			break;
   257	
   258		case ORETURN:
   259			walkexprlist(n->list, &n->ninit);
   260			if(n->list == nil)
   261				break;
   262			if((curfn->type->outnamed && count(n->list) > 1) || paramoutheap(curfn)) {
   263				// assign to the function out parameters,
   264				// so that reorder3 can fix up conflicts
   265				rl = nil;
   266				for(ll=curfn->dcl; ll != nil; ll=ll->next) {
   267					cl = ll->n->class & ~PHEAP;
   268					if(cl == PAUTO)
   269						break;
   270					if(cl == PPARAMOUT)
   271						rl = list(rl, ll->n);
   272				}
   273				if(samelist(rl, n->list)) {
   274					// special return in disguise
   275					n->list = nil;
   276					break;
   277				}
   278				if(count(n->list) == 1 && count(rl) > 1) {
   279					// OAS2FUNC in disguise
   280					f = n->list->n;
   281					if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
   282						fatal("expected return of call, have %#N", f);
   283					n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
   284					break;
   285				}
   286				ll = ascompatee(n->op, rl, n->list, &n->ninit);
   287				n->list = reorder3(ll);
   288				break;
   289			}
   290			ll = ascompatte(n->op, 0, getoutarg(curfn->type), n->list, 1, &n->ninit);
   291			n->list = ll;
   292			break;
   293	
   294		case OSELECT:
   295			walkselect(n);
   296			break;
   297	
   298		case OSWITCH:
   299			walkswitch(n);
   300			break;
   301	
   302		case ORANGE:
   303			walkrange(n);
   304			break;
   305	
   306		case OXFALL:
   307			yyerror("fallthrough statement out of place");
   308			n->op = OFALL;
   309			break;
   310		}
   311	
   312		*np = n;
   313	}
   314	
   315	
   316	/*
   317	 * walk the whole tree of the body of an
   318	 * expression or simple statement.
   319	 * the types expressions are calculated.
   320	 * compile-time constants are evaluated.
   321	 * complex side effects like statements are appended to init
   322	 */
   323	
   324	void
   325	walkexprlist(NodeList *l, NodeList **init)
   326	{
   327		for(; l; l=l->next)
   328			walkexpr(&l->n, init);
   329	}
   330	
   331	void
   332	walkexprlistsafe(NodeList *l, NodeList **init)
   333	{
   334		for(; l; l=l->next) {
   335			l->n = safeexpr(l->n, init);
   336			walkexpr(&l->n, init);
   337		}
   338	}
   339	
   340	void
   341	walkexpr(Node **np, NodeList **init)
   342	{
   343		Node *r, *l, *var, *a;
   344		NodeList *ll, *lr, *lpost;
   345		Type *t;
   346		int et;
   347		int64 v, v1, v2, len;
   348		int32 lno;
   349		Node *n, *fn;
   350		char buf[100], *p;
   351	
   352		n = *np;
   353	
   354		if(n == N)
   355			return;
   356	
   357		if(init == &n->ninit) {
   358			// not okay to use n->ninit when walking n,
   359			// because we might replace n with some other node
   360			// and would lose the init list.
   361			fatal("walkexpr init == &n->ninit");
   362		}
   363	
   364		// annoying case - not typechecked
   365		if(n->op == OKEY) {
   366			walkexpr(&n->left, init);
   367			walkexpr(&n->right, init);
   368			return;
   369		}
   370	
   371		lno = setlineno(n);
   372	
   373		if(debug['w'] > 1)
   374			dump("walk-before", n);
   375	
   376		if(n->typecheck != 1) {
   377			dump("missed typecheck", n);
   378			fatal("missed typecheck");
   379		}
   380	
   381		t = T;
   382		et = Txxx;
   383	
   384		switch(n->op) {
   385		default:
   386			dump("walk", n);
   387			fatal("walkexpr: switch 1 unknown op %N", n);
   388			goto ret;
   389	
   390		case OTYPE:
   391		case ONONAME:
   392		case OINDREG:
   393		case OEMPTY:
   394			goto ret;
   395	
   396		case ONOT:
   397		case OMINUS:
   398		case OPLUS:
   399		case OCOM:
   400		case OREAL:
   401		case OIMAG:
   402		case ODOT:
   403		case ODOTPTR:
   404		case ODOTMETH:
   405		case ODOTINTER:
   406		case OIND:
   407			walkexpr(&n->left, init);
   408			goto ret;
   409	
   410		case OLEN:
   411		case OCAP:
   412			walkexpr(&n->left, init);
   413			
   414			// replace len(*[10]int) with 10.
   415			// delayed until now to preserve side effects.
   416			t = n->left->type;
   417			if(isptr[t->etype])
   418				t = t->type;
   419			if(isfixedarray(t)) {
   420				safeexpr(n->left, init);
   421				nodconst(n, n->type, t->bound);
   422				n->typecheck = 1;
   423			}
   424			goto ret;
   425		
   426		case OLSH:
   427		case ORSH:
   428		case OAND:
   429		case OOR:
   430		case OXOR:
   431		case OSUB:
   432		case OMUL:
   433		case OEQ:
   434		case ONE:
   435		case OLT:
   436		case OLE:
   437		case OGE:
   438		case OGT:
   439		case OADD:
   440		case OCOMPLEX:
   441			walkexpr(&n->left, init);
   442			walkexpr(&n->right, init);
   443			goto ret;
   444		
   445		case OANDAND:
   446		case OOROR:
   447			walkexpr(&n->left, init);
   448			// cannot put side effects from n->right on init,
   449			// because they cannot run before n->left is checked.
   450			// save elsewhere and store on the eventual n->right.
   451			ll = nil;
   452			walkexpr(&n->right, &ll);
   453			n->right->ninit = concat(n->right->ninit, ll);
   454			goto ret;
   455	
   456		case OPRINT:
   457		case OPRINTN:
   458			walkexprlist(n->list, init);
   459			n = walkprint(n, init, 0);
   460			goto ret;
   461	
   462		case OPANIC:
   463			n = mkcall("panic", T, init, n->left);
   464			goto ret;
   465	
   466		case ORECOVER:
   467			n = mkcall("recover", n->type, init, nod(OADDR, nodfp, N));
   468			goto ret;
   469	
   470		case OLITERAL:
   471			n->addable = 1;
   472			goto ret;
   473	
   474		case ONAME:
   475			if(!(n->class & PHEAP) && n->class != PPARAMREF)
   476				n->addable = 1;
   477			goto ret;
   478	
   479		case OCALLINTER:
   480			t = n->left->type;
   481			if(n->list && n->list->n->op == OAS)
   482				goto ret;
   483			walkexpr(&n->left, init);
   484			walkexprlist(n->list, init);
   485			ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
   486			n->list = reorder1(ll);
   487			goto ret;
   488	
   489		case OCALLFUNC:
   490			t = n->left->type;
   491			if(n->list && n->list->n->op == OAS)
   492				goto ret;
   493	
   494			if(n->left->op == OCLOSURE) {
   495				walkcallclosure(n, init);
   496				t = n->left->type;
   497			}
   498	
   499			walkexpr(&n->left, init);
   500			walkexprlist(n->list, init);
   501	
   502			ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
   503			n->list = reorder1(ll);
   504			goto ret;
   505	
   506		case OCALLMETH:
   507			t = n->left->type;
   508			if(n->list && n->list->n->op == OAS)
   509				goto ret;
   510			walkexpr(&n->left, init);
   511			walkexprlist(n->list, init);
   512			ll = ascompatte(n->op, 0, getthis(t), list1(n->left->left), 0, init);
   513			lr = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
   514			ll = concat(ll, lr);
   515			n->left->left = N;
   516			ullmancalc(n->left);
   517			n->list = reorder1(ll);
   518			goto ret;
   519	
   520		case OAS:
   521			*init = concat(*init, n->ninit);
   522			n->ninit = nil;
   523			walkexpr(&n->left, init);
   524			n->left = safeexpr(n->left, init);
   525	
   526			if(oaslit(n, init))
   527				goto ret;
   528	
   529			walkexpr(&n->right, init);
   530			if(n->left != N && n->right != N) {
   531				r = convas(nod(OAS, n->left, n->right), init);
   532				r->dodata = n->dodata;
   533				n = r;
   534			}
   535	
   536			goto ret;
   537	
   538		case OAS2:
   539			*init = concat(*init, n->ninit);
   540			n->ninit = nil;
   541			walkexprlistsafe(n->list, init);
   542			walkexprlistsafe(n->rlist, init);
   543			ll = ascompatee(OAS, n->list, n->rlist, init);
   544			ll = reorder3(ll);
   545			n = liststmt(ll);
   546			goto ret;
   547	
   548		case OAS2FUNC:
   549		as2func:
   550			// a,b,... = fn()
   551			*init = concat(*init, n->ninit);
   552			n->ninit = nil;
   553			r = n->rlist->n;
   554			walkexprlistsafe(n->list, init);
   555			walkexpr(&r, init);
   556			l = n->list->n;
   557			
   558			// all the really hard stuff - explicit function calls and so on -
   559			// is gone, but map assignments remain.
   560			// if there are map assignments here, assign via
   561			// temporaries, because ascompatet assumes
   562			// the targets can be addressed without function calls
   563			// and map index has an implicit one.
   564			lpost = nil;
   565			if(l->op == OINDEXMAP) {
   566				var = nod(OXXX, N, N);
   567				tempname(var, l->type);
   568				n->list->n = var;
   569				a = nod(OAS, l, var);
   570				typecheck(&a, Etop);
   571				lpost = list(lpost, a);
   572			}
   573			l = n->list->next->n;
   574			if(l->op == OINDEXMAP) {
   575				var = nod(OXXX, N, N);
   576				tempname(var, l->type);
   577				n->list->next->n = var;
   578				a = nod(OAS, l, var);
   579				typecheck(&a, Etop);
   580				lpost = list(lpost, a);
   581			}
   582			ll = ascompatet(n->op, n->list, &r->type, 0, init);
   583			walkexprlist(lpost, init);
   584			n = liststmt(concat(concat(list1(r), ll), lpost));
   585			goto ret;
   586	
   587		case OAS2RECV:
   588			*init = concat(*init, n->ninit);
   589			n->ninit = nil;
   590			r = n->rlist->n;
   591			walkexprlistsafe(n->list, init);
   592			walkexpr(&r->left, init);
   593			fn = chanfn("chanrecv2", 2, r->left->type);
   594			r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left);
   595			n->rlist->n = r;
   596			n->op = OAS2FUNC;
   597			goto as2func;
   598	
   599		case OAS2MAPR:
   600			// a,b = m[i];
   601			*init = concat(*init, n->ninit);
   602			n->ninit = nil;
   603			r = n->rlist->n;
   604			walkexprlistsafe(n->list, init);
   605			walkexpr(&r->left, init);
   606			fn = mapfn("mapaccess2", r->left->type);
   607			r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right);
   608			n->rlist = list1(r);
   609			n->op = OAS2FUNC;
   610			goto as2func;
   611	
   612		case OAS2MAPW:
   613			// map[] = a,b - mapassign2
   614			// a,b = m[i];
   615			*init = concat(*init, n->ninit);
   616			n->ninit = nil;
   617			walkexprlistsafe(n->list, init);
   618			l = n->list->n;
   619			t = l->left->type;
   620			n = mkcall1(mapfn("mapassign2", t), T, init, typename(t), l->left, l->right, n->rlist->n, n->rlist->next->n);
   621			goto ret;
   622	
   623		case OAS2DOTTYPE:
   624			// a,b = i.(T)
   625			*init = concat(*init, n->ninit);
   626			n->ninit = nil;
   627			r = n->rlist->n;
   628			walkexprlistsafe(n->list, init);
   629			r->op = ODOTTYPE2;
   630			walkexpr(&r, init);
   631			ll = ascompatet(n->op, n->list, &r->type, 0, init);
   632			n = liststmt(concat(list1(r), ll));
   633			goto ret;
   634	
   635		case ODOTTYPE:
   636		case ODOTTYPE2:
   637			// Build name of function: assertI2E2 etc.
   638			strcpy(buf, "assert");
   639			p = buf+strlen(buf);
   640			if(isnilinter(n->left->type))
   641				*p++ = 'E';
   642			else
   643				*p++ = 'I';
   644			*p++ = '2';
   645			if(isnilinter(n->type))
   646				*p++ = 'E';
   647			else if(isinter(n->type))
   648				*p++ = 'I';
   649			else
   650				*p++ = 'T';
   651			if(n->op == ODOTTYPE2)
   652				*p++ = '2';
   653			*p = '\0';
   654		
   655			fn = syslook(buf, 1);
   656			ll = list1(typename(n->type));
   657			ll = list(ll, n->left);
   658			argtype(fn, n->left->type);
   659			argtype(fn, n->type);
   660			n = nod(OCALL, fn, N);
   661			n->list = ll;
   662			typecheck(&n, Erv | Efnstruct);
   663			walkexpr(&n, init);
   664			goto ret;
   665	
   666		case OCONVIFACE:
   667			// Build name of function: convI2E etc.
   668			// Not all names are possible
   669			// (e.g., we'll never generate convE2E or convE2I).
   670			walkexpr(&n->left, init);
   671			strcpy(buf, "conv");
   672			p = buf+strlen(buf);
   673			if(isnilinter(n->left->type))
   674				*p++ = 'E';
   675			else if(isinter(n->left->type))
   676				*p++ = 'I';
   677			else
   678				*p++ = 'T';
   679			*p++ = '2';
   680			if(isnilinter(n->type))
   681				*p++ = 'E';
   682			else
   683				*p++ = 'I';
   684			*p = '\0';
   685			
   686			fn = syslook(buf, 1);
   687			ll = nil;
   688			if(!isinter(n->left->type))
   689				ll = list(ll, typename(n->left->type));
   690			if(!isnilinter(n->type))
   691				ll = list(ll, typename(n->type));
   692			ll = list(ll, n->left);
   693			argtype(fn, n->left->type);
   694			argtype(fn, n->type);
   695			dowidth(fn->type);
   696			n = nod(OCALL, fn, N);
   697			n->list = ll;
   698			typecheck(&n, Erv);
   699			walkexpr(&n, init);
   700			goto ret;
   701	
   702		case OCONV:
   703		case OCONVNOP:
   704			if(thechar == '5') {
   705				if(isfloat[n->left->type->etype]) {
   706					if(n->type->etype == TINT64) {
   707						n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
   708						goto ret;
   709					}
   710					if(n->type->etype == TUINT64) {
   711						n = mkcall("float64touint64", n->type, init, conv(n->left, types[TFLOAT64]));
   712						goto ret;
   713					}
   714				}
   715				if(isfloat[n->type->etype]) {
   716					if(n->left->type->etype == TINT64) {
   717						n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
   718						goto ret;
   719					}
   720					if(n->left->type->etype == TUINT64) {
   721						n = mkcall("uint64tofloat64", n->type, init, conv(n->left, types[TUINT64]));
   722						goto ret;
   723					}
   724				}
   725			}
   726			walkexpr(&n->left, init);
   727			goto ret;
   728	
   729		case OASOP:
   730			if(n->etype == OANDNOT) {
   731				n->etype = OAND;
   732				n->right = nod(OCOM, n->right, N);
   733				typecheck(&n->right, Erv);
   734			}
   735			n->left = safeexpr(n->left, init);
   736			walkexpr(&n->left, init);
   737			l = n->left;
   738			walkexpr(&n->right, init);
   739	
   740			/*
   741			 * on 32-bit arch, rewrite 64-bit ops into l = l op r.
   742			 * on 386, rewrite float ops into l = l op r.
   743			 * everywhere, rewrite map ops into l = l op r.
   744			 * everywhere, rewrite string += into l = l op r.
   745			 * everywhere, rewrite complex /= into l = l op r.
   746			 * TODO(rsc): Maybe this rewrite should be done always?
   747			 */
   748			et = n->left->type->etype;
   749			if((widthptr == 4 && (et == TUINT64 || et == TINT64)) ||
   750			   (thechar == '8' && isfloat[et]) ||
   751			   l->op == OINDEXMAP ||
   752			   et == TSTRING ||
   753			   (iscomplex[et] && n->etype == ODIV)) {
   754				l = safeexpr(n->left, init);
   755				a = l;
   756				if(a->op == OINDEXMAP) {
   757					// map index has "lhs" bit set in a->etype.
   758					// make a copy so we can clear it on the rhs.
   759					a = nod(OXXX, N, N);
   760					*a = *l;
   761					a->etype = 0;
   762				}
   763				r = nod(OAS, l, nod(n->etype, a, n->right));
   764				typecheck(&r, Etop);
   765				walkexpr(&r, init);
   766				n = r;
   767			}
   768			goto ret;
   769	
   770		case OANDNOT:
   771			walkexpr(&n->left, init);
   772			walkexpr(&n->right, init);
   773			n->op = OAND;
   774			n->right = nod(OCOM, n->right, N);
   775			typecheck(&n->right, Erv);
   776			goto ret;
   777	
   778		case ODIV:
   779		case OMOD:
   780			walkexpr(&n->left, init);
   781			walkexpr(&n->right, init);
   782			/*
   783			 * rewrite complex div into function call.
   784			 */
   785			et = n->left->type->etype;
   786			if(iscomplex[et] && n->op == ODIV) {
   787				t = n->type;
   788				n = mkcall("complex128div", types[TCOMPLEX128], init,
   789					conv(n->left, types[TCOMPLEX128]),
   790					conv(n->right, types[TCOMPLEX128]));
   791				n = conv(n, t);
   792				goto ret;
   793			}
   794			/*
   795			 * rewrite div and mod into function calls
   796			 * on 32-bit architectures.
   797			 */
   798			if(widthptr > 4 || (et != TUINT64 && et != TINT64))
   799				goto ret;
   800			if(et == TINT64)
   801				strcpy(namebuf, "int64");
   802			else
   803				strcpy(namebuf, "uint64");
   804			if(n->op == ODIV)
   805				strcat(namebuf, "div");
   806			else
   807				strcat(namebuf, "mod");
   808			n = mkcall(namebuf, n->type, init,
   809				conv(n->left, types[et]), conv(n->right, types[et]));
   810			goto ret;
   811	
   812		case OINDEX:
   813			walkexpr(&n->left, init);
   814			walkexpr(&n->right, init);
   815	
   816			// if range of type cannot exceed static array bound,
   817			// disable bounds check
   818			if(isfixedarray(n->left->type))
   819			if(n->right->type->width < 4)
   820			if((1<<(8*n->right->type->width)) <= n->left->type->bound)
   821				n->etype = 1;
   822	
   823			if(isconst(n->left, CTSTR))
   824			if(n->right->type->width < 4)
   825			if((1<<(8*n->right->type->width)) <= n->left->val.u.sval->len)
   826				n->etype = 1;
   827	
   828			// check for static out of bounds
   829			if(isconst(n->right, CTINT) && !n->etype) {
   830				v = mpgetfix(n->right->val.u.xval);
   831				len = 1LL<<60;
   832				t = n->left->type;
   833				if(isconst(n->left, CTSTR))
   834					len = n->left->val.u.sval->len;
   835				if(t != T && isptr[t->etype])
   836					t = t->type;
   837				if(isfixedarray(t))
   838					len = t->bound;
   839				if(v < 0 || v >= (1LL<<31) || v >= len)
   840					yyerror("index out of bounds");
   841				else if(isconst(n->left, CTSTR)) {
   842					// replace "abc"[2] with 'b'.
   843					// delayed until now because "abc"[2] is not
   844					// an ideal constant.
   845					nodconst(n, n->type, n->left->val.u.sval->s[v]);
   846				}
   847			}
   848			goto ret;
   849	
   850		case OINDEXMAP:
   851			if(n->etype == 1)
   852				goto ret;
   853	
   854			t = n->left->type;
   855			n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
   856			goto ret;
   857	
   858		case ORECV:
   859			walkexpr(&n->left, init);
   860			walkexpr(&n->right, init);
   861			n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left);
   862			goto ret;
   863	
   864		case OSLICE:
   865		case OSLICEARR:
   866			walkexpr(&n->left, init);
   867			n->left = safeexpr(n->left, init);
   868			walkexpr(&n->right->left, init);
   869			n->right->left = safeexpr(n->right->left, init);
   870			walkexpr(&n->right->right, init);
   871			n->right->right = safeexpr(n->right->right, init);
   872	
   873			len = 1LL<<60;
   874			t = n->left->type;
   875			if(t != T && isptr[t->etype])
   876				t = t->type;
   877			if(isfixedarray(t))
   878				len = t->bound;
   879	
   880			// check for static out of bounds
   881			// NOTE: v > len not v >= len.
   882			v1 = -1;
   883			v2 = -1;
   884			if(isconst(n->right->left, CTINT)) {
   885				v1 = mpgetfix(n->right->left->val.u.xval);
   886				if(v1 < 0 || v1 >= (1LL<<31) || v1 > len) {
   887					yyerror("slice index out of bounds");
   888					v1 = -1;
   889				}
   890			}
   891			if(isconst(n->right->right, CTINT)) {
   892				v2 = mpgetfix(n->right->right->val.u.xval);
   893				if(v2 < 0 || v2 >= (1LL<<31) || v2 > len) {
   894					yyerror("slice index out of bounds");
   895					v2 = -1;
   896				}
   897			}
   898			if(v1 >= 0 && v2 >= 0 && v1 > v2)
   899				yyerror("inverted slice range");
   900			
   901			if(n->op == OSLICEARR)
   902				goto slicearray;
   903	
   904			// dynamic slice
   905			// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
   906			// sliceslice1(old []any, lb uint64, width uint64) (ary []any)
   907			t = n->type;
   908			et = n->etype;
   909			if(n->right->left == N)
   910				l = nodintconst(0);
   911			else
   912				l = conv(n->right->left, types[TUINT64]);
   913			if(n->right->right != N) {
   914				fn = syslook("sliceslice", 1);
   915				argtype(fn, t->type);			// any-1
   916				argtype(fn, t->type);			// any-2
   917				n = mkcall1(fn, t, init,
   918					n->left,
   919					l,
   920					conv(n->right->right, types[TUINT64]),
   921					nodintconst(t->type->width));
   922			} else {
   923				fn = syslook("sliceslice1", 1);
   924				argtype(fn, t->type);			// any-1
   925				argtype(fn, t->type);			// any-2
   926				n = mkcall1(fn, t, init,
   927					n->left,
   928					l,
   929					nodintconst(t->type->width));
   930			}
   931			n->etype = et;  // preserve no-typecheck flag from OSLICE to the slice* call.
   932			goto ret;
   933	
   934		slicearray:
   935			// static slice
   936			// slicearray(old *any, uint64 nel, lb uint64, hb uint64, width uint64) (ary []any)
   937			t = n->type;
   938			fn = syslook("slicearray", 1);
   939			argtype(fn, n->left->type->type);	// any-1
   940			argtype(fn, t->type);			// any-2
   941			if(n->right->left == N)
   942				l = nodintconst(0);
   943			else
   944				l = conv(n->right->left, types[TUINT64]);
   945			if(n->right->right == N)
   946				r = nodintconst(n->left->type->type->bound);
   947			else
   948				r = conv(n->right->right, types[TUINT64]);
   949			n = mkcall1(fn, t, init,
   950				n->left, nodintconst(n->left->type->type->bound),
   951				l,
   952				r,
   953				nodintconst(t->type->width));
   954			goto ret;
   955	
   956		case OADDR:;
   957			Node *nvar, *nstar;
   958	
   959			// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
   960			// initialize with
   961			//	nvar := new(*Point);
   962			//	*nvar = Point(1, 2);
   963			// and replace expression with nvar
   964			switch(n->left->op) {
   965			case OARRAYLIT:
   966			case OMAPLIT:
   967			case OSTRUCTLIT:
   968				nvar = makenewvar(n->type, init, &nstar);
   969				anylit(0, n->left, nstar, init);
   970				n = nvar;
   971				goto ret;
   972			}
   973	
   974			walkexpr(&n->left, init);
   975			goto ret;
   976	
   977		case ONEW:
   978			n = callnew(n->type->type);
   979			goto ret;
   980	
   981		case OCMPSTR:
   982			// If one argument to the comparison is an empty string,
   983			// comparing the lengths instead will yield the same result
   984			// without the function call.
   985			if((isconst(n->left, CTSTR) && n->left->val.u.sval->len == 0) ||
   986			   (isconst(n->right, CTSTR) && n->right->val.u.sval->len == 0)) {
   987				r = nod(n->etype, nod(OLEN, n->left, N), nod(OLEN, n->right, N));
   988				typecheck(&r, Erv);
   989				walkexpr(&r, init);
   990				n = r;
   991				goto ret;
   992			}
   993	
   994			// s + "badgerbadgerbadger" == "badgerbadgerbadger"
   995			if((n->etype == OEQ || n->etype == ONE) &&
   996			   isconst(n->right, CTSTR) &&
   997			   n->left->op == OADDSTR && isconst(n->left->right, CTSTR) &&
   998			   cmpslit(n->right, n->left->right) == 0) {
   999				r = nod(n->etype, nod(OLEN, n->left->left, N), nodintconst(0));
  1000				typecheck(&r, Erv);
  1001				walkexpr(&r, init);
  1002				n = r;
  1003				goto ret;
  1004			}
  1005	
  1006			// prepare for rewrite below
  1007			if(n->etype == OEQ || n->etype == ONE) {
  1008				n->left = cheapexpr(n->left, init);
  1009				n->right = cheapexpr(n->right, init);
  1010			}
  1011	
  1012			// sys_cmpstring(s1, s2) :: 0
  1013			r = mkcall("cmpstring", types[TINT], init,
  1014				conv(n->left, types[TSTRING]),
  1015				conv(n->right, types[TSTRING]));
  1016			r = nod(n->etype, r, nodintconst(0));
  1017	
  1018			// quick check of len before full compare for == or !=
  1019			if(n->etype == OEQ || n->etype == ONE) {
  1020				if(n->etype == OEQ)
  1021					r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
  1022				else
  1023					r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
  1024				typecheck(&r, Erv);
  1025				walkexpr(&r, nil);
  1026			}
  1027			typecheck(&r, Erv);
  1028			n = r;
  1029			goto ret;
  1030	
  1031		case OADDSTR:
  1032			n = addstr(n, init);
  1033			goto ret;
  1034	
  1035		case OSLICESTR:
  1036			// sys_slicestring(s, lb, hb)
  1037			if(n->right->left == N)
  1038				l = nodintconst(0);
  1039			else
  1040				l = conv(n->right->left, types[TINT]);
  1041			if(n->right->right) {
  1042				n = mkcall("slicestring", n->type, init,
  1043					conv(n->left, types[TSTRING]),
  1044					l,
  1045					conv(n->right->right, types[TINT]));
  1046			} else {
  1047				n = mkcall("slicestring1", n->type, init,
  1048					conv(n->left, types[TSTRING]),
  1049					l);
  1050			}
  1051			goto ret;
  1052		
  1053		case OAPPEND:
  1054			if(n->isddd)
  1055				n = appendslice(n, init);
  1056			else
  1057				n = append(n, init);
  1058			goto ret;
  1059	
  1060		case OCOPY:
  1061			if(n->right->type->etype == TSTRING)
  1062				fn = syslook("slicestringcopy", 1);
  1063			else
  1064				fn = syslook("slicecopy", 1);
  1065			argtype(fn, n->left->type);
  1066			argtype(fn, n->right->type);
  1067			n = mkcall1(fn, n->type, init,
  1068				n->left, n->right,
  1069				nodintconst(n->left->type->type->width));
  1070			goto ret;
  1071	
  1072		case OCLOSE:
  1073			// cannot use chanfn - closechan takes any, not chan any
  1074			fn = syslook("closechan", 1);
  1075			argtype(fn, n->left->type);
  1076			n = mkcall1(fn, T, init, n->left);
  1077			goto ret;
  1078	
  1079		case OMAKECHAN:
  1080			n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
  1081				typename(n->type),
  1082				conv(n->left, types[TINT64]));
  1083			goto ret;
  1084	
  1085		case OMAKEMAP:
  1086			t = n->type;
  1087	
  1088			fn = syslook("makemap", 1);
  1089			argtype(fn, t->down);	// any-1
  1090			argtype(fn, t->type);	// any-2
  1091	
  1092			n = mkcall1(fn, n->type, init,
  1093				typename(n->type),
  1094				conv(n->left, types[TINT64]));
  1095			goto ret;
  1096	
  1097		case OMAKESLICE:
  1098			// makeslice(t *Type, nel int64, max int64) (ary []any)
  1099			l = n->left;
  1100			r = n->right;
  1101			if(r == nil)
  1102				l = r = safeexpr(l, init);
  1103			t = n->type;
  1104			fn = syslook("makeslice", 1);
  1105			argtype(fn, t->type);			// any-1
  1106			n = mkcall1(fn, n->type, init,
  1107				typename(n->type),
  1108				conv(l, types[TINT64]),
  1109				conv(r, types[TINT64]));
  1110			goto ret;
  1111	
  1112		case ORUNESTR:
  1113			// sys_intstring(v)
  1114			n = mkcall("intstring", n->type, init,
  1115				conv(n->left, types[TINT64]));
  1116			goto ret;
  1117	
  1118		case OARRAYBYTESTR:
  1119			// slicebytetostring([]byte) string;
  1120			n = mkcall("slicebytetostring", n->type, init, n->left);
  1121			goto ret;
  1122	
  1123		case OARRAYRUNESTR:
  1124			// sliceinttostring([]int) string;
  1125			n = mkcall("sliceinttostring", n->type, init, n->left);
  1126			goto ret;
  1127	
  1128		case OSTRARRAYBYTE:
  1129			// stringtoslicebyte(string) []byte;
  1130			n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
  1131			goto ret;
  1132	
  1133		case OSTRARRAYRUNE:
  1134			// stringtosliceint(string) []int
  1135			n = mkcall("stringtosliceint", n->type, init, n->left);
  1136			goto ret;
  1137	
  1138		case OCMPIFACE:
  1139			// ifaceeq(i1 any-1, i2 any-2) (ret bool);
  1140			if(!eqtype(n->left->type, n->right->type))
  1141				fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type);
  1142			if(isnilinter(n->left->type))
  1143				fn = syslook("efaceeq", 1);
  1144			else
  1145				fn = syslook("ifaceeq", 1);
  1146			argtype(fn, n->right->type);
  1147			argtype(fn, n->left->type);
  1148			r = mkcall1(fn, n->type, init, n->left, n->right);
  1149			if(n->etype == ONE) {
  1150				r = nod(ONOT, r, N);
  1151				typecheck(&r, Erv);
  1152			}
  1153			n = r;
  1154			goto ret;
  1155	
  1156		case OARRAYLIT:
  1157		case OMAPLIT:
  1158		case OSTRUCTLIT:
  1159			nvar = nod(OXXX, N, N);
  1160			tempname(nvar, n->type);
  1161			anylit(0, n, nvar, init);
  1162			n = nvar;
  1163			goto ret;
  1164	
  1165		case OSEND:
  1166			n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n->right);
  1167			goto ret;
  1168	
  1169		case OCLOSURE:
  1170			n = walkclosure(n, init);
  1171			goto ret;
  1172		}
  1173		fatal("missing switch %O", n->op);
  1174	
  1175	ret:
  1176		if(debug['w'] && n != N)
  1177			dump("walk", n);
  1178	
  1179		ullmancalc(n);
  1180		lineno = lno;
  1181		*np = n;
  1182	}
  1183	
  1184	static Node*
  1185	makenewvar(Type *t, NodeList **init, Node **nstar)
  1186	{
  1187		Node *nvar, *nas;
  1188	
  1189		nvar = nod(OXXX, N, N);
  1190		tempname(nvar, t);
  1191		nas = nod(OAS, nvar, callnew(t->type));
  1192		typecheck(&nas, Etop);
  1193		walkexpr(&nas, init);
  1194		*init = list(*init, nas);
  1195	
  1196		*nstar = nod(OIND, nvar, N);
  1197		typecheck(nstar, Erv);
  1198		return nvar;
  1199	}
  1200	
  1201	static Node*
  1202	ascompatee1(int op, Node *l, Node *r, NodeList **init)
  1203	{
  1204		return convas(nod(OAS, l, r), init);
  1205	}
  1206	
  1207	static NodeList*
  1208	ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
  1209	{
  1210		NodeList *ll, *lr, *nn;
  1211	
  1212		/*
  1213		 * check assign expression list to
  1214		 * a expression list. called in
  1215		 *	expr-list = expr-list
  1216		 */
  1217	
  1218		// ensure order of evaluation for function calls
  1219		for(ll=nl; ll; ll=ll->next)
  1220			ll->n = safeexpr(ll->n, init);
  1221		for(lr=nr; lr; lr=lr->next)
  1222			lr->n = safeexpr(lr->n, init);
  1223	
  1224		nn = nil;
  1225		for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next)
  1226			nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
  1227	
  1228		// cannot happen: caller checked that lists had same length
  1229		if(ll || lr)
  1230			yyerror("error in shape across %O", op);
  1231		return nn;
  1232	}
  1233	
  1234	/*
  1235	 * l is an lv and rt is the type of an rv
  1236	 * return 1 if this implies a function call
  1237	 * evaluating the lv or a function call
  1238	 * in the conversion of the types
  1239	 */
  1240	static int
  1241	fncall(Node *l, Type *rt)
  1242	{
  1243		if(l->ullman >= UINF || l->op == OINDEXMAP)
  1244			return 1;
  1245		if(eqtype(l->type, rt))
  1246			return 0;
  1247		return 1;
  1248	}
  1249	
  1250	static NodeList*
  1251	ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
  1252	{
  1253		Node *l, *tmp, *a;
  1254		NodeList *ll;
  1255		Type *r;
  1256		Iter saver;
  1257		int ucount;
  1258		NodeList *nn, *mm;
  1259	
  1260		/*
  1261		 * check assign type list to
  1262		 * a expression list. called in
  1263		 *	expr-list = func()
  1264		 */
  1265		r = structfirst(&saver, nr);
  1266		nn = nil;
  1267		mm = nil;
  1268		ucount = 0;
  1269		for(ll=nl; ll; ll=ll->next) {
  1270			if(r == T)
  1271				break;
  1272			l = ll->n;
  1273			if(isblank(l)) {
  1274				r = structnext(&saver);
  1275				continue;
  1276			}
  1277	
  1278			// any lv that causes a fn call must be
  1279			// deferred until all the return arguments
  1280			// have been pulled from the output arguments
  1281			if(fncall(l, r->type)) {
  1282				tmp = nod(OXXX, N, N);
  1283				tempname(tmp, r->type);
  1284				typecheck(&tmp, Erv);
  1285				a = nod(OAS, l, tmp);
  1286				a = convas(a, init);
  1287				mm = list(mm, a);
  1288				l = tmp;
  1289			}
  1290	
  1291			a = nod(OAS, l, nodarg(r, fp));
  1292			a = convas(a, init);
  1293			ullmancalc(a);
  1294			if(a->ullman >= UINF)
  1295				ucount++;
  1296			nn = list(nn, a);
  1297			r = structnext(&saver);
  1298		}
  1299	
  1300		if(ll != nil || r != T)
  1301			yyerror("assignment count mismatch: %d = %d",
  1302				count(nl), structcount(*nr));
  1303		if(ucount)
  1304			fatal("reorder2: too many function calls evaluating parameters");
  1305		return concat(nn, mm);
  1306	}
  1307	
  1308	 /*
  1309	 * package all the arguments that match a ... T parameter into a []T.
  1310	 */
  1311	static NodeList*
  1312	mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init)
  1313	{
  1314		Node *a, *n;
  1315		Type *tslice;
  1316	
  1317		tslice = typ(TARRAY);
  1318		tslice->type = l->type->type;
  1319		tslice->bound = -1;
  1320	
  1321		n = nod(OCOMPLIT, N, typenod(tslice));
  1322		n->list = lr0;
  1323		typecheck(&n, Erv);
  1324		if(n->type == T)
  1325			fatal("mkdotargslice: typecheck failed");
  1326		walkexpr(&n, init);
  1327	
  1328		a = nod(OAS, nodarg(l, fp), n);
  1329		nn = list(nn, convas(a, init));
  1330		return nn;
  1331	}
  1332	
  1333	/*
  1334	 * helpers for shape errors
  1335	 */
  1336	static char*
  1337	dumptypes(Type **nl, char *what)
  1338	{
  1339		int first;
  1340		Type *l;
  1341		Iter savel;
  1342		Fmt fmt;
  1343	
  1344		fmtstrinit(&fmt);
  1345		fmtprint(&fmt, "\t");
  1346		l = structfirst(&savel, nl);
  1347		first = 1;
  1348		for(l = structfirst(&savel, nl); l != T; l = structnext(&savel)) {
  1349			if(first)
  1350				first = 0;
  1351			else
  1352				fmtprint(&fmt, ", ");
  1353			fmtprint(&fmt, "%T", l);
  1354		}
  1355		if(first)
  1356			fmtprint(&fmt, "[no arguments %s]", what);
  1357		return fmtstrflush(&fmt);
  1358	}
  1359	
  1360	static char*
  1361	dumpnodetypes(NodeList *l, char *what)
  1362	{
  1363		int first;
  1364		Node *r;
  1365		Fmt fmt;
  1366	
  1367		fmtstrinit(&fmt);
  1368		fmtprint(&fmt, "\t");
  1369		first = 1;
  1370		for(; l; l=l->next) {
  1371			r = l->n;
  1372			if(first)
  1373				first = 0;
  1374			else
  1375				fmtprint(&fmt, ", ");
  1376			fmtprint(&fmt, "%T", r->type);
  1377		}
  1378		if(first)
  1379			fmtprint(&fmt, "[no arguments %s]", what);
  1380		return fmtstrflush(&fmt);
  1381	}
  1382	
  1383	/*
  1384	 * check assign expression list to
  1385	 * a type list. called in
  1386	 *	return expr-list
  1387	 *	func(expr-list)
  1388	 */
  1389	static NodeList*
  1390	ascompatte(int op, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init)
  1391	{
  1392		Type *l, *ll;
  1393		Node *r, *a;
  1394		NodeList *nn, *lr0, *alist;
  1395		Iter savel;
  1396		char *l1, *l2;
  1397	
  1398		lr0 = lr;
  1399		l = structfirst(&savel, nl);
  1400		r = N;
  1401		if(lr)
  1402			r = lr->n;
  1403		nn = nil;
  1404		
  1405		// f(g()) where g has multiple return values
  1406		if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
  1407			// optimization - can do block copy
  1408			if(eqtypenoname(r->type, *nl)) {
  1409				a = nodarg(*nl, fp);
  1410				a->type = r->type;
  1411				nn = list1(convas(nod(OAS, a, r), init));
  1412				goto ret;
  1413			}
  1414			
  1415			// conversions involved.
  1416			// copy into temporaries.
  1417			alist = nil;
  1418			for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
  1419				a = nod(OXXX, N, N);
  1420				tempname(a, l->type);
  1421				alist = list(alist, a);
  1422			}
  1423			a = nod(OAS2, N, N);
  1424			a->list = alist;
  1425			a->rlist = lr;
  1426			typecheck(&a, Etop);
  1427			walkstmt(&a);
  1428			*init = list(*init, a);
  1429			lr = alist;
  1430			r = lr->n;
  1431			l = structfirst(&savel, nl);
  1432		}
  1433	
  1434	loop:
  1435		if(l != T && l->isddd) {
  1436			// the ddd parameter must be last
  1437			ll = structnext(&savel);
  1438			if(ll != T)
  1439				yyerror("... must be last argument");
  1440	
  1441			// special case --
  1442			// only if we are assigning a single ddd
  1443			// argument to a ddd parameter then it is
  1444			// passed thru unencapsulated
  1445			if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
  1446				a = nod(OAS, nodarg(l, fp), r);
  1447				a = convas(a, init);
  1448				nn = list(nn, a);
  1449				goto ret;
  1450			}
  1451	
  1452			// normal case -- make a slice of all
  1453			// remaining arguments and pass it to
  1454			// the ddd parameter.
  1455			nn = mkdotargslice(lr, nn, l, fp, init);
  1456			goto ret;
  1457		}
  1458	
  1459		if(l == T || r == N) {
  1460			if(l != T || r != N) {
  1461				l1 = dumptypes(nl, "expected");
  1462				l2 = dumpnodetypes(lr0, "given");
  1463				if(l != T)
  1464					yyerror("not enough arguments to %O\n%s\n%s", op, l1, l2);
  1465				else
  1466					yyerror("too many arguments to %O\n%s\n%s", op, l1, l2);
  1467			}
  1468			goto ret;
  1469		}
  1470	
  1471		a = nod(OAS, nodarg(l, fp), r);
  1472		a = convas(a, init);
  1473		nn = list(nn, a);
  1474	
  1475		l = structnext(&savel);
  1476		r = N;
  1477		lr = lr->next;
  1478		if(lr != nil)
  1479			r = lr->n;
  1480		goto loop;
  1481	
  1482	ret:
  1483		for(lr=nn; lr; lr=lr->next)
  1484			lr->n->typecheck = 1;
  1485		return nn;
  1486	}
  1487	
  1488	// generate code for print
  1489	static Node*
  1490	walkprint(Node *nn, NodeList **init, int defer)
  1491	{
  1492		Node *r;
  1493		Node *n;
  1494		NodeList *l, *all;
  1495		Node *on;
  1496		Type *t;
  1497		int notfirst, et, op;
  1498		NodeList *calls, *intypes, *args;
  1499		Fmt fmt;
  1500	
  1501		on = nil;
  1502		op = nn->op;
  1503		all = nn->list;
  1504		calls = nil;
  1505		notfirst = 0;
  1506		intypes = nil;
  1507		args = nil;
  1508	
  1509		memset(&fmt, 0, sizeof fmt);
  1510		if(defer) {
  1511			// defer print turns into defer printf with format string
  1512			fmtstrinit(&fmt);
  1513			intypes = list(intypes, nod(ODCLFIELD, N, typenod(types[TSTRING])));
  1514			args = list1(nod(OXXX, N, N));
  1515		}
  1516	
  1517		for(l=all; l; l=l->next) {
  1518			if(notfirst) {
  1519				if(defer)
  1520					fmtprint(&fmt, " ");
  1521				else
  1522					calls = list(calls, mkcall("printsp", T, init));
  1523			}
  1524			notfirst = op == OPRINTN;
  1525	
  1526			n = l->n;
  1527			if(n->op == OLITERAL) {
  1528				switch(n->val.ctype) {
  1529				case CTINT:
  1530					defaultlit(&n, types[TINT64]);
  1531					break;
  1532				case CTFLT:
  1533					defaultlit(&n, types[TFLOAT64]);
  1534					break;
  1535				}
  1536			}
  1537			if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL)
  1538				defaultlit(&n, types[TINT64]);
  1539			defaultlit(&n, nil);
  1540			l->n = n;
  1541			if(n->type == T || n->type->etype == TFORW)
  1542				continue;
  1543	
  1544			t = n->type;
  1545			et = n->type->etype;
  1546			if(isinter(n->type)) {
  1547				if(defer) {
  1548					if(isnilinter(n->type))
  1549						fmtprint(&fmt, "%%e");
  1550					else
  1551						fmtprint(&fmt, "%%i");
  1552				} else {
  1553					if(isnilinter(n->type))
  1554						on = syslook("printeface", 1);
  1555					else
  1556						on = syslook("printiface", 1);
  1557					argtype(on, n->type);		// any-1
  1558				}
  1559			} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
  1560				if(defer) {
  1561					fmtprint(&fmt, "%%p");
  1562				} else {
  1563					on = syslook("printpointer", 1);
  1564					argtype(on, n->type);	// any-1
  1565				}
  1566			} else if(isslice(n->type)) {
  1567				if(defer) {
  1568					fmtprint(&fmt, "%%a");
  1569				} else {
  1570					on = syslook("printslice", 1);
  1571					argtype(on, n->type);	// any-1
  1572				}
  1573			} else if(isint[et]) {
  1574				if(defer) {
  1575					if(et == TUINT64)
  1576						fmtprint(&fmt, "%%U");
  1577					else {
  1578						fmtprint(&fmt, "%%D");
  1579						t = types[TINT64];
  1580					}
  1581				} else {
  1582					if(et == TUINT64)
  1583						on = syslook("printuint", 0);
  1584					else
  1585						on = syslook("printint", 0);
  1586				}
  1587			} else if(isfloat[et]) {
  1588				if(defer) {
  1589					fmtprint(&fmt, "%%f");
  1590					t = types[TFLOAT64];
  1591				} else
  1592					on = syslook("printfloat", 0);
  1593			} else if(iscomplex[et]) {
  1594				if(defer) {
  1595					fmtprint(&fmt, "%%C");
  1596					t = types[TCOMPLEX128];
  1597				} else
  1598					on = syslook("printcomplex", 0);
  1599			} else if(et == TBOOL) {
  1600				if(defer)
  1601					fmtprint(&fmt, "%%t");
  1602				else
  1603					on = syslook("printbool", 0);
  1604			} else if(et == TSTRING) {
  1605				if(defer)
  1606					fmtprint(&fmt, "%%S");
  1607				else
  1608					on = syslook("printstring", 0);
  1609			} else {
  1610				badtype(OPRINT, n->type, T);
  1611				continue;
  1612			}
  1613	
  1614			if(!defer) {
  1615				t = *getinarg(on->type);
  1616				if(t != nil)
  1617					t = t->type;
  1618				if(t != nil)
  1619					t = t->type;
  1620			}
  1621	
  1622			if(!eqtype(t, n->type)) {
  1623				n = nod(OCONV, n, N);
  1624				n->type = t;
  1625			}
  1626	
  1627			if(defer) {
  1628				intypes = list(intypes, nod(ODCLFIELD, N, typenod(t)));
  1629				args = list(args, n);
  1630			} else {
  1631				r = nod(OCALL, on, N);
  1632				r->list = list1(n);
  1633				calls = list(calls, r);
  1634			}
  1635		}
  1636	
  1637		if(defer) {
  1638			if(op == OPRINTN)
  1639				fmtprint(&fmt, "\n");
  1640			on = syslook("goprintf", 1);
  1641			on->type = functype(nil, intypes, nil);
  1642			args->n = nod(OLITERAL, N, N);
  1643			args->n->val.ctype = CTSTR;
  1644			args->n->val.u.sval = strlit(fmtstrflush(&fmt));
  1645			r = nod(OCALL, on, N);
  1646			r->list = args;
  1647			typecheck(&r, Etop);
  1648			walkexpr(&r, init);
  1649		} else {
  1650			if(op == OPRINTN)
  1651				calls = list(calls, mkcall("printnl", T, nil));
  1652			typechecklist(calls, Etop);
  1653			walkexprlist(calls, init);
  1654	
  1655			r = nod(OEMPTY, N, N);
  1656			typecheck(&r, Etop);
  1657			walkexpr(&r, init);
  1658			r->ninit = calls;
  1659		}
  1660		return r;
  1661	}
  1662	
  1663	Node*
  1664	callnew(Type *t)
  1665	{
  1666		Node *fn;
  1667	
  1668		dowidth(t);
  1669		fn = syslook("new", 1);
  1670		argtype(fn, t);
  1671		return mkcall1(fn, ptrto(t), nil, nodintconst(t->width));
  1672	}
  1673	
  1674	static Node*
  1675	convas(Node *n, NodeList **init)
  1676	{
  1677		Type *lt, *rt;
  1678	
  1679		if(n->op != OAS)
  1680			fatal("convas: not OAS %O", n->op);
  1681	
  1682		n->typecheck = 1;
  1683	
  1684		if(n->left == N || n->right == N)
  1685			goto out;
  1686	
  1687		lt = n->left->type;
  1688		rt = n->right->type;
  1689		if(lt == T || rt == T)
  1690			goto out;
  1691	
  1692		if(isblank(n->left)) {
  1693			defaultlit(&n->right, T);
  1694			goto out;
  1695		}
  1696	
  1697		if(n->left->op == OINDEXMAP) {
  1698			n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init,
  1699				typename(n->left->left->type),
  1700				n->left->left, n->left->right, n->right);
  1701			goto out;
  1702		}
  1703		
  1704		if(eqtype(lt, rt))
  1705			goto out;
  1706		
  1707		n->right = assignconv(n->right, lt, "assignment");
  1708		walkexpr(&n->right, init);
  1709	
  1710	out:
  1711		ullmancalc(n);
  1712		return n;
  1713	}
  1714	
  1715	/*
  1716	 * from ascompat[te]
  1717	 * evaluating actual function arguments.
  1718	 *	f(a,b)
  1719	 * if there is exactly one function expr,
  1720	 * then it is done first. otherwise must
  1721	 * make temp variables
  1722	 */
  1723	NodeList*
  1724	reorder1(NodeList *all)
  1725	{
  1726		Node *f, *a, *n;
  1727		NodeList *l, *r, *g;
  1728		int c, d, t;
  1729	
  1730		c = 0;	// function calls
  1731		t = 0;	// total parameters
  1732	
  1733		for(l=all; l; l=l->next) {
  1734			n = l->n;
  1735			t++;
  1736			ullmancalc(n);
  1737			if(n->ullman >= UINF)
  1738				c++;
  1739		}
  1740		if(c == 0 || t == 1)
  1741			return all;
  1742	
  1743		g = nil;	// fncalls assigned to tempnames
  1744		f = N;	// last fncall assigned to stack
  1745		r = nil;	// non fncalls and tempnames assigned to stack
  1746		d = 0;
  1747		for(l=all; l; l=l->next) {
  1748			n = l->n;
  1749			if(n->ullman < UINF) {
  1750				r = list(r, n);
  1751				continue;
  1752			}
  1753			d++;
  1754			if(d == c) {
  1755				f = n;
  1756				continue;
  1757			}
  1758	
  1759			// make assignment of fncall to tempname
  1760			a = nod(OXXX, N, N);
  1761			tempname(a, n->right->type);
  1762			a = nod(OAS, a, n->right);
  1763			g = list(g, a);
  1764	
  1765			// put normal arg assignment on list
  1766			// with fncall replaced by tempname
  1767			n->right = a->left;
  1768			r = list(r, n);
  1769		}
  1770	
  1771		if(f != N)
  1772			g = list(g, f);
  1773		return concat(g, r);
  1774	}
  1775	
  1776	/*
  1777	 * from ascompat[ee]
  1778	 *	a,b = c,d
  1779	 * simultaneous assignment. there cannot
  1780	 * be later use of an earlier lvalue.
  1781	 */
  1782	
  1783	static int
  1784	vmatch2(Node *l, Node *r)
  1785	{
  1786		NodeList *ll;
  1787	
  1788		/*
  1789		 * isolate all right sides
  1790		 */
  1791		if(r == N)
  1792			return 0;
  1793		switch(r->op) {
  1794		case ONAME:
  1795			// match each right given left
  1796			if(l == r)
  1797				return 1;
  1798		case OLITERAL:
  1799			return 0;
  1800		}
  1801		if(vmatch2(l, r->left))
  1802			return 1;
  1803		if(vmatch2(l, r->right))
  1804			return 1;
  1805		for(ll=r->list; ll; ll=ll->next)
  1806			if(vmatch2(l, ll->n))
  1807				return 1;
  1808		return 0;
  1809	}
  1810	
  1811	int
  1812	vmatch1(Node *l, Node *r)
  1813	{
  1814		NodeList *ll;
  1815	
  1816		/*
  1817		 * isolate all left sides
  1818		 */
  1819		if(l == N || r == N)
  1820			return 0;
  1821		switch(l->op) {
  1822		case ONAME:
  1823			switch(l->class) {
  1824			case PPARAM:
  1825			case PPARAMREF:
  1826			case PAUTO:
  1827				break;
  1828			default:
  1829				// assignment to non-stack variable
  1830				// must be delayed if right has function calls.
  1831				if(r->ullman >= UINF)
  1832					return 1;
  1833				break;
  1834			}
  1835			return vmatch2(l, r);
  1836		case OLITERAL:
  1837			return 0;
  1838		}
  1839		if(vmatch1(l->left, r))
  1840			return 1;
  1841		if(vmatch1(l->right, r))
  1842			return 1;
  1843		for(ll=l->list; ll; ll=ll->next)
  1844			if(vmatch1(ll->n, r))
  1845				return 1;
  1846		return 0;
  1847	}
  1848	
  1849	NodeList*
  1850	reorder3(NodeList *all)
  1851	{
  1852		Node *n1, *n2, *q;
  1853		int c1, c2;
  1854		NodeList *l1, *l2, *r;
  1855	
  1856		r = nil;
  1857		for(l1=all, c1=0; l1; l1=l1->next, c1++) {
  1858			n1 = l1->n;
  1859			for(l2=all, c2=0; l2; l2=l2->next, c2++) {
  1860				n2 = l2->n;
  1861				if(c2 > c1) {
  1862					if(vmatch1(n1->left, n2->right)) {
  1863						// delay assignment to n1->left
  1864						q = nod(OXXX, N, N);
  1865						tempname(q, n1->right->type);
  1866						q = nod(OAS, n1->left, q);
  1867						n1->left = q->right;
  1868						r = list(r, q);
  1869						break;
  1870					}
  1871				}
  1872			}
  1873		}
  1874		return concat(all, r);
  1875	}
  1876	
  1877	/*
  1878	 * walk through argin parameters.
  1879	 * generate and return code to allocate
  1880	 * copies of escaped parameters to the heap.
  1881	 */
  1882	static NodeList*
  1883	paramstoheap(Type **argin, int out)
  1884	{
  1885		Type *t;
  1886		Iter savet;
  1887		Node *v;
  1888		NodeList *nn;
  1889	
  1890		nn = nil;
  1891		for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
  1892			v = t->nname;
  1893			if(v == N && out && hasdefer) {
  1894				// Defer might stop a panic and show the
  1895				// return values as they exist at the time of panic.
  1896				// Make sure to zero them on entry to the function.
  1897				nn = list(nn, nod(OAS, nodarg(t, 1), N));
  1898			}
  1899			if(v == N || !(v->class & PHEAP))
  1900				continue;
  1901	
  1902			// generate allocation & copying code
  1903			if(v->alloc == nil)
  1904				v->alloc = callnew(v->type);
  1905			nn = list(nn, nod(OAS, v->heapaddr, v->alloc));
  1906			if((v->class & ~PHEAP) != PPARAMOUT)
  1907				nn = list(nn, nod(OAS, v, v->stackparam));
  1908		}
  1909		return nn;
  1910	}
  1911	
  1912	/*
  1913	 * walk through argout parameters copying back to stack
  1914	 */
  1915	static NodeList*
  1916	returnsfromheap(Type **argin)
  1917	{
  1918		Type *t;
  1919		Iter savet;
  1920		Node *v;
  1921		NodeList *nn;
  1922	
  1923		nn = nil;
  1924		for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
  1925			v = t->nname;
  1926			if(v == N || v->class != (PHEAP|PPARAMOUT))
  1927				continue;
  1928			nn = list(nn, nod(OAS, v->stackparam, v));
  1929		}
  1930		return nn;
  1931	}
  1932	
  1933	/*
  1934	 * take care of migrating any function in/out args
  1935	 * between the stack and the heap.  adds code to
  1936	 * curfn's before and after lists.
  1937	 */
  1938	static void
  1939	heapmoves(void)
  1940	{
  1941		NodeList *nn;
  1942		int32 lno;
  1943		
  1944		lno = lineno;
  1945		lineno = curfn->lineno;
  1946		nn = paramstoheap(getthis(curfn->type), 0);
  1947		nn = concat(nn, paramstoheap(getinarg(curfn->type), 0));
  1948		nn = concat(nn, paramstoheap(getoutarg(curfn->type), 1));
  1949		curfn->enter = concat(curfn->enter, nn);
  1950		lineno = curfn->endlineno;
  1951		curfn->exit = returnsfromheap(getoutarg(curfn->type));
  1952		lineno = lno;
  1953	}
  1954	
  1955	static Node*
  1956	vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
  1957	{
  1958		int i, n;
  1959		Node *r;
  1960		NodeList *args;
  1961	
  1962		if(fn->type == T || fn->type->etype != TFUNC)
  1963			fatal("mkcall %#N %T", fn, fn->type);
  1964	
  1965		args = nil;
  1966		n = fn->type->intuple;
  1967		for(i=0; i<n; i++)
  1968			args = list(args, va_arg(va, Node*));
  1969	
  1970		r = nod(OCALL, fn, N);
  1971		r->list = args;
  1972		if(fn->type->outtuple > 0)
  1973			typecheck(&r, Erv | Efnstruct);
  1974		else
  1975			typecheck(&r, Etop);
  1976		walkexpr(&r, init);
  1977		r->type = t;
  1978		return r;
  1979	}
  1980	
  1981	Node*
  1982	mkcall(char *name, Type *t, NodeList **init, ...)
  1983	{
  1984		Node *r;
  1985		va_list va;
  1986	
  1987		va_start(va, init);
  1988		r = vmkcall(syslook(name, 0), t, init, va);
  1989		va_end(va);
  1990		return r;
  1991	}
  1992	
  1993	Node*
  1994	mkcall1(Node *fn, Type *t, NodeList **init, ...)
  1995	{
  1996		Node *r;
  1997		va_list va;
  1998	
  1999		va_start(va, init);
  2000		r = vmkcall(fn, t, init, va);
  2001		va_end(va);
  2002		return r;
  2003	}
  2004	
  2005	static Node*
  2006	conv(Node *n, Type *t)
  2007	{
  2008		if(eqtype(n->type, t))
  2009			return n;
  2010		n = nod(OCONV, n, N);
  2011		n->type = t;
  2012		typecheck(&n, Erv);
  2013		return n;
  2014	}
  2015	
  2016	Node*
  2017	chanfn(char *name, int n, Type *t)
  2018	{
  2019		Node *fn;
  2020		int i;
  2021	
  2022		if(t->etype != TCHAN)
  2023			fatal("chanfn %T", t);
  2024		fn = syslook(name, 1);
  2025		for(i=0; i<n; i++)
  2026			argtype(fn, t->type);
  2027		return fn;
  2028	}
  2029	
  2030	static Node*
  2031	mapfn(char *name, Type *t)
  2032	{
  2033		Node *fn;
  2034	
  2035		if(t->etype != TMAP)
  2036			fatal("mapfn %T", t);
  2037		fn = syslook(name, 1);
  2038		argtype(fn, t->down);
  2039		argtype(fn, t->type);
  2040		argtype(fn, t->down);
  2041		argtype(fn, t->type);
  2042		return fn;
  2043	}
  2044	
  2045	static Node*
  2046	addstr(Node *n, NodeList **init)
  2047	{
  2048		Node *r, *cat, *typstr;
  2049		NodeList *in, *args;
  2050		int i, count;
  2051		
  2052		count = 0;
  2053		for(r=n; r->op == OADDSTR; r=r->left)
  2054			count++;	// r->right
  2055		count++;	// r
  2056	
  2057		// prepare call of runtime.catstring of type int, string, string, string
  2058		// with as many strings as we have.
  2059		cat = syslook("concatstring", 1);
  2060		cat->type = T;
  2061		cat->ntype = nod(OTFUNC, N, N);
  2062		in = list1(nod(ODCLFIELD, N, typenod(types[TINT])));	// count
  2063		typstr = typenod(types[TSTRING]);
  2064		for(i=0; i<count; i++)
  2065			in = list(in, nod(ODCLFIELD, N, typstr));
  2066		cat->ntype->list = in;
  2067		cat->ntype->rlist = list1(nod(ODCLFIELD, N, typstr));
  2068	
  2069		args = nil;
  2070		for(r=n; r->op == OADDSTR; r=r->left)
  2071			args = concat(list1(conv(r->right, types[TSTRING])), args);
  2072		args = concat(list1(conv(r, types[TSTRING])), args);
  2073		args = concat(list1(nodintconst(count)), args);
  2074	
  2075		r = nod(OCALL, cat, N);
  2076		r->list = args;
  2077		typecheck(&r, Erv);
  2078		walkexpr(&r, init);
  2079		r->type = n->type;
  2080		
  2081		return r;
  2082	}
  2083	
  2084	static Node*
  2085	appendslice(Node *n, NodeList **init)
  2086	{
  2087		Node *f;
  2088		
  2089		f = syslook("appendslice", 1);
  2090		argtype(f, n->type);
  2091		argtype(f, n->type->type);
  2092		argtype(f, n->type);
  2093		return mkcall1(f, n->type, init, typename(n->type), n->list->n, n->list->next->n);
  2094	}
  2095	
  2096	// expand append(src, a [, b]* ) to
  2097	//
  2098	//   init {
  2099	//     s := src
  2100	//     const argc = len(args) - 1
  2101	//     if cap(s) - len(s) < argc {
  2102	//          s = growslice(s, argc) 
  2103	//     }
  2104	//     n := len(s)
  2105	//     s = s[:n+argc]
  2106	//     s[n] = a
  2107	//     s[n+1] = b
  2108	//     ...
  2109	//   }
  2110	//   s
  2111	static Node*
  2112	append(Node *n, NodeList **init)
  2113	{
  2114		NodeList *l, *a;
  2115		Node *nsrc, *ns, *nn, *na, *nx, *fn;
  2116		int argc;
  2117	
  2118		walkexprlistsafe(n->list, init);
  2119	
  2120		nsrc = n->list->n;
  2121		argc = count(n->list) - 1;
  2122		if (argc < 1) {
  2123			return nsrc;
  2124		}
  2125	
  2126		l = nil;
  2127	
  2128		ns = nod(OXXX, N, N);             // var s
  2129		tempname(ns, nsrc->type);
  2130		l = list(l, nod(OAS, ns, nsrc));  // s = src
  2131	
  2132		na = nodintconst(argc);         // const argc
  2133		nx = nod(OIF, N, N);            // if cap(s) - len(s) < argc
  2134		nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
  2135	
  2136		fn = syslook("growslice", 1);   //   growslice(<type>, old []T, n int64) (ret []T)
  2137		argtype(fn, ns->type->type);    // 1 old []any 
  2138		argtype(fn, ns->type->type);    // 2 ret []any
  2139	
  2140		nx->nbody = list1(nod(OAS, ns, mkcall1(fn,  ns->type, &nx->ninit,
  2141						       typename(ns->type),
  2142						       ns,
  2143						       conv(na, types[TINT64]))));
  2144		l = list(l, nx);
  2145	
  2146		nn = nod(OXXX, N, N);                            // var n
  2147		tempname(nn, types[TINT]);
  2148		l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));     // n = len(s)
  2149	
  2150		nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));   // ...s[:n+argc]
  2151		nx->etype = 1;  // disable bounds check
  2152		l = list(l, nod(OAS, ns, nx));                  // s = s[:n+argc]
  2153	
  2154		for (a = n->list->next;  a != nil; a = a->next) {
  2155			nx = nod(OINDEX, ns, nn);               // s[n] ...
  2156			nx->etype = 1;  // disable bounds check
  2157			l = list(l, nod(OAS, nx, a->n));        // s[n] = arg
  2158			if (a->next != nil)
  2159				l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1))));  // n = n + 1
  2160		}
  2161	
  2162		typechecklist(l, Etop);
  2163		walkstmtlist(l);
  2164		*init = concat(*init, l);
  2165		return ns;
  2166	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.