github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/cmd/compile/internal/gc/walk.go (about)

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