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/internal/obj"
      9 	"fmt"
     10 )
     11 
     12 /*
     13  * generate:
     14  *	res = n;
     15  * simplifies and calls Thearch.Gmove.
     16  * if wb is true, need to emit write barriers.
     17  */
     18 func Cgen(n, res *Node) {
     19 	cgen_wb(n, res, false)
     20 }
     21 
     22 func cgen_wb(n, res *Node, wb bool) {
     23 	if Debug['g'] != 0 {
     24 		op := "cgen"
     25 		if wb {
     26 			op = "cgen_wb"
     27 		}
     28 		Dump("\n"+op+"-n", n)
     29 		Dump(op+"-res", res)
     30 	}
     31 
     32 	if n == nil || n.Type == nil {
     33 		return
     34 	}
     35 
     36 	if res == nil || res.Type == nil {
     37 		Fatal("cgen: res nil")
     38 	}
     39 
     40 	for n.Op == OCONVNOP {
     41 		n = n.Left
     42 	}
     43 
     44 	switch n.Op {
     45 	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
     46 		cgen_slice(n, res, wb)
     47 		return
     48 
     49 	case OEFACE:
     50 		if res.Op != ONAME || !res.Addable || wb {
     51 			var n1 Node
     52 			Tempname(&n1, n.Type)
     53 			Cgen_eface(n, &n1)
     54 			cgen_wb(&n1, res, wb)
     55 		} else {
     56 			Cgen_eface(n, res)
     57 		}
     58 		return
     59 
     60 	case ODOTTYPE:
     61 		cgen_dottype(n, res, nil, wb)
     62 		return
     63 
     64 	case OAPPEND:
     65 		cgen_append(n, res)
     66 		return
     67 	}
     68 
     69 	if n.Ullman >= UINF {
     70 		if n.Op == OINDREG {
     71 			Fatal("cgen: this is going to miscompile")
     72 		}
     73 		if res.Ullman >= UINF {
     74 			var n1 Node
     75 			Tempname(&n1, n.Type)
     76 			Cgen(n, &n1)
     77 			cgen_wb(&n1, res, wb)
     78 			return
     79 		}
     80 	}
     81 
     82 	if Isfat(n.Type) {
     83 		if n.Type.Width < 0 {
     84 			Fatal("forgot to compute width for %v", n.Type)
     85 		}
     86 		sgen_wb(n, res, n.Type.Width, wb)
     87 		return
     88 	}
     89 
     90 	if !res.Addable {
     91 		if n.Ullman > res.Ullman {
     92 			if Ctxt.Arch.Regsize == 4 && Is64(n.Type) {
     93 				var n1 Node
     94 				Tempname(&n1, n.Type)
     95 				Cgen(n, &n1)
     96 				cgen_wb(&n1, res, wb)
     97 				return
     98 			}
     99 
    100 			var n1 Node
    101 			Regalloc(&n1, n.Type, res)
    102 			Cgen(n, &n1)
    103 			if n1.Ullman > res.Ullman {
    104 				Dump("n1", &n1)
    105 				Dump("res", res)
    106 				Fatal("loop in cgen")
    107 			}
    108 
    109 			cgen_wb(&n1, res, wb)
    110 			Regfree(&n1)
    111 			return
    112 		}
    113 
    114 		var f int
    115 		if res.Ullman < UINF {
    116 			if Complexop(n, res) {
    117 				Complexgen(n, res)
    118 				return
    119 			}
    120 
    121 			f = 1 // gen thru register
    122 			switch n.Op {
    123 			case OLITERAL:
    124 				if Smallintconst(n) {
    125 					f = 0
    126 				}
    127 
    128 			case OREGISTER:
    129 				f = 0
    130 			}
    131 
    132 			if !Iscomplex[n.Type.Etype] && Ctxt.Arch.Regsize == 8 && !wb {
    133 				a := Thearch.Optoas(OAS, res.Type)
    134 				var addr obj.Addr
    135 				if Thearch.Sudoaddable(a, res, &addr) {
    136 					var p1 *obj.Prog
    137 					if f != 0 {
    138 						var n2 Node
    139 						Regalloc(&n2, res.Type, nil)
    140 						Cgen(n, &n2)
    141 						p1 = Thearch.Gins(a, &n2, nil)
    142 						Regfree(&n2)
    143 					} else {
    144 						p1 = Thearch.Gins(a, n, nil)
    145 					}
    146 					p1.To = addr
    147 					if Debug['g'] != 0 {
    148 						fmt.Printf("%v [ignore previous line]\n", p1)
    149 					}
    150 					Thearch.Sudoclean()
    151 					return
    152 				}
    153 			}
    154 		}
    155 
    156 		if Ctxt.Arch.Thechar == '8' {
    157 			// no registers to speak of
    158 			var n1, n2 Node
    159 			Tempname(&n1, n.Type)
    160 			Cgen(n, &n1)
    161 			Igen(res, &n2, nil)
    162 			cgen_wb(&n1, &n2, wb)
    163 			Regfree(&n2)
    164 			return
    165 		}
    166 
    167 		var n1 Node
    168 		Igen(res, &n1, nil)
    169 		cgen_wb(n, &n1, wb)
    170 		Regfree(&n1)
    171 		return
    172 	}
    173 
    174 	// update addressability for string, slice
    175 	// can't do in walk because n->left->addable
    176 	// changes if n->left is an escaping local variable.
    177 	switch n.Op {
    178 	case OSPTR, OLEN:
    179 		if Isslice(n.Left.Type) || Istype(n.Left.Type, TSTRING) {
    180 			n.Addable = n.Left.Addable
    181 		}
    182 
    183 	case OCAP:
    184 		if Isslice(n.Left.Type) {
    185 			n.Addable = n.Left.Addable
    186 		}
    187 
    188 	case OITAB:
    189 		n.Addable = n.Left.Addable
    190 	}
    191 
    192 	if wb {
    193 		if int(Simtype[res.Type.Etype]) != Tptr {
    194 			Fatal("cgen_wb of type %v", res.Type)
    195 		}
    196 		if n.Ullman >= UINF {
    197 			var n1 Node
    198 			Tempname(&n1, n.Type)
    199 			Cgen(n, &n1)
    200 			n = &n1
    201 		}
    202 		cgen_wbptr(n, res)
    203 		return
    204 	}
    205 
    206 	// Write barrier now handled. Code below this line can ignore wb.
    207 
    208 	if Ctxt.Arch.Thechar == '5' { // TODO(rsc): Maybe more often?
    209 		// if both are addressable, move
    210 		if n.Addable && res.Addable {
    211 			if Is64(n.Type) || Is64(res.Type) || n.Op == OREGISTER || res.Op == OREGISTER || Iscomplex[n.Type.Etype] || Iscomplex[res.Type.Etype] {
    212 				Thearch.Gmove(n, res)
    213 			} else {
    214 				var n1 Node
    215 				Regalloc(&n1, n.Type, nil)
    216 				Thearch.Gmove(n, &n1)
    217 				Cgen(&n1, res)
    218 				Regfree(&n1)
    219 			}
    220 
    221 			return
    222 		}
    223 
    224 		// if both are not addressable, use a temporary.
    225 		if !n.Addable && !res.Addable {
    226 			// could use regalloc here sometimes,
    227 			// but have to check for ullman >= UINF.
    228 			var n1 Node
    229 			Tempname(&n1, n.Type)
    230 			Cgen(n, &n1)
    231 			Cgen(&n1, res)
    232 			return
    233 		}
    234 
    235 		// if result is not addressable directly but n is,
    236 		// compute its address and then store via the address.
    237 		if !res.Addable {
    238 			var n1 Node
    239 			Igen(res, &n1, nil)
    240 			Cgen(n, &n1)
    241 			Regfree(&n1)
    242 			return
    243 		}
    244 	}
    245 
    246 	if Complexop(n, res) {
    247 		Complexgen(n, res)
    248 		return
    249 	}
    250 
    251 	if (Ctxt.Arch.Thechar == '6' || Ctxt.Arch.Thechar == '8') && n.Addable {
    252 		Thearch.Gmove(n, res)
    253 		return
    254 	}
    255 
    256 	if Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
    257 		// if both are addressable, move
    258 		if n.Addable {
    259 			if n.Op == OREGISTER || res.Op == OREGISTER {
    260 				Thearch.Gmove(n, res)
    261 			} else {
    262 				var n1 Node
    263 				Regalloc(&n1, n.Type, nil)
    264 				Thearch.Gmove(n, &n1)
    265 				Cgen(&n1, res)
    266 				Regfree(&n1)
    267 			}
    268 			return
    269 		}
    270 	}
    271 
    272 	// if n is sudoaddable generate addr and move
    273 	if Ctxt.Arch.Thechar == '5' && !Is64(n.Type) && !Is64(res.Type) && !Iscomplex[n.Type.Etype] && !Iscomplex[res.Type.Etype] {
    274 		a := Thearch.Optoas(OAS, n.Type)
    275 		var addr obj.Addr
    276 		if Thearch.Sudoaddable(a, n, &addr) {
    277 			if res.Op != OREGISTER {
    278 				var n2 Node
    279 				Regalloc(&n2, res.Type, nil)
    280 				p1 := Thearch.Gins(a, nil, &n2)
    281 				p1.From = addr
    282 				if Debug['g'] != 0 {
    283 					fmt.Printf("%v [ignore previous line]\n", p1)
    284 				}
    285 				Thearch.Gmove(&n2, res)
    286 				Regfree(&n2)
    287 			} else {
    288 				p1 := Thearch.Gins(a, nil, res)
    289 				p1.From = addr
    290 				if Debug['g'] != 0 {
    291 					fmt.Printf("%v [ignore previous line]\n", p1)
    292 				}
    293 			}
    294 			Thearch.Sudoclean()
    295 			return
    296 		}
    297 	}
    298 
    299 	nl := n.Left
    300 	nr := n.Right
    301 
    302 	if nl != nil && nl.Ullman >= UINF {
    303 		if nr != nil && nr.Ullman >= UINF {
    304 			var n1 Node
    305 			Tempname(&n1, nl.Type)
    306 			Cgen(nl, &n1)
    307 			n2 := *n
    308 			n2.Left = &n1
    309 			Cgen(&n2, res)
    310 			return
    311 		}
    312 	}
    313 
    314 	// 64-bit ops are hard on 32-bit machine.
    315 	if Ctxt.Arch.Regsize == 4 && (Is64(n.Type) || Is64(res.Type) || n.Left != nil && Is64(n.Left.Type)) {
    316 		switch n.Op {
    317 		// math goes to cgen64.
    318 		case OMINUS,
    319 			OCOM,
    320 			OADD,
    321 			OSUB,
    322 			OMUL,
    323 			OLROT,
    324 			OLSH,
    325 			ORSH,
    326 			OAND,
    327 			OOR,
    328 			OXOR:
    329 			Thearch.Cgen64(n, res)
    330 			return
    331 		}
    332 	}
    333 
    334 	if Thearch.Cgen_float != nil && nl != nil && Isfloat[n.Type.Etype] && Isfloat[nl.Type.Etype] {
    335 		Thearch.Cgen_float(n, res)
    336 		return
    337 	}
    338 
    339 	if !Iscomplex[n.Type.Etype] && Ctxt.Arch.Regsize == 8 {
    340 		a := Thearch.Optoas(OAS, n.Type)
    341 		var addr obj.Addr
    342 		if Thearch.Sudoaddable(a, n, &addr) {
    343 			if res.Op == OREGISTER {
    344 				p1 := Thearch.Gins(a, nil, res)
    345 				p1.From = addr
    346 			} else {
    347 				var n2 Node
    348 				Regalloc(&n2, n.Type, nil)
    349 				p1 := Thearch.Gins(a, nil, &n2)
    350 				p1.From = addr
    351 				Thearch.Gins(a, &n2, res)
    352 				Regfree(&n2)
    353 			}
    354 
    355 			Thearch.Sudoclean()
    356 			return
    357 		}
    358 	}
    359 
    360 	var a int
    361 	switch n.Op {
    362 	default:
    363 		Dump("cgen", n)
    364 		Dump("cgen-res", res)
    365 		Fatal("cgen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
    366 
    367 	case OOROR, OANDAND,
    368 		OEQ, ONE,
    369 		OLT, OLE,
    370 		OGE, OGT,
    371 		ONOT:
    372 		Bvgen(n, res, true)
    373 		return
    374 
    375 	case OPLUS:
    376 		Cgen(nl, res)
    377 		return
    378 
    379 		// unary
    380 	case OCOM:
    381 		a := Thearch.Optoas(OXOR, nl.Type)
    382 
    383 		var n1 Node
    384 		Regalloc(&n1, nl.Type, nil)
    385 		Cgen(nl, &n1)
    386 		var n2 Node
    387 		Nodconst(&n2, nl.Type, -1)
    388 		Thearch.Gins(a, &n2, &n1)
    389 		cgen_norm(n, &n1, res)
    390 		return
    391 
    392 	case OMINUS:
    393 		if Isfloat[nl.Type.Etype] {
    394 			nr = Nodintconst(-1)
    395 			Convlit(&nr, n.Type)
    396 			a = Thearch.Optoas(OMUL, nl.Type)
    397 			goto sbop
    398 		}
    399 
    400 		a := Thearch.Optoas(int(n.Op), nl.Type)
    401 		// unary
    402 		var n1 Node
    403 		Regalloc(&n1, nl.Type, res)
    404 
    405 		Cgen(nl, &n1)
    406 		if Ctxt.Arch.Thechar == '5' {
    407 			var n2 Node
    408 			Nodconst(&n2, nl.Type, 0)
    409 			Thearch.Gins(a, &n2, &n1)
    410 		} else if Ctxt.Arch.Thechar == '7' {
    411 			Thearch.Gins(a, &n1, &n1)
    412 		} else {
    413 			Thearch.Gins(a, nil, &n1)
    414 		}
    415 		cgen_norm(n, &n1, res)
    416 		return
    417 
    418 	case OSQRT:
    419 		var n1 Node
    420 		Regalloc(&n1, nl.Type, res)
    421 		Cgen(n.Left, &n1)
    422 		Thearch.Gins(Thearch.Optoas(OSQRT, nl.Type), &n1, &n1)
    423 		Thearch.Gmove(&n1, res)
    424 		Regfree(&n1)
    425 		return
    426 
    427 	case OGETG:
    428 		Thearch.Getg(res)
    429 		return
    430 
    431 		// symmetric binary
    432 	case OAND,
    433 		OOR,
    434 		OXOR,
    435 		OADD,
    436 		OMUL:
    437 		if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(int(n.Op), nl, nr, res) {
    438 			break
    439 		}
    440 		a = Thearch.Optoas(int(n.Op), nl.Type)
    441 		goto sbop
    442 
    443 		// asymmetric binary
    444 	case OSUB:
    445 		a = Thearch.Optoas(int(n.Op), nl.Type)
    446 		goto abop
    447 
    448 	case OHMUL:
    449 		Thearch.Cgen_hmul(nl, nr, res)
    450 
    451 	case OCONV:
    452 		if Eqtype(n.Type, nl.Type) || Noconv(n.Type, nl.Type) {
    453 			Cgen(nl, res)
    454 			return
    455 		}
    456 
    457 		if Ctxt.Arch.Thechar == '8' {
    458 			var n1 Node
    459 			var n2 Node
    460 			Tempname(&n2, n.Type)
    461 			Mgen(nl, &n1, res)
    462 			Thearch.Gmove(&n1, &n2)
    463 			Thearch.Gmove(&n2, res)
    464 			Mfree(&n1)
    465 			break
    466 		}
    467 
    468 		var n1 Node
    469 		var n2 Node
    470 		if Ctxt.Arch.Thechar == '5' {
    471 			if nl.Addable && !Is64(nl.Type) {
    472 				Regalloc(&n1, nl.Type, res)
    473 				Thearch.Gmove(nl, &n1)
    474 			} else {
    475 				if n.Type.Width > int64(Widthptr) || Is64(nl.Type) || Isfloat[nl.Type.Etype] {
    476 					Tempname(&n1, nl.Type)
    477 				} else {
    478 					Regalloc(&n1, nl.Type, res)
    479 				}
    480 				Cgen(nl, &n1)
    481 			}
    482 			if n.Type.Width > int64(Widthptr) || Is64(n.Type) || Isfloat[n.Type.Etype] {
    483 				Tempname(&n2, n.Type)
    484 			} else {
    485 				Regalloc(&n2, n.Type, nil)
    486 			}
    487 		} else {
    488 			if n.Type.Width > nl.Type.Width {
    489 				// If loading from memory, do conversion during load,
    490 				// so as to avoid use of 8-bit register in, say, int(*byteptr).
    491 				switch nl.Op {
    492 				case ODOT, ODOTPTR, OINDEX, OIND, ONAME:
    493 					Igen(nl, &n1, res)
    494 					Regalloc(&n2, n.Type, res)
    495 					Thearch.Gmove(&n1, &n2)
    496 					Thearch.Gmove(&n2, res)
    497 					Regfree(&n2)
    498 					Regfree(&n1)
    499 					return
    500 				}
    501 			}
    502 			Regalloc(&n1, nl.Type, res)
    503 			Regalloc(&n2, n.Type, &n1)
    504 			Cgen(nl, &n1)
    505 		}
    506 
    507 		// if we do the conversion n1 -> n2 here
    508 		// reusing the register, then gmove won't
    509 		// have to allocate its own register.
    510 		Thearch.Gmove(&n1, &n2)
    511 		Thearch.Gmove(&n2, res)
    512 		if n2.Op == OREGISTER {
    513 			Regfree(&n2)
    514 		}
    515 		if n1.Op == OREGISTER {
    516 			Regfree(&n1)
    517 		}
    518 
    519 	case ODOT,
    520 		ODOTPTR,
    521 		OINDEX,
    522 		OIND,
    523 		ONAME: // PHEAP or PPARAMREF var
    524 		var n1 Node
    525 		Igen(n, &n1, res)
    526 
    527 		Thearch.Gmove(&n1, res)
    528 		Regfree(&n1)
    529 
    530 		// interface table is first word of interface value
    531 	case OITAB:
    532 		var n1 Node
    533 		Igen(nl, &n1, res)
    534 
    535 		n1.Type = n.Type
    536 		Thearch.Gmove(&n1, res)
    537 		Regfree(&n1)
    538 
    539 	case OSPTR:
    540 		// pointer is the first word of string or slice.
    541 		if Isconst(nl, CTSTR) {
    542 			var n1 Node
    543 			Regalloc(&n1, Types[Tptr], res)
    544 			p1 := Thearch.Gins(Thearch.Optoas(OAS, n1.Type), nil, &n1)
    545 			Datastring(nl.Val().U.(string), &p1.From)
    546 			p1.From.Type = obj.TYPE_ADDR
    547 			Thearch.Gmove(&n1, res)
    548 			Regfree(&n1)
    549 			break
    550 		}
    551 
    552 		var n1 Node
    553 		Igen(nl, &n1, res)
    554 		n1.Type = n.Type
    555 		Thearch.Gmove(&n1, res)
    556 		Regfree(&n1)
    557 
    558 	case OLEN:
    559 		if Istype(nl.Type, TMAP) || Istype(nl.Type, TCHAN) {
    560 			// map and chan have len in the first int-sized word.
    561 			// a zero pointer means zero length
    562 			var n1 Node
    563 			Regalloc(&n1, Types[Tptr], res)
    564 
    565 			Cgen(nl, &n1)
    566 
    567 			var n2 Node
    568 			Nodconst(&n2, Types[Tptr], 0)
    569 			p1 := Thearch.Ginscmp(OEQ, Types[Tptr], &n1, &n2, 0)
    570 
    571 			n2 = n1
    572 			n2.Op = OINDREG
    573 			n2.Type = Types[Simtype[TINT]]
    574 			Thearch.Gmove(&n2, &n1)
    575 
    576 			Patch(p1, Pc)
    577 
    578 			Thearch.Gmove(&n1, res)
    579 			Regfree(&n1)
    580 			break
    581 		}
    582 
    583 		if Istype(nl.Type, TSTRING) || Isslice(nl.Type) {
    584 			// both slice and string have len one pointer into the struct.
    585 			// a zero pointer means zero length
    586 			var n1 Node
    587 			Igen(nl, &n1, res)
    588 
    589 			n1.Type = Types[Simtype[TUINT]]
    590 			n1.Xoffset += int64(Array_nel)
    591 			Thearch.Gmove(&n1, res)
    592 			Regfree(&n1)
    593 			break
    594 		}
    595 
    596 		Fatal("cgen: OLEN: unknown type %v", Tconv(nl.Type, obj.FmtLong))
    597 
    598 	case OCAP:
    599 		if Istype(nl.Type, TCHAN) {
    600 			// chan has cap in the second int-sized word.
    601 			// a zero pointer means zero length
    602 			var n1 Node
    603 			Regalloc(&n1, Types[Tptr], res)
    604 
    605 			Cgen(nl, &n1)
    606 
    607 			var n2 Node
    608 			Nodconst(&n2, Types[Tptr], 0)
    609 			p1 := Thearch.Ginscmp(OEQ, Types[Tptr], &n1, &n2, 0)
    610 
    611 			n2 = n1
    612 			n2.Op = OINDREG
    613 			n2.Xoffset = int64(Widthint)
    614 			n2.Type = Types[Simtype[TINT]]
    615 			Thearch.Gmove(&n2, &n1)
    616 
    617 			Patch(p1, Pc)
    618 
    619 			Thearch.Gmove(&n1, res)
    620 			Regfree(&n1)
    621 			break
    622 		}
    623 
    624 		if Isslice(nl.Type) {
    625 			var n1 Node
    626 			Igen(nl, &n1, res)
    627 			n1.Type = Types[Simtype[TUINT]]
    628 			n1.Xoffset += int64(Array_cap)
    629 			Thearch.Gmove(&n1, res)
    630 			Regfree(&n1)
    631 			break
    632 		}
    633 
    634 		Fatal("cgen: OCAP: unknown type %v", Tconv(nl.Type, obj.FmtLong))
    635 
    636 	case OADDR:
    637 		if n.Bounded { // let race detector avoid nil checks
    638 			Disable_checknil++
    639 		}
    640 		Agen(nl, res)
    641 		if n.Bounded {
    642 			Disable_checknil--
    643 		}
    644 
    645 	case OCALLMETH:
    646 		cgen_callmeth(n, 0)
    647 		cgen_callret(n, res)
    648 
    649 	case OCALLINTER:
    650 		cgen_callinter(n, res, 0)
    651 		cgen_callret(n, res)
    652 
    653 	case OCALLFUNC:
    654 		cgen_call(n, 0)
    655 		cgen_callret(n, res)
    656 
    657 	case OMOD, ODIV:
    658 		if Isfloat[n.Type.Etype] || Thearch.Dodiv == nil {
    659 			a = Thearch.Optoas(int(n.Op), nl.Type)
    660 			goto abop
    661 		}
    662 
    663 		if nl.Ullman >= nr.Ullman {
    664 			var n1 Node
    665 			Regalloc(&n1, nl.Type, res)
    666 			Cgen(nl, &n1)
    667 			cgen_div(int(n.Op), &n1, nr, res)
    668 			Regfree(&n1)
    669 		} else {
    670 			var n2 Node
    671 			if !Smallintconst(nr) {
    672 				Regalloc(&n2, nr.Type, res)
    673 				Cgen(nr, &n2)
    674 			} else {
    675 				n2 = *nr
    676 			}
    677 
    678 			cgen_div(int(n.Op), nl, &n2, res)
    679 			if n2.Op != OLITERAL {
    680 				Regfree(&n2)
    681 			}
    682 		}
    683 
    684 	case OLSH, ORSH, OLROT:
    685 		Thearch.Cgen_shift(int(n.Op), n.Bounded, nl, nr, res)
    686 	}
    687 
    688 	return
    689 
    690 	/*
    691 	 * put simplest on right - we'll generate into left
    692 	 * and then adjust it using the computation of right.
    693 	 * constants and variables have the same ullman
    694 	 * count, so look for constants specially.
    695 	 *
    696 	 * an integer constant we can use as an immediate
    697 	 * is simpler than a variable - we can use the immediate
    698 	 * in the adjustment instruction directly - so it goes
    699 	 * on the right.
    700 	 *
    701 	 * other constants, like big integers or floating point
    702 	 * constants, require a mov into a register, so those
    703 	 * might as well go on the left, so we can reuse that
    704 	 * register for the computation.
    705 	 */
    706 sbop: // symmetric binary
    707 	if nl.Ullman < nr.Ullman || (nl.Ullman == nr.Ullman && (Smallintconst(nl) || (nr.Op == OLITERAL && !Smallintconst(nr)))) {
    708 		r := nl
    709 		nl = nr
    710 		nr = r
    711 	}
    712 
    713 abop: // asymmetric binary
    714 	var n1 Node
    715 	var n2 Node
    716 	if Ctxt.Arch.Thechar == '8' {
    717 		// no registers, sigh
    718 		if Smallintconst(nr) {
    719 			var n1 Node
    720 			Mgen(nl, &n1, res)
    721 			var n2 Node
    722 			Regalloc(&n2, nl.Type, &n1)
    723 			Thearch.Gmove(&n1, &n2)
    724 			Thearch.Gins(a, nr, &n2)
    725 			Thearch.Gmove(&n2, res)
    726 			Regfree(&n2)
    727 			Mfree(&n1)
    728 		} else if nl.Ullman >= nr.Ullman {
    729 			var nt Node
    730 			Tempname(&nt, nl.Type)
    731 			Cgen(nl, &nt)
    732 			var n2 Node
    733 			Mgen(nr, &n2, nil)
    734 			var n1 Node
    735 			Regalloc(&n1, nl.Type, res)
    736 			Thearch.Gmove(&nt, &n1)
    737 			Thearch.Gins(a, &n2, &n1)
    738 			Thearch.Gmove(&n1, res)
    739 			Regfree(&n1)
    740 			Mfree(&n2)
    741 		} else {
    742 			var n2 Node
    743 			Regalloc(&n2, nr.Type, res)
    744 			Cgen(nr, &n2)
    745 			var n1 Node
    746 			Regalloc(&n1, nl.Type, nil)
    747 			Cgen(nl, &n1)
    748 			Thearch.Gins(a, &n2, &n1)
    749 			Regfree(&n2)
    750 			Thearch.Gmove(&n1, res)
    751 			Regfree(&n1)
    752 		}
    753 		return
    754 	}
    755 
    756 	if nl.Ullman >= nr.Ullman {
    757 		Regalloc(&n1, nl.Type, res)
    758 		Cgen(nl, &n1)
    759 
    760 		if Smallintconst(nr) && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
    761 			n2 = *nr
    762 		} else {
    763 			Regalloc(&n2, nr.Type, nil)
    764 			Cgen(nr, &n2)
    765 		}
    766 	} else {
    767 		if Smallintconst(nr) && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
    768 			n2 = *nr
    769 		} else {
    770 			Regalloc(&n2, nr.Type, res)
    771 			Cgen(nr, &n2)
    772 		}
    773 
    774 		Regalloc(&n1, nl.Type, nil)
    775 		Cgen(nl, &n1)
    776 	}
    777 
    778 	Thearch.Gins(a, &n2, &n1)
    779 	if n2.Op != OLITERAL {
    780 		Regfree(&n2)
    781 	}
    782 	cgen_norm(n, &n1, res)
    783 }
    784 
    785 var sys_wbptr *Node
    786 
    787 func cgen_wbptr(n, res *Node) {
    788 	if Curfn != nil && Curfn.Func.Nowritebarrier {
    789 		Yyerror("write barrier prohibited")
    790 	}
    791 	if Debug_wb > 0 {
    792 		Warn("write barrier")
    793 	}
    794 
    795 	var dst, src Node
    796 	Igen(res, &dst, nil)
    797 	if n.Op == OREGISTER {
    798 		src = *n
    799 		Regrealloc(&src)
    800 	} else {
    801 		Cgenr(n, &src, nil)
    802 	}
    803 
    804 	wbEnabled := syslook("writeBarrierEnabled", 0)
    805 	pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
    806 	Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
    807 	pjmp := Gbranch(obj.AJMP, nil, 0)
    808 	Patch(pbr, Pc)
    809 	var adst Node
    810 	Agenr(&dst, &adst, &dst)
    811 	p := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &adst, nil)
    812 	a := &p.To
    813 	a.Type = obj.TYPE_MEM
    814 	a.Reg = int16(Thearch.REGSP)
    815 	a.Offset = 0
    816 	if HasLinkRegister() {
    817 		a.Offset += int64(Widthptr)
    818 	}
    819 	p2 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, nil)
    820 	p2.To = p.To
    821 	p2.To.Offset += int64(Widthptr)
    822 	Regfree(&adst)
    823 	if sys_wbptr == nil {
    824 		sys_wbptr = writebarrierfn("writebarrierptr", Types[Tptr], Types[Tptr])
    825 	}
    826 	Ginscall(sys_wbptr, 0)
    827 	Patch(pjmp, Pc)
    828 
    829 	Regfree(&dst)
    830 	Regfree(&src)
    831 }
    832 
    833 func cgen_wbfat(n, res *Node) {
    834 	if Curfn != nil && Curfn.Func.Nowritebarrier {
    835 		Yyerror("write barrier prohibited")
    836 	}
    837 	if Debug_wb > 0 {
    838 		Warn("write barrier")
    839 	}
    840 	needType := true
    841 	funcName := "typedmemmove"
    842 	var dst, src Node
    843 	if n.Ullman >= res.Ullman {
    844 		Agenr(n, &src, nil)
    845 		Agenr(res, &dst, nil)
    846 	} else {
    847 		Agenr(res, &dst, nil)
    848 		Agenr(n, &src, nil)
    849 	}
    850 	p := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &dst, nil)
    851 	a := &p.To
    852 	a.Type = obj.TYPE_MEM
    853 	a.Reg = int16(Thearch.REGSP)
    854 	a.Offset = 0
    855 	if HasLinkRegister() {
    856 		a.Offset += int64(Widthptr)
    857 	}
    858 	if needType {
    859 		a.Offset += int64(Widthptr)
    860 	}
    861 	p2 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, nil)
    862 	p2.To = p.To
    863 	p2.To.Offset += int64(Widthptr)
    864 	Regfree(&dst)
    865 	if needType {
    866 		src.Type = Types[Tptr]
    867 		Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), typename(n.Type), &src)
    868 		p3 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, nil)
    869 		p3.To = p2.To
    870 		p3.To.Offset -= 2 * int64(Widthptr)
    871 	}
    872 	Regfree(&src)
    873 	Ginscall(writebarrierfn(funcName, Types[Tptr], Types[Tptr]), 0)
    874 }
    875 
    876 // cgen_norm moves n1 to res, truncating to expected type if necessary.
    877 // n1 is a register, and cgen_norm frees it.
    878 func cgen_norm(n, n1, res *Node) {
    879 	switch Ctxt.Arch.Thechar {
    880 	case '6', '8':
    881 		// We use sized math, so the result is already truncated.
    882 	default:
    883 		switch n.Op {
    884 		case OADD, OSUB, OMUL, ODIV, OCOM, OMINUS:
    885 			// TODO(rsc): What about left shift?
    886 			Thearch.Gins(Thearch.Optoas(OAS, n.Type), n1, n1)
    887 		}
    888 	}
    889 
    890 	Thearch.Gmove(n1, res)
    891 	Regfree(n1)
    892 }
    893 
    894 func Mgen(n *Node, n1 *Node, rg *Node) {
    895 	n1.Op = OEMPTY
    896 
    897 	if n.Addable {
    898 		*n1 = *n
    899 		if n1.Op == OREGISTER || n1.Op == OINDREG {
    900 			reg[n.Reg-int16(Thearch.REGMIN)]++
    901 		}
    902 		return
    903 	}
    904 
    905 	Tempname(n1, n.Type)
    906 	Cgen(n, n1)
    907 	if n.Type.Width <= int64(Widthptr) || Isfloat[n.Type.Etype] {
    908 		n2 := *n1
    909 		Regalloc(n1, n.Type, rg)
    910 		Thearch.Gmove(&n2, n1)
    911 	}
    912 }
    913 
    914 func Mfree(n *Node) {
    915 	if n.Op == OREGISTER {
    916 		Regfree(n)
    917 	}
    918 }
    919 
    920 /*
    921  * allocate a register (reusing res if possible) and generate
    922  *  a = n
    923  * The caller must call Regfree(a).
    924  */
    925 func Cgenr(n *Node, a *Node, res *Node) {
    926 	if Debug['g'] != 0 {
    927 		Dump("cgenr-n", n)
    928 	}
    929 
    930 	if Isfat(n.Type) {
    931 		Fatal("cgenr on fat node")
    932 	}
    933 
    934 	if n.Addable {
    935 		Regalloc(a, n.Type, res)
    936 		Thearch.Gmove(n, a)
    937 		return
    938 	}
    939 
    940 	switch n.Op {
    941 	case ONAME,
    942 		ODOT,
    943 		ODOTPTR,
    944 		OINDEX,
    945 		OCALLFUNC,
    946 		OCALLMETH,
    947 		OCALLINTER:
    948 		var n1 Node
    949 		Igen(n, &n1, res)
    950 		Regalloc(a, Types[Tptr], &n1)
    951 		Thearch.Gmove(&n1, a)
    952 		Regfree(&n1)
    953 
    954 	default:
    955 		Regalloc(a, n.Type, res)
    956 		Cgen(n, a)
    957 	}
    958 }
    959 
    960 /*
    961  * allocate a register (reusing res if possible) and generate
    962  * a = &n
    963  * The caller must call Regfree(a).
    964  * The generated code checks that the result is not nil.
    965  */
    966 func Agenr(n *Node, a *Node, res *Node) {
    967 	if Debug['g'] != 0 {
    968 		Dump("\nagenr-n", n)
    969 	}
    970 
    971 	nl := n.Left
    972 	nr := n.Right
    973 
    974 	switch n.Op {
    975 	case ODOT, ODOTPTR, OCALLFUNC, OCALLMETH, OCALLINTER:
    976 		var n1 Node
    977 		Igen(n, &n1, res)
    978 		Regalloc(a, Types[Tptr], &n1)
    979 		Agen(&n1, a)
    980 		Regfree(&n1)
    981 
    982 	case OIND:
    983 		Cgenr(n.Left, a, res)
    984 		Cgen_checknil(a)
    985 
    986 	case OINDEX:
    987 		if Ctxt.Arch.Thechar == '5' {
    988 			var p2 *obj.Prog // to be patched to panicindex.
    989 			w := uint32(n.Type.Width)
    990 			bounded := Debug['B'] != 0 || n.Bounded
    991 			var n1 Node
    992 			var n3 Node
    993 			if nr.Addable {
    994 				var tmp Node
    995 				if !Isconst(nr, CTINT) {
    996 					Tempname(&tmp, Types[TINT32])
    997 				}
    998 				if !Isconst(nl, CTSTR) {
    999 					Agenr(nl, &n3, res)
   1000 				}
   1001 				if !Isconst(nr, CTINT) {
   1002 					p2 = Thearch.Cgenindex(nr, &tmp, bounded)
   1003 					Regalloc(&n1, tmp.Type, nil)
   1004 					Thearch.Gmove(&tmp, &n1)
   1005 				}
   1006 			} else if nl.Addable {
   1007 				if !Isconst(nr, CTINT) {
   1008 					var tmp Node
   1009 					Tempname(&tmp, Types[TINT32])
   1010 					p2 = Thearch.Cgenindex(nr, &tmp, bounded)
   1011 					Regalloc(&n1, tmp.Type, nil)
   1012 					Thearch.Gmove(&tmp, &n1)
   1013 				}
   1014 
   1015 				if !Isconst(nl, CTSTR) {
   1016 					Agenr(nl, &n3, res)
   1017 				}
   1018 			} else {
   1019 				var tmp Node
   1020 				Tempname(&tmp, Types[TINT32])
   1021 				p2 = Thearch.Cgenindex(nr, &tmp, bounded)
   1022 				nr = &tmp
   1023 				if !Isconst(nl, CTSTR) {
   1024 					Agenr(nl, &n3, res)
   1025 				}
   1026 				Regalloc(&n1, tmp.Type, nil)
   1027 				Thearch.Gins(Thearch.Optoas(OAS, tmp.Type), &tmp, &n1)
   1028 			}
   1029 
   1030 			// &a is in &n3 (allocated in res)
   1031 			// i is in &n1 (if not constant)
   1032 			// w is width
   1033 
   1034 			// constant index
   1035 			if Isconst(nr, CTINT) {
   1036 				if Isconst(nl, CTSTR) {
   1037 					Fatal("constant string constant index")
   1038 				}
   1039 				v := uint64(Mpgetfix(nr.Val().U.(*Mpint)))
   1040 				var n2 Node
   1041 				if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1042 					if Debug['B'] == 0 && !n.Bounded {
   1043 						n1 = n3
   1044 						n1.Op = OINDREG
   1045 						n1.Type = Types[Tptr]
   1046 						n1.Xoffset = int64(Array_nel)
   1047 						Nodconst(&n2, Types[TUINT32], int64(v))
   1048 						p1 := Thearch.Ginscmp(OGT, Types[TUINT32], &n1, &n2, +1)
   1049 						Ginscall(Panicindex, -1)
   1050 						Patch(p1, Pc)
   1051 					}
   1052 
   1053 					n1 = n3
   1054 					n1.Op = OINDREG
   1055 					n1.Type = Types[Tptr]
   1056 					n1.Xoffset = int64(Array_array)
   1057 					Thearch.Gmove(&n1, &n3)
   1058 				}
   1059 
   1060 				Nodconst(&n2, Types[Tptr], int64(v*uint64(w)))
   1061 				Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1062 				*a = n3
   1063 				break
   1064 			}
   1065 
   1066 			var n2 Node
   1067 			Regalloc(&n2, Types[TINT32], &n1) // i
   1068 			Thearch.Gmove(&n1, &n2)
   1069 			Regfree(&n1)
   1070 
   1071 			var n4 Node
   1072 			if Debug['B'] == 0 && !n.Bounded {
   1073 				// check bounds
   1074 				if Isconst(nl, CTSTR) {
   1075 					Nodconst(&n4, Types[TUINT32], int64(len(nl.Val().U.(string))))
   1076 				} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1077 					n1 = n3
   1078 					n1.Op = OINDREG
   1079 					n1.Type = Types[Tptr]
   1080 					n1.Xoffset = int64(Array_nel)
   1081 					Regalloc(&n4, Types[TUINT32], nil)
   1082 					Thearch.Gmove(&n1, &n4)
   1083 				} else {
   1084 					Nodconst(&n4, Types[TUINT32], nl.Type.Bound)
   1085 				}
   1086 				p1 := Thearch.Ginscmp(OLT, Types[TUINT32], &n2, &n4, +1)
   1087 				if n4.Op == OREGISTER {
   1088 					Regfree(&n4)
   1089 				}
   1090 				if p2 != nil {
   1091 					Patch(p2, Pc)
   1092 				}
   1093 				Ginscall(Panicindex, -1)
   1094 				Patch(p1, Pc)
   1095 			}
   1096 
   1097 			if Isconst(nl, CTSTR) {
   1098 				Regalloc(&n3, Types[Tptr], res)
   1099 				p1 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &n3)
   1100 				Datastring(nl.Val().U.(string), &p1.From)
   1101 				p1.From.Type = obj.TYPE_ADDR
   1102 			} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1103 				n1 = n3
   1104 				n1.Op = OINDREG
   1105 				n1.Type = Types[Tptr]
   1106 				n1.Xoffset = int64(Array_array)
   1107 				Thearch.Gmove(&n1, &n3)
   1108 			}
   1109 
   1110 			if w == 0 {
   1111 				// nothing to do
   1112 			} else if Thearch.AddIndex != nil && Thearch.AddIndex(&n2, int64(w), &n3) {
   1113 				// done by back end
   1114 			} else if w == 1 {
   1115 				Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1116 			} else {
   1117 				if w&(w-1) == 0 {
   1118 					// Power of 2.  Use shift.
   1119 					Thearch.Ginscon(Thearch.Optoas(OLSH, Types[TUINT32]), int64(log2(uint64(w))), &n2)
   1120 				} else {
   1121 					// Not a power of 2.  Use multiply.
   1122 					Regalloc(&n4, Types[TUINT32], nil)
   1123 					Nodconst(&n1, Types[TUINT32], int64(w))
   1124 					Thearch.Gmove(&n1, &n4)
   1125 					Thearch.Gins(Thearch.Optoas(OMUL, Types[TUINT32]), &n4, &n2)
   1126 					Regfree(&n4)
   1127 				}
   1128 				Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1129 			}
   1130 			*a = n3
   1131 			Regfree(&n2)
   1132 			break
   1133 		}
   1134 		if Ctxt.Arch.Thechar == '8' {
   1135 			var p2 *obj.Prog // to be patched to panicindex.
   1136 			w := uint32(n.Type.Width)
   1137 			bounded := Debug['B'] != 0 || n.Bounded
   1138 			var n3 Node
   1139 			var tmp Node
   1140 			var n1 Node
   1141 			if nr.Addable {
   1142 				// Generate &nl first, and move nr into register.
   1143 				if !Isconst(nl, CTSTR) {
   1144 					Igen(nl, &n3, res)
   1145 				}
   1146 				if !Isconst(nr, CTINT) {
   1147 					p2 = Thearch.Igenindex(nr, &tmp, bounded)
   1148 					Regalloc(&n1, tmp.Type, nil)
   1149 					Thearch.Gmove(&tmp, &n1)
   1150 				}
   1151 			} else if nl.Addable {
   1152 				// Generate nr first, and move &nl into register.
   1153 				if !Isconst(nr, CTINT) {
   1154 					p2 = Thearch.Igenindex(nr, &tmp, bounded)
   1155 					Regalloc(&n1, tmp.Type, nil)
   1156 					Thearch.Gmove(&tmp, &n1)
   1157 				}
   1158 
   1159 				if !Isconst(nl, CTSTR) {
   1160 					Igen(nl, &n3, res)
   1161 				}
   1162 			} else {
   1163 				p2 = Thearch.Igenindex(nr, &tmp, bounded)
   1164 				nr = &tmp
   1165 				if !Isconst(nl, CTSTR) {
   1166 					Igen(nl, &n3, res)
   1167 				}
   1168 				Regalloc(&n1, tmp.Type, nil)
   1169 				Thearch.Gins(Thearch.Optoas(OAS, tmp.Type), &tmp, &n1)
   1170 			}
   1171 
   1172 			// For fixed array we really want the pointer in n3.
   1173 			var n2 Node
   1174 			if Isfixedarray(nl.Type) {
   1175 				Regalloc(&n2, Types[Tptr], &n3)
   1176 				Agen(&n3, &n2)
   1177 				Regfree(&n3)
   1178 				n3 = n2
   1179 			}
   1180 
   1181 			// &a[0] is in n3 (allocated in res)
   1182 			// i is in n1 (if not constant)
   1183 			// len(a) is in nlen (if needed)
   1184 			// w is width
   1185 
   1186 			// constant index
   1187 			if Isconst(nr, CTINT) {
   1188 				if Isconst(nl, CTSTR) {
   1189 					Fatal("constant string constant index") // front end should handle
   1190 				}
   1191 				v := uint64(Mpgetfix(nr.Val().U.(*Mpint)))
   1192 				if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1193 					if Debug['B'] == 0 && !n.Bounded {
   1194 						nlen := n3
   1195 						nlen.Type = Types[TUINT32]
   1196 						nlen.Xoffset += int64(Array_nel)
   1197 						Nodconst(&n2, Types[TUINT32], int64(v))
   1198 						p1 := Thearch.Ginscmp(OGT, Types[TUINT32], &nlen, &n2, +1)
   1199 						Ginscall(Panicindex, -1)
   1200 						Patch(p1, Pc)
   1201 					}
   1202 				}
   1203 
   1204 				// Load base pointer in n2 = n3.
   1205 				Regalloc(&n2, Types[Tptr], &n3)
   1206 
   1207 				n3.Type = Types[Tptr]
   1208 				n3.Xoffset += int64(Array_array)
   1209 				Thearch.Gmove(&n3, &n2)
   1210 				Regfree(&n3)
   1211 				if v*uint64(w) != 0 {
   1212 					Nodconst(&n1, Types[Tptr], int64(v*uint64(w)))
   1213 					Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n1, &n2)
   1214 				}
   1215 				*a = n2
   1216 				break
   1217 			}
   1218 
   1219 			// i is in register n1, extend to 32 bits.
   1220 			t := Types[TUINT32]
   1221 
   1222 			if Issigned[n1.Type.Etype] {
   1223 				t = Types[TINT32]
   1224 			}
   1225 
   1226 			Regalloc(&n2, t, &n1) // i
   1227 			Thearch.Gmove(&n1, &n2)
   1228 			Regfree(&n1)
   1229 
   1230 			if Debug['B'] == 0 && !n.Bounded {
   1231 				// check bounds
   1232 				t := Types[TUINT32]
   1233 
   1234 				var nlen Node
   1235 				if Isconst(nl, CTSTR) {
   1236 					Nodconst(&nlen, t, int64(len(nl.Val().U.(string))))
   1237 				} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1238 					nlen = n3
   1239 					nlen.Type = t
   1240 					nlen.Xoffset += int64(Array_nel)
   1241 				} else {
   1242 					Nodconst(&nlen, t, nl.Type.Bound)
   1243 				}
   1244 
   1245 				p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
   1246 				if p2 != nil {
   1247 					Patch(p2, Pc)
   1248 				}
   1249 				Ginscall(Panicindex, -1)
   1250 				Patch(p1, Pc)
   1251 			}
   1252 
   1253 			if Isconst(nl, CTSTR) {
   1254 				Regalloc(&n3, Types[Tptr], res)
   1255 				p1 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &n3)
   1256 				Datastring(nl.Val().U.(string), &p1.From)
   1257 				p1.From.Type = obj.TYPE_ADDR
   1258 				Thearch.Gins(Thearch.Optoas(OADD, n3.Type), &n2, &n3)
   1259 				goto indexdone1
   1260 			}
   1261 
   1262 			// Load base pointer in n3.
   1263 			Regalloc(&tmp, Types[Tptr], &n3)
   1264 
   1265 			if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1266 				n3.Type = Types[Tptr]
   1267 				n3.Xoffset += int64(Array_array)
   1268 				Thearch.Gmove(&n3, &tmp)
   1269 			}
   1270 
   1271 			Regfree(&n3)
   1272 			n3 = tmp
   1273 
   1274 			if w == 0 {
   1275 				// nothing to do
   1276 			} else if Thearch.AddIndex != nil && Thearch.AddIndex(&n2, int64(w), &n3) {
   1277 				// done by back end
   1278 			} else if w == 1 {
   1279 				Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1280 			} else {
   1281 				if w&(w-1) == 0 {
   1282 					// Power of 2.  Use shift.
   1283 					Thearch.Ginscon(Thearch.Optoas(OLSH, Types[TUINT32]), int64(log2(uint64(w))), &n2)
   1284 				} else {
   1285 					// Not a power of 2.  Use multiply.
   1286 					Thearch.Ginscon(Thearch.Optoas(OMUL, Types[TUINT32]), int64(w), &n2)
   1287 				}
   1288 				Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1289 			}
   1290 
   1291 		indexdone1:
   1292 			*a = n3
   1293 			Regfree(&n2)
   1294 			break
   1295 		}
   1296 
   1297 		freelen := 0
   1298 		w := uint64(n.Type.Width)
   1299 
   1300 		// Generate the non-addressable child first.
   1301 		var n3 Node
   1302 		var nlen Node
   1303 		var tmp Node
   1304 		var n1 Node
   1305 		if nr.Addable {
   1306 			goto irad
   1307 		}
   1308 		if nl.Addable {
   1309 			Cgenr(nr, &n1, nil)
   1310 			if !Isconst(nl, CTSTR) {
   1311 				if Isfixedarray(nl.Type) {
   1312 					Agenr(nl, &n3, res)
   1313 				} else {
   1314 					Igen(nl, &nlen, res)
   1315 					freelen = 1
   1316 					nlen.Type = Types[Tptr]
   1317 					nlen.Xoffset += int64(Array_array)
   1318 					Regalloc(&n3, Types[Tptr], res)
   1319 					Thearch.Gmove(&nlen, &n3)
   1320 					nlen.Type = Types[Simtype[TUINT]]
   1321 					nlen.Xoffset += int64(Array_nel) - int64(Array_array)
   1322 				}
   1323 			}
   1324 
   1325 			goto index
   1326 		}
   1327 
   1328 		Tempname(&tmp, nr.Type)
   1329 		Cgen(nr, &tmp)
   1330 		nr = &tmp
   1331 
   1332 	irad:
   1333 		if !Isconst(nl, CTSTR) {
   1334 			if Isfixedarray(nl.Type) {
   1335 				Agenr(nl, &n3, res)
   1336 			} else {
   1337 				if !nl.Addable {
   1338 					if res != nil && res.Op == OREGISTER { // give up res, which we don't need yet.
   1339 						Regfree(res)
   1340 					}
   1341 
   1342 					// igen will need an addressable node.
   1343 					var tmp2 Node
   1344 					Tempname(&tmp2, nl.Type)
   1345 					Cgen(nl, &tmp2)
   1346 					nl = &tmp2
   1347 
   1348 					if res != nil && res.Op == OREGISTER { // reacquire res
   1349 						Regrealloc(res)
   1350 					}
   1351 				}
   1352 
   1353 				Igen(nl, &nlen, res)
   1354 				freelen = 1
   1355 				nlen.Type = Types[Tptr]
   1356 				nlen.Xoffset += int64(Array_array)
   1357 				Regalloc(&n3, Types[Tptr], res)
   1358 				Thearch.Gmove(&nlen, &n3)
   1359 				nlen.Type = Types[Simtype[TUINT]]
   1360 				nlen.Xoffset += int64(Array_nel) - int64(Array_array)
   1361 			}
   1362 		}
   1363 
   1364 		if !Isconst(nr, CTINT) {
   1365 			Cgenr(nr, &n1, nil)
   1366 		}
   1367 
   1368 		goto index
   1369 
   1370 		// &a is in &n3 (allocated in res)
   1371 		// i is in &n1 (if not constant)
   1372 		// len(a) is in nlen (if needed)
   1373 		// w is width
   1374 
   1375 		// constant index
   1376 	index:
   1377 		if Isconst(nr, CTINT) {
   1378 			if Isconst(nl, CTSTR) {
   1379 				Fatal("constant string constant index") // front end should handle
   1380 			}
   1381 			v := uint64(Mpgetfix(nr.Val().U.(*Mpint)))
   1382 			if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1383 				if Debug['B'] == 0 && !n.Bounded {
   1384 					p1 := Thearch.Ginscmp(OGT, Types[Simtype[TUINT]], &nlen, Nodintconst(int64(v)), +1)
   1385 					Ginscall(Panicindex, -1)
   1386 					Patch(p1, Pc)
   1387 				}
   1388 
   1389 				Regfree(&nlen)
   1390 			}
   1391 
   1392 			if v*w != 0 {
   1393 				Thearch.Ginscon(Thearch.Optoas(OADD, Types[Tptr]), int64(v*w), &n3)
   1394 			}
   1395 			*a = n3
   1396 			break
   1397 		}
   1398 
   1399 		// type of the index
   1400 		t := Types[TUINT64]
   1401 
   1402 		if Issigned[n1.Type.Etype] {
   1403 			t = Types[TINT64]
   1404 		}
   1405 
   1406 		var n2 Node
   1407 		Regalloc(&n2, t, &n1) // i
   1408 		Thearch.Gmove(&n1, &n2)
   1409 		Regfree(&n1)
   1410 
   1411 		if Debug['B'] == 0 && !n.Bounded {
   1412 			// check bounds
   1413 			t = Types[Simtype[TUINT]]
   1414 
   1415 			if Is64(nr.Type) {
   1416 				t = Types[TUINT64]
   1417 			}
   1418 			if Isconst(nl, CTSTR) {
   1419 				Nodconst(&nlen, t, int64(len(nl.Val().U.(string))))
   1420 			} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
   1421 				// nlen already initialized
   1422 			} else {
   1423 				Nodconst(&nlen, t, nl.Type.Bound)
   1424 			}
   1425 
   1426 			p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
   1427 			Ginscall(Panicindex, -1)
   1428 			Patch(p1, Pc)
   1429 		}
   1430 
   1431 		if Isconst(nl, CTSTR) {
   1432 			Regalloc(&n3, Types[Tptr], res)
   1433 			p1 := Thearch.Gins(Thearch.Optoas(OAS, n3.Type), nil, &n3) // XXX was LEAQ!
   1434 			Datastring(nl.Val().U.(string), &p1.From)
   1435 			p1.From.Type = obj.TYPE_ADDR
   1436 			Thearch.Gins(Thearch.Optoas(OADD, n3.Type), &n2, &n3)
   1437 			goto indexdone
   1438 		}
   1439 
   1440 		if w == 0 {
   1441 			// nothing to do
   1442 		} else if Thearch.AddIndex != nil && Thearch.AddIndex(&n2, int64(w), &n3) {
   1443 			// done by back end
   1444 		} else if w == 1 {
   1445 			Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1446 		} else {
   1447 			if w&(w-1) == 0 {
   1448 				// Power of 2.  Use shift.
   1449 				Thearch.Ginscon(Thearch.Optoas(OLSH, t), int64(log2(w)), &n2)
   1450 			} else {
   1451 				// Not a power of 2.  Use multiply.
   1452 				Thearch.Ginscon(Thearch.Optoas(OMUL, t), int64(w), &n2)
   1453 			}
   1454 			Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
   1455 		}
   1456 
   1457 	indexdone:
   1458 		*a = n3
   1459 		Regfree(&n2)
   1460 		if freelen != 0 {
   1461 			Regfree(&nlen)
   1462 		}
   1463 
   1464 	default:
   1465 		Regalloc(a, Types[Tptr], res)
   1466 		Agen(n, a)
   1467 	}
   1468 }
   1469 
   1470 // log2 returns the logarithm base 2 of n.  n must be a power of 2.
   1471 func log2(n uint64) int {
   1472 	x := 0
   1473 	for n>>uint(x) != 1 {
   1474 		x++
   1475 	}
   1476 	return x
   1477 }
   1478 
   1479 /*
   1480  * generate:
   1481  *	res = &n;
   1482  * The generated code checks that the result is not nil.
   1483  */
   1484 func Agen(n *Node, res *Node) {
   1485 	if Debug['g'] != 0 {
   1486 		Dump("\nagen-res", res)
   1487 		Dump("agen-r", n)
   1488 	}
   1489 
   1490 	if n == nil || n.Type == nil {
   1491 		return
   1492 	}
   1493 
   1494 	for n.Op == OCONVNOP {
   1495 		n = n.Left
   1496 	}
   1497 
   1498 	if Isconst(n, CTNIL) && n.Type.Width > int64(Widthptr) {
   1499 		// Use of a nil interface or nil slice.
   1500 		// Create a temporary we can take the address of and read.
   1501 		// The generated code is just going to panic, so it need not
   1502 		// be terribly efficient. See issue 3670.
   1503 		var n1 Node
   1504 		Tempname(&n1, n.Type)
   1505 
   1506 		Gvardef(&n1)
   1507 		Thearch.Clearfat(&n1)
   1508 		var n2 Node
   1509 		Regalloc(&n2, Types[Tptr], res)
   1510 		var n3 Node
   1511 		n3.Op = OADDR
   1512 		n3.Left = &n1
   1513 		Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &n3, &n2)
   1514 		Thearch.Gmove(&n2, res)
   1515 		Regfree(&n2)
   1516 		return
   1517 	}
   1518 
   1519 	if n.Op == OINDREG && n.Xoffset == 0 {
   1520 		// Generate MOVW R0, R1 instead of MOVW $0(R0), R1.
   1521 		// This allows better move propagation in the back ends
   1522 		// (and maybe it helps the processor).
   1523 		n1 := *n
   1524 		n1.Op = OREGISTER
   1525 		n1.Type = res.Type
   1526 		Thearch.Gmove(&n1, res)
   1527 		return
   1528 	}
   1529 
   1530 	if n.Addable {
   1531 		if n.Op == OREGISTER {
   1532 			Fatal("agen OREGISTER")
   1533 		}
   1534 		var n1 Node
   1535 		n1.Op = OADDR
   1536 		n1.Left = n
   1537 		var n2 Node
   1538 		Regalloc(&n2, Types[Tptr], res)
   1539 		Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &n1, &n2)
   1540 		Thearch.Gmove(&n2, res)
   1541 		Regfree(&n2)
   1542 		return
   1543 	}
   1544 
   1545 	nl := n.Left
   1546 
   1547 	switch n.Op {
   1548 	default:
   1549 		Fatal("agen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
   1550 
   1551 	case OCALLMETH:
   1552 		cgen_callmeth(n, 0)
   1553 		cgen_aret(n, res)
   1554 
   1555 	case OCALLINTER:
   1556 		cgen_callinter(n, res, 0)
   1557 		cgen_aret(n, res)
   1558 
   1559 	case OCALLFUNC:
   1560 		cgen_call(n, 0)
   1561 		cgen_aret(n, res)
   1562 
   1563 	case OEFACE, ODOTTYPE, OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
   1564 		var n1 Node
   1565 		Tempname(&n1, n.Type)
   1566 		Cgen(n, &n1)
   1567 		Agen(&n1, res)
   1568 
   1569 	case OINDEX:
   1570 		var n1 Node
   1571 		Agenr(n, &n1, res)
   1572 		Thearch.Gmove(&n1, res)
   1573 		Regfree(&n1)
   1574 
   1575 	case ONAME:
   1576 		// should only get here with names in this func.
   1577 		if n.Name.Funcdepth > 0 && n.Name.Funcdepth != Funcdepth {
   1578 			Dump("bad agen", n)
   1579 			Fatal("agen: bad ONAME funcdepth %d != %d", n.Name.Funcdepth, Funcdepth)
   1580 		}
   1581 
   1582 		// should only get here for heap vars or paramref
   1583 		if n.Class&PHEAP == 0 && n.Class != PPARAMREF {
   1584 			Dump("bad agen", n)
   1585 			Fatal("agen: bad ONAME class %#x", n.Class)
   1586 		}
   1587 
   1588 		Cgen(n.Name.Heapaddr, res)
   1589 		if n.Xoffset != 0 {
   1590 			addOffset(res, n.Xoffset)
   1591 		}
   1592 
   1593 	case OIND:
   1594 		Cgen(nl, res)
   1595 		Cgen_checknil(res)
   1596 
   1597 	case ODOT:
   1598 		Agen(nl, res)
   1599 		if n.Xoffset != 0 {
   1600 			addOffset(res, n.Xoffset)
   1601 		}
   1602 
   1603 	case ODOTPTR:
   1604 		Cgen(nl, res)
   1605 		Cgen_checknil(res)
   1606 		if n.Xoffset != 0 {
   1607 			addOffset(res, n.Xoffset)
   1608 		}
   1609 	}
   1610 }
   1611 
   1612 func addOffset(res *Node, offset int64) {
   1613 	if Ctxt.Arch.Thechar == '6' || Ctxt.Arch.Thechar == '8' {
   1614 		Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), Nodintconst(offset), res)
   1615 		return
   1616 	}
   1617 
   1618 	var n1, n2 Node
   1619 	Regalloc(&n1, Types[Tptr], nil)
   1620 	Thearch.Gmove(res, &n1)
   1621 	Regalloc(&n2, Types[Tptr], nil)
   1622 	Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), Nodintconst(offset), &n2)
   1623 	Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n1)
   1624 	Thearch.Gmove(&n1, res)
   1625 	Regfree(&n1)
   1626 	Regfree(&n2)
   1627 }
   1628 
   1629 // Igen computes the address &n, stores it in a register r,
   1630 // and rewrites a to refer to *r. The chosen r may be the
   1631 // stack pointer, it may be borrowed from res, or it may
   1632 // be a newly allocated register. The caller must call Regfree(a)
   1633 // to free r when the address is no longer needed.
   1634 // The generated code ensures that &n is not nil.
   1635 func Igen(n *Node, a *Node, res *Node) {
   1636 	if Debug['g'] != 0 {
   1637 		Dump("\nigen-n", n)
   1638 	}
   1639 
   1640 	switch n.Op {
   1641 	case ONAME:
   1642 		if (n.Class&PHEAP != 0) || n.Class == PPARAMREF {
   1643 			break
   1644 		}
   1645 		*a = *n
   1646 		return
   1647 
   1648 	case OINDREG:
   1649 		// Increase the refcount of the register so that igen's caller
   1650 		// has to call Regfree.
   1651 		if n.Reg != int16(Thearch.REGSP) {
   1652 			reg[n.Reg-int16(Thearch.REGMIN)]++
   1653 		}
   1654 		*a = *n
   1655 		return
   1656 
   1657 	case ODOT:
   1658 		Igen(n.Left, a, res)
   1659 		a.Xoffset += n.Xoffset
   1660 		a.Type = n.Type
   1661 		Fixlargeoffset(a)
   1662 		return
   1663 
   1664 	case ODOTPTR:
   1665 		Cgenr(n.Left, a, res)
   1666 		Cgen_checknil(a)
   1667 		a.Op = OINDREG
   1668 		a.Xoffset += n.Xoffset
   1669 		a.Type = n.Type
   1670 		Fixlargeoffset(a)
   1671 		return
   1672 
   1673 	case OCALLFUNC, OCALLMETH, OCALLINTER:
   1674 		switch n.Op {
   1675 		case OCALLFUNC:
   1676 			cgen_call(n, 0)
   1677 
   1678 		case OCALLMETH:
   1679 			cgen_callmeth(n, 0)
   1680 
   1681 		case OCALLINTER:
   1682 			cgen_callinter(n, nil, 0)
   1683 		}
   1684 
   1685 		var flist Iter
   1686 		fp := Structfirst(&flist, Getoutarg(n.Left.Type))
   1687 		*a = Node{}
   1688 		a.Op = OINDREG
   1689 		a.Reg = int16(Thearch.REGSP)
   1690 		a.Addable = true
   1691 		a.Xoffset = fp.Width
   1692 		if HasLinkRegister() {
   1693 			a.Xoffset += int64(Ctxt.Arch.Ptrsize)
   1694 		}
   1695 		a.Type = n.Type
   1696 		return
   1697 
   1698 		// Index of fixed-size array by constant can
   1699 	// put the offset in the addressing.
   1700 	// Could do the same for slice except that we need
   1701 	// to use the real index for the bounds checking.
   1702 	case OINDEX:
   1703 		if Isfixedarray(n.Left.Type) || (Isptr[n.Left.Type.Etype] && Isfixedarray(n.Left.Left.Type)) {
   1704 			if Isconst(n.Right, CTINT) {
   1705 				// Compute &a.
   1706 				if !Isptr[n.Left.Type.Etype] {
   1707 					Igen(n.Left, a, res)
   1708 				} else {
   1709 					var n1 Node
   1710 					Igen(n.Left, &n1, res)
   1711 					Cgen_checknil(&n1)
   1712 					Regalloc(a, Types[Tptr], res)
   1713 					Thearch.Gmove(&n1, a)
   1714 					Regfree(&n1)
   1715 					a.Op = OINDREG
   1716 				}
   1717 
   1718 				// Compute &a[i] as &a + i*width.
   1719 				a.Type = n.Type
   1720 
   1721 				a.Xoffset += Mpgetfix(n.Right.Val().U.(*Mpint)) * n.Type.Width
   1722 				Fixlargeoffset(a)
   1723 				return
   1724 			}
   1725 		}
   1726 	}
   1727 
   1728 	Agenr(n, a, res)
   1729 	a.Op = OINDREG
   1730 	a.Type = n.Type
   1731 }
   1732 
   1733 // Bgen generates code for branches:
   1734 //
   1735 // 	if n == wantTrue {
   1736 // 		goto to
   1737 // 	}
   1738 func Bgen(n *Node, wantTrue bool, likely int, to *obj.Prog) {
   1739 	bgenx(n, nil, wantTrue, likely, to)
   1740 }
   1741 
   1742 // Bvgen generates code for calculating boolean values:
   1743 // 	res = n == wantTrue
   1744 func Bvgen(n, res *Node, wantTrue bool) {
   1745 	if Thearch.Ginsboolval == nil {
   1746 		// Direct value generation not implemented for this architecture.
   1747 		// Implement using jumps.
   1748 		bvgenjump(n, res, wantTrue, true)
   1749 		return
   1750 	}
   1751 	bgenx(n, res, wantTrue, 0, nil)
   1752 }
   1753 
   1754 // bvgenjump implements boolean value generation using jumps:
   1755 // 	if n == wantTrue {
   1756 // 		res = 1
   1757 // 	} else {
   1758 // 		res = 0
   1759 // 	}
   1760 // geninit controls whether n's Ninit is generated.
   1761 func bvgenjump(n, res *Node, wantTrue, geninit bool) {
   1762 	init := n.Ninit
   1763 	if !geninit {
   1764 		n.Ninit = nil
   1765 	}
   1766 	p1 := Gbranch(obj.AJMP, nil, 0)
   1767 	p2 := Pc
   1768 	Thearch.Gmove(Nodbool(true), res)
   1769 	p3 := Gbranch(obj.AJMP, nil, 0)
   1770 	Patch(p1, Pc)
   1771 	Bgen(n, wantTrue, 0, p2)
   1772 	Thearch.Gmove(Nodbool(false), res)
   1773 	Patch(p3, Pc)
   1774 	n.Ninit = init
   1775 }
   1776 
   1777 // bgenx is the backend for Bgen and Bvgen.
   1778 // If res is nil, it generates a branch.
   1779 // Otherwise, it generates a boolean value.
   1780 func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
   1781 	if Debug['g'] != 0 {
   1782 		fmt.Printf("\nbgenx wantTrue=%t likely=%d to=%v\n", wantTrue, likely, to)
   1783 		Dump("n", n)
   1784 		Dump("res", res)
   1785 	}
   1786 
   1787 	genval := res != nil
   1788 
   1789 	if n == nil {
   1790 		n = Nodbool(true)
   1791 	}
   1792 
   1793 	Genlist(n.Ninit)
   1794 
   1795 	if n.Type == nil {
   1796 		Convlit(&n, Types[TBOOL])
   1797 		if n.Type == nil {
   1798 			return
   1799 		}
   1800 	}
   1801 
   1802 	if n.Type.Etype != TBOOL {
   1803 		Fatal("bgen: bad type %v for %v", n.Type, Oconv(int(n.Op), 0))
   1804 	}
   1805 
   1806 	for n.Op == OCONVNOP {
   1807 		n = n.Left
   1808 		Genlist(n.Ninit)
   1809 	}
   1810 
   1811 	if Thearch.Bgen_float != nil && n.Left != nil && Isfloat[n.Left.Type.Etype] {
   1812 		if genval {
   1813 			bvgenjump(n, res, wantTrue, false)
   1814 			return
   1815 		}
   1816 		Thearch.Bgen_float(n, wantTrue, likely, to)
   1817 		return
   1818 	}
   1819 
   1820 	switch n.Op {
   1821 	default:
   1822 		if genval {
   1823 			Cgen(n, res)
   1824 			if !wantTrue {
   1825 				Thearch.Gins(Thearch.Optoas(OXOR, Types[TUINT8]), Nodintconst(1), res)
   1826 			}
   1827 			return
   1828 		}
   1829 
   1830 		var tmp Node
   1831 		Regalloc(&tmp, n.Type, nil)
   1832 		Cgen(n, &tmp)
   1833 		bgenNonZero(&tmp, nil, wantTrue, likely, to)
   1834 		Regfree(&tmp)
   1835 		return
   1836 
   1837 	case ONAME:
   1838 		if genval {
   1839 			// 5g, 7g, and 9g might need a temporary or other help here,
   1840 			// but they don't support direct generation of a bool value yet.
   1841 			// We can fix that as we go.
   1842 			switch Ctxt.Arch.Thechar {
   1843 			case '5', '7', '9':
   1844 				Fatal("genval 5g, 7g, 9g ONAMES not fully implemented")
   1845 			}
   1846 			Cgen(n, res)
   1847 			if !wantTrue {
   1848 				Thearch.Gins(Thearch.Optoas(OXOR, Types[TUINT8]), Nodintconst(1), res)
   1849 			}
   1850 			return
   1851 		}
   1852 
   1853 		if n.Addable && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
   1854 			// no need for a temporary
   1855 			bgenNonZero(n, nil, wantTrue, likely, to)
   1856 			return
   1857 		}
   1858 		var tmp Node
   1859 		Regalloc(&tmp, n.Type, nil)
   1860 		Cgen(n, &tmp)
   1861 		bgenNonZero(&tmp, nil, wantTrue, likely, to)
   1862 		Regfree(&tmp)
   1863 		return
   1864 
   1865 	case OLITERAL:
   1866 		// n is a constant.
   1867 		if !Isconst(n, CTBOOL) {
   1868 			Fatal("bgen: non-bool const %v\n", Nconv(n, obj.FmtLong))
   1869 		}
   1870 		if genval {
   1871 			Cgen(Nodbool(wantTrue == n.Val().U.(bool)), res)
   1872 			return
   1873 		}
   1874 		// If n == wantTrue, jump; otherwise do nothing.
   1875 		if wantTrue == n.Val().U.(bool) {
   1876 			Patch(Gbranch(obj.AJMP, nil, likely), to)
   1877 		}
   1878 		return
   1879 
   1880 	case OANDAND, OOROR:
   1881 		and := (n.Op == OANDAND) == wantTrue
   1882 		if genval {
   1883 			p1 := Gbranch(obj.AJMP, nil, 0)
   1884 			p2 := Gbranch(obj.AJMP, nil, 0)
   1885 			Patch(p2, Pc)
   1886 			Cgen(Nodbool(!and), res)
   1887 			p3 := Gbranch(obj.AJMP, nil, 0)
   1888 			Patch(p1, Pc)
   1889 			Bgen(n.Left, wantTrue != and, 0, p2)
   1890 			Bvgen(n.Right, res, wantTrue)
   1891 			Patch(p3, Pc)
   1892 			return
   1893 		}
   1894 
   1895 		if and {
   1896 			p1 := Gbranch(obj.AJMP, nil, 0)
   1897 			p2 := Gbranch(obj.AJMP, nil, 0)
   1898 			Patch(p1, Pc)
   1899 			Bgen(n.Left, !wantTrue, -likely, p2)
   1900 			Bgen(n.Right, !wantTrue, -likely, p2)
   1901 			p1 = Gbranch(obj.AJMP, nil, 0)
   1902 			Patch(p1, to)
   1903 			Patch(p2, Pc)
   1904 		} else {
   1905 			Bgen(n.Left, wantTrue, likely, to)
   1906 			Bgen(n.Right, wantTrue, likely, to)
   1907 		}
   1908 		return
   1909 
   1910 	case ONOT: // unary
   1911 		if n.Left == nil || n.Left.Type == nil {
   1912 			return
   1913 		}
   1914 		bgenx(n.Left, res, !wantTrue, likely, to)
   1915 		return
   1916 
   1917 	case OEQ, ONE, OLT, OGT, OLE, OGE:
   1918 		if n.Left == nil || n.Left.Type == nil || n.Right == nil || n.Right.Type == nil {
   1919 			return
   1920 		}
   1921 	}
   1922 
   1923 	// n.Op is one of OEQ, ONE, OLT, OGT, OLE, OGE
   1924 	nl := n.Left
   1925 	nr := n.Right
   1926 	a := int(n.Op)
   1927 
   1928 	if !wantTrue {
   1929 		if Isfloat[nr.Type.Etype] {
   1930 			// Brcom is not valid on floats when NaN is involved.
   1931 			ll := n.Ninit // avoid re-genning Ninit
   1932 			n.Ninit = nil
   1933 			if genval {
   1934 				bgenx(n, res, true, likely, to)
   1935 				Thearch.Gins(Thearch.Optoas(OXOR, Types[TUINT8]), Nodintconst(1), res) // res = !res
   1936 				n.Ninit = ll
   1937 				return
   1938 			}
   1939 			p1 := Gbranch(obj.AJMP, nil, 0)
   1940 			p2 := Gbranch(obj.AJMP, nil, 0)
   1941 			Patch(p1, Pc)
   1942 			bgenx(n, res, true, -likely, p2)
   1943 			Patch(Gbranch(obj.AJMP, nil, 0), to)
   1944 			Patch(p2, Pc)
   1945 			n.Ninit = ll
   1946 			return
   1947 		}
   1948 
   1949 		a = Brcom(a)
   1950 	}
   1951 	wantTrue = true
   1952 
   1953 	// make simplest on right
   1954 	if nl.Op == OLITERAL || (nl.Ullman < nr.Ullman && nl.Ullman < UINF) {
   1955 		a = Brrev(a)
   1956 		nl, nr = nr, nl
   1957 	}
   1958 
   1959 	if Isslice(nl.Type) || Isinter(nl.Type) {
   1960 		// front end should only leave cmp to literal nil
   1961 		if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
   1962 			if Isslice(nl.Type) {
   1963 				Yyerror("illegal slice comparison")
   1964 			} else {
   1965 				Yyerror("illegal interface comparison")
   1966 			}
   1967 			return
   1968 		}
   1969 
   1970 		var ptr Node
   1971 		Igen(nl, &ptr, nil)
   1972 		if Isslice(nl.Type) {
   1973 			ptr.Xoffset += int64(Array_array)
   1974 		}
   1975 		ptr.Type = Types[Tptr]
   1976 		var tmp Node
   1977 		Regalloc(&tmp, ptr.Type, &ptr)
   1978 		Cgen(&ptr, &tmp)
   1979 		Regfree(&ptr)
   1980 		bgenNonZero(&tmp, res, a == OEQ != wantTrue, likely, to)
   1981 		Regfree(&tmp)
   1982 		return
   1983 	}
   1984 
   1985 	if Iscomplex[nl.Type.Etype] {
   1986 		complexbool(a, nl, nr, res, wantTrue, likely, to)
   1987 		return
   1988 	}
   1989 
   1990 	if Ctxt.Arch.Regsize == 4 && Is64(nr.Type) {
   1991 		if genval {
   1992 			// TODO: Teach Cmp64 to generate boolean values and remove this.
   1993 			bvgenjump(n, res, wantTrue, false)
   1994 			return
   1995 		}
   1996 		if !nl.Addable || Isconst(nl, CTINT) {
   1997 			nl = CgenTemp(nl)
   1998 		}
   1999 		if !nr.Addable {
   2000 			nr = CgenTemp(nr)
   2001 		}
   2002 		Thearch.Cmp64(nl, nr, a, likely, to)
   2003 		return
   2004 	}
   2005 
   2006 	if nr.Ullman >= UINF {
   2007 		var n1 Node
   2008 		Regalloc(&n1, nl.Type, nil)
   2009 		Cgen(nl, &n1)
   2010 		nl = &n1
   2011 
   2012 		var tmp Node
   2013 		Tempname(&tmp, nl.Type)
   2014 		Thearch.Gmove(&n1, &tmp)
   2015 		Regfree(&n1)
   2016 
   2017 		var n2 Node
   2018 		Regalloc(&n2, nr.Type, nil)
   2019 		Cgen(nr, &n2)
   2020 		nr = &n2
   2021 
   2022 		Regalloc(&n1, nl.Type, nil)
   2023 		Cgen(&tmp, &n1)
   2024 		Regfree(&n1)
   2025 		Regfree(&n2)
   2026 	} else {
   2027 		var n1 Node
   2028 		if !nl.Addable && Ctxt.Arch.Thechar == '8' {
   2029 			Tempname(&n1, nl.Type)
   2030 		} else {
   2031 			Regalloc(&n1, nl.Type, nil)
   2032 			defer Regfree(&n1)
   2033 		}
   2034 		Cgen(nl, &n1)
   2035 		nl = &n1
   2036 
   2037 		if Smallintconst(nr) && Ctxt.Arch.Thechar != '9' {
   2038 			Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
   2039 			bins(nr.Type, res, a, likely, to)
   2040 			return
   2041 		}
   2042 
   2043 		if !nr.Addable && Ctxt.Arch.Thechar == '8' {
   2044 			nr = CgenTemp(nr)
   2045 		}
   2046 
   2047 		var n2 Node
   2048 		Regalloc(&n2, nr.Type, nil)
   2049 		Cgen(nr, &n2)
   2050 		nr = &n2
   2051 		Regfree(&n2)
   2052 	}
   2053 
   2054 	l, r := nl, nr
   2055 
   2056 	// On x86, only < and <= work right with NaN; reverse if needed
   2057 	if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (a == OGT || a == OGE) {
   2058 		l, r = r, l
   2059 		a = Brrev(a)
   2060 	}
   2061 
   2062 	// Do the comparison.
   2063 	Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), l, r)
   2064 
   2065 	// Handle floating point special cases.
   2066 	// Note that 8g has Bgen_float and is handled above.
   2067 	if Isfloat[nl.Type.Etype] {
   2068 		switch Ctxt.Arch.Thechar {
   2069 		case '5':
   2070 			if genval {
   2071 				Fatal("genval 5g Isfloat special cases not implemented")
   2072 			}
   2073 			switch n.Op {
   2074 			case ONE:
   2075 				Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, likely), to)
   2076 				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
   2077 			default:
   2078 				p := Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, -likely)
   2079 				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
   2080 				Patch(p, Pc)
   2081 			}
   2082 			return
   2083 		case '6':
   2084 			switch n.Op {
   2085 			case OEQ:
   2086 				// neither NE nor P
   2087 				if genval {
   2088 					var reg Node
   2089 					Regalloc(&reg, Types[TBOOL], nil)
   2090 					Thearch.Ginsboolval(Thearch.Optoas(OEQ, nr.Type), &reg)
   2091 					Thearch.Ginsboolval(Thearch.Optoas(OPC, nr.Type), res)
   2092 					Thearch.Gins(Thearch.Optoas(OAND, Types[TBOOL]), &reg, res)
   2093 					Regfree(&reg)
   2094 				} else {
   2095 					p1 := Gbranch(Thearch.Optoas(ONE, nr.Type), nil, -likely)
   2096 					p2 := Gbranch(Thearch.Optoas(OPS, nr.Type), nil, -likely)
   2097 					Patch(Gbranch(obj.AJMP, nil, 0), to)
   2098 					Patch(p1, Pc)
   2099 					Patch(p2, Pc)
   2100 				}
   2101 				return
   2102 			case ONE:
   2103 				// either NE or P
   2104 				if genval {
   2105 					var reg Node
   2106 					Regalloc(&reg, Types[TBOOL], nil)
   2107 					Thearch.Ginsboolval(Thearch.Optoas(ONE, nr.Type), &reg)
   2108 					Thearch.Ginsboolval(Thearch.Optoas(OPS, nr.Type), res)
   2109 					Thearch.Gins(Thearch.Optoas(OOR, Types[TBOOL]), &reg, res)
   2110 					Regfree(&reg)
   2111 				} else {
   2112 					Patch(Gbranch(Thearch.Optoas(ONE, nr.Type), nil, likely), to)
   2113 					Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nil, likely), to)
   2114 				}
   2115 				return
   2116 			}
   2117 		case '7', '9':
   2118 			if genval {
   2119 				Fatal("genval 7g, 9g Isfloat special cases not implemented")
   2120 			}
   2121 			switch n.Op {
   2122 			// On arm64 and ppc64, <= and >= mishandle NaN. Must decompose into < or > and =.
   2123 			// TODO(josh): Convert a <= b to b > a instead?
   2124 			case OLE, OGE:
   2125 				if a == OLE {
   2126 					a = OLT
   2127 				} else {
   2128 					a = OGT
   2129 				}
   2130 				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
   2131 				Patch(Gbranch(Thearch.Optoas(OEQ, nr.Type), nr.Type, likely), to)
   2132 				return
   2133 			}
   2134 		}
   2135 	}
   2136 
   2137 	// Not a special case. Insert the conditional jump or value gen.
   2138 	bins(nr.Type, res, a, likely, to)
   2139 }
   2140 
   2141 func bgenNonZero(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
   2142 	// TODO: Optimize on systems that can compare to zero easily.
   2143 	a := ONE
   2144 	if !wantTrue {
   2145 		a = OEQ
   2146 	}
   2147 	var zero Node
   2148 	Nodconst(&zero, n.Type, 0)
   2149 	Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &zero)
   2150 	bins(n.Type, res, a, likely, to)
   2151 }
   2152 
   2153 // bins inserts an instruction to handle the result of a compare.
   2154 // If res is non-nil, it inserts appropriate value generation instructions.
   2155 // If res is nil, it inserts a branch to to.
   2156 func bins(typ *Type, res *Node, a, likely int, to *obj.Prog) {
   2157 	a = Thearch.Optoas(a, typ)
   2158 	if res != nil {
   2159 		// value gen
   2160 		Thearch.Ginsboolval(a, res)
   2161 	} else {
   2162 		// jump
   2163 		Patch(Gbranch(a, typ, likely), to)
   2164 	}
   2165 }
   2166 
   2167 // stkof returns n's offset from SP if n is on the stack
   2168 // (either a local variable or the return value from a function call
   2169 // or the arguments to a function call).
   2170 // If n is not on the stack, stkof returns -1000.
   2171 // If n is on the stack but in an unknown location
   2172 // (due to array index arithmetic), stkof returns +1000.
   2173 //
   2174 // NOTE(rsc): It is possible that the ODOT and OINDEX cases
   2175 // are not relevant here, since it shouldn't be possible for them
   2176 // to be involved in an overlapping copy. Only function results
   2177 // from one call and the arguments to the next can overlap in
   2178 // any non-trivial way. If they can be dropped, then this function
   2179 // becomes much simpler and also more trustworthy.
   2180 // The fact that it works at all today is probably due to the fact
   2181 // that ODOT and OINDEX are irrelevant.
   2182 func stkof(n *Node) int64 {
   2183 	switch n.Op {
   2184 	case OINDREG:
   2185 		if n.Reg != int16(Thearch.REGSP) {
   2186 			return -1000 // not on stack
   2187 		}
   2188 		return n.Xoffset
   2189 
   2190 	case ODOT:
   2191 		t := n.Left.Type
   2192 		if Isptr[t.Etype] {
   2193 			break
   2194 		}
   2195 		off := stkof(n.Left)
   2196 		if off == -1000 || off == +1000 {
   2197 			return off
   2198 		}
   2199 		return off + n.Xoffset
   2200 
   2201 	case OINDEX:
   2202 		t := n.Left.Type
   2203 		if !Isfixedarray(t) {
   2204 			break
   2205 		}
   2206 		off := stkof(n.Left)
   2207 		if off == -1000 || off == +1000 {
   2208 			return off
   2209 		}
   2210 		if Isconst(n.Right, CTINT) {
   2211 			return off + t.Type.Width*Mpgetfix(n.Right.Val().U.(*Mpint))
   2212 		}
   2213 		return +1000 // on stack but not sure exactly where
   2214 
   2215 	case OCALLMETH, OCALLINTER, OCALLFUNC:
   2216 		t := n.Left.Type
   2217 		if Isptr[t.Etype] {
   2218 			t = t.Type
   2219 		}
   2220 
   2221 		var flist Iter
   2222 		t = Structfirst(&flist, Getoutarg(t))
   2223 		if t != nil {
   2224 			w := t.Width
   2225 			if HasLinkRegister() {
   2226 				w += int64(Ctxt.Arch.Ptrsize)
   2227 			}
   2228 			return w
   2229 		}
   2230 	}
   2231 
   2232 	// botch - probably failing to recognize address
   2233 	// arithmetic on the above. eg INDEX and DOT
   2234 	return -1000 // not on stack
   2235 }
   2236 
   2237 /*
   2238  * block copy:
   2239  *	memmove(&ns, &n, w);
   2240  * if wb is true, needs write barrier.
   2241  */
   2242 func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
   2243 	if Debug['g'] != 0 {
   2244 		op := "sgen"
   2245 		if wb {
   2246 			op = "sgen-wb"
   2247 		}
   2248 		fmt.Printf("\n%s w=%d\n", op, w)
   2249 		Dump("r", n)
   2250 		Dump("res", ns)
   2251 	}
   2252 
   2253 	if n.Ullman >= UINF && ns.Ullman >= UINF {
   2254 		Fatal("sgen UINF")
   2255 	}
   2256 
   2257 	if w < 0 {
   2258 		Fatal("sgen copy %d", w)
   2259 	}
   2260 
   2261 	// If copying .args, that's all the results, so record definition sites
   2262 	// for them for the liveness analysis.
   2263 	if ns.Op == ONAME && ns.Sym.Name == ".args" {
   2264 		for l := Curfn.Func.Dcl; l != nil; l = l.Next {
   2265 			if l.N.Class == PPARAMOUT {
   2266 				Gvardef(l.N)
   2267 			}
   2268 		}
   2269 	}
   2270 
   2271 	// Avoid taking the address for simple enough types.
   2272 	if componentgen_wb(n, ns, wb) {
   2273 		return
   2274 	}
   2275 
   2276 	if w == 0 {
   2277 		// evaluate side effects only
   2278 		var nodr Node
   2279 		Regalloc(&nodr, Types[Tptr], nil)
   2280 		Agen(ns, &nodr)
   2281 		Agen(n, &nodr)
   2282 		Regfree(&nodr)
   2283 		return
   2284 	}
   2285 
   2286 	// offset on the stack
   2287 	osrc := stkof(n)
   2288 	odst := stkof(ns)
   2289 
   2290 	if odst != -1000 {
   2291 		// on stack, write barrier not needed after all
   2292 		wb = false
   2293 	}
   2294 
   2295 	if osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000) || wb && osrc != -1000 {
   2296 		// osrc and odst both on stack, and at least one is in
   2297 		// an unknown position.  Could generate code to test
   2298 		// for forward/backward copy, but instead just copy
   2299 		// to a temporary location first.
   2300 		//
   2301 		// OR: write barrier needed and source is on stack.
   2302 		// Invoking the write barrier will use the stack to prepare its call.
   2303 		// Copy to temporary.
   2304 		var tmp Node
   2305 		Tempname(&tmp, n.Type)
   2306 		sgen_wb(n, &tmp, w, false)
   2307 		sgen_wb(&tmp, ns, w, wb)
   2308 		return
   2309 	}
   2310 
   2311 	if wb {
   2312 		cgen_wbfat(n, ns)
   2313 		return
   2314 	}
   2315 
   2316 	Thearch.Blockcopy(n, ns, osrc, odst, w)
   2317 }
   2318 
   2319 /*
   2320  * generate:
   2321  *	call f
   2322  *	proc=-1	normal call but no return
   2323  *	proc=0	normal call
   2324  *	proc=1	goroutine run in new proc
   2325  *	proc=2	defer call save away stack
   2326   *	proc=3	normal call to C pointer (not Go func value)
   2327 */
   2328 func Ginscall(f *Node, proc int) {
   2329 	if f.Type != nil {
   2330 		extra := int32(0)
   2331 		if proc == 1 || proc == 2 {
   2332 			extra = 2 * int32(Widthptr)
   2333 		}
   2334 		Setmaxarg(f.Type, extra)
   2335 	}
   2336 
   2337 	switch proc {
   2338 	default:
   2339 		Fatal("Ginscall: bad proc %d", proc)
   2340 
   2341 	case 0, // normal call
   2342 		-1: // normal call but no return
   2343 		if f.Op == ONAME && f.Class == PFUNC {
   2344 			if f == Deferreturn {
   2345 				// Deferred calls will appear to be returning to
   2346 				// the CALL deferreturn(SB) that we are about to emit.
   2347 				// However, the stack trace code will show the line
   2348 				// of the instruction byte before the return PC.
   2349 				// To avoid that being an unrelated instruction,
   2350 				// insert an actual hardware NOP that will have the right line number.
   2351 				// This is different from obj.ANOP, which is a virtual no-op
   2352 				// that doesn't make it into the instruction stream.
   2353 				Thearch.Ginsnop()
   2354 			}
   2355 
   2356 			p := Thearch.Gins(obj.ACALL, nil, f)
   2357 			Afunclit(&p.To, f)
   2358 			if proc == -1 || Noreturn(p) {
   2359 				Thearch.Gins(obj.AUNDEF, nil, nil)
   2360 			}
   2361 			break
   2362 		}
   2363 
   2364 		var reg Node
   2365 		Nodreg(&reg, Types[Tptr], Thearch.REGCTXT)
   2366 		var r1 Node
   2367 		Nodreg(&r1, Types[Tptr], Thearch.REGCALLX)
   2368 		Thearch.Gmove(f, &reg)
   2369 		reg.Op = OINDREG
   2370 		Thearch.Gmove(&reg, &r1)
   2371 		reg.Op = OREGISTER
   2372 		Thearch.Gins(obj.ACALL, &reg, &r1)
   2373 
   2374 	case 3: // normal call of c function pointer
   2375 		Thearch.Gins(obj.ACALL, nil, f)
   2376 
   2377 	case 1, // call in new proc (go)
   2378 		2: // deferred call (defer)
   2379 		var stk Node
   2380 
   2381 		// size of arguments at 0(SP)
   2382 		stk.Op = OINDREG
   2383 		stk.Reg = int16(Thearch.REGSP)
   2384 		stk.Xoffset = 0
   2385 		if HasLinkRegister() {
   2386 			stk.Xoffset += int64(Ctxt.Arch.Ptrsize)
   2387 		}
   2388 		Thearch.Ginscon(Thearch.Optoas(OAS, Types[TINT32]), int64(Argsize(f.Type)), &stk)
   2389 
   2390 		// FuncVal* at 8(SP)
   2391 		stk.Xoffset = int64(Widthptr)
   2392 		if HasLinkRegister() {
   2393 			stk.Xoffset += int64(Ctxt.Arch.Ptrsize)
   2394 		}
   2395 
   2396 		var reg Node
   2397 		Nodreg(&reg, Types[Tptr], Thearch.REGCALLX2)
   2398 		Thearch.Gmove(f, &reg)
   2399 		Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &reg, &stk)
   2400 
   2401 		if proc == 1 {
   2402 			Ginscall(Newproc, 0)
   2403 		} else {
   2404 			if Hasdefer == 0 {
   2405 				Fatal("hasdefer=0 but has defer")
   2406 			}
   2407 			Ginscall(Deferproc, 0)
   2408 		}
   2409 
   2410 		if proc == 2 {
   2411 			Nodreg(&reg, Types[TINT32], Thearch.REGRETURN)
   2412 			p := Thearch.Ginscmp(OEQ, Types[TINT32], &reg, Nodintconst(0), +1)
   2413 			cgen_ret(nil)
   2414 			Patch(p, Pc)
   2415 		}
   2416 	}
   2417 }
   2418 
   2419 /*
   2420  * n is call to interface method.
   2421  * generate res = n.
   2422  */
   2423 func cgen_callinter(n *Node, res *Node, proc int) {
   2424 	i := n.Left
   2425 	if i.Op != ODOTINTER {
   2426 		Fatal("cgen_callinter: not ODOTINTER %v", Oconv(int(i.Op), 0))
   2427 	}
   2428 
   2429 	f := i.Right // field
   2430 	if f.Op != ONAME {
   2431 		Fatal("cgen_callinter: not ONAME %v", Oconv(int(f.Op), 0))
   2432 	}
   2433 
   2434 	i = i.Left // interface
   2435 
   2436 	if !i.Addable {
   2437 		var tmpi Node
   2438 		Tempname(&tmpi, i.Type)
   2439 		Cgen(i, &tmpi)
   2440 		i = &tmpi
   2441 	}
   2442 
   2443 	Genlist(n.List) // assign the args
   2444 
   2445 	// i is now addable, prepare an indirected
   2446 	// register to hold its address.
   2447 	var nodi Node
   2448 	Igen(i, &nodi, res) // REG = &inter
   2449 
   2450 	var nodsp Node
   2451 	Nodindreg(&nodsp, Types[Tptr], Thearch.REGSP)
   2452 	nodsp.Xoffset = 0
   2453 	if HasLinkRegister() {
   2454 		nodsp.Xoffset += int64(Ctxt.Arch.Ptrsize)
   2455 	}
   2456 	if proc != 0 {
   2457 		nodsp.Xoffset += 2 * int64(Widthptr) // leave room for size & fn
   2458 	}
   2459 	nodi.Type = Types[Tptr]
   2460 	nodi.Xoffset += int64(Widthptr)
   2461 	Cgen(&nodi, &nodsp) // {0, 8(nacl), or 16}(SP) = 8(REG) -- i.data
   2462 
   2463 	var nodo Node
   2464 	Regalloc(&nodo, Types[Tptr], res)
   2465 
   2466 	nodi.Type = Types[Tptr]
   2467 	nodi.Xoffset -= int64(Widthptr)
   2468 	Cgen(&nodi, &nodo) // REG = 0(REG) -- i.tab
   2469 	Regfree(&nodi)
   2470 
   2471 	var nodr Node
   2472 	Regalloc(&nodr, Types[Tptr], &nodo)
   2473 	if n.Left.Xoffset == BADWIDTH {
   2474 		Fatal("cgen_callinter: badwidth")
   2475 	}
   2476 	Cgen_checknil(&nodo) // in case offset is huge
   2477 	nodo.Op = OINDREG
   2478 	nodo.Xoffset = n.Left.Xoffset + 3*int64(Widthptr) + 8
   2479 	if proc == 0 {
   2480 		// plain call: use direct c function pointer - more efficient
   2481 		Cgen(&nodo, &nodr) // REG = 32+offset(REG) -- i.tab->fun[f]
   2482 		proc = 3
   2483 	} else {
   2484 		// go/defer. generate go func value.
   2485 		Agen(&nodo, &nodr) // REG = &(32+offset(REG)) -- i.tab->fun[f]
   2486 	}
   2487 
   2488 	nodr.Type = n.Left.Type
   2489 	Ginscall(&nodr, proc)
   2490 
   2491 	Regfree(&nodr)
   2492 	Regfree(&nodo)
   2493 }
   2494 
   2495 /*
   2496  * generate function call;
   2497  *	proc=0	normal call
   2498  *	proc=1	goroutine run in new proc
   2499  *	proc=2	defer call save away stack
   2500  */
   2501 func cgen_call(n *Node, proc int) {
   2502 	if n == nil {
   2503 		return
   2504 	}
   2505 
   2506 	var afun Node
   2507 	if n.Left.Ullman >= UINF {
   2508 		// if name involves a fn call
   2509 		// precompute the address of the fn
   2510 		Tempname(&afun, Types[Tptr])
   2511 
   2512 		Cgen(n.Left, &afun)
   2513 	}
   2514 
   2515 	Genlist(n.List) // assign the args
   2516 	t := n.Left.Type
   2517 
   2518 	// call tempname pointer
   2519 	if n.Left.Ullman >= UINF {
   2520 		var nod Node
   2521 		Regalloc(&nod, Types[Tptr], nil)
   2522 		Cgen_as(&nod, &afun)
   2523 		nod.Type = t
   2524 		Ginscall(&nod, proc)
   2525 		Regfree(&nod)
   2526 		return
   2527 	}
   2528 
   2529 	// call pointer
   2530 	if n.Left.Op != ONAME || n.Left.Class != PFUNC {
   2531 		var nod Node
   2532 		Regalloc(&nod, Types[Tptr], nil)
   2533 		Cgen_as(&nod, n.Left)
   2534 		nod.Type = t
   2535 		Ginscall(&nod, proc)
   2536 		Regfree(&nod)
   2537 		return
   2538 	}
   2539 
   2540 	// call direct
   2541 	n.Left.Name.Method = true
   2542 
   2543 	Ginscall(n.Left, proc)
   2544 }
   2545 
   2546 func HasLinkRegister() bool {
   2547 	c := Ctxt.Arch.Thechar
   2548 	return c != '6' && c != '8'
   2549 }
   2550 
   2551 /*
   2552  * call to n has already been generated.
   2553  * generate:
   2554  *	res = return value from call.
   2555  */
   2556 func cgen_callret(n *Node, res *Node) {
   2557 	t := n.Left.Type
   2558 	if t.Etype == TPTR32 || t.Etype == TPTR64 {
   2559 		t = t.Type
   2560 	}
   2561 
   2562 	var flist Iter
   2563 	fp := Structfirst(&flist, Getoutarg(t))
   2564 	if fp == nil {
   2565 		Fatal("cgen_callret: nil")
   2566 	}
   2567 
   2568 	var nod Node
   2569 	nod.Op = OINDREG
   2570 	nod.Reg = int16(Thearch.REGSP)
   2571 	nod.Addable = true
   2572 
   2573 	nod.Xoffset = fp.Width
   2574 	if HasLinkRegister() {
   2575 		nod.Xoffset += int64(Ctxt.Arch.Ptrsize)
   2576 	}
   2577 	nod.Type = fp.Type
   2578 	Cgen_as(res, &nod)
   2579 }
   2580 
   2581 /*
   2582  * call to n has already been generated.
   2583  * generate:
   2584  *	res = &return value from call.
   2585  */
   2586 func cgen_aret(n *Node, res *Node) {
   2587 	t := n.Left.Type
   2588 	if Isptr[t.Etype] {
   2589 		t = t.Type
   2590 	}
   2591 
   2592 	var flist Iter
   2593 	fp := Structfirst(&flist, Getoutarg(t))
   2594 	if fp == nil {
   2595 		Fatal("cgen_aret: nil")
   2596 	}
   2597 
   2598 	var nod1 Node
   2599 	nod1.Op = OINDREG
   2600 	nod1.Reg = int16(Thearch.REGSP)
   2601 	nod1.Addable = true
   2602 	nod1.Xoffset = fp.Width
   2603 	if HasLinkRegister() {
   2604 		nod1.Xoffset += int64(Ctxt.Arch.Ptrsize)
   2605 	}
   2606 	nod1.Type = fp.Type
   2607 
   2608 	if res.Op != OREGISTER {
   2609 		var nod2 Node
   2610 		Regalloc(&nod2, Types[Tptr], res)
   2611 		Agen(&nod1, &nod2)
   2612 		Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &nod2, res)
   2613 		Regfree(&nod2)
   2614 	} else {
   2615 		Agen(&nod1, res)
   2616 	}
   2617 }
   2618 
   2619 /*
   2620  * generate return.
   2621  * n->left is assignments to return values.
   2622  */
   2623 func cgen_ret(n *Node) {
   2624 	if n != nil {
   2625 		Genlist(n.List) // copy out args
   2626 	}
   2627 	if Hasdefer != 0 {
   2628 		Ginscall(Deferreturn, 0)
   2629 	}
   2630 	Genlist(Curfn.Func.Exit)
   2631 	p := Thearch.Gins(obj.ARET, nil, nil)
   2632 	if n != nil && n.Op == ORETJMP {
   2633 		p.To.Type = obj.TYPE_MEM
   2634 		p.To.Name = obj.NAME_EXTERN
   2635 		p.To.Sym = Linksym(n.Left.Sym)
   2636 	}
   2637 }
   2638 
   2639 /*
   2640  * generate division according to op, one of:
   2641  *	res = nl / nr
   2642  *	res = nl % nr
   2643  */
   2644 func cgen_div(op int, nl *Node, nr *Node, res *Node) {
   2645 	var w int
   2646 
   2647 	// TODO(rsc): arm64 needs to support the relevant instructions
   2648 	// in peep and optoas in order to enable this.
   2649 	// TODO(rsc): ppc64 needs to support the relevant instructions
   2650 	// in peep and optoas in order to enable this.
   2651 	if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
   2652 		goto longdiv
   2653 	}
   2654 	w = int(nl.Type.Width * 8)
   2655 
   2656 	// Front end handled 32-bit division. We only need to handle 64-bit.
   2657 	// try to do division by multiply by (2^w)/d
   2658 	// see hacker's delight chapter 10
   2659 	switch Simtype[nl.Type.Etype] {
   2660 	default:
   2661 		goto longdiv
   2662 
   2663 	case TUINT64:
   2664 		var m Magic
   2665 		m.W = w
   2666 		m.Ud = uint64(Mpgetfix(nr.Val().U.(*Mpint)))
   2667 		Umagic(&m)
   2668 		if m.Bad != 0 {
   2669 			break
   2670 		}
   2671 		if op == OMOD {
   2672 			goto longmod
   2673 		}
   2674 
   2675 		var n1 Node
   2676 		Cgenr(nl, &n1, nil)
   2677 		var n2 Node
   2678 		Nodconst(&n2, nl.Type, int64(m.Um))
   2679 		var n3 Node
   2680 		Regalloc(&n3, nl.Type, res)
   2681 		Thearch.Cgen_hmul(&n1, &n2, &n3)
   2682 
   2683 		if m.Ua != 0 {
   2684 			// need to add numerator accounting for overflow
   2685 			Thearch.Gins(Thearch.Optoas(OADD, nl.Type), &n1, &n3)
   2686 
   2687 			Nodconst(&n2, nl.Type, 1)
   2688 			Thearch.Gins(Thearch.Optoas(ORROTC, nl.Type), &n2, &n3)
   2689 			Nodconst(&n2, nl.Type, int64(m.S)-1)
   2690 			Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n3)
   2691 		} else {
   2692 			Nodconst(&n2, nl.Type, int64(m.S))
   2693 			Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n3) // shift dx
   2694 		}
   2695 
   2696 		Thearch.Gmove(&n3, res)
   2697 		Regfree(&n1)
   2698 		Regfree(&n3)
   2699 		return
   2700 
   2701 	case TINT64:
   2702 		var m Magic
   2703 		m.W = w
   2704 		m.Sd = Mpgetfix(nr.Val().U.(*Mpint))
   2705 		Smagic(&m)
   2706 		if m.Bad != 0 {
   2707 			break
   2708 		}
   2709 		if op == OMOD {
   2710 			goto longmod
   2711 		}
   2712 
   2713 		var n1 Node
   2714 		Cgenr(nl, &n1, res)
   2715 		var n2 Node
   2716 		Nodconst(&n2, nl.Type, m.Sm)
   2717 		var n3 Node
   2718 		Regalloc(&n3, nl.Type, nil)
   2719 		Thearch.Cgen_hmul(&n1, &n2, &n3)
   2720 
   2721 		if m.Sm < 0 {
   2722 			// need to add numerator
   2723 			Thearch.Gins(Thearch.Optoas(OADD, nl.Type), &n1, &n3)
   2724 		}
   2725 
   2726 		Nodconst(&n2, nl.Type, int64(m.S))
   2727 		Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n3) // shift n3
   2728 
   2729 		Nodconst(&n2, nl.Type, int64(w)-1)
   2730 
   2731 		Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n1) // -1 iff num is neg
   2732 		Thearch.Gins(Thearch.Optoas(OSUB, nl.Type), &n1, &n3) // added
   2733 
   2734 		if m.Sd < 0 {
   2735 			// this could probably be removed
   2736 			// by factoring it into the multiplier
   2737 			Thearch.Gins(Thearch.Optoas(OMINUS, nl.Type), nil, &n3)
   2738 		}
   2739 
   2740 		Thearch.Gmove(&n3, res)
   2741 		Regfree(&n1)
   2742 		Regfree(&n3)
   2743 		return
   2744 	}
   2745 
   2746 	goto longdiv
   2747 
   2748 	// division and mod using (slow) hardware instruction
   2749 longdiv:
   2750 	Thearch.Dodiv(op, nl, nr, res)
   2751 
   2752 	return
   2753 
   2754 	// mod using formula A%B = A-(A/B*B) but
   2755 	// we know that there is a fast algorithm for A/B
   2756 longmod:
   2757 	var n1 Node
   2758 	Regalloc(&n1, nl.Type, res)
   2759 
   2760 	Cgen(nl, &n1)
   2761 	var n2 Node
   2762 	Regalloc(&n2, nl.Type, nil)
   2763 	cgen_div(ODIV, &n1, nr, &n2)
   2764 	a := Thearch.Optoas(OMUL, nl.Type)
   2765 	if w == 8 {
   2766 		// use 2-operand 16-bit multiply
   2767 		// because there is no 2-operand 8-bit multiply
   2768 		a = Thearch.Optoas(OMUL, Types[TINT16]) // XXX was IMULW
   2769 	}
   2770 
   2771 	if !Smallintconst(nr) {
   2772 		var n3 Node
   2773 		Regalloc(&n3, nl.Type, nil)
   2774 		Cgen(nr, &n3)
   2775 		Thearch.Gins(a, &n3, &n2)
   2776 		Regfree(&n3)
   2777 	} else {
   2778 		Thearch.Gins(a, nr, &n2)
   2779 	}
   2780 	Thearch.Gins(Thearch.Optoas(OSUB, nl.Type), &n2, &n1)
   2781 	Thearch.Gmove(&n1, res)
   2782 	Regfree(&n1)
   2783 	Regfree(&n2)
   2784 }
   2785 
   2786 func Fixlargeoffset(n *Node) {
   2787 	if n == nil {
   2788 		return
   2789 	}
   2790 	if n.Op != OINDREG {
   2791 		return
   2792 	}
   2793 	if n.Reg == int16(Thearch.REGSP) { // stack offset cannot be large
   2794 		return
   2795 	}
   2796 	if n.Xoffset != int64(int32(n.Xoffset)) {
   2797 		// offset too large, add to register instead.
   2798 		a := *n
   2799 
   2800 		a.Op = OREGISTER
   2801 		a.Type = Types[Tptr]
   2802 		a.Xoffset = 0
   2803 		Cgen_checknil(&a)
   2804 		Thearch.Ginscon(Thearch.Optoas(OADD, Types[Tptr]), n.Xoffset, &a)
   2805 		n.Xoffset = 0
   2806 	}
   2807 }
   2808 
   2809 func cgen_append(n, res *Node) {
   2810 	if Debug['g'] != 0 {
   2811 		Dump("cgen_append-n", n)
   2812 		Dump("cgen_append-res", res)
   2813 	}
   2814 	if res.Op != ONAME && !samesafeexpr(res, n.List.N) {
   2815 		Dump("cgen_append-n", n)
   2816 		Dump("cgen_append-res", res)
   2817 		Fatal("append not lowered")
   2818 	}
   2819 	for l := n.List; l != nil; l = l.Next {
   2820 		if l.N.Ullman >= UINF {
   2821 			Fatal("append with function call arguments")
   2822 		}
   2823 	}
   2824 
   2825 	// res = append(src, x, y, z)
   2826 	//
   2827 	// If res and src are the same, we can avoid writing to base and cap
   2828 	// unless we grow the underlying array.
   2829 	needFullUpdate := !samesafeexpr(res, n.List.N)
   2830 
   2831 	// Copy src triple into base, len, cap.
   2832 	base := temp(Types[Tptr])
   2833 	len := temp(Types[TUINT])
   2834 	cap := temp(Types[TUINT])
   2835 
   2836 	var src Node
   2837 	Igen(n.List.N, &src, nil)
   2838 	src.Type = Types[Tptr]
   2839 	Thearch.Gmove(&src, base)
   2840 	src.Type = Types[TUINT]
   2841 	src.Xoffset += int64(Widthptr)
   2842 	Thearch.Gmove(&src, len)
   2843 	src.Xoffset += int64(Widthptr)
   2844 	Thearch.Gmove(&src, cap)
   2845 
   2846 	// if len+argc <= cap goto L1
   2847 	var rlen Node
   2848 	Regalloc(&rlen, Types[TUINT], nil)
   2849 	Thearch.Gmove(len, &rlen)
   2850 	Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(count(n.List)-1), &rlen)
   2851 	p := Thearch.Ginscmp(OLE, Types[TUINT], &rlen, cap, +1)
   2852 	// Note: rlen and src are Regrealloc'ed below at the target of the
   2853 	// branch we just emitted; do not reuse these Go variables for
   2854 	// other purposes. They need to still describe the same things
   2855 	// below that they describe right here.
   2856 	Regfree(&src)
   2857 
   2858 	// base, len, cap = growslice(type, base, len, cap, newlen)
   2859 	var arg Node
   2860 	arg.Op = OINDREG
   2861 	arg.Reg = int16(Thearch.REGSP)
   2862 	arg.Addable = true
   2863 	arg.Xoffset = 0
   2864 	if HasLinkRegister() {
   2865 		arg.Xoffset = int64(Ctxt.Arch.Ptrsize)
   2866 	}
   2867 	arg.Type = Ptrto(Types[TUINT8])
   2868 	Cgen(typename(res.Type), &arg)
   2869 	arg.Xoffset += int64(Widthptr)
   2870 
   2871 	arg.Type = Types[Tptr]
   2872 	Cgen(base, &arg)
   2873 	arg.Xoffset += int64(Widthptr)
   2874 
   2875 	arg.Type = Types[TUINT]
   2876 	Cgen(len, &arg)
   2877 	arg.Xoffset += int64(Widthptr)
   2878 
   2879 	arg.Type = Types[TUINT]
   2880 	Cgen(cap, &arg)
   2881 	arg.Xoffset += int64(Widthptr)
   2882 
   2883 	arg.Type = Types[TUINT]
   2884 	Cgen(&rlen, &arg)
   2885 	arg.Xoffset += int64(Widthptr)
   2886 	Regfree(&rlen)
   2887 
   2888 	fn := syslook("growslice", 1)
   2889 	substArgTypes(fn, res.Type.Type, res.Type.Type)
   2890 	Ginscall(fn, 0)
   2891 
   2892 	if Widthptr == 4 && Widthreg == 8 {
   2893 		arg.Xoffset += 4
   2894 	}
   2895 
   2896 	arg.Type = Types[Tptr]
   2897 	Cgen(&arg, base)
   2898 	arg.Xoffset += int64(Widthptr)
   2899 
   2900 	arg.Type = Types[TUINT]
   2901 	Cgen(&arg, len)
   2902 	arg.Xoffset += int64(Widthptr)
   2903 
   2904 	arg.Type = Types[TUINT]
   2905 	Cgen(&arg, cap)
   2906 
   2907 	// Update res with base, len+argc, cap.
   2908 	if needFullUpdate {
   2909 		if Debug_append > 0 {
   2910 			Warn("append: full update")
   2911 		}
   2912 		Patch(p, Pc)
   2913 	}
   2914 	if res.Op == ONAME {
   2915 		Gvardef(res)
   2916 	}
   2917 	var dst, r1 Node
   2918 	Igen(res, &dst, nil)
   2919 	dst.Type = Types[TUINT]
   2920 	dst.Xoffset += int64(Widthptr)
   2921 	Regalloc(&r1, Types[TUINT], nil)
   2922 	Thearch.Gmove(len, &r1)
   2923 	Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(count(n.List)-1), &r1)
   2924 	Thearch.Gmove(&r1, &dst)
   2925 	Regfree(&r1)
   2926 	dst.Xoffset += int64(Widthptr)
   2927 	Thearch.Gmove(cap, &dst)
   2928 	dst.Type = Types[Tptr]
   2929 	dst.Xoffset -= 2 * int64(Widthptr)
   2930 	cgen_wb(base, &dst, needwritebarrier(&dst, base))
   2931 	Regfree(&dst)
   2932 
   2933 	if !needFullUpdate {
   2934 		if Debug_append > 0 {
   2935 			Warn("append: len-only update")
   2936 		}
   2937 		// goto L2;
   2938 		// L1:
   2939 		//	update len only
   2940 		// L2:
   2941 		q := Gbranch(obj.AJMP, nil, 0)
   2942 		Patch(p, Pc)
   2943 		// At the goto above, src refers to cap and rlen holds the new len
   2944 		if src.Op == OREGISTER || src.Op == OINDREG {
   2945 			Regrealloc(&src)
   2946 		}
   2947 		Regrealloc(&rlen)
   2948 		src.Xoffset -= int64(Widthptr)
   2949 		Thearch.Gmove(&rlen, &src)
   2950 		Regfree(&src)
   2951 		Regfree(&rlen)
   2952 		Patch(q, Pc)
   2953 	}
   2954 
   2955 	// Copy data into place.
   2956 	// Could do write barrier check around entire copy instead of each element.
   2957 	// Could avoid reloading registers on each iteration if we know the cgen_wb
   2958 	// is not going to use a write barrier.
   2959 	i := 0
   2960 	var r2 Node
   2961 	for l := n.List.Next; l != nil; l = l.Next {
   2962 		Regalloc(&r1, Types[Tptr], nil)
   2963 		Thearch.Gmove(base, &r1)
   2964 		Regalloc(&r2, Types[TUINT], nil)
   2965 		Thearch.Gmove(len, &r2)
   2966 		if i > 0 {
   2967 			Thearch.Gins(Thearch.Optoas(OADD, Types[TUINT]), Nodintconst(int64(i)), &r2)
   2968 		}
   2969 		w := res.Type.Type.Width
   2970 		if Thearch.AddIndex != nil && Thearch.AddIndex(&r2, w, &r1) {
   2971 			// r1 updated by back end
   2972 		} else if w == 1 {
   2973 			Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &r2, &r1)
   2974 		} else {
   2975 			Thearch.Ginscon(Thearch.Optoas(OMUL, Types[TUINT]), int64(w), &r2)
   2976 			Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &r2, &r1)
   2977 		}
   2978 		Regfree(&r2)
   2979 
   2980 		r1.Op = OINDREG
   2981 		r1.Type = res.Type.Type
   2982 		cgen_wb(l.N, &r1, needwritebarrier(&r1, l.N))
   2983 		Regfree(&r1)
   2984 		i++
   2985 	}
   2986 }
   2987 
   2988 // Generate res = n, where n is x[i:j] or x[i:j:k].
   2989 // If wb is true, need write barrier updating res's base pointer.
   2990 // On systems with 32-bit ints, i, j, k are guaranteed to be 32-bit values.
   2991 func cgen_slice(n, res *Node, wb bool) {
   2992 	if Debug['g'] != 0 {
   2993 		Dump("cgen_slice-n", n)
   2994 		Dump("cgen_slice-res", res)
   2995 	}
   2996 
   2997 	needFullUpdate := !samesafeexpr(n.Left, res)
   2998 
   2999 	// orderexpr has made sure that x is safe (but possibly expensive)
   3000 	// and i, j, k are cheap. On a system with registers (anything but 386)
   3001 	// we can evaluate x first and then know we have enough registers
   3002 	// for i, j, k as well.
   3003 	var x, xbase, xlen, xcap, i, j, k Node
   3004 	if n.Op != OSLICEARR && n.Op != OSLICE3ARR {
   3005 		Igen(n.Left, &x, nil)
   3006 	}
   3007 
   3008 	indexRegType := Types[TUINT]
   3009 	if Widthreg > Widthptr { // amd64p32
   3010 		indexRegType = Types[TUINT64]
   3011 	}
   3012 
   3013 	// On most systems, we use registers.
   3014 	// The 386 has basically no registers, so substitute functions
   3015 	// that can work with temporaries instead.
   3016 	regalloc := Regalloc
   3017 	ginscon := Thearch.Ginscon
   3018 	gins := Thearch.Gins
   3019 	if Thearch.Thechar == '8' {
   3020 		regalloc = func(n *Node, t *Type, reuse *Node) {
   3021 			Tempname(n, t)
   3022 		}
   3023 		ginscon = func(as int, c int64, n *Node) {
   3024 			var n1 Node
   3025 			Regalloc(&n1, n.Type, n)
   3026 			Thearch.Gmove(n, &n1)
   3027 			Thearch.Ginscon(as, c, &n1)
   3028 			Thearch.Gmove(&n1, n)
   3029 			Regfree(&n1)
   3030 		}
   3031 		gins = func(as int, f, t *Node) *obj.Prog {
   3032 			var n1 Node
   3033 			Regalloc(&n1, t.Type, t)
   3034 			Thearch.Gmove(t, &n1)
   3035 			Thearch.Gins(as, f, &n1)
   3036 			Thearch.Gmove(&n1, t)
   3037 			Regfree(&n1)
   3038 			return nil
   3039 		}
   3040 	}
   3041 
   3042 	panics := make([]*obj.Prog, 0, 6) // 3 loads + 3 checks
   3043 
   3044 	loadlen := func() {
   3045 		if xlen.Op != 0 {
   3046 			return
   3047 		}
   3048 		if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
   3049 			Nodconst(&xlen, indexRegType, n.Left.Type.Type.Bound)
   3050 			return
   3051 		}
   3052 		if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
   3053 			Nodconst(&xlen, indexRegType, int64(len(n.Left.Val().U.(string))))
   3054 			return
   3055 		}
   3056 		regalloc(&xlen, indexRegType, nil)
   3057 		x.Xoffset += int64(Widthptr)
   3058 		x.Type = Types[TUINT]
   3059 		Thearch.Gmove(&x, &xlen)
   3060 		x.Xoffset -= int64(Widthptr)
   3061 	}
   3062 
   3063 	loadcap := func() {
   3064 		if xcap.Op != 0 {
   3065 			return
   3066 		}
   3067 		if n.Op == OSLICEARR || n.Op == OSLICE3ARR || n.Op == OSLICESTR {
   3068 			loadlen()
   3069 			xcap = xlen
   3070 			if xcap.Op == OREGISTER {
   3071 				Regrealloc(&xcap)
   3072 			}
   3073 			return
   3074 		}
   3075 		regalloc(&xcap, indexRegType, nil)
   3076 		x.Xoffset += 2 * int64(Widthptr)
   3077 		x.Type = Types[TUINT]
   3078 		Thearch.Gmove(&x, &xcap)
   3079 		x.Xoffset -= 2 * int64(Widthptr)
   3080 	}
   3081 
   3082 	var x1, x2, x3 *Node // unevaluated index arguments
   3083 	x1 = n.Right.Left
   3084 	switch n.Op {
   3085 	default:
   3086 		x2 = n.Right.Right
   3087 	case OSLICE3, OSLICE3ARR:
   3088 		x2 = n.Right.Right.Left
   3089 		x3 = n.Right.Right.Right
   3090 	}
   3091 
   3092 	// load computes src into targ, but if src refers to the len or cap of n.Left,
   3093 	// load copies those from xlen, xcap, loading xlen if needed.
   3094 	// If targ.Op == OREGISTER on return, it must be Regfreed,
   3095 	// but it should not be modified without first checking whether it is
   3096 	// xlen or xcap's register.
   3097 	load := func(src, targ *Node) {
   3098 		if src == nil {
   3099 			return
   3100 		}
   3101 		switch src.Op {
   3102 		case OLITERAL:
   3103 			*targ = *src
   3104 			return
   3105 		case OLEN:
   3106 			// NOTE(rsc): This doesn't actually trigger, because order.go
   3107 			// has pulled all the len and cap calls into separate assignments
   3108 			// to temporaries. There are tests in test/sliceopt.go that could
   3109 			// be enabled if this is fixed.
   3110 			if samesafeexpr(n.Left, src.Left) {
   3111 				if Debug_slice > 0 {
   3112 					Warn("slice: reuse len")
   3113 				}
   3114 				loadlen()
   3115 				*targ = xlen
   3116 				if targ.Op == OREGISTER {
   3117 					Regrealloc(targ)
   3118 				}
   3119 				return
   3120 			}
   3121 		case OCAP:
   3122 			// NOTE(rsc): This doesn't actually trigger; see note in case OLEN above.
   3123 			if samesafeexpr(n.Left, src.Left) {
   3124 				if Debug_slice > 0 {
   3125 					Warn("slice: reuse cap")
   3126 				}
   3127 				loadcap()
   3128 				*targ = xcap
   3129 				if targ.Op == OREGISTER {
   3130 					Regrealloc(targ)
   3131 				}
   3132 				return
   3133 			}
   3134 		}
   3135 		if i.Op != 0 && samesafeexpr(x1, src) {
   3136 			if Debug_slice > 0 {
   3137 				Warn("slice: reuse 1st index")
   3138 			}
   3139 			*targ = i
   3140 			if targ.Op == OREGISTER {
   3141 				Regrealloc(targ)
   3142 			}
   3143 			return
   3144 		}
   3145 		if j.Op != 0 && samesafeexpr(x2, src) {
   3146 			if Debug_slice > 0 {
   3147 				Warn("slice: reuse 2nd index")
   3148 			}
   3149 			*targ = j
   3150 			if targ.Op == OREGISTER {
   3151 				Regrealloc(targ)
   3152 			}
   3153 			return
   3154 		}
   3155 		if Thearch.Cgenindex != nil {
   3156 			regalloc(targ, indexRegType, nil)
   3157 			p := Thearch.Cgenindex(src, targ, false)
   3158 			if p != nil {
   3159 				panics = append(panics, p)
   3160 			}
   3161 		} else if Thearch.Igenindex != nil {
   3162 			p := Thearch.Igenindex(src, targ, false)
   3163 			if p != nil {
   3164 				panics = append(panics, p)
   3165 			}
   3166 		} else {
   3167 			regalloc(targ, indexRegType, nil)
   3168 			var tmp Node
   3169 			Cgenr(src, &tmp, targ)
   3170 			Thearch.Gmove(&tmp, targ)
   3171 			Regfree(&tmp)
   3172 		}
   3173 	}
   3174 
   3175 	load(x1, &i)
   3176 	load(x2, &j)
   3177 	load(x3, &k)
   3178 
   3179 	// i defaults to 0.
   3180 	if i.Op == 0 {
   3181 		Nodconst(&i, indexRegType, 0)
   3182 	}
   3183 
   3184 	// j defaults to len(x)
   3185 	if j.Op == 0 {
   3186 		loadlen()
   3187 		j = xlen
   3188 		if j.Op == OREGISTER {
   3189 			Regrealloc(&j)
   3190 		}
   3191 	}
   3192 
   3193 	// k defaults to cap(x)
   3194 	// Only need to load it if we're recalculating cap or doing a full update.
   3195 	if k.Op == 0 && n.Op != OSLICESTR && (!iszero(&i) || needFullUpdate) {
   3196 		loadcap()
   3197 		k = xcap
   3198 		if k.Op == OREGISTER {
   3199 			Regrealloc(&k)
   3200 		}
   3201 	}
   3202 
   3203 	// Check constant indexes for negative values, and against constant length if known.
   3204 	// The func obvious below checks for out-of-order constant indexes.
   3205 	var bound int64 = -1
   3206 	if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
   3207 		bound = n.Left.Type.Type.Bound
   3208 	} else if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
   3209 		bound = int64(len(n.Left.Val().U.(string)))
   3210 	}
   3211 	if Isconst(&i, CTINT) {
   3212 		if mpcmpfixc(i.Val().U.(*Mpint), 0) < 0 || bound >= 0 && mpcmpfixc(i.Val().U.(*Mpint), bound) > 0 {
   3213 			Yyerror("slice index out of bounds")
   3214 		}
   3215 	}
   3216 	if Isconst(&j, CTINT) {
   3217 		if mpcmpfixc(j.Val().U.(*Mpint), 0) < 0 || bound >= 0 && mpcmpfixc(j.Val().U.(*Mpint), bound) > 0 {
   3218 			Yyerror("slice index out of bounds")
   3219 		}
   3220 	}
   3221 	if Isconst(&k, CTINT) {
   3222 		if mpcmpfixc(k.Val().U.(*Mpint), 0) < 0 || bound >= 0 && mpcmpfixc(k.Val().U.(*Mpint), bound) > 0 {
   3223 			Yyerror("slice index out of bounds")
   3224 		}
   3225 	}
   3226 
   3227 	// same reports whether n1 and n2 are the same register or constant.
   3228 	same := func(n1, n2 *Node) bool {
   3229 		return n1.Op == OREGISTER && n2.Op == OREGISTER && n1.Reg == n2.Reg ||
   3230 			n1.Op == ONAME && n2.Op == ONAME && n1.Orig == n2.Orig && n1.Type == n2.Type && n1.Xoffset == n2.Xoffset ||
   3231 			n1.Op == OLITERAL && n2.Op == OLITERAL && Mpcmpfixfix(n1.Val().U.(*Mpint), n2.Val().U.(*Mpint)) == 0
   3232 	}
   3233 
   3234 	// obvious reports whether n1 <= n2 is obviously true,
   3235 	// and it calls Yyerror if n1 <= n2 is obviously false.
   3236 	obvious := func(n1, n2 *Node) bool {
   3237 		if Debug['B'] != 0 { // -B disables bounds checks
   3238 			return true
   3239 		}
   3240 		if same(n1, n2) {
   3241 			return true // n1 == n2
   3242 		}
   3243 		if iszero(n1) {
   3244 			return true // using unsigned compare, so 0 <= n2 always true
   3245 		}
   3246 		if xlen.Op != 0 && same(n1, &xlen) && xcap.Op != 0 && same(n2, &xcap) {
   3247 			return true // len(x) <= cap(x) always true
   3248 		}
   3249 		if Isconst(n1, CTINT) && Isconst(n2, CTINT) {
   3250 			if Mpcmpfixfix(n1.Val().U.(*Mpint), n2.Val().U.(*Mpint)) <= 0 {
   3251 				return true // n1, n2 constants such that n1 <= n2
   3252 			}
   3253 			Yyerror("slice index out of bounds")
   3254 			return true
   3255 		}
   3256 		return false
   3257 	}
   3258 
   3259 	compare := func(n1, n2 *Node) {
   3260 		// n1 might be a 64-bit constant, even on 32-bit architectures,
   3261 		// but it will be represented in 32 bits.
   3262 		if Ctxt.Arch.Regsize == 4 && Is64(n1.Type) {
   3263 			if mpcmpfixc(n1.Val().U.(*Mpint), 1<<31) >= 0 {
   3264 				Fatal("missed slice out of bounds check")
   3265 			}
   3266 			var tmp Node
   3267 			Nodconst(&tmp, indexRegType, Mpgetfix(n1.Val().U.(*Mpint)))
   3268 			n1 = &tmp
   3269 		}
   3270 		p := Thearch.Ginscmp(OGT, indexRegType, n1, n2, -1)
   3271 		panics = append(panics, p)
   3272 	}
   3273 
   3274 	loadcap()
   3275 	max := &xcap
   3276 	if k.Op != 0 && (n.Op == OSLICE3 || n.Op == OSLICE3ARR) {
   3277 		if obvious(&k, max) {
   3278 			if Debug_slice > 0 {
   3279 				Warn("slice: omit check for 3rd index")
   3280 			}
   3281 		} else {
   3282 			compare(&k, max)
   3283 		}
   3284 		max = &k
   3285 	}
   3286 	if j.Op != 0 {
   3287 		if obvious(&j, max) {
   3288 			if Debug_slice > 0 {
   3289 				Warn("slice: omit check for 2nd index")
   3290 			}
   3291 		} else {
   3292 			compare(&j, max)
   3293 		}
   3294 		max = &j
   3295 	}
   3296 	if i.Op != 0 {
   3297 		if obvious(&i, max) {
   3298 			if Debug_slice > 0 {
   3299 				Warn("slice: omit check for 1st index")
   3300 			}
   3301 		} else {
   3302 			compare(&i, max)
   3303 		}
   3304 		max = &i
   3305 	}
   3306 	if k.Op != 0 && i.Op != 0 {
   3307 		obvious(&i, &k) // emit compile-time error for x[3:n:2]
   3308 	}
   3309 
   3310 	if len(panics) > 0 {
   3311 		p := Gbranch(obj.AJMP, nil, 0)
   3312 		for _, q := range panics {
   3313 			Patch(q, Pc)
   3314 		}
   3315 		Ginscall(panicslice, -1)
   3316 		Patch(p, Pc)
   3317 	}
   3318 
   3319 	// Checks are done.
   3320 	// Compute new len as j-i, cap as k-i.
   3321 	// If i and j are same register, len is constant 0.
   3322 	// If i and k are same register, cap is constant 0.
   3323 	// If j and k are same register, len and cap are same.
   3324 
   3325 	// Done with xlen and xcap.
   3326 	// Now safe to modify j and k even if they alias xlen, xcap.
   3327 	if xlen.Op == OREGISTER {
   3328 		Regfree(&xlen)
   3329 	}
   3330 	if xcap.Op == OREGISTER {
   3331 		Regfree(&xcap)
   3332 	}
   3333 
   3334 	// are j and k the same value?
   3335 	sameJK := same(&j, &k)
   3336 
   3337 	if i.Op != 0 {
   3338 		// j -= i
   3339 		if same(&i, &j) {
   3340 			if Debug_slice > 0 {
   3341 				Warn("slice: result len == 0")
   3342 			}
   3343 			if j.Op == OREGISTER {
   3344 				Regfree(&j)
   3345 			}
   3346 			Nodconst(&j, indexRegType, 0)
   3347 		} else {
   3348 			switch j.Op {
   3349 			case OLITERAL:
   3350 				if Isconst(&i, CTINT) {
   3351 					Nodconst(&j, indexRegType, Mpgetfix(j.Val().U.(*Mpint))-Mpgetfix(i.Val().U.(*Mpint)))
   3352 					if Debug_slice > 0 {
   3353 						Warn("slice: result len == %d", Mpgetfix(j.Val().U.(*Mpint)))
   3354 					}
   3355 					break
   3356 				}
   3357 				fallthrough
   3358 			case ONAME:
   3359 				if !istemp(&j) {
   3360 					var r Node
   3361 					regalloc(&r, indexRegType, nil)
   3362 					Thearch.Gmove(&j, &r)
   3363 					j = r
   3364 				}
   3365 				fallthrough
   3366 			case OREGISTER:
   3367 				if i.Op == OLITERAL {
   3368 					v := Mpgetfix(i.Val().U.(*Mpint))
   3369 					if v != 0 {
   3370 						ginscon(Thearch.Optoas(OSUB, indexRegType), v, &j)
   3371 					}
   3372 				} else {
   3373 					gins(Thearch.Optoas(OSUB, indexRegType), &i, &j)
   3374 				}
   3375 			}
   3376 		}
   3377 
   3378 		// k -= i if k different from j and cap is needed.j
   3379 		// (The modifications to j above cannot affect i: if j and i were aliased,
   3380 		// we replace j with a constant 0 instead of doing a subtraction,
   3381 		// leaving i unmodified.)
   3382 		if k.Op == 0 {
   3383 			if Debug_slice > 0 && n.Op != OSLICESTR {
   3384 				Warn("slice: result cap not computed")
   3385 			}
   3386 			// no need
   3387 		} else if same(&i, &k) {
   3388 			if k.Op == OREGISTER {
   3389 				Regfree(&k)
   3390 			}
   3391 			Nodconst(&k, indexRegType, 0)
   3392 			if Debug_slice > 0 {
   3393 				Warn("slice: result cap == 0")
   3394 			}
   3395 		} else if sameJK {
   3396 			if Debug_slice > 0 {
   3397 				Warn("slice: result cap == result len")
   3398 			}
   3399 			// k and j were the same value; make k-i the same as j-i.
   3400 			if k.Op == OREGISTER {
   3401 				Regfree(&k)
   3402 			}
   3403 			k = j
   3404 			if k.Op == OREGISTER {
   3405 				Regrealloc(&k)
   3406 			}
   3407 		} else {
   3408 			switch k.Op {
   3409 			case OLITERAL:
   3410 				if Isconst(&i, CTINT) {
   3411 					Nodconst(&k, indexRegType, Mpgetfix(k.Val().U.(*Mpint))-Mpgetfix(i.Val().U.(*Mpint)))
   3412 					if Debug_slice > 0 {
   3413 						Warn("slice: result cap == %d", Mpgetfix(k.Val().U.(*Mpint)))
   3414 					}
   3415 					break
   3416 				}
   3417 				fallthrough
   3418 			case ONAME:
   3419 				if !istemp(&k) {
   3420 					var r Node
   3421 					regalloc(&r, indexRegType, nil)
   3422 					Thearch.Gmove(&k, &r)
   3423 					k = r
   3424 				}
   3425 				fallthrough
   3426 			case OREGISTER:
   3427 				if same(&i, &k) {
   3428 					Regfree(&k)
   3429 					Nodconst(&k, indexRegType, 0)
   3430 					if Debug_slice > 0 {
   3431 						Warn("slice: result cap == 0")
   3432 					}
   3433 				} else if i.Op == OLITERAL {
   3434 					v := Mpgetfix(i.Val().U.(*Mpint))
   3435 					if v != 0 {
   3436 						ginscon(Thearch.Optoas(OSUB, indexRegType), v, &k)
   3437 					}
   3438 				} else {
   3439 					gins(Thearch.Optoas(OSUB, indexRegType), &i, &k)
   3440 				}
   3441 			}
   3442 		}
   3443 	}
   3444 
   3445 	adjustBase := true
   3446 	if i.Op == 0 || iszero(&i) {
   3447 		if Debug_slice > 0 {
   3448 			Warn("slice: skip base adjustment for 1st index 0")
   3449 		}
   3450 		adjustBase = false
   3451 	} else if k.Op != 0 && iszero(&k) || k.Op == 0 && iszero(&j) {
   3452 		if Debug_slice > 0 {
   3453 			if n.Op == OSLICESTR {
   3454 				Warn("slice: skip base adjustment for string len == 0")
   3455 			} else {
   3456 				Warn("slice: skip base adjustment for cap == 0")
   3457 			}
   3458 		}
   3459 		adjustBase = false
   3460 	}
   3461 
   3462 	if !adjustBase && !needFullUpdate {
   3463 		if Debug_slice > 0 {
   3464 			if k.Op != 0 {
   3465 				Warn("slice: len/cap-only update")
   3466 			} else {
   3467 				Warn("slice: len-only update")
   3468 			}
   3469 		}
   3470 		if i.Op == OREGISTER {
   3471 			Regfree(&i)
   3472 		}
   3473 		// Write len (and cap if needed) back to x.
   3474 		x.Xoffset += int64(Widthptr)
   3475 		x.Type = Types[TUINT]
   3476 		Thearch.Gmove(&j, &x)
   3477 		x.Xoffset -= int64(Widthptr)
   3478 		if k.Op != 0 {
   3479 			x.Xoffset += 2 * int64(Widthptr)
   3480 			x.Type = Types[TUINT]
   3481 			Thearch.Gmove(&k, &x)
   3482 			x.Xoffset -= 2 * int64(Widthptr)
   3483 		}
   3484 		Regfree(&x)
   3485 	} else {
   3486 		// Compute new base. May smash i.
   3487 		if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
   3488 			Cgenr(n.Left, &xbase, nil)
   3489 			Cgen_checknil(&xbase)
   3490 		} else {
   3491 			regalloc(&xbase, Ptrto(res.Type.Type), nil)
   3492 			x.Type = xbase.Type
   3493 			Thearch.Gmove(&x, &xbase)
   3494 			Regfree(&x)
   3495 		}
   3496 		if i.Op != 0 && adjustBase {
   3497 			// Branch around the base adjustment if the resulting cap will be 0.
   3498 			var p *obj.Prog
   3499 			size := &k
   3500 			if k.Op == 0 {
   3501 				size = &j
   3502 			}
   3503 			if Isconst(size, CTINT) {
   3504 				// zero was checked above, must be non-zero.
   3505 			} else {
   3506 				var tmp Node
   3507 				Nodconst(&tmp, indexRegType, 0)
   3508 				p = Thearch.Ginscmp(OEQ, indexRegType, size, &tmp, -1)
   3509 			}
   3510 			var w int64
   3511 			if n.Op == OSLICESTR {
   3512 				w = 1 // res is string, elem size is 1 (byte)
   3513 			} else {
   3514 				w = res.Type.Type.Width // res is []T, elem size is T.width
   3515 			}
   3516 			if Isconst(&i, CTINT) {
   3517 				ginscon(Thearch.Optoas(OADD, xbase.Type), Mpgetfix(i.Val().U.(*Mpint))*w, &xbase)
   3518 			} else if Thearch.AddIndex != nil && Thearch.AddIndex(&i, w, &xbase) {
   3519 				// done by back end
   3520 			} else if w == 1 {
   3521 				gins(Thearch.Optoas(OADD, xbase.Type), &i, &xbase)
   3522 			} else {
   3523 				if i.Op == ONAME && !istemp(&i) {
   3524 					var tmp Node
   3525 					Tempname(&tmp, i.Type)
   3526 					Thearch.Gmove(&i, &tmp)
   3527 					i = tmp
   3528 				}
   3529 				ginscon(Thearch.Optoas(OMUL, i.Type), w, &i)
   3530 				gins(Thearch.Optoas(OADD, xbase.Type), &i, &xbase)
   3531 			}
   3532 			if p != nil {
   3533 				Patch(p, Pc)
   3534 			}
   3535 		}
   3536 		if i.Op == OREGISTER {
   3537 			Regfree(&i)
   3538 		}
   3539 
   3540 		// Write len, cap, base to result.
   3541 		if res.Op == ONAME {
   3542 			Gvardef(res)
   3543 		}
   3544 		Igen(res, &x, nil)
   3545 		x.Xoffset += int64(Widthptr)
   3546 		x.Type = Types[TUINT]
   3547 		Thearch.Gmove(&j, &x)
   3548 		x.Xoffset -= int64(Widthptr)
   3549 		if k.Op != 0 {
   3550 			x.Xoffset += 2 * int64(Widthptr)
   3551 			Thearch.Gmove(&k, &x)
   3552 			x.Xoffset -= 2 * int64(Widthptr)
   3553 		}
   3554 		x.Type = xbase.Type
   3555 		cgen_wb(&xbase, &x, wb)
   3556 		Regfree(&xbase)
   3557 		Regfree(&x)
   3558 	}
   3559 
   3560 	if j.Op == OREGISTER {
   3561 		Regfree(&j)
   3562 	}
   3563 	if k.Op == OREGISTER {
   3564 		Regfree(&k)
   3565 	}
   3566 }
   3567