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