github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/walk.go (about)

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