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