github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/cmd/compile/internal/gc/cgen.go (about)

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