github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/compile/internal/gc/walk.go (about)

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