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