github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/8g/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  // TODO(rsc):
     6  //	assume CLD?
     7  
     8  #include <u.h>
     9  #include <libc.h>
    10  #include "gg.h"
    11  
    12  void
    13  mgen(Node *n, Node *n1, Node *rg)
    14  {
    15  	Node n2;
    16  
    17  	n1->op = OEMPTY;
    18  
    19  	if(n->addable) {
    20  		*n1 = *n;
    21  		if(n1->op == OREGISTER || n1->op == OINDREG)
    22  			reg[n->val.u.reg]++;
    23  		return;
    24  	}
    25  	tempname(n1, n->type);
    26  	cgen(n, n1);
    27  	if(n->type->width <= widthptr || isfloat[n->type->etype]) {
    28  		n2 = *n1;
    29  		regalloc(n1, n->type, rg);
    30  		gmove(&n2, n1);
    31  	}
    32  }
    33  
    34  void
    35  mfree(Node *n)
    36  {
    37  	if(n->op == OREGISTER)
    38  		regfree(n);
    39  }
    40  
    41  /*
    42   * generate:
    43   *	res = n;
    44   * simplifies and calls gmove.
    45   *
    46   * TODO:
    47   *	sudoaddable
    48   */
    49  void
    50  cgen(Node *n, Node *res)
    51  {
    52  	Node *nl, *nr, *r, n1, n2, nt;
    53  	Prog *p1, *p2, *p3;
    54  	int a;
    55  
    56  	if(debug['g']) {
    57  		dump("\ncgen-n", n);
    58  		dump("cgen-res", res);
    59  	}
    60  
    61  	if(n == N || n->type == T)
    62  		fatal("cgen: n nil");
    63  	if(res == N || res->type == T)
    64  		fatal("cgen: res nil");
    65  
    66  	switch(n->op) {
    67  	case OSLICE:
    68  	case OSLICEARR:
    69  	case OSLICESTR:
    70  	case OSLICE3:
    71  	case OSLICE3ARR:
    72  		if (res->op != ONAME || !res->addable) {
    73  			tempname(&n1, n->type);
    74  			cgen_slice(n, &n1);
    75  			cgen(&n1, res);
    76  		} else
    77  			cgen_slice(n, res);
    78  		return;
    79  	case OEFACE:
    80  		if (res->op != ONAME || !res->addable) {
    81  			tempname(&n1, n->type);
    82  			cgen_eface(n, &n1);
    83  			cgen(&n1, res);
    84  		} else
    85  			cgen_eface(n, res);
    86  		return;
    87  	}
    88  
    89  	while(n->op == OCONVNOP)
    90  		n = n->left;
    91  
    92  	// function calls on both sides?  introduce temporary
    93  	if(n->ullman >= UINF && res->ullman >= UINF) {
    94  		tempname(&n1, n->type);
    95  		cgen(n, &n1);
    96  		cgen(&n1, res);
    97  		return;
    98  	}
    99  
   100  	// structs etc get handled specially
   101  	if(isfat(n->type)) {
   102  		if(n->type->width < 0)
   103  			fatal("forgot to compute width for %T", n->type);
   104  		sgen(n, res, n->type->width);
   105  		return;
   106  	}
   107  
   108  	// update addressability for string, slice
   109  	// can't do in walk because n->left->addable
   110  	// changes if n->left is an escaping local variable.
   111  	switch(n->op) {
   112  	case OLEN:
   113  		if(isslice(n->left->type) || istype(n->left->type, TSTRING))
   114  			n->addable = n->left->addable;
   115  		break;
   116  	case OCAP:
   117  		if(isslice(n->left->type))
   118  			n->addable = n->left->addable;
   119  		break;
   120  	case OITAB:
   121  		n->addable = n->left->addable;
   122  		break;
   123  	}
   124  
   125  	// if both are addressable, move
   126  	if(n->addable && res->addable) {
   127  		gmove(n, res);
   128  		return;
   129  	}
   130  
   131  	// if both are not addressable, use a temporary.
   132  	if(!n->addable && !res->addable) {
   133  		// could use regalloc here sometimes,
   134  		// but have to check for ullman >= UINF.
   135  		tempname(&n1, n->type);
   136  		cgen(n, &n1);
   137  		cgen(&n1, res);
   138  		return;
   139  	}
   140  
   141  	// if result is not addressable directly but n is,
   142  	// compute its address and then store via the address.
   143  	if(!res->addable) {
   144  		igen(res, &n1, N);
   145  		cgen(n, &n1);
   146  		regfree(&n1);
   147  		return;
   148  	}
   149  
   150  	// complex types
   151  	if(complexop(n, res)) {
   152  		complexgen(n, res);
   153  		return;
   154  	}
   155  
   156  	// otherwise, the result is addressable but n is not.
   157  	// let's do some computation.
   158  
   159  	// use ullman to pick operand to eval first.
   160  	nl = n->left;
   161  	nr = n->right;
   162  	if(nl != N && nl->ullman >= UINF)
   163  	if(nr != N && nr->ullman >= UINF) {
   164  		// both are hard
   165  		tempname(&n1, nl->type);
   166  		cgen(nl, &n1);
   167  		n2 = *n;
   168  		n2.left = &n1;
   169  		cgen(&n2, res);
   170  		return;
   171  	}
   172  
   173  	// 64-bit ops are hard on 32-bit machine.
   174  	if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
   175  		switch(n->op) {
   176  		// math goes to cgen64.
   177  		case OMINUS:
   178  		case OCOM:
   179  		case OADD:
   180  		case OSUB:
   181  		case OMUL:
   182  		case OLROT:
   183  		case OLSH:
   184  		case ORSH:
   185  		case OAND:
   186  		case OOR:
   187  		case OXOR:
   188  			cgen64(n, res);
   189  			return;
   190  		}
   191  	}
   192  
   193  	if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) {
   194  		cgen_float(n, res);
   195  		return;
   196  	}
   197  
   198  	switch(n->op) {
   199  	default:
   200  		dump("cgen", n);
   201  		fatal("cgen %O", n->op);
   202  		break;
   203  
   204  	case OREAL:
   205  	case OIMAG:
   206  	case OCOMPLEX:
   207  		fatal("unexpected complex");
   208  		return;
   209  
   210  	// these call bgen to get a bool value
   211  	case OOROR:
   212  	case OANDAND:
   213  	case OEQ:
   214  	case ONE:
   215  	case OLT:
   216  	case OLE:
   217  	case OGE:
   218  	case OGT:
   219  	case ONOT:
   220  		p1 = gbranch(AJMP, T, 0);
   221  		p2 = pc;
   222  		gmove(nodbool(1), res);
   223  		p3 = gbranch(AJMP, T, 0);
   224  		patch(p1, pc);
   225  		bgen(n, 1, 0, p2);
   226  		gmove(nodbool(0), res);
   227  		patch(p3, pc);
   228  		return;
   229  
   230  	case OPLUS:
   231  		cgen(nl, res);
   232  		return;
   233  
   234  	case OMINUS:
   235  	case OCOM:
   236  		a = optoas(n->op, nl->type);
   237  		goto uop;
   238  
   239  	// symmetric binary
   240  	case OAND:
   241  	case OOR:
   242  	case OXOR:
   243  	case OADD:
   244  	case OMUL:
   245  		a = optoas(n->op, nl->type);
   246  		if(a == AIMULB) {
   247  			cgen_bmul(n->op, nl, nr, res);
   248  			break;
   249  		}
   250  		goto sbop;
   251  
   252  	// asymmetric binary
   253  	case OSUB:
   254  		a = optoas(n->op, nl->type);
   255  		goto abop;
   256  
   257  	case OHMUL:
   258  		cgen_hmul(nl, nr, res);
   259  		break;
   260  
   261  	case OCONV:
   262  		if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
   263  			cgen(nl, res);
   264  			break;
   265  		}
   266  
   267  		tempname(&n2, n->type);
   268  		mgen(nl, &n1, res);
   269  		gmove(&n1, &n2);
   270  		gmove(&n2, res);
   271  		mfree(&n1);
   272  		break;
   273  
   274  	case ODOT:
   275  	case ODOTPTR:
   276  	case OINDEX:
   277  	case OIND:
   278  	case ONAME:	// PHEAP or PPARAMREF var
   279  		igen(n, &n1, res);
   280  		gmove(&n1, res);
   281  		regfree(&n1);
   282  		break;
   283  
   284  	case OITAB:
   285  		igen(nl, &n1, res);
   286  		n1.type = ptrto(types[TUINTPTR]);
   287  		gmove(&n1, res);
   288  		regfree(&n1);
   289  		break;
   290  
   291  	case OLEN:
   292  		if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
   293  			// map has len in the first 32-bit word.
   294  			// a zero pointer means zero length
   295  			tempname(&n1, types[tptr]);
   296  			cgen(nl, &n1);
   297  			regalloc(&n2, types[tptr], N);
   298  			gmove(&n1, &n2);
   299  			n1 = n2;
   300  
   301  			nodconst(&n2, types[tptr], 0);
   302  			gins(optoas(OCMP, types[tptr]), &n1, &n2);
   303  			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
   304  
   305  			n2 = n1;
   306  			n2.op = OINDREG;
   307  			n2.type = types[TINT32];
   308  			gmove(&n2, &n1);
   309  
   310  			patch(p1, pc);
   311  
   312  			gmove(&n1, res);
   313  			regfree(&n1);
   314  			break;
   315  		}
   316  		if(istype(nl->type, TSTRING) || isslice(nl->type)) {
   317  			// both slice and string have len one pointer into the struct.
   318  			igen(nl, &n1, res);
   319  			n1.type = types[TUINT32];
   320  			n1.xoffset += Array_nel;
   321  			gmove(&n1, res);
   322  			regfree(&n1);
   323  			break;
   324  		}
   325  		fatal("cgen: OLEN: unknown type %lT", nl->type);
   326  		break;
   327  
   328  	case OCAP:
   329  		if(istype(nl->type, TCHAN)) {
   330  			// chan has cap in the second 32-bit word.
   331  			// a zero pointer means zero length
   332  			regalloc(&n1, types[tptr], res);
   333  			cgen(nl, &n1);
   334  
   335  			nodconst(&n2, types[tptr], 0);
   336  			gins(optoas(OCMP, types[tptr]), &n1, &n2);
   337  			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
   338  
   339  			n2 = n1;
   340  			n2.op = OINDREG;
   341  			n2.xoffset = 4;
   342  			n2.type = types[TINT32];
   343  			gmove(&n2, &n1);
   344  
   345  			patch(p1, pc);
   346  
   347  			gmove(&n1, res);
   348  			regfree(&n1);
   349  			break;
   350  		}
   351  		if(isslice(nl->type)) {
   352  			igen(nl, &n1, res);
   353  			n1.type = types[TUINT32];
   354  			n1.xoffset += Array_cap;
   355  			gmove(&n1, res);
   356  			regfree(&n1);
   357  			break;
   358  		}
   359  		fatal("cgen: OCAP: unknown type %lT", nl->type);
   360  		break;
   361  
   362  	case OADDR:
   363  		agen(nl, res);
   364  		break;
   365  
   366  	case OCALLMETH:
   367  		cgen_callmeth(n, 0);
   368  		cgen_callret(n, res);
   369  		break;
   370  
   371  	case OCALLINTER:
   372  		cgen_callinter(n, res, 0);
   373  		cgen_callret(n, res);
   374  		break;
   375  
   376  	case OCALLFUNC:
   377  		cgen_call(n, 0);
   378  		cgen_callret(n, res);
   379  		break;
   380  
   381  	case OMOD:
   382  	case ODIV:
   383  		cgen_div(n->op, nl, nr, res);
   384  		break;
   385  
   386  	case OLSH:
   387  	case ORSH:
   388  	case OLROT:
   389  		cgen_shift(n->op, n->bounded, nl, nr, res);
   390  		break;
   391  	}
   392  	return;
   393  
   394  sbop:	// symmetric binary
   395  	if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
   396  		r = nl;
   397  		nl = nr;
   398  		nr = r;
   399  	}
   400  
   401  abop:	// asymmetric binary
   402  	if(smallintconst(nr)) {
   403  		mgen(nl, &n1, res);
   404  		regalloc(&n2, nl->type, &n1);
   405  		gmove(&n1, &n2);
   406  		gins(a, nr, &n2);
   407  		gmove(&n2, res);
   408  		regfree(&n2);
   409  		mfree(&n1);
   410  	} else if(nl->ullman >= nr->ullman) {
   411  		tempname(&nt, nl->type);
   412  		cgen(nl, &nt);
   413  		mgen(nr, &n2, N);
   414  		regalloc(&n1, nl->type, res);
   415  		gmove(&nt, &n1);
   416  		gins(a, &n2, &n1);
   417  		gmove(&n1, res);
   418  		regfree(&n1);
   419  		mfree(&n2);
   420  	} else {
   421  		regalloc(&n2, nr->type, res);
   422  		cgen(nr, &n2);
   423  		regalloc(&n1, nl->type, N);
   424  		cgen(nl, &n1);
   425  		gins(a, &n2, &n1);
   426  		regfree(&n2);
   427  		gmove(&n1, res);
   428  		regfree(&n1);
   429  	}
   430  	return;
   431  
   432  uop:	// unary
   433  	tempname(&n1, nl->type);
   434  	cgen(nl, &n1);
   435  	gins(a, N, &n1);
   436  	gmove(&n1, res);
   437  	return;
   438  }
   439  
   440  /*
   441   * generate an addressable node in res, containing the value of n.
   442   * n is an array index, and might be any size; res width is <= 32-bit.
   443   * returns Prog* to patch to panic call.
   444   */
   445  static Prog*
   446  igenindex(Node *n, Node *res, int bounded)
   447  {
   448  	Node tmp, lo, hi, zero;
   449  
   450  	if(!is64(n->type)) {
   451  		if(n->addable) {
   452  			// nothing to do.
   453  			*res = *n;
   454  		} else {
   455  			tempname(res, types[TUINT32]);
   456  			cgen(n, res);
   457  		}
   458  		return nil;
   459  	}
   460  
   461  	tempname(&tmp, types[TINT64]);
   462  	cgen(n, &tmp);
   463  	split64(&tmp, &lo, &hi);
   464  	tempname(res, types[TUINT32]);
   465  	gmove(&lo, res);
   466  	if(bounded) {
   467  		splitclean();
   468  		return nil;
   469  	}
   470  	nodconst(&zero, types[TINT32], 0);
   471  	gins(ACMPL, &hi, &zero);
   472  	splitclean();
   473  	return gbranch(AJNE, T, +1);
   474  }
   475  		
   476  /*
   477   * address gen
   478   *	res = &n;
   479   * The generated code checks that the result is not nil.
   480   */
   481  void
   482  agen(Node *n, Node *res)
   483  {
   484  	Node *nl, *nr;
   485  	Node n1, n2, n3, tmp, nlen;
   486  	Type *t;
   487  	uint32 w;
   488  	uint64 v;
   489  	Prog *p1, *p2;
   490  	int bounded;
   491  
   492  	if(debug['g']) {
   493  		dump("\nagen-res", res);
   494  		dump("agen-r", n);
   495  	}
   496  	if(n == N || n->type == T || res == N || res->type == T)
   497  		fatal("agen");
   498  
   499  	while(n->op == OCONVNOP)
   500  		n = n->left;
   501  
   502  	if(isconst(n, CTNIL) && n->type->width > widthptr) {
   503  		// Use of a nil interface or nil slice.
   504  		// Create a temporary we can take the address of and read.
   505  		// The generated code is just going to panic, so it need not
   506  		// be terribly efficient. See issue 3670.
   507  		tempname(&n1, n->type);
   508  		clearfat(&n1);
   509  		regalloc(&n2, types[tptr], res);
   510  		gins(ALEAL, &n1, &n2);
   511  		gmove(&n2, res);
   512  		regfree(&n2);
   513  		return;
   514  	}
   515  		
   516  	// addressable var is easy
   517  	if(n->addable) {
   518  		if(n->op == OREGISTER)
   519  			fatal("agen OREGISTER");
   520  		regalloc(&n1, types[tptr], res);
   521  		gins(ALEAL, n, &n1);
   522  		gmove(&n1, res);
   523  		regfree(&n1);
   524  		return;
   525  	}
   526  
   527  	// let's compute
   528  	nl = n->left;
   529  	nr = n->right;
   530  
   531  	switch(n->op) {
   532  	default:
   533  		fatal("agen %O", n->op);
   534  
   535  	case OCALLMETH:
   536  		cgen_callmeth(n, 0);
   537  		cgen_aret(n, res);
   538  		break;
   539  
   540  	case OCALLINTER:
   541  		cgen_callinter(n, res, 0);
   542  		cgen_aret(n, res);
   543  		break;
   544  
   545  	case OCALLFUNC:
   546  		cgen_call(n, 0);
   547  		cgen_aret(n, res);
   548  		break;
   549  
   550  	case OSLICE:
   551  	case OSLICEARR:
   552  	case OSLICESTR:
   553  	case OSLICE3:
   554  	case OSLICE3ARR:
   555  		tempname(&n1, n->type);
   556  		cgen_slice(n, &n1);
   557  		agen(&n1, res);
   558  		break;
   559  
   560  	case OEFACE:
   561  		tempname(&n1, n->type);
   562  		cgen_eface(n, &n1);
   563  		agen(&n1, res);
   564  		break;
   565  
   566  	case OINDEX:
   567  		p2 = nil;  // to be patched to panicindex.
   568  		w = n->type->width;
   569  		bounded = debug['B'] || n->bounded;
   570  		if(nr->addable) {
   571  			// Generate &nl first, and move nr into register.
   572  			if(!isconst(nl, CTSTR))
   573  				igen(nl, &n3, res);
   574  			if(!isconst(nr, CTINT)) {
   575  				p2 = igenindex(nr, &tmp, bounded);
   576  				regalloc(&n1, tmp.type, N);
   577  				gmove(&tmp, &n1);
   578  			}
   579  		} else if(nl->addable) {
   580  			// Generate nr first, and move &nl into register.
   581  			if(!isconst(nr, CTINT)) {
   582  				p2 = igenindex(nr, &tmp, bounded);
   583  				regalloc(&n1, tmp.type, N);
   584  				gmove(&tmp, &n1);
   585  			}
   586  			if(!isconst(nl, CTSTR))
   587  				igen(nl, &n3, res);
   588  		} else {
   589  			p2 = igenindex(nr, &tmp, bounded);
   590  			nr = &tmp;
   591  			if(!isconst(nl, CTSTR))
   592  				igen(nl, &n3, res);
   593  			regalloc(&n1, tmp.type, N);
   594  			gins(optoas(OAS, tmp.type), &tmp, &n1);
   595  		}
   596  
   597  		// For fixed array we really want the pointer in n3.
   598  		if(isfixedarray(nl->type)) {
   599  			regalloc(&n2, types[tptr], &n3);
   600  			agen(&n3, &n2);
   601  			regfree(&n3);
   602  			n3 = n2;
   603  		}
   604  
   605  		// &a[0] is in n3 (allocated in res)
   606  		// i is in n1 (if not constant)
   607  		// len(a) is in nlen (if needed)
   608  		// w is width
   609  
   610  		// constant index
   611  		if(isconst(nr, CTINT)) {
   612  			if(isconst(nl, CTSTR))
   613  				fatal("constant string constant index");  // front end should handle
   614  			v = mpgetfix(nr->val.u.xval);
   615  			if(isslice(nl->type) || nl->type->etype == TSTRING) {
   616  				if(!debug['B'] && !n->bounded) {
   617  					nlen = n3;
   618  					nlen.type = types[TUINT32];
   619  					nlen.xoffset += Array_nel;
   620  					nodconst(&n2, types[TUINT32], v);
   621  					gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
   622  					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
   623  					ginscall(panicindex, -1);
   624  					patch(p1, pc);
   625  				}
   626  			}
   627  
   628  			// Load base pointer in n2 = n3.
   629  			regalloc(&n2, types[tptr], &n3);
   630  			n3.type = types[tptr];
   631  			n3.xoffset += Array_array;
   632  			gmove(&n3, &n2);
   633  			regfree(&n3);
   634  			if (v*w != 0) {
   635  				nodconst(&n1, types[tptr], v*w);
   636  				gins(optoas(OADD, types[tptr]), &n1, &n2);
   637  			}
   638  			gmove(&n2, res);
   639  			regfree(&n2);
   640  			break;
   641  		}
   642  
   643  		// i is in register n1, extend to 32 bits.
   644  		t = types[TUINT32];
   645  		if(issigned[n1.type->etype])
   646  			t = types[TINT32];
   647  
   648  		regalloc(&n2, t, &n1);			// i
   649  		gmove(&n1, &n2);
   650  		regfree(&n1);
   651  
   652  		if(!debug['B'] && !n->bounded) {
   653  			// check bounds
   654  			t = types[TUINT32];
   655  			if(isconst(nl, CTSTR)) {
   656  				nodconst(&nlen, t, nl->val.u.sval->len);
   657  			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
   658  				nlen = n3;
   659  				nlen.type = t;
   660  				nlen.xoffset += Array_nel;
   661  			} else {
   662  				nodconst(&nlen, t, nl->type->bound);
   663  			}
   664  			gins(optoas(OCMP, t), &n2, &nlen);
   665  			p1 = gbranch(optoas(OLT, t), T, +1);
   666  			if(p2)
   667  				patch(p2, pc);
   668  			ginscall(panicindex, -1);
   669  			patch(p1, pc);
   670  		}
   671  
   672  		if(isconst(nl, CTSTR)) {
   673  			regalloc(&n3, types[tptr], res);
   674  			p1 = gins(ALEAL, N, &n3);
   675  			datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
   676  			p1->from.scale = 1;
   677  			p1->from.index = n2.val.u.reg;
   678  			goto indexdone;
   679  		}
   680  
   681  		// Load base pointer in n3.
   682  		regalloc(&tmp, types[tptr], &n3);
   683  		if(isslice(nl->type) || nl->type->etype == TSTRING) {
   684  			n3.type = types[tptr];
   685  			n3.xoffset += Array_array;
   686  			gmove(&n3, &tmp);
   687  		}
   688  		regfree(&n3);
   689  		n3 = tmp;
   690  
   691  		if(w == 0) {
   692  			// nothing to do
   693  		} else if(w == 1 || w == 2 || w == 4 || w == 8) {
   694  			// LEAL (n3)(n2*w), n3
   695  			p1 = gins(ALEAL, &n2, &n3);
   696  			p1->from.scale = w;
   697  			p1->from.index = p1->from.type;
   698  			p1->from.type = p1->to.type + D_INDIR;
   699  		} else {
   700  			nodconst(&tmp, types[TUINT32], w);
   701  			gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
   702  			gins(optoas(OADD, types[tptr]), &n2, &n3);
   703  		}
   704  
   705  	indexdone:
   706  		gmove(&n3, res);
   707  		regfree(&n2);
   708  		regfree(&n3);
   709  		break;
   710  
   711  	case ONAME:
   712  		// should only get here with names in this func.
   713  		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
   714  			dump("bad agen", n);
   715  			fatal("agen: bad ONAME funcdepth %d != %d",
   716  				n->funcdepth, funcdepth);
   717  		}
   718  
   719  		// should only get here for heap vars or paramref
   720  		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
   721  			dump("bad agen", n);
   722  			fatal("agen: bad ONAME class %#x", n->class);
   723  		}
   724  		cgen(n->heapaddr, res);
   725  		if(n->xoffset != 0) {
   726  			nodconst(&n1, types[tptr], n->xoffset);
   727  			gins(optoas(OADD, types[tptr]), &n1, res);
   728  		}
   729  		break;
   730  
   731  	case OIND:
   732  		cgen(nl, res);
   733  		cgen_checknil(res);
   734  		break;
   735  
   736  	case ODOT:
   737  		agen(nl, res);
   738  		if(n->xoffset != 0) {
   739  			nodconst(&n1, types[tptr], n->xoffset);
   740  			gins(optoas(OADD, types[tptr]), &n1, res);
   741  		}
   742  		break;
   743  
   744  	case ODOTPTR:
   745  		t = nl->type;
   746  		if(!isptr[t->etype])
   747  			fatal("agen: not ptr %N", n);
   748  		cgen(nl, res);
   749  		cgen_checknil(res);
   750  		if(n->xoffset != 0) {
   751  			nodconst(&n1, types[tptr], n->xoffset);
   752  			gins(optoas(OADD, types[tptr]), &n1, res);
   753  		}
   754  		break;
   755  	}
   756  }
   757  
   758  /*
   759   * generate:
   760   *	newreg = &n;
   761   *	res = newreg
   762   *
   763   * on exit, a has been changed to be *newreg.
   764   * caller must regfree(a).
   765   * The generated code checks that the result is not *nil.
   766   */
   767  void
   768  igen(Node *n, Node *a, Node *res)
   769  {
   770  	Type *fp;
   771  	Iter flist;
   772  	Node n1;
   773  
   774  	if(debug['g']) {
   775  		dump("\nigen-n", n);
   776  	}
   777  	switch(n->op) {
   778  	case ONAME:
   779  		if((n->class&PHEAP) || n->class == PPARAMREF)
   780  			break;
   781  		*a = *n;
   782  		return;
   783  
   784  	case OINDREG:
   785  		// Increase the refcount of the register so that igen's caller
   786  		// has to call regfree.
   787  		if(n->val.u.reg != D_SP)
   788  			reg[n->val.u.reg]++;
   789  		*a = *n;
   790  		return;
   791  
   792  	case ODOT:
   793  		igen(n->left, a, res);
   794  		a->xoffset += n->xoffset;
   795  		a->type = n->type;
   796  		return;
   797  
   798  	case ODOTPTR:
   799  		switch(n->left->op) {
   800  		case ODOT:
   801  		case ODOTPTR:
   802  		case OCALLFUNC:
   803  		case OCALLMETH:
   804  		case OCALLINTER:
   805  			// igen-able nodes.
   806  			igen(n->left, &n1, res);
   807  			regalloc(a, types[tptr], &n1);
   808  			gmove(&n1, a);
   809  			regfree(&n1);
   810  			break;
   811  		default:
   812  			regalloc(a, types[tptr], res);
   813  			cgen(n->left, a);
   814  		}
   815  		cgen_checknil(a);
   816  		a->op = OINDREG;
   817  		a->xoffset += n->xoffset;
   818  		a->type = n->type;
   819  		return;
   820  
   821  	case OCALLFUNC:
   822  	case OCALLMETH:
   823  	case OCALLINTER:
   824  		switch(n->op) {
   825  		case OCALLFUNC:
   826  			cgen_call(n, 0);
   827  			break;
   828  		case OCALLMETH:
   829  			cgen_callmeth(n, 0);
   830  			break;
   831  		case OCALLINTER:
   832  			cgen_callinter(n, N, 0);
   833  			break;
   834  		}
   835  		fp = structfirst(&flist, getoutarg(n->left->type));
   836  		memset(a, 0, sizeof *a);
   837  		a->op = OINDREG;
   838  		a->val.u.reg = D_SP;
   839  		a->addable = 1;
   840  		a->xoffset = fp->width;
   841  		a->type = n->type;
   842  		return;
   843  	}
   844  	// release register for now, to avoid
   845  	// confusing tempname.
   846  	if(res != N && res->op == OREGISTER)
   847  		reg[res->val.u.reg]--;
   848  	tempname(&n1, types[tptr]);
   849  	agen(n, &n1);
   850  	if(res != N && res->op == OREGISTER)
   851  		reg[res->val.u.reg]++;
   852  	regalloc(a, types[tptr], res);
   853  	gmove(&n1, a);
   854  	a->op = OINDREG;
   855  	a->type = n->type;
   856  }
   857  
   858  /*
   859   * branch gen
   860   *	if(n == true) goto to;
   861   */
   862  void
   863  bgen(Node *n, int true, int likely, Prog *to)
   864  {
   865  	int et, a;
   866  	Node *nl, *nr, *r;
   867  	Node n1, n2, tmp;
   868  	Prog *p1, *p2;
   869  
   870  	if(debug['g']) {
   871  		dump("\nbgen", n);
   872  	}
   873  
   874  	if(n == N)
   875  		n = nodbool(1);
   876  
   877  	if(n->ninit != nil)
   878  		genlist(n->ninit);
   879  
   880  	if(n->type == T) {
   881  		convlit(&n, types[TBOOL]);
   882  		if(n->type == T)
   883  			return;
   884  	}
   885  
   886  	et = n->type->etype;
   887  	if(et != TBOOL) {
   888  		yyerror("cgen: bad type %T for %O", n->type, n->op);
   889  		patch(gins(AEND, N, N), to);
   890  		return;
   891  	}
   892  	nl = n->left;
   893  	nr = N;
   894  
   895  	if(nl != N && isfloat[nl->type->etype]) {
   896  		bgen_float(n, true, likely, to);
   897  		return;
   898  	}
   899  
   900  	switch(n->op) {
   901  	default:
   902  	def:
   903  		regalloc(&n1, n->type, N);
   904  		cgen(n, &n1);
   905  		nodconst(&n2, n->type, 0);
   906  		gins(optoas(OCMP, n->type), &n1, &n2);
   907  		a = AJNE;
   908  		if(!true)
   909  			a = AJEQ;
   910  		patch(gbranch(a, n->type, likely), to);
   911  		regfree(&n1);
   912  		return;
   913  
   914  	case OLITERAL:
   915  		// need to ask if it is bool?
   916  		if(!true == !n->val.u.bval)
   917  			patch(gbranch(AJMP, T, 0), to);
   918  		return;
   919  
   920  	case ONAME:
   921  		if(!n->addable)
   922  			goto def;
   923  		nodconst(&n1, n->type, 0);
   924  		gins(optoas(OCMP, n->type), n, &n1);
   925  		a = AJNE;
   926  		if(!true)
   927  			a = AJEQ;
   928  		patch(gbranch(a, n->type, likely), to);
   929  		return;
   930  
   931  	case OANDAND:
   932  		if(!true)
   933  			goto caseor;
   934  
   935  	caseand:
   936  		p1 = gbranch(AJMP, T, 0);
   937  		p2 = gbranch(AJMP, T, 0);
   938  		patch(p1, pc);
   939  		bgen(n->left, !true, -likely, p2);
   940  		bgen(n->right, !true, -likely, p2);
   941  		p1 = gbranch(AJMP, T, 0);
   942  		patch(p1, to);
   943  		patch(p2, pc);
   944  		return;
   945  
   946  	case OOROR:
   947  		if(!true)
   948  			goto caseand;
   949  
   950  	caseor:
   951  		bgen(n->left, true, likely, to);
   952  		bgen(n->right, true, likely, to);
   953  		return;
   954  
   955  	case OEQ:
   956  	case ONE:
   957  	case OLT:
   958  	case OGT:
   959  	case OLE:
   960  	case OGE:
   961  		nr = n->right;
   962  		if(nr == N || nr->type == T)
   963  			return;
   964  
   965  	case ONOT:	// unary
   966  		nl = n->left;
   967  		if(nl == N || nl->type == T)
   968  			return;
   969  	}
   970  
   971  	switch(n->op) {
   972  	case ONOT:
   973  		bgen(nl, !true, likely, to);
   974  		break;
   975  
   976  	case OEQ:
   977  	case ONE:
   978  	case OLT:
   979  	case OGT:
   980  	case OLE:
   981  	case OGE:
   982  		a = n->op;
   983  		if(!true) {
   984  			a = brcom(a);
   985  			true = !true;
   986  		}
   987  
   988  		// make simplest on right
   989  		if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
   990  			a = brrev(a);
   991  			r = nl;
   992  			nl = nr;
   993  			nr = r;
   994  		}
   995  
   996  		if(isslice(nl->type)) {
   997  			// front end should only leave cmp to literal nil
   998  			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
   999  				yyerror("illegal slice comparison");
  1000  				break;
  1001  			}
  1002  			a = optoas(a, types[tptr]);
  1003  			igen(nl, &n1, N);
  1004  			n1.xoffset += Array_array;
  1005  			n1.type = types[tptr];
  1006  			nodconst(&tmp, types[tptr], 0);
  1007  			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
  1008  			patch(gbranch(a, types[tptr], likely), to);
  1009  			regfree(&n1);
  1010  			break;
  1011  		}
  1012  
  1013  		if(isinter(nl->type)) {
  1014  			// front end should only leave cmp to literal nil
  1015  			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
  1016  				yyerror("illegal interface comparison");
  1017  				break;
  1018  			}
  1019  			a = optoas(a, types[tptr]);
  1020  			igen(nl, &n1, N);
  1021  			n1.type = types[tptr];
  1022  			nodconst(&tmp, types[tptr], 0);
  1023  			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
  1024  			patch(gbranch(a, types[tptr], likely), to);
  1025  			regfree(&n1);
  1026  			break;
  1027  		}
  1028  
  1029  		if(iscomplex[nl->type->etype]) {
  1030  			complexbool(a, nl, nr, true, likely, to);
  1031  			break;
  1032  		}
  1033  
  1034  		if(is64(nr->type)) {
  1035  			if(!nl->addable || isconst(nl, CTINT)) {
  1036  				tempname(&n1, nl->type);
  1037  				cgen(nl, &n1);
  1038  				nl = &n1;
  1039  			}
  1040  			if(!nr->addable) {
  1041  				tempname(&n2, nr->type);
  1042  				cgen(nr, &n2);
  1043  				nr = &n2;
  1044  			}
  1045  			cmp64(nl, nr, a, likely, to);
  1046  			break;
  1047  		}
  1048  
  1049  		if(nr->ullman >= UINF) {
  1050  			if(!nl->addable) {
  1051  				tempname(&n1, nl->type);
  1052  				cgen(nl, &n1);
  1053  				nl = &n1;
  1054  			}
  1055  			if(!nr->addable) {
  1056  				tempname(&tmp, nr->type);
  1057  				cgen(nr, &tmp);
  1058  				nr = &tmp;
  1059  			}
  1060  			regalloc(&n2, nr->type, N);
  1061  			cgen(nr, &n2);
  1062  			nr = &n2;
  1063  			goto cmp;
  1064  		}
  1065  
  1066  		if(!nl->addable) {
  1067  			tempname(&n1, nl->type);
  1068  			cgen(nl, &n1);
  1069  			nl = &n1;
  1070  		}
  1071  
  1072  		if(smallintconst(nr)) {
  1073  			gins(optoas(OCMP, nr->type), nl, nr);
  1074  			patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
  1075  			break;
  1076  		}
  1077  
  1078  		if(!nr->addable) {
  1079  			tempname(&tmp, nr->type);
  1080  			cgen(nr, &tmp);
  1081  			nr = &tmp;
  1082  		}
  1083  		regalloc(&n2, nr->type, N);
  1084  		gmove(nr, &n2);
  1085  		nr = &n2;
  1086  
  1087  cmp:
  1088  		gins(optoas(OCMP, nr->type), nl, nr);
  1089  		patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
  1090  
  1091  		if(nl->op == OREGISTER)
  1092  			regfree(nl);
  1093  		regfree(nr);
  1094  		break;
  1095  	}
  1096  }
  1097  
  1098  /*
  1099   * n is on stack, either local variable
  1100   * or return value from function call.
  1101   * return n's offset from SP.
  1102   */
  1103  int32
  1104  stkof(Node *n)
  1105  {
  1106  	Type *t;
  1107  	Iter flist;
  1108  	int32 off;
  1109  
  1110  	switch(n->op) {
  1111  	case OINDREG:
  1112  		return n->xoffset;
  1113  
  1114  	case ODOT:
  1115  		t = n->left->type;
  1116  		if(isptr[t->etype])
  1117  			break;
  1118  		off = stkof(n->left);
  1119  		if(off == -1000 || off == 1000)
  1120  			return off;
  1121  		return off + n->xoffset;
  1122  
  1123  	case OINDEX:
  1124  		t = n->left->type;
  1125  		if(!isfixedarray(t))
  1126  			break;
  1127  		off = stkof(n->left);
  1128  		if(off == -1000 || off == 1000)
  1129  			return off;
  1130  		if(isconst(n->right, CTINT))
  1131  			return off + t->type->width * mpgetfix(n->right->val.u.xval);
  1132  		return 1000;
  1133  		
  1134  	case OCALLMETH:
  1135  	case OCALLINTER:
  1136  	case OCALLFUNC:
  1137  		t = n->left->type;
  1138  		if(isptr[t->etype])
  1139  			t = t->type;
  1140  
  1141  		t = structfirst(&flist, getoutarg(t));
  1142  		if(t != T)
  1143  			return t->width;
  1144  		break;
  1145  	}
  1146  
  1147  	// botch - probably failing to recognize address
  1148  	// arithmetic on the above. eg INDEX and DOT
  1149  	return -1000;
  1150  }
  1151  
  1152  /*
  1153   * struct gen
  1154   *	memmove(&res, &n, w);
  1155   */
  1156  void
  1157  sgen(Node *n, Node *res, int64 w)
  1158  {
  1159  	Node dst, src, tdst, tsrc;
  1160  	int32 c, q, odst, osrc;
  1161  
  1162  	if(debug['g']) {
  1163  		print("\nsgen w=%lld\n", w);
  1164  		dump("r", n);
  1165  		dump("res", res);
  1166  	}
  1167  	if(n->ullman >= UINF && res->ullman >= UINF)
  1168  		fatal("sgen UINF");
  1169  
  1170  	if(w < 0 || (int32)w != w)
  1171  		fatal("sgen copy %lld", w);
  1172  
  1173  	if(w == 0) {
  1174  		// evaluate side effects only.
  1175  		tempname(&tdst, types[tptr]);
  1176  		agen(res, &tdst);
  1177  		agen(n, &tdst);
  1178  		return;
  1179  	}
  1180  
  1181  	// Avoid taking the address for simple enough types.
  1182  	if(componentgen(n, res))
  1183  		return;
  1184  
  1185  	// offset on the stack
  1186  	osrc = stkof(n);
  1187  	odst = stkof(res);
  1188  	
  1189  	if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
  1190  		// osrc and odst both on stack, and at least one is in
  1191  		// an unknown position.  Could generate code to test
  1192  		// for forward/backward copy, but instead just copy
  1193  		// to a temporary location first.
  1194  		tempname(&tsrc, n->type);
  1195  		sgen(n, &tsrc, w);
  1196  		sgen(&tsrc, res, w);
  1197  		return;
  1198  	}
  1199  
  1200  	nodreg(&dst, types[tptr], D_DI);
  1201  	nodreg(&src, types[tptr], D_SI);
  1202  
  1203  	tempname(&tsrc, types[tptr]);
  1204  	tempname(&tdst, types[tptr]);
  1205  	if(!n->addable)
  1206  		agen(n, &tsrc);
  1207  	if(!res->addable)
  1208  		agen(res, &tdst);
  1209  	if(n->addable)
  1210  		agen(n, &src);
  1211  	else
  1212  		gmove(&tsrc, &src);
  1213  	if(res->addable)
  1214  		agen(res, &dst);
  1215  	else
  1216  		gmove(&tdst, &dst);
  1217  
  1218  	c = w % 4;	// bytes
  1219  	q = w / 4;	// doublewords
  1220  
  1221  	// if we are copying forward on the stack and
  1222  	// the src and dst overlap, then reverse direction
  1223  	if(osrc < odst && odst < osrc+w) {
  1224  		// reverse direction
  1225  		gins(ASTD, N, N);		// set direction flag
  1226  		if(c > 0) {
  1227  			gconreg(AADDL, w-1, D_SI);
  1228  			gconreg(AADDL, w-1, D_DI);
  1229  
  1230  			gconreg(AMOVL, c, D_CX);
  1231  			gins(AREP, N, N);	// repeat
  1232  			gins(AMOVSB, N, N);	// MOVB *(SI)-,*(DI)-
  1233  		}
  1234  
  1235  		if(q > 0) {
  1236  			if(c > 0) {
  1237  				gconreg(AADDL, -3, D_SI);
  1238  				gconreg(AADDL, -3, D_DI);
  1239  			} else {
  1240  				gconreg(AADDL, w-4, D_SI);
  1241  				gconreg(AADDL, w-4, D_DI);
  1242  			}
  1243  			gconreg(AMOVL, q, D_CX);
  1244  			gins(AREP, N, N);	// repeat
  1245  			gins(AMOVSL, N, N);	// MOVL *(SI)-,*(DI)-
  1246  		}
  1247  		// we leave with the flag clear
  1248  		gins(ACLD, N, N);
  1249  	} else {
  1250  		gins(ACLD, N, N);	// paranoia.  TODO(rsc): remove?
  1251  		// normal direction
  1252  		if(q >= 4) {
  1253  			gconreg(AMOVL, q, D_CX);
  1254  			gins(AREP, N, N);	// repeat
  1255  			gins(AMOVSL, N, N);	// MOVL *(SI)+,*(DI)+
  1256  		} else
  1257  		while(q > 0) {
  1258  			gins(AMOVSL, N, N);	// MOVL *(SI)+,*(DI)+
  1259  			q--;
  1260  		}
  1261  		while(c > 0) {
  1262  			gins(AMOVSB, N, N);	// MOVB *(SI)+,*(DI)+
  1263  			c--;
  1264  		}
  1265  	}
  1266  }
  1267  
  1268  static int
  1269  cadable(Node *n)
  1270  {
  1271  	if(!n->addable) {
  1272  		// dont know how it happens,
  1273  		// but it does
  1274  		return 0;
  1275  	}
  1276  
  1277  	switch(n->op) {
  1278  	case ONAME:
  1279  		return 1;
  1280  	}
  1281  	return 0;
  1282  }
  1283  
  1284  /*
  1285   * copy a composite value by moving its individual components.
  1286   * Slices, strings and interfaces are supported.
  1287   * nr is N when assigning a zero value.
  1288   * return 1 if can do, 0 if can't.
  1289   */
  1290  int
  1291  componentgen(Node *nr, Node *nl)
  1292  {
  1293  	Node nodl, nodr;
  1294  	int freel, freer;
  1295  
  1296  	freel = 0;
  1297  	freer = 0;
  1298  
  1299  	switch(nl->type->etype) {
  1300  	default:
  1301  		goto no;
  1302  
  1303  	case TARRAY:
  1304  		if(!isslice(nl->type))
  1305  			goto no;
  1306  	case TSTRING:
  1307  	case TINTER:
  1308  		break;
  1309  	}
  1310  
  1311  	nodl = *nl;
  1312  	if(!cadable(nl)) {
  1313  		if(nr == N || !cadable(nr))
  1314  			goto no;
  1315  		igen(nl, &nodl, N);
  1316  		freel = 1;
  1317  	}
  1318  
  1319  	if(nr != N) {
  1320  		nodr = *nr;
  1321  		if(!cadable(nr)) {
  1322  			igen(nr, &nodr, N);
  1323  			freer = 1;
  1324  		}
  1325  	}
  1326  
  1327  	switch(nl->type->etype) {
  1328  	case TARRAY:
  1329  		nodl.xoffset += Array_array;
  1330  		nodl.type = ptrto(nl->type->type);
  1331  
  1332  		if(nr != N) {
  1333  			nodr.xoffset += Array_array;
  1334  			nodr.type = nodl.type;
  1335  		} else
  1336  			nodconst(&nodr, nodl.type, 0);
  1337  		gmove(&nodr, &nodl);
  1338  
  1339  		nodl.xoffset += Array_nel-Array_array;
  1340  		nodl.type = types[TUINT32];
  1341  
  1342  		if(nr != N) {
  1343  			nodr.xoffset += Array_nel-Array_array;
  1344  			nodr.type = nodl.type;
  1345  		} else
  1346  			nodconst(&nodr, nodl.type, 0);
  1347  		gmove(&nodr, &nodl);
  1348  
  1349  		nodl.xoffset += Array_cap-Array_nel;
  1350  		nodl.type = types[TUINT32];
  1351  
  1352  		if(nr != N) {
  1353  			nodr.xoffset += Array_cap-Array_nel;
  1354  			nodr.type = nodl.type;
  1355  		} else
  1356  			nodconst(&nodr, nodl.type, 0);
  1357  		gmove(&nodr, &nodl);
  1358  
  1359  		goto yes;
  1360  
  1361  	case TSTRING:
  1362  		nodl.xoffset += Array_array;
  1363  		nodl.type = ptrto(types[TUINT8]);
  1364  
  1365  		if(nr != N) {
  1366  			nodr.xoffset += Array_array;
  1367  			nodr.type = nodl.type;
  1368  		} else
  1369  			nodconst(&nodr, nodl.type, 0);
  1370  		gmove(&nodr, &nodl);
  1371  
  1372  		nodl.xoffset += Array_nel-Array_array;
  1373  		nodl.type = types[TUINT32];
  1374  
  1375  		if(nr != N) {
  1376  			nodr.xoffset += Array_nel-Array_array;
  1377  			nodr.type = nodl.type;
  1378  		} else
  1379  			nodconst(&nodr, nodl.type, 0);
  1380  		gmove(&nodr, &nodl);
  1381  
  1382  		goto yes;
  1383  
  1384  	case TINTER:
  1385  		nodl.xoffset += Array_array;
  1386  		nodl.type = ptrto(types[TUINT8]);
  1387  
  1388  		if(nr != N) {
  1389  			nodr.xoffset += Array_array;
  1390  			nodr.type = nodl.type;
  1391  		} else
  1392  			nodconst(&nodr, nodl.type, 0);
  1393  		gmove(&nodr, &nodl);
  1394  
  1395  		nodl.xoffset += Array_nel-Array_array;
  1396  		nodl.type = ptrto(types[TUINT8]);
  1397  
  1398  		if(nr != N) {
  1399  			nodr.xoffset += Array_nel-Array_array;
  1400  			nodr.type = nodl.type;
  1401  		} else
  1402  			nodconst(&nodr, nodl.type, 0);
  1403  		gmove(&nodr, &nodl);
  1404  
  1405  		goto yes;
  1406  	}
  1407  
  1408  no:
  1409  	if(freer)
  1410  		regfree(&nodr);
  1411  	if(freel)
  1412  		regfree(&nodl);
  1413  	return 0;
  1414  
  1415  yes:
  1416  	if(freer)
  1417  		regfree(&nodr);
  1418  	if(freel)
  1419  		regfree(&nodl);
  1420  	return 1;
  1421  }