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