github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/5g/cgen.c (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  #include <u.h>
     6  #include <libc.h>
     7  #include "gg.h"
     8  
     9  /*
    10   * generate:
    11   *	res = n;
    12   * simplifies and calls gmove.
    13   */
    14  void
    15  cgen(Node *n, Node *res)
    16  {
    17  	Node *nl, *nr, *r;
    18  	Node n1, n2, f0, f1;
    19  	int a, w, rg;
    20  	Prog *p1, *p2, *p3;
    21  	Addr addr;
    22  
    23  	if(debug['g']) {
    24  		dump("\ncgen-n", n);
    25  		dump("cgen-res", res);
    26  	}
    27  	if(n == N || n->type == T)
    28  		goto ret;
    29  
    30  	if(res == N || res->type == T)
    31  		fatal("cgen: res nil");
    32  
    33  	switch(n->op) {
    34  	case OSLICE:
    35  	case OSLICEARR:
    36  	case OSLICESTR:
    37  	case OSLICE3:
    38  	case OSLICE3ARR:
    39  		if (res->op != ONAME || !res->addable) {
    40  			tempname(&n1, n->type);
    41  			cgen_slice(n, &n1);
    42  			cgen(&n1, res);
    43  		} else
    44  			cgen_slice(n, res);
    45  		return;
    46  	case OEFACE:
    47  		if (res->op != ONAME || !res->addable) {
    48  			tempname(&n1, n->type);
    49  			cgen_eface(n, &n1);
    50  			cgen(&n1, res);
    51  		} else
    52  			cgen_eface(n, res);
    53  		return;
    54  	}
    55  
    56  	while(n->op == OCONVNOP)
    57  		n = n->left;
    58  
    59  	if(n->ullman >= UINF) {
    60  		if(n->op == OINDREG)
    61  			fatal("cgen: this is going to misscompile");
    62  		if(res->ullman >= UINF) {
    63  			tempname(&n1, n->type);
    64  			cgen(n, &n1);
    65  			cgen(&n1, res);
    66  			goto ret;
    67  		}
    68  	}
    69  
    70  	if(isfat(n->type)) {
    71  		if(n->type->width < 0)
    72  			fatal("forgot to compute width for %T", n->type);
    73  		sgen(n, res, n->type->width);
    74  		goto ret;
    75  	}
    76  
    77  
    78  	// update addressability for string, slice
    79  	// can't do in walk because n->left->addable
    80  	// changes if n->left is an escaping local variable.
    81  	switch(n->op) {
    82  	case OSPTR:
    83  	case OLEN:
    84  		if(isslice(n->left->type) || istype(n->left->type, TSTRING))
    85  			n->addable = n->left->addable;
    86  		break;
    87  	case OCAP:
    88  		if(isslice(n->left->type))
    89  			n->addable = n->left->addable;
    90  		break;
    91  	case OITAB:
    92  		n->addable = n->left->addable;
    93  		break;
    94  	}
    95  
    96  	// if both are addressable, move
    97  	if(n->addable && res->addable) {
    98  		if(is64(n->type) || is64(res->type) ||
    99  		   n->op == OREGISTER || res->op == OREGISTER ||
   100  		   iscomplex[n->type->etype] || iscomplex[res->type->etype]) {
   101  			gmove(n, res);
   102  		} else {
   103  			regalloc(&n1, n->type, N);
   104  			gmove(n, &n1);
   105  			cgen(&n1, res);
   106  			regfree(&n1);
   107  		}
   108  		goto ret;
   109  	}
   110  
   111  	// if both are not addressable, use a temporary.
   112  	if(!n->addable && !res->addable) {
   113  		// could use regalloc here sometimes,
   114  		// but have to check for ullman >= UINF.
   115  		tempname(&n1, n->type);
   116  		cgen(n, &n1);
   117  		cgen(&n1, res);
   118  		return;
   119  	}
   120  
   121  	// if result is not addressable directly but n is,
   122  	// compute its address and then store via the address.
   123  	if(!res->addable) {
   124  		igen(res, &n1, N);
   125  		cgen(n, &n1);
   126  		regfree(&n1);
   127  		return;
   128  	}
   129  
   130  	if(complexop(n, res)) {
   131  		complexgen(n, res);
   132  		return;
   133  	}
   134  
   135  	// if n is sudoaddable generate addr and move
   136  	if (!is64(n->type) && !is64(res->type) && !iscomplex[n->type->etype] && !iscomplex[res->type->etype]) {
   137  		a = optoas(OAS, n->type);
   138  		if(sudoaddable(a, n, &addr, &w)) {
   139  			if (res->op != OREGISTER) {
   140  				regalloc(&n2, res->type, N);
   141  				p1 = gins(a, N, &n2);
   142  				p1->from = addr;
   143  				if(debug['g'])
   144  					print("%P [ignore previous line]\n", p1);
   145  				gmove(&n2, res);
   146  				regfree(&n2);
   147  			} else {
   148  				p1 = gins(a, N, res);
   149  				p1->from = addr;
   150  				if(debug['g'])
   151  					print("%P [ignore previous line]\n", p1);
   152  			}
   153  			sudoclean();
   154  			goto ret;
   155  		}
   156  	}
   157  
   158  	// otherwise, the result is addressable but n is not.
   159  	// let's do some computation.
   160  
   161  	nl = n->left;
   162  	nr = n->right;
   163  
   164  	if(nl != N && nl->ullman >= UINF)
   165  	if(nr != N && nr->ullman >= UINF) {
   166  		tempname(&n1, nl->type);
   167  		cgen(nl, &n1);
   168  		n2 = *n;
   169  		n2.left = &n1;
   170  		cgen(&n2, res);
   171  		goto ret;
   172  	}
   173  
   174  	// 64-bit ops are hard on 32-bit machine.
   175  	if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
   176  		switch(n->op) {
   177  		// math goes to cgen64.
   178  		case OMINUS:
   179  		case OCOM:
   180  		case OADD:
   181  		case OSUB:
   182  		case OMUL:
   183  		case OLROT:
   184  		case OLSH:
   185  		case ORSH:
   186  		case OAND:
   187  		case OOR:
   188  		case OXOR:
   189  			cgen64(n, res);
   190  			return;
   191  		}
   192  	}
   193  
   194  	if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
   195  		goto flt;
   196  	switch(n->op) {
   197  	default:
   198  		dump("cgen", n);
   199  		fatal("cgen: unknown op %+hN", n);
   200  		break;
   201  
   202  	case OREAL:
   203  	case OIMAG:
   204  	case OCOMPLEX:
   205  		fatal("unexpected complex");
   206  		break;
   207  
   208  	// these call bgen to get a bool value
   209  	case OOROR:
   210  	case OANDAND:
   211  	case OEQ:
   212  	case ONE:
   213  	case OLT:
   214  	case OLE:
   215  	case OGE:
   216  	case OGT:
   217  	case ONOT:
   218  		p1 = gbranch(AB, T, 0);
   219  		p2 = pc;
   220  		gmove(nodbool(1), res);
   221  		p3 = gbranch(AB, T, 0);
   222  		patch(p1, pc);
   223  		bgen(n, 1, 0, p2);
   224  		gmove(nodbool(0), res);
   225  		patch(p3, pc);
   226  		goto ret;
   227  
   228  	case OPLUS:
   229  		cgen(nl, res);
   230  		goto ret;
   231  
   232  	// unary
   233  	case OCOM:
   234  		a = optoas(OXOR, nl->type);
   235  		regalloc(&n1, nl->type, N);
   236  		cgen(nl, &n1);
   237  		nodconst(&n2, nl->type, -1);
   238  		gins(a, &n2, &n1);
   239  		gmove(&n1, res);
   240  		regfree(&n1);
   241  		goto ret;
   242  
   243  	case OMINUS:
   244  		regalloc(&n1, nl->type, N);
   245  		cgen(nl, &n1);
   246  		nodconst(&n2, nl->type, 0);
   247  		gins(optoas(OMINUS, nl->type), &n2, &n1);
   248  		gmove(&n1, res);
   249  		regfree(&n1);
   250  		goto ret;
   251  
   252  	// symmetric binary
   253  	case OAND:
   254  	case OOR:
   255  	case OXOR:
   256  	case OADD:
   257  	case OMUL:
   258  		a = optoas(n->op, nl->type);
   259  		goto sbop;
   260  
   261  	// asymmetric binary
   262  	case OSUB:
   263  		a = optoas(n->op, nl->type);
   264  		goto abop;
   265  
   266  	case OHMUL:
   267  		cgen_hmul(nl, nr, res);
   268  		break;
   269  
   270  	case OLROT:
   271  	case OLSH:
   272  	case ORSH:
   273  		cgen_shift(n->op, n->bounded, nl, nr, res);
   274  		break;
   275  
   276  	case OCONV:
   277  		if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
   278  			cgen(nl, res);
   279  			break;
   280  		}
   281  		if(nl->addable && !is64(nl->type)) {
   282  			regalloc(&n1, nl->type, res);
   283  			gmove(nl, &n1);
   284  		} else {
   285  			if(n->type->width > widthptr || is64(nl->type) || isfloat[nl->type->etype])
   286  				tempname(&n1, nl->type);
   287  			else
   288  				regalloc(&n1, nl->type, res);
   289  			cgen(nl, &n1);
   290  		}
   291  		if(n->type->width > widthptr || is64(n->type) || isfloat[n->type->etype])
   292  			tempname(&n2, n->type);
   293  		else
   294  			regalloc(&n2, n->type, N);
   295  		gmove(&n1, &n2);
   296  		gmove(&n2, res);
   297  		if(n1.op == OREGISTER)
   298  			regfree(&n1);
   299  		if(n2.op == OREGISTER)
   300  			regfree(&n2);
   301  		break;
   302  
   303  	case ODOT:
   304  	case ODOTPTR:
   305  	case OINDEX:
   306  	case OIND:
   307  	case ONAME:	// PHEAP or PPARAMREF var
   308  		igen(n, &n1, res);
   309  		gmove(&n1, res);
   310  		regfree(&n1);
   311  		break;
   312  
   313  	case OITAB:
   314  		// interface table is first word of interface value
   315  		igen(nl, &n1, res);
   316  		n1.type = n->type;
   317  		gmove(&n1, res);
   318  		regfree(&n1);
   319  		break;
   320  
   321  	case OSPTR:
   322  		// pointer is the first word of string or slice.
   323  		if(isconst(nl, CTSTR)) {
   324  			regalloc(&n1, types[tptr], res);
   325  			p1 = gins(AMOVW, N, &n1);
   326  			datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
   327  			gmove(&n1, res);
   328  			regfree(&n1);
   329  			break;
   330  		}
   331  		igen(nl, &n1, res);
   332  		n1.type = n->type;
   333  		gmove(&n1, res);
   334  		regfree(&n1);
   335  		break;
   336  
   337  	case OLEN:
   338  		if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
   339  			// map has len in the first 32-bit word.
   340  			// a zero pointer means zero length
   341  			regalloc(&n1, types[tptr], res);
   342  			cgen(nl, &n1);
   343  
   344  			nodconst(&n2, types[tptr], 0);
   345  			gcmp(optoas(OCMP, types[tptr]), &n1, &n2);
   346  			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
   347  
   348  			n2 = n1;
   349  			n2.op = OINDREG;
   350  			n2.type = types[TINT32];
   351  			gmove(&n2, &n1);
   352  
   353  			patch(p1, pc);
   354  
   355  			gmove(&n1, res);
   356  			regfree(&n1);
   357  			break;
   358  		}
   359  		if(istype(nl->type, TSTRING) || isslice(nl->type)) {
   360  			// both slice and string have len one pointer into the struct.
   361  			igen(nl, &n1, res);
   362  			n1.type = types[TUINT32];
   363  			n1.xoffset += Array_nel;
   364  			gmove(&n1, res);
   365  			regfree(&n1);
   366  			break;
   367  		}
   368  		fatal("cgen: OLEN: unknown type %lT", nl->type);
   369  		break;
   370  
   371  	case OCAP:
   372  		if(istype(nl->type, TCHAN)) {
   373  			// chan has cap in the second 32-bit word.
   374  			// a zero pointer means zero length
   375  			regalloc(&n1, types[tptr], res);
   376  			cgen(nl, &n1);
   377  
   378  			nodconst(&n2, types[tptr], 0);
   379  			gcmp(optoas(OCMP, types[tptr]), &n1, &n2);
   380  			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
   381  
   382  			n2 = n1;
   383  			n2.op = OINDREG;
   384  			n2.xoffset = 4;
   385  			n2.type = types[TINT32];
   386  			gmove(&n2, &n1);
   387  
   388  			patch(p1, pc);
   389  
   390  			gmove(&n1, res);
   391  			regfree(&n1);
   392  			break;
   393  		}
   394  		if(isslice(nl->type)) {
   395  			igen(nl, &n1, res);
   396  			n1.type = types[TUINT32];
   397  			n1.xoffset += Array_cap;
   398  			gmove(&n1, res);
   399  			regfree(&n1);
   400  			break;
   401  		}
   402  		fatal("cgen: OCAP: unknown type %lT", nl->type);
   403  		break;
   404  
   405  	case OADDR:
   406  		agen(nl, res);
   407  		break;
   408  
   409  	case OCALLMETH:
   410  	case OCALLFUNC:
   411  		// Release res so that it is available for cgen_call.
   412  		// Pick it up again after the call.
   413  		rg = -1;
   414  		if(n->ullman >= UINF) {
   415  			if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
   416  				rg = res->val.u.reg;
   417  				reg[rg]--;
   418  			}
   419  		}
   420  		if(n->op == OCALLMETH)
   421  			cgen_callmeth(n, 0);
   422  		else
   423  			cgen_call(n, 0);
   424  		if(rg >= 0)
   425  			reg[rg]++;
   426  		cgen_callret(n, res);
   427  		break;
   428  
   429  	case OCALLINTER:
   430  		cgen_callinter(n, res, 0);
   431  		cgen_callret(n, res);
   432  		break;
   433  
   434  	case OMOD:
   435  	case ODIV:
   436  		a = optoas(n->op, nl->type);
   437  		goto abop;
   438  	}
   439  	goto ret;
   440  
   441  sbop:	// symmetric binary
   442  	if(nl->ullman < nr->ullman) {
   443  		r = nl;
   444  		nl = nr;
   445  		nr = r;
   446  	}
   447  
   448  abop:	// asymmetric binary
   449  	// TODO(kaib): use fewer registers here.
   450  	if(nl->ullman >= nr->ullman) {
   451  		regalloc(&n1, nl->type, res);
   452  		cgen(nl, &n1);
   453  		switch(n->op) {
   454  		case OADD:
   455  		case OSUB:
   456  		case OAND:
   457  		case OOR:
   458  		case OXOR:
   459  			if(smallintconst(nr)) {
   460  				n2 = *nr;
   461  				break;
   462  			}
   463  		default:
   464  			regalloc(&n2, nr->type, N);
   465  			cgen(nr, &n2);
   466  		}
   467  	} else {
   468  		switch(n->op) {
   469  		case OADD:
   470  		case OSUB:
   471  		case OAND:
   472  		case OOR:
   473  		case OXOR:
   474  			if(smallintconst(nr)) {
   475  				n2 = *nr;
   476  				break;
   477  			}
   478  		default:
   479  			regalloc(&n2, nr->type, res);
   480  			cgen(nr, &n2);
   481  		}
   482  		regalloc(&n1, nl->type, N);
   483  		cgen(nl, &n1);
   484  	}
   485  	gins(a, &n2, &n1);
   486  	// Normalize result for types smaller than word.
   487  	if(n->type->width < widthptr) {
   488  		switch(n->op) {
   489  		case OADD:
   490  		case OSUB:
   491  		case OMUL:
   492  			gins(optoas(OAS, n->type), &n1, &n1);
   493  			break;
   494  		}
   495  	}
   496  	gmove(&n1, res);
   497  	regfree(&n1);
   498  	if(n2.op != OLITERAL)
   499  		regfree(&n2);
   500  	goto ret;
   501  
   502  flt:	// floating-point.
   503  	regalloc(&f0, nl->type, res);
   504  	if(nr != N)
   505  		goto flt2;
   506  
   507  	if(n->op == OMINUS) {
   508  		nr = nodintconst(-1);
   509  		convlit(&nr, n->type);
   510  		n->op = OMUL;
   511  		goto flt2;
   512  	}
   513  
   514  	// unary
   515  	cgen(nl, &f0);
   516  	if(n->op != OCONV && n->op != OPLUS)
   517  		gins(optoas(n->op, n->type), &f0, &f0);
   518  	gmove(&f0, res);
   519  	regfree(&f0);
   520  	goto ret;
   521  
   522  flt2:	// binary
   523  	if(nl->ullman >= nr->ullman) {
   524  		cgen(nl, &f0);
   525  		regalloc(&f1, n->type, N);
   526  		gmove(&f0, &f1);
   527  		cgen(nr, &f0);
   528  		gins(optoas(n->op, n->type), &f0, &f1);
   529  	} else {
   530  		cgen(nr, &f0);
   531  		regalloc(&f1, n->type, N);
   532  		cgen(nl, &f1);
   533  		gins(optoas(n->op, n->type), &f0, &f1);
   534  	}
   535  	gmove(&f1, res);
   536  	regfree(&f0);
   537  	regfree(&f1);
   538  	goto ret;
   539  
   540  ret:
   541  	;
   542  }
   543  
   544  /*
   545   * generate array index into res.
   546   * n might be any size; res is 32-bit.
   547   * returns Prog* to patch to panic call.
   548   */
   549  Prog*
   550  cgenindex(Node *n, Node *res, int bounded)
   551  {
   552  	Node tmp, lo, hi, zero, n1, n2;
   553  
   554  	if(!is64(n->type)) {
   555  		cgen(n, res);
   556  		return nil;
   557  	}
   558  
   559  	tempname(&tmp, types[TINT64]);
   560  	cgen(n, &tmp);
   561  	split64(&tmp, &lo, &hi);
   562  	gmove(&lo, res);
   563  	if(bounded) {
   564  		splitclean();
   565  		return nil;
   566  	}
   567  	regalloc(&n1, types[TINT32], N);
   568  	regalloc(&n2, types[TINT32], N);
   569  	nodconst(&zero, types[TINT32], 0);
   570  	gmove(&hi, &n1);
   571  	gmove(&zero, &n2);
   572  	gcmp(ACMP, &n1, &n2);
   573  	regfree(&n2);
   574  	regfree(&n1);
   575  	splitclean();
   576  	return gbranch(ABNE, T, -1);
   577  }
   578  
   579  /*
   580   * generate:
   581   *	res = &n;
   582   * The generated code checks that the result is not nil.
   583   */
   584  void
   585  agen(Node *n, Node *res)
   586  {
   587  	Node *nl;
   588  	Node n1, n2, n3;
   589  	int r;
   590  
   591  	if(debug['g']) {
   592  		dump("\nagen-res", res);
   593  		dump("agen-r", n);
   594  	}
   595  	if(n == N || n->type == T || res == N || res->type == T)
   596  		fatal("agen");
   597  
   598  	while(n->op == OCONVNOP)
   599  		n = n->left;
   600  
   601  	if(isconst(n, CTNIL) && n->type->width > widthptr) {
   602  		// Use of a nil interface or nil slice.
   603  		// Create a temporary we can take the address of and read.
   604  		// The generated code is just going to panic, so it need not
   605  		// be terribly efficient. See issue 3670.
   606  		tempname(&n1, n->type);
   607  		gvardef(&n1);
   608  		clearfat(&n1);
   609  		regalloc(&n2, types[tptr], res);
   610  		gins(AMOVW, &n1, &n2);
   611  		gmove(&n2, res);
   612  		regfree(&n2);
   613  		goto ret;
   614  	}
   615  		
   616  
   617  	if(n->addable) {
   618  		memset(&n1, 0, sizeof n1);
   619  		n1.op = OADDR;
   620  		n1.left = n;
   621  		regalloc(&n2, types[tptr], res);
   622  		gins(AMOVW, &n1, &n2);
   623  		gmove(&n2, res);
   624  		regfree(&n2);
   625  		goto ret;
   626  	}
   627  
   628  	nl = n->left;
   629  
   630  	switch(n->op) {
   631  	default:
   632  		fatal("agen: unknown op %+hN", n);
   633  		break;
   634  
   635  	case OCALLMETH:
   636  	case OCALLFUNC:
   637  		// Release res so that it is available for cgen_call.
   638  		// Pick it up again after the call.
   639  		r = -1;
   640  		if(n->ullman >= UINF) {
   641  			if(res->op == OREGISTER || res->op == OINDREG) {
   642  				r = res->val.u.reg;
   643  				reg[r]--;
   644  			}
   645  		}
   646  		if(n->op == OCALLMETH)
   647  			cgen_callmeth(n, 0);
   648  		else
   649  			cgen_call(n, 0);
   650  		if(r >= 0)
   651  			reg[r]++;
   652  		cgen_aret(n, res);
   653  		break;
   654  
   655  	case OCALLINTER:
   656  		cgen_callinter(n, res, 0);
   657  		cgen_aret(n, res);
   658  		break;
   659  
   660  	case OSLICE:
   661  	case OSLICEARR:
   662  	case OSLICESTR:
   663  	case OSLICE3:
   664  	case OSLICE3ARR:
   665  		tempname(&n1, n->type);
   666  		cgen_slice(n, &n1);
   667  		agen(&n1, res);
   668  		break;
   669  
   670  	case OEFACE:
   671  		tempname(&n1, n->type);
   672  		cgen_eface(n, &n1);
   673  		agen(&n1, res);
   674  		break;
   675  
   676  	case OINDEX:
   677  		agenr(n, &n1, res);
   678  		gmove(&n1, res);
   679  		regfree(&n1);
   680  		break;
   681  
   682  	case ONAME:
   683  		// should only get here with names in this func.
   684  		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
   685  			dump("bad agen", n);
   686  			fatal("agen: bad ONAME funcdepth %d != %d",
   687  				n->funcdepth, funcdepth);
   688  		}
   689  
   690  		// should only get here for heap vars or paramref
   691  		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
   692  			dump("bad agen", n);
   693  			fatal("agen: bad ONAME class %#x", n->class);
   694  		}
   695  		cgen(n->heapaddr, res);
   696  		if(n->xoffset != 0) {
   697  			nodconst(&n1, types[TINT32], n->xoffset);
   698  			regalloc(&n2, n1.type, N);
   699  			regalloc(&n3, types[TINT32], N);
   700  			gmove(&n1, &n2);
   701  			gmove(res, &n3);
   702  			gins(optoas(OADD, types[tptr]), &n2, &n3);
   703  			gmove(&n3, res);
   704  			regfree(&n2);
   705  			regfree(&n3);
   706  		}
   707  		break;
   708  
   709  	case OIND:
   710  		cgen(nl, res);
   711  		cgen_checknil(res);
   712  		break;
   713  
   714  	case ODOT:
   715  		agen(nl, res);
   716  		if(n->xoffset != 0) {
   717  			nodconst(&n1, types[TINT32], n->xoffset);
   718  			regalloc(&n2, n1.type, N);
   719  			regalloc(&n3, types[TINT32], N);
   720  			gmove(&n1, &n2);
   721  			gmove(res, &n3);
   722  			gins(optoas(OADD, types[tptr]), &n2, &n3);
   723  			gmove(&n3, res);
   724  			regfree(&n2);
   725  			regfree(&n3);
   726  		}
   727  		break;
   728  
   729  	case ODOTPTR:
   730  		cgen(nl, res);
   731  		cgen_checknil(res);
   732  		if(n->xoffset != 0) {
   733  			nodconst(&n1, types[TINT32], n->xoffset);
   734  			regalloc(&n2, n1.type, N);
   735  			regalloc(&n3, types[tptr], N);
   736  			gmove(&n1, &n2);
   737  			gmove(res, &n3);
   738  			gins(optoas(OADD, types[tptr]), &n2, &n3);
   739  			gmove(&n3, res);
   740  			regfree(&n2);
   741  			regfree(&n3);
   742  		}
   743  		break;
   744  	}
   745  
   746  ret:
   747  	;
   748  }
   749  
   750  /*
   751   * generate:
   752   *	newreg = &n;
   753   *	res = newreg
   754   *
   755   * on exit, a has been changed to be *newreg.
   756   * caller must regfree(a).
   757   * The generated code checks that the result is not *nil.
   758   */
   759  void
   760  igen(Node *n, Node *a, Node *res)
   761  {
   762  	Node n1;
   763  	int r;
   764  
   765  	if(debug['g']) {
   766  		dump("\nigen-n", n);
   767  	}
   768  	switch(n->op) {
   769  	case ONAME:
   770  		if((n->class&PHEAP) || n->class == PPARAMREF)
   771  			break;
   772  		*a = *n;
   773  		return;
   774  
   775  	case OINDREG:
   776  		// Increase the refcount of the register so that igen's caller
   777  		// has to call regfree.
   778  		if(n->val.u.reg != REGSP)
   779  			reg[n->val.u.reg]++;
   780  		*a = *n;
   781  		return;
   782  
   783  	case ODOT:
   784  		igen(n->left, a, res);
   785  		a->xoffset += n->xoffset;
   786  		a->type = n->type;
   787  		return;
   788  
   789  	case ODOTPTR:
   790  		if(n->left->addable
   791  			|| n->left->op == OCALLFUNC
   792  			|| n->left->op == OCALLMETH
   793  			|| n->left->op == OCALLINTER) {
   794  			// igen-able nodes.
   795  			igen(n->left, &n1, res);
   796  			regalloc(a, types[tptr], &n1);
   797  			gmove(&n1, a);
   798  			regfree(&n1);
   799  		} else {
   800  			regalloc(a, types[tptr], res);
   801  			cgen(n->left, a);
   802  		}
   803  		cgen_checknil(a);
   804  		a->op = OINDREG;
   805  		a->xoffset = n->xoffset;
   806  		a->type = n->type;
   807  		return;
   808  
   809  	case OCALLMETH:
   810  	case OCALLFUNC:
   811  	case OCALLINTER:
   812  		// Release res so that it is available for cgen_call.
   813  		// Pick it up again after the call.
   814  		r = -1;
   815  		if(n->ullman >= UINF) {
   816  			if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
   817  				r = res->val.u.reg;
   818  				reg[r]--;
   819  			}
   820  		}
   821  		switch(n->op) {
   822  		case OCALLMETH:
   823  			cgen_callmeth(n, 0);
   824  			break;
   825  		case OCALLFUNC:
   826  			cgen_call(n, 0);
   827  			break;
   828  		case OCALLINTER:
   829  			cgen_callinter(n, N, 0);
   830  			break;
   831  		}
   832  		if(r >= 0)
   833  			reg[r]++;
   834  		regalloc(a, types[tptr], res);
   835  		cgen_aret(n, a);
   836  		a->op = OINDREG;
   837  		a->type = n->type;
   838  		return;
   839  	}
   840  
   841  	agenr(n, a, res);
   842  	a->op = OINDREG;
   843  	a->type = n->type;
   844  }
   845  
   846  /*
   847   * allocate a register in res and generate
   848   *  newreg = &n
   849   * The caller must call regfree(a).
   850   */
   851  void
   852  cgenr(Node *n, Node *a, Node *res)
   853  {
   854  	Node n1;
   855  
   856  	if(debug['g'])
   857  		dump("cgenr-n", n);
   858  
   859  	if(isfat(n->type))
   860  		fatal("cgenr on fat node");
   861  
   862  	if(n->addable) {
   863  		regalloc(a, types[tptr], res);
   864  		gmove(n, a);
   865  		return;
   866  	}
   867  
   868  	switch(n->op) {
   869  	case ONAME:
   870  	case ODOT:
   871  	case ODOTPTR:
   872  	case OINDEX:
   873  	case OCALLFUNC:
   874  	case OCALLMETH:
   875  	case OCALLINTER:
   876  		igen(n, &n1, res);
   877  		regalloc(a, types[tptr], &n1);
   878  		gmove(&n1, a);
   879  		regfree(&n1);
   880  		break;
   881  	default:
   882  		regalloc(a, n->type, res);
   883  		cgen(n, a);
   884  		break;
   885  	}
   886  }
   887  
   888  /*
   889   * generate:
   890   *	newreg = &n;
   891   *
   892   * caller must regfree(a).
   893   * The generated code checks that the result is not nil.
   894   */
   895  void
   896  agenr(Node *n, Node *a, Node *res)
   897  {
   898  	Node *nl, *nr;
   899  	Node n1, n2, n3, n4, tmp;
   900  	Prog *p1, *p2;
   901  	uint32 w;
   902  	uint64 v;
   903  	int bounded;
   904  
   905  	if(debug['g'])
   906  		dump("agenr-n", n);
   907  
   908  	nl = n->left;
   909  	nr = n->right;
   910  
   911  	switch(n->op) {
   912  	case ODOT:
   913  	case ODOTPTR:
   914  	case OCALLFUNC:
   915  	case OCALLMETH:
   916  	case OCALLINTER:
   917  		igen(n, &n1, res);
   918  		regalloc(a, types[tptr], &n1);
   919  		agen(&n1, a);
   920  		regfree(&n1);
   921  		break;
   922  
   923  	case OIND:
   924  		cgenr(n->left, a, res);
   925  		cgen_checknil(a);
   926  		break;
   927  
   928  	case OINDEX:
   929  		p2 = nil;  // to be patched to panicindex.
   930  		w = n->type->width;
   931  		bounded = debug['B'] || n->bounded;
   932  		if(nr->addable) {
   933  			if(!isconst(nr, CTINT))
   934  				tempname(&tmp, types[TINT32]);
   935  			if(!isconst(nl, CTSTR))
   936  				agenr(nl, &n3, res);
   937  			if(!isconst(nr, CTINT)) {
   938  				p2 = cgenindex(nr, &tmp, bounded);
   939  				regalloc(&n1, tmp.type, N);
   940  				gmove(&tmp, &n1);
   941  			}
   942  		} else
   943  		if(nl->addable) {
   944  			if(!isconst(nr, CTINT)) {
   945  				tempname(&tmp, types[TINT32]);
   946  				p2 = cgenindex(nr, &tmp, bounded);
   947  				regalloc(&n1, tmp.type, N);
   948  				gmove(&tmp, &n1);
   949  			}
   950  			if(!isconst(nl, CTSTR)) {
   951  				agenr(nl, &n3, res);
   952  			}
   953  		} else {
   954  			tempname(&tmp, types[TINT32]);
   955  			p2 = cgenindex(nr, &tmp, bounded);
   956  			nr = &tmp;
   957  			if(!isconst(nl, CTSTR))
   958  				agenr(nl, &n3, res);
   959  			regalloc(&n1, tmp.type, N);
   960  			gins(optoas(OAS, tmp.type), &tmp, &n1);
   961  		}
   962  
   963  		// &a is in &n3 (allocated in res)
   964  		// i is in &n1 (if not constant)
   965  		// w is width
   966  
   967  		// constant index
   968  		if(isconst(nr, CTINT)) {
   969  			if(isconst(nl, CTSTR))
   970  				fatal("constant string constant index");
   971  			v = mpgetfix(nr->val.u.xval);
   972  			if(isslice(nl->type) || nl->type->etype == TSTRING) {
   973  				if(!debug['B'] && !n->bounded) {
   974  					n1 = n3;
   975  					n1.op = OINDREG;
   976  					n1.type = types[tptr];
   977  					n1.xoffset = Array_nel;
   978  					regalloc(&n4, n1.type, N);
   979  					gmove(&n1, &n4);
   980  					nodconst(&n2, types[TUINT32], v);
   981  					gcmp(optoas(OCMP, types[TUINT32]), &n4, &n2);
   982  					regfree(&n4);
   983  					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
   984  					ginscall(panicindex, 0);
   985  					patch(p1, pc);
   986  				}
   987  
   988  				n1 = n3;
   989  				n1.op = OINDREG;
   990  				n1.type = types[tptr];
   991  				n1.xoffset = Array_array;
   992  				gmove(&n1, &n3);
   993  			}
   994  
   995  			nodconst(&n2, types[tptr], v*w);
   996  			gins(optoas(OADD, types[tptr]), &n2, &n3);
   997  			*a = n3;
   998  			break;
   999  		}
  1000  
  1001  		regalloc(&n2, types[TINT32], &n1);			// i
  1002  		gmove(&n1, &n2);
  1003  		regfree(&n1);
  1004  
  1005  		if(!debug['B'] && !n->bounded) {
  1006  			// check bounds
  1007  			if(isconst(nl, CTSTR)) {
  1008  				nodconst(&n4, types[TUINT32], nl->val.u.sval->len);
  1009  			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
  1010  				n1 = n3;
  1011  				n1.op = OINDREG;
  1012  				n1.type = types[tptr];
  1013  				n1.xoffset = Array_nel;
  1014  				regalloc(&n4, types[TUINT32], N);
  1015  				gmove(&n1, &n4);
  1016  			} else {
  1017  				nodconst(&n4, types[TUINT32], nl->type->bound);
  1018  			}
  1019  			gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
  1020  			if(n4.op == OREGISTER)
  1021  				regfree(&n4);
  1022  			p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
  1023  			if(p2)
  1024  				patch(p2, pc);
  1025  			ginscall(panicindex, 0);
  1026  			patch(p1, pc);
  1027  		}
  1028  		
  1029  		if(isconst(nl, CTSTR)) {
  1030  			regalloc(&n3, types[tptr], res);
  1031  			p1 = gins(AMOVW, N, &n3);
  1032  			datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
  1033  			p1->from.type = D_CONST;
  1034  		} else
  1035  		if(isslice(nl->type) || nl->type->etype == TSTRING) {
  1036  			n1 = n3;
  1037  			n1.op = OINDREG;
  1038  			n1.type = types[tptr];
  1039  			n1.xoffset = Array_array;
  1040  			gmove(&n1, &n3);
  1041  		}
  1042  
  1043  		if(w == 0) {
  1044  			// nothing to do
  1045  		} else if(w == 1 || w == 2 || w == 4 || w == 8) {
  1046  			memset(&n4, 0, sizeof n4);
  1047  			n4.op = OADDR;
  1048  			n4.left = &n2;
  1049  			cgen(&n4, &n3);
  1050  			if (w == 1)
  1051  				gins(AADD, &n2, &n3);
  1052  			else if(w == 2)
  1053  				gshift(AADD, &n2, SHIFT_LL, 1, &n3);
  1054  			else if(w == 4)
  1055  				gshift(AADD, &n2, SHIFT_LL, 2, &n3);
  1056  			else if(w == 8)
  1057  				gshift(AADD, &n2, SHIFT_LL, 3, &n3);
  1058  		} else {
  1059  			regalloc(&n4, types[TUINT32], N);
  1060  			nodconst(&n1, types[TUINT32], w);
  1061  			gmove(&n1, &n4);
  1062  			gins(optoas(OMUL, types[TUINT32]), &n4, &n2);
  1063  			gins(optoas(OADD, types[tptr]), &n2, &n3);
  1064  			regfree(&n4);
  1065  		}
  1066  
  1067  		*a = n3;
  1068  		regfree(&n2);
  1069  		break;
  1070  
  1071  	default:
  1072  		regalloc(a, types[tptr], res);
  1073  		agen(n, a);
  1074  		break;
  1075  	}
  1076  }
  1077  
  1078  void
  1079  gencmp0(Node *n, Type *t, int o, int likely, Prog *to)
  1080  {
  1081  	Node n1, n2, n3;
  1082  	int a;
  1083  
  1084  	regalloc(&n1, t, N);
  1085  	cgen(n, &n1);
  1086  	a = optoas(OCMP, t);
  1087  	if(a != ACMP) {
  1088  		nodconst(&n2, t, 0);
  1089  		regalloc(&n3, t, N);
  1090  		gmove(&n2, &n3);
  1091  		gcmp(a, &n1, &n3);
  1092  		regfree(&n3);
  1093  	} else
  1094  		gins(ATST, &n1, N);
  1095  	a = optoas(o, t);
  1096  	patch(gbranch(a, t, likely), to);
  1097  	regfree(&n1);
  1098  }
  1099  
  1100  /*
  1101   * generate:
  1102   *	if(n == true) goto to;
  1103   */
  1104  void
  1105  bgen(Node *n, int true, int likely, Prog *to)
  1106  {
  1107  	int et, a;
  1108  	Node *nl, *nr, *r;
  1109  	Node n1, n2, n3, tmp;
  1110  	NodeList *ll;
  1111  	Prog *p1, *p2;
  1112  
  1113  	if(debug['g']) {
  1114  		dump("\nbgen", n);
  1115  	}
  1116  
  1117  	if(n == N)
  1118  		n = nodbool(1);
  1119  
  1120  	if(n->ninit != nil)
  1121  		genlist(n->ninit);
  1122  
  1123  	if(n->type == T) {
  1124  		convlit(&n, types[TBOOL]);
  1125  		if(n->type == T)
  1126  			goto ret;
  1127  	}
  1128  
  1129  	et = n->type->etype;
  1130  	if(et != TBOOL) {
  1131  		yyerror("cgen: bad type %T for %O", n->type, n->op);
  1132  		patch(gins(AEND, N, N), to);
  1133  		goto ret;
  1134  	}
  1135  	nr = N;
  1136  
  1137  	switch(n->op) {
  1138  	default:
  1139  		a = ONE;
  1140  		if(!true)
  1141  			a = OEQ;
  1142  		gencmp0(n, n->type, a, likely, to);
  1143  		goto ret;
  1144  
  1145  	case OLITERAL:
  1146  		// need to ask if it is bool?
  1147  		if(!true == !n->val.u.bval)
  1148  			patch(gbranch(AB, T, 0), to);
  1149  		goto ret;
  1150  
  1151  	case OANDAND:
  1152  		if(!true)
  1153  			goto caseor;
  1154  
  1155  	caseand:
  1156  		p1 = gbranch(AB, T, 0);
  1157  		p2 = gbranch(AB, T, 0);
  1158  		patch(p1, pc);
  1159  		bgen(n->left, !true, -likely, p2);
  1160  		bgen(n->right, !true, -likely, p2);
  1161  		p1 = gbranch(AB, T, 0);
  1162  		patch(p1, to);
  1163  		patch(p2, pc);
  1164  		goto ret;
  1165  
  1166  	case OOROR:
  1167  		if(!true)
  1168  			goto caseand;
  1169  
  1170  	caseor:
  1171  		bgen(n->left, true, likely, to);
  1172  		bgen(n->right, true, likely, to);
  1173  		goto ret;
  1174  
  1175  	case OEQ:
  1176  	case ONE:
  1177  	case OLT:
  1178  	case OGT:
  1179  	case OLE:
  1180  	case OGE:
  1181  		nr = n->right;
  1182  		if(nr == N || nr->type == T)
  1183  			goto ret;
  1184  
  1185  	case ONOT:	// unary
  1186  		nl = n->left;
  1187  		if(nl == N || nl->type == T)
  1188  			goto ret;
  1189  	}
  1190  
  1191  	switch(n->op) {
  1192  
  1193  	case ONOT:
  1194  		bgen(nl, !true, likely, to);
  1195  		goto ret;
  1196  
  1197  	case OEQ:
  1198  	case ONE:
  1199  	case OLT:
  1200  	case OGT:
  1201  	case OLE:
  1202  	case OGE:
  1203  		a = n->op;
  1204  		if(!true) {
  1205  			if(isfloat[nl->type->etype]) {
  1206  				// brcom is not valid on floats when NaN is involved.
  1207  				p1 = gbranch(AB, T, 0);
  1208  				p2 = gbranch(AB, T, 0);
  1209  				patch(p1, pc);
  1210  				ll = n->ninit;
  1211  				n->ninit = nil;
  1212  				bgen(n, 1, -likely, p2);
  1213  				n->ninit = ll;
  1214  				patch(gbranch(AB, T, 0), to);
  1215  				patch(p2, pc);
  1216  				goto ret;
  1217  			}				
  1218  			a = brcom(a);
  1219  			true = !true;
  1220  		}
  1221  
  1222  		// make simplest on right
  1223  		if(nl->op == OLITERAL || (nl->ullman < UINF && nl->ullman < nr->ullman)) {
  1224  			a = brrev(a);
  1225  			r = nl;
  1226  			nl = nr;
  1227  			nr = r;
  1228  		}
  1229  
  1230  		if(isslice(nl->type)) {
  1231  			// only valid to cmp darray to literal nil
  1232  			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
  1233  				yyerror("illegal array comparison");
  1234  				break;
  1235  			}
  1236  
  1237  			igen(nl, &n1, N);
  1238  			n1.xoffset += Array_array;
  1239  			n1.type = types[tptr];
  1240  			gencmp0(&n1, types[tptr], a, likely, to);
  1241  			regfree(&n1);
  1242  			break;
  1243  		}
  1244  
  1245  		if(isinter(nl->type)) {
  1246  			// front end shold only leave cmp to literal nil
  1247  			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
  1248  				yyerror("illegal interface comparison");
  1249  				break;
  1250  			}
  1251  
  1252  			igen(nl, &n1, N);
  1253  			n1.type = types[tptr];
  1254  			n1.xoffset += 0;
  1255  			gencmp0(&n1, types[tptr], a, likely, to);
  1256  			regfree(&n1);
  1257  			break;
  1258  		}
  1259  
  1260  		if(iscomplex[nl->type->etype]) {
  1261  			complexbool(a, nl, nr, true, likely, to);
  1262  			break;
  1263  		}
  1264  
  1265  		if(is64(nr->type)) {
  1266  			if(!nl->addable) {
  1267  				tempname(&n1, nl->type);
  1268  				cgen(nl, &n1);
  1269  				nl = &n1;
  1270  			}
  1271  			if(!nr->addable) {
  1272  				tempname(&n2, nr->type);
  1273  				cgen(nr, &n2);
  1274  				nr = &n2;
  1275  			}
  1276  			cmp64(nl, nr, a, likely, to);
  1277  			break;
  1278  		}
  1279  
  1280  		if(nr->op == OLITERAL) {
  1281  			if(isconst(nr, CTINT) &&  mpgetfix(nr->val.u.xval) == 0) {
  1282  				gencmp0(nl, nl->type, a, likely, to);
  1283  				break;
  1284  			}
  1285  			if(nr->val.ctype == CTNIL) {
  1286  				gencmp0(nl, nl->type, a, likely, to);
  1287  				break;
  1288  			}
  1289  		}
  1290  
  1291  		a = optoas(a, nr->type);
  1292  
  1293  		if(nr->ullman >= UINF) {
  1294  			regalloc(&n1, nl->type, N);
  1295  			cgen(nl, &n1);
  1296  
  1297  			tempname(&tmp, nl->type);
  1298  			gmove(&n1, &tmp);
  1299  			regfree(&n1);
  1300  
  1301  			regalloc(&n2, nr->type, N);
  1302  			cgen(nr, &n2);
  1303  
  1304  			regalloc(&n1, nl->type, N);
  1305  			cgen(&tmp, &n1);
  1306  
  1307  			gcmp(optoas(OCMP, nr->type), &n1, &n2);
  1308  			patch(gbranch(a, nr->type, likely), to);
  1309  
  1310  			regfree(&n1);
  1311  			regfree(&n2);
  1312  			break;
  1313  		}
  1314  
  1315  		tempname(&n3, nl->type);
  1316  		cgen(nl, &n3);
  1317  
  1318  		tempname(&tmp, nr->type);
  1319  		cgen(nr, &tmp);
  1320  
  1321  		regalloc(&n1, nl->type, N);
  1322  		gmove(&n3, &n1);
  1323  
  1324  		regalloc(&n2, nr->type, N);
  1325  		gmove(&tmp, &n2);
  1326  
  1327  		gcmp(optoas(OCMP, nr->type), &n1, &n2);
  1328  		if(isfloat[nl->type->etype]) {
  1329  			if(n->op == ONE) {
  1330  				p1 = gbranch(ABVS, nr->type, likely);
  1331  				patch(gbranch(a, nr->type, likely), to);
  1332  				patch(p1, to);
  1333  			} else {
  1334  				p1 = gbranch(ABVS, nr->type, -likely);
  1335  				patch(gbranch(a, nr->type, likely), to);
  1336  				patch(p1, pc);
  1337  			}
  1338  		} else {
  1339  			patch(gbranch(a, nr->type, likely), to);
  1340  		}
  1341  		regfree(&n1);
  1342  		regfree(&n2);
  1343  		break;
  1344  	}
  1345  	goto ret;
  1346  
  1347  ret:
  1348  	;
  1349  }
  1350  
  1351  /*
  1352   * n is on stack, either local variable
  1353   * or return value from function call.
  1354   * return n's offset from SP.
  1355   */
  1356  int32
  1357  stkof(Node *n)
  1358  {
  1359  	Type *t;
  1360  	Iter flist;
  1361  	int32 off;
  1362  
  1363  	switch(n->op) {
  1364  	case OINDREG:
  1365  		return n->xoffset;
  1366  
  1367  	case ODOT:
  1368  		t = n->left->type;
  1369  		if(isptr[t->etype])
  1370  			break;
  1371  		off = stkof(n->left);
  1372  		if(off == -1000 || off == 1000)
  1373  			return off;
  1374  		return off + n->xoffset;
  1375  
  1376  	case OINDEX:
  1377  		t = n->left->type;
  1378  		if(!isfixedarray(t))
  1379  			break;
  1380  		off = stkof(n->left);
  1381  		if(off == -1000 || off == 1000)
  1382  			return off;
  1383  		if(isconst(n->right, CTINT))
  1384  			return off + t->type->width * mpgetfix(n->right->val.u.xval);
  1385  		return 1000;
  1386  		
  1387  	case OCALLMETH:
  1388  	case OCALLINTER:
  1389  	case OCALLFUNC:
  1390  		t = n->left->type;
  1391  		if(isptr[t->etype])
  1392  			t = t->type;
  1393  
  1394  		t = structfirst(&flist, getoutarg(t));
  1395  		if(t != T)
  1396  			return t->width + 4;	// correct for LR
  1397  		break;
  1398  	}
  1399  
  1400  	// botch - probably failing to recognize address
  1401  	// arithmetic on the above. eg INDEX and DOT
  1402  	return -1000;
  1403  }
  1404  
  1405  /*
  1406   * block copy:
  1407   *	memmove(&res, &n, w);
  1408   * NB: character copy assumed little endian architecture
  1409   */
  1410  void
  1411  sgen(Node *n, Node *res, int64 w)
  1412  {
  1413  	Node dst, src, tmp, nend, r0, r1, r2, *f;
  1414  	int32 c, odst, osrc;
  1415  	int dir, align, op;
  1416  	Prog *p, *ploop;
  1417  	NodeList *l;
  1418  
  1419  	if(debug['g']) {
  1420  		print("\nsgen w=%lld\n", w);
  1421  		dump("r", n);
  1422  		dump("res", res);
  1423  	}
  1424  
  1425  	if(n->ullman >= UINF && res->ullman >= UINF)
  1426  		fatal("sgen UINF");
  1427  
  1428  	if(w < 0 || (int32)w != w)
  1429  		fatal("sgen copy %lld", w);
  1430  
  1431  	if(n->type == T)
  1432  		fatal("sgen: missing type");
  1433  
  1434  	if(w == 0) {
  1435  		// evaluate side effects only.
  1436  		regalloc(&dst, types[tptr], N);
  1437  		agen(res, &dst);
  1438  		agen(n, &dst);
  1439  		regfree(&dst);
  1440  		return;
  1441  	}
  1442  
  1443  	// If copying .args, that's all the results, so record definition sites
  1444  	// for them for the liveness analysis.
  1445  	if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
  1446  		for(l = curfn->dcl; l != nil; l = l->next)
  1447  			if(l->n->class == PPARAMOUT)
  1448  				gvardef(l->n);
  1449  
  1450  	// Avoid taking the address for simple enough types.
  1451  	if(componentgen(n, res))
  1452  		return;
  1453  	
  1454  	// determine alignment.
  1455  	// want to avoid unaligned access, so have to use
  1456  	// smaller operations for less aligned types.
  1457  	// for example moving [4]byte must use 4 MOVB not 1 MOVW.
  1458  	align = n->type->align;
  1459  	switch(align) {
  1460  	default:
  1461  		fatal("sgen: invalid alignment %d for %T", align, n->type);
  1462  	case 1:
  1463  		op = AMOVB;
  1464  		break;
  1465  	case 2:
  1466  		op = AMOVH;
  1467  		break;
  1468  	case 4:
  1469  		op = AMOVW;
  1470  		break;
  1471  	}
  1472  	if(w%align)
  1473  		fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type);
  1474  	c = w / align;
  1475  
  1476  	// offset on the stack
  1477  	osrc = stkof(n);
  1478  	odst = stkof(res);
  1479  	if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
  1480  		// osrc and odst both on stack, and at least one is in
  1481  		// an unknown position.  Could generate code to test
  1482  		// for forward/backward copy, but instead just copy
  1483  		// to a temporary location first.
  1484  		tempname(&tmp, n->type);
  1485  		sgen(n, &tmp, w);
  1486  		sgen(&tmp, res, w);
  1487  		return;
  1488  	}
  1489  	if(osrc%align != 0 || odst%align != 0)
  1490  		fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
  1491  
  1492  	// if we are copying forward on the stack and
  1493  	// the src and dst overlap, then reverse direction
  1494  	dir = align;
  1495  	if(osrc < odst && odst < osrc+w)
  1496  		dir = -dir;
  1497  
  1498  	if(op == AMOVW && !nacl && dir > 0 && c >= 4 && c <= 128) {
  1499  		r0.op = OREGISTER;
  1500  		r0.val.u.reg = REGALLOC_R0;
  1501  		r1.op = OREGISTER;
  1502  		r1.val.u.reg = REGALLOC_R0 + 1;
  1503  		r2.op = OREGISTER;
  1504  		r2.val.u.reg = REGALLOC_R0 + 2;
  1505  
  1506  		regalloc(&src, types[tptr], &r1);
  1507  		regalloc(&dst, types[tptr], &r2);
  1508  		if(n->ullman >= res->ullman) {
  1509  			// eval n first
  1510  			agen(n, &src);
  1511  			if(res->op == ONAME)
  1512  				gvardef(res);
  1513  			agen(res, &dst);
  1514  		} else {
  1515  			// eval res first
  1516  			if(res->op == ONAME)
  1517  				gvardef(res);
  1518  			agen(res, &dst);
  1519  			agen(n, &src);
  1520  		}
  1521  		regalloc(&tmp, types[tptr], &r0);
  1522  		f = sysfunc("duffcopy");
  1523  		p = gins(ADUFFCOPY, N, f);
  1524  		afunclit(&p->to, f);
  1525  		// 8 and 128 = magic constants: see ../../runtime/asm_arm.s
  1526  		p->to.offset = 8*(128-c);
  1527  
  1528  		regfree(&tmp);
  1529  		regfree(&src);
  1530  		regfree(&dst);
  1531  		return;
  1532  	}
  1533  	
  1534  	if(n->ullman >= res->ullman) {
  1535  		agenr(n, &dst, res);	// temporarily use dst
  1536  		regalloc(&src, types[tptr], N);
  1537  		gins(AMOVW, &dst, &src);
  1538  		if(res->op == ONAME)
  1539  			gvardef(res);
  1540  		agen(res, &dst);
  1541  	} else {
  1542  		if(res->op == ONAME)
  1543  			gvardef(res);
  1544  		agenr(res, &dst, res);
  1545  		agenr(n, &src, N);
  1546  	}
  1547  
  1548  	regalloc(&tmp, types[TUINT32], N);
  1549  
  1550  	// set up end marker
  1551  	memset(&nend, 0, sizeof nend);
  1552  	if(c >= 4) {
  1553  		regalloc(&nend, types[TUINT32], N);
  1554  
  1555  		p = gins(AMOVW, &src, &nend);
  1556  		p->from.type = D_CONST;
  1557  		if(dir < 0)
  1558  			p->from.offset = dir;
  1559  		else
  1560  			p->from.offset = w;
  1561  	}
  1562  
  1563  	// move src and dest to the end of block if necessary
  1564  	if(dir < 0) {
  1565  		p = gins(AMOVW, &src, &src);
  1566  		p->from.type = D_CONST;
  1567  		p->from.offset = w + dir;
  1568  
  1569  		p = gins(AMOVW, &dst, &dst);
  1570  		p->from.type = D_CONST;
  1571  		p->from.offset = w + dir;
  1572  	}
  1573  	
  1574  	// move
  1575  	if(c >= 4) {
  1576  		p = gins(op, &src, &tmp);
  1577  		p->from.type = D_OREG;
  1578  		p->from.offset = dir;
  1579  		p->scond |= C_PBIT;
  1580  		ploop = p;
  1581  
  1582  		p = gins(op, &tmp, &dst);
  1583  		p->to.type = D_OREG;
  1584  		p->to.offset = dir;
  1585  		p->scond |= C_PBIT;
  1586  
  1587  		p = gins(ACMP, &src, N);
  1588  		raddr(&nend, p);
  1589  
  1590  		patch(gbranch(ABNE, T, 0), ploop);
  1591   		regfree(&nend);
  1592  	} else {
  1593  		while(c-- > 0) {
  1594  			p = gins(op, &src, &tmp);
  1595  			p->from.type = D_OREG;
  1596  			p->from.offset = dir;
  1597  			p->scond |= C_PBIT;
  1598  	
  1599  			p = gins(op, &tmp, &dst);
  1600  			p->to.type = D_OREG;
  1601  			p->to.offset = dir;
  1602  			p->scond |= C_PBIT;
  1603  		}
  1604  	}
  1605  
  1606  	regfree(&dst);
  1607  	regfree(&src);
  1608  	regfree(&tmp);
  1609  }
  1610  
  1611  static int
  1612  cadable(Node *n)
  1613  {
  1614  	if(!n->addable) {
  1615  		// dont know how it happens,
  1616  		// but it does
  1617  		return 0;
  1618  	}
  1619  
  1620  	switch(n->op) {
  1621  	case ONAME:
  1622  		return 1;
  1623  	}
  1624  	return 0;
  1625  }
  1626  
  1627  /*
  1628   * copy a composite value by moving its individual components.
  1629   * Slices, strings and interfaces are supported.
  1630   * nr is N when assigning a zero value.
  1631   * return 1 if can do, 0 if cant.
  1632   */
  1633  int
  1634  componentgen(Node *nr, Node *nl)
  1635  {
  1636  	Node nodl, nodr, tmp;
  1637  	Type *t;
  1638  	int freel, freer;
  1639  	vlong fldcount;
  1640  	vlong loffset, roffset;
  1641  
  1642  	freel = 0;
  1643  	freer = 0;
  1644  
  1645  	switch(nl->type->etype) {
  1646  	default:
  1647  		goto no;
  1648  
  1649  	case TARRAY:
  1650  		t = nl->type;
  1651  
  1652  		// Slices are ok.
  1653  		if(isslice(t))
  1654  			break;
  1655  		// Small arrays are ok.
  1656  		if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
  1657  			break;
  1658  
  1659  		goto no;
  1660  
  1661  	case TSTRUCT:
  1662  		// Small structs with non-fat types are ok.
  1663  		// Zero-sized structs are treated separately elsewhere.
  1664  		fldcount = 0;
  1665  		for(t=nl->type->type; t; t=t->down) {
  1666  			if(isfat(t->type))
  1667  				goto no;
  1668  			if(t->etype != TFIELD)
  1669  				fatal("componentgen: not a TFIELD: %lT", t);
  1670  			fldcount++;
  1671  		}
  1672  		if(fldcount == 0 || fldcount > 4)
  1673  			goto no;
  1674  
  1675  		break;
  1676  
  1677  	case TSTRING:
  1678  	case TINTER:
  1679  		break;
  1680  	}
  1681  
  1682  	nodl = *nl;
  1683  	if(!cadable(nl)) {
  1684  		if(nr == N || !cadable(nr))
  1685  			goto no;
  1686  		igen(nl, &nodl, N);
  1687  		freel = 1;
  1688  	}
  1689  
  1690  	if(nr != N) {
  1691  		nodr = *nr;
  1692  		if(!cadable(nr)) {
  1693  			igen(nr, &nodr, N);
  1694  			freer = 1;
  1695  		}
  1696  	} else {
  1697  		// When zeroing, prepare a register containing zero.
  1698  		nodconst(&tmp, nl->type, 0);
  1699  		regalloc(&nodr, types[TUINT], N);
  1700  		gmove(&tmp, &nodr);
  1701  		freer = 1;
  1702  	}
  1703  
  1704  	
  1705  	// nl and nr are 'cadable' which basically means they are names (variables) now.
  1706  	// If they are the same variable, don't generate any code, because the
  1707  	// VARDEF we generate will mark the old value as dead incorrectly.
  1708  	// (And also the assignments are useless.)
  1709  	if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
  1710  		goto yes;
  1711  
  1712  	switch(nl->type->etype) {
  1713  	case TARRAY:
  1714  		// componentgen for arrays.
  1715  		if(nl->op == ONAME)
  1716  			gvardef(nl);
  1717  		t = nl->type;
  1718  		if(!isslice(t)) {
  1719  			nodl.type = t->type;
  1720  			nodr.type = nodl.type;
  1721  			for(fldcount=0; fldcount < t->bound; fldcount++) {
  1722  				if(nr == N)
  1723  					clearslim(&nodl);
  1724  				else
  1725  					gmove(&nodr, &nodl);
  1726  				nodl.xoffset += t->type->width;
  1727  				nodr.xoffset += t->type->width;
  1728  			}
  1729  			goto yes;
  1730  		}
  1731  
  1732  		// componentgen for slices.
  1733  		nodl.xoffset += Array_array;
  1734  		nodl.type = ptrto(nl->type->type);
  1735  
  1736  		if(nr != N) {
  1737  			nodr.xoffset += Array_array;
  1738  			nodr.type = nodl.type;
  1739  		}
  1740  		gmove(&nodr, &nodl);
  1741  
  1742  		nodl.xoffset += Array_nel-Array_array;
  1743  		nodl.type = types[simtype[TUINT]];
  1744  
  1745  		if(nr != N) {
  1746  			nodr.xoffset += Array_nel-Array_array;
  1747  			nodr.type = nodl.type;
  1748  		}
  1749  		gmove(&nodr, &nodl);
  1750  
  1751  		nodl.xoffset += Array_cap-Array_nel;
  1752  		nodl.type = types[simtype[TUINT]];
  1753  
  1754  		if(nr != N) {
  1755  			nodr.xoffset += Array_cap-Array_nel;
  1756  			nodr.type = nodl.type;
  1757  		}
  1758  		gmove(&nodr, &nodl);
  1759  
  1760  		goto yes;
  1761  
  1762  	case TSTRING:
  1763  		if(nl->op == ONAME)
  1764  			gvardef(nl);
  1765  		nodl.xoffset += Array_array;
  1766  		nodl.type = ptrto(types[TUINT8]);
  1767  
  1768  		if(nr != N) {
  1769  			nodr.xoffset += Array_array;
  1770  			nodr.type = nodl.type;
  1771  		}
  1772  		gmove(&nodr, &nodl);
  1773  
  1774  		nodl.xoffset += Array_nel-Array_array;
  1775  		nodl.type = types[simtype[TUINT]];
  1776  
  1777  		if(nr != N) {
  1778  			nodr.xoffset += Array_nel-Array_array;
  1779  			nodr.type = nodl.type;
  1780  		}
  1781  		gmove(&nodr, &nodl);
  1782  
  1783  		goto yes;
  1784  
  1785  	case TINTER:
  1786  		if(nl->op == ONAME)
  1787  			gvardef(nl);
  1788  		nodl.xoffset += Array_array;
  1789  		nodl.type = ptrto(types[TUINT8]);
  1790  
  1791  		if(nr != N) {
  1792  			nodr.xoffset += Array_array;
  1793  			nodr.type = nodl.type;
  1794  		}
  1795  		gmove(&nodr, &nodl);
  1796  
  1797  		nodl.xoffset += Array_nel-Array_array;
  1798  		nodl.type = ptrto(types[TUINT8]);
  1799  
  1800  		if(nr != N) {
  1801  			nodr.xoffset += Array_nel-Array_array;
  1802  			nodr.type = nodl.type;
  1803  		}
  1804  		gmove(&nodr, &nodl);
  1805  
  1806  		goto yes;
  1807  
  1808  	case TSTRUCT:
  1809  		if(nl->op == ONAME)
  1810  			gvardef(nl);
  1811  		loffset = nodl.xoffset;
  1812  		roffset = nodr.xoffset;
  1813  		// funarg structs may not begin at offset zero.
  1814  		if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
  1815  			loffset -= nl->type->type->width;
  1816  		if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
  1817  			roffset -= nr->type->type->width;
  1818  
  1819  		for(t=nl->type->type; t; t=t->down) {
  1820  			nodl.xoffset = loffset + t->width;
  1821  			nodl.type = t->type;
  1822  
  1823  			if(nr == N)
  1824  				clearslim(&nodl);
  1825  			else {
  1826  				nodr.xoffset = roffset + t->width;
  1827  				nodr.type = nodl.type;
  1828  				gmove(&nodr, &nodl);
  1829  			}
  1830  		}
  1831  		goto yes;
  1832  	}
  1833  
  1834  no:
  1835  	if(freer)
  1836  		regfree(&nodr);
  1837  	if(freel)
  1838  		regfree(&nodl);
  1839  	return 0;
  1840  
  1841  yes:
  1842  	if(freer)
  1843  		regfree(&nodr);
  1844  	if(freel)
  1845  		regfree(&nodl);
  1846  	return 1;
  1847  }