github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/cmd/compile/internal/gc/walk.go (about)

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