github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/5c/cgen.c (about)

     1  // Inferno utils/5c/cgen.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5c/cgen.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  #include "gc.h"
    32  #include "../../runtime/funcdata.h"
    33  
    34  void
    35  _cgen(Node *n, Node *nn, int inrel)
    36  {
    37  	Node *l, *r;
    38  	Prog *p1;
    39  	Node nod, nod1, nod2, nod3, nod4;
    40  	int o, t;
    41  	int32 v, curs;
    42  
    43  	if(debug['g']) {
    44  		prtree(nn, "cgen lhs");
    45  		prtree(n, "cgen");
    46  	}
    47  	if(n == Z || n->type == T)
    48  		return;
    49  	if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
    50  		sugen(n, nn, n->type->width);
    51  		return;
    52  	}
    53  	l = n->left;
    54  	r = n->right;
    55  	o = n->op;
    56  	if(n->addable >= INDEXED) {
    57  		if(nn == Z) {
    58  			switch(o) {
    59  			default:
    60  				nullwarn(Z, Z);
    61  				break;
    62  			case OINDEX:
    63  				nullwarn(l, r);
    64  				break;
    65  			}
    66  			return;
    67  		}
    68  		gmove(n, nn);
    69  		return;
    70  	}
    71  	curs = cursafe;
    72  
    73  	if(n->complex >= FNX)
    74  	if(l->complex >= FNX)
    75  	if(r != Z && r->complex >= FNX)
    76  	switch(o) {
    77  	default:
    78  		regret(&nod, r, 0, 0);
    79  		cgen(r, &nod);
    80  
    81  		regsalloc(&nod1, r);
    82  		gopcode(OAS, &nod, Z, &nod1);
    83  
    84  		regfree(&nod);
    85  		nod = *n;
    86  		nod.right = &nod1;
    87  		cgen(&nod, nn);
    88  		return;
    89  
    90  	case OFUNC:
    91  	case OCOMMA:
    92  	case OANDAND:
    93  	case OOROR:
    94  	case OCOND:
    95  	case ODOT:
    96  		break;
    97  	}
    98  
    99  	switch(o) {
   100  	default:
   101  		diag(n, "unknown op in cgen: %O", o);
   102  		break;
   103  
   104  	case OAS:
   105  		if(l->op == OBIT)
   106  			goto bitas;
   107  		if(l->addable >= INDEXED && l->complex < FNX) {
   108  			if(nn != Z || r->addable < INDEXED) {
   109  				if(r->complex >= FNX && nn == Z)
   110  					regret(&nod, r, 0, 0);
   111  				else
   112  					regalloc(&nod, r, nn);
   113  				cgen(r, &nod);
   114  				gmove(&nod, l);
   115  				if(nn != Z)
   116  					gmove(&nod, nn);
   117  				regfree(&nod);
   118  			} else
   119  				gmove(r, l);
   120  			break;
   121  		}
   122  		if(l->complex >= r->complex) {
   123  			reglcgen(&nod1, l, Z);
   124  			if(r->addable >= INDEXED) {
   125  				gmove(r, &nod1);
   126  				if(nn != Z)
   127  					gmove(r, nn);
   128  				regfree(&nod1);
   129  				break;
   130  			}
   131  			regalloc(&nod, r, nn);
   132  			cgen(r, &nod);
   133  		} else {
   134  			regalloc(&nod, r, nn);
   135  			cgen(r, &nod);
   136  			reglcgen(&nod1, l, Z);
   137  		}
   138  		gmove(&nod, &nod1);
   139  		regfree(&nod);
   140  		regfree(&nod1);
   141  		break;
   142  
   143  	bitas:
   144  		n = l->left;
   145  		regalloc(&nod, r, nn);
   146  		if(l->complex >= r->complex) {
   147  			reglcgen(&nod1, n, Z);
   148  			cgen(r, &nod);
   149  		} else {
   150  			cgen(r, &nod);
   151  			reglcgen(&nod1, n, Z);
   152  		}
   153  		regalloc(&nod2, n, Z);
   154  		gopcode(OAS, &nod1, Z, &nod2);
   155  		bitstore(l, &nod, &nod1, &nod2, nn);
   156  		break;
   157  
   158  	case OBIT:
   159  		if(nn == Z) {
   160  			nullwarn(l, Z);
   161  			break;
   162  		}
   163  		bitload(n, &nod, Z, Z, nn);
   164  		gopcode(OAS, &nod, Z, nn);
   165  		regfree(&nod);
   166  		break;
   167  
   168  	case ODIV:
   169  	case OMOD:
   170  		if(nn != Z)
   171  		if((t = vlog(r)) >= 0) {
   172  			/* signed div/mod by constant power of 2 */
   173  			cgen(l, nn);
   174  			gopcode(OGE, nodconst(0), nn, Z);
   175  			p1 = p;
   176  			if(o == ODIV) {
   177  				gopcode(OADD, nodconst((1<<t)-1), Z, nn);
   178  				patch(p1, pc);
   179  				gopcode(OASHR, nodconst(t), Z, nn);
   180  			} else {
   181  				gopcode(OSUB, nn, nodconst(0), nn);
   182  				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
   183  				gopcode(OSUB, nn, nodconst(0), nn);
   184  				gbranch(OGOTO);
   185  				patch(p1, pc);
   186  				p1 = p;
   187  				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
   188  				patch(p1, pc);
   189  			}
   190  			break;
   191  		}
   192  		goto muldiv;
   193  
   194  	case OSUB:
   195  		if(nn != Z)
   196  		if(l->op == OCONST)
   197  		if(!typefd[n->type->etype]) {
   198  			cgen(r, nn);
   199  			gopcode(o, Z, l, nn);
   200  			break;
   201  		}
   202  	case OADD:
   203  	case OAND:
   204  	case OOR:
   205  	case OXOR:
   206  	case OLSHR:
   207  	case OASHL:
   208  	case OASHR:
   209  		/*
   210  		 * immediate operands
   211  		 */
   212  		if(nn != Z)
   213  		if(r->op == OCONST)
   214  		if(!typefd[n->type->etype]) {
   215  			cgen(l, nn);
   216  			if(r->vconst == 0)
   217  			if(o != OAND)
   218  				break;
   219  			if(nn != Z)
   220  				gopcode(o, r, Z, nn);
   221  			break;
   222  		}
   223  
   224  	case OLMUL:
   225  	case OLDIV:
   226  	case OLMOD:
   227  	case OMUL:
   228  	muldiv:
   229  		if(nn == Z) {
   230  			nullwarn(l, r);
   231  			break;
   232  		}
   233  		if(o == OMUL || o == OLMUL) {
   234  			if(mulcon(n, nn))
   235  				break;
   236  		}
   237  		if(l->complex >= r->complex) {
   238  			regalloc(&nod, l, nn);
   239  			cgen(l, &nod);
   240  			regalloc(&nod1, r, Z);
   241  			cgen(r, &nod1);
   242  			gopcode(o, &nod1, Z, &nod);
   243  		} else {
   244  			regalloc(&nod, r, nn);
   245  			cgen(r, &nod);
   246  			regalloc(&nod1, l, Z);
   247  			cgen(l, &nod1);
   248  			gopcode(o, &nod, &nod1, &nod);
   249  		}
   250  		gopcode(OAS, &nod, Z, nn);
   251  		regfree(&nod);
   252  		regfree(&nod1);
   253  		break;
   254  
   255  	case OASLSHR:
   256  	case OASASHL:
   257  	case OASASHR:
   258  	case OASAND:
   259  	case OASADD:
   260  	case OASSUB:
   261  	case OASXOR:
   262  	case OASOR:
   263  		if(l->op == OBIT)
   264  			goto asbitop;
   265  		if(r->op == OCONST)
   266  		if(!typefd[r->type->etype])
   267  		if(!typefd[n->type->etype]) {
   268  			if(l->addable < INDEXED)
   269  				reglcgen(&nod2, l, Z);
   270  			else
   271  				nod2 = *l;
   272  			regalloc(&nod, r, nn);
   273  			gopcode(OAS, &nod2, Z, &nod);
   274  			gopcode(o, r, Z, &nod);
   275  			gopcode(OAS, &nod, Z, &nod2);
   276  
   277  			regfree(&nod);
   278  			if(l->addable < INDEXED)
   279  				regfree(&nod2);
   280  			break;
   281  		}
   282  
   283  	case OASLMUL:
   284  	case OASLDIV:
   285  	case OASLMOD:
   286  	case OASMUL:
   287  	case OASDIV:
   288  	case OASMOD:
   289  		if(l->op == OBIT)
   290  			goto asbitop;
   291  		if(l->complex >= r->complex) {
   292  			if(l->addable < INDEXED)
   293  				reglcgen(&nod2, l, Z);
   294  			else
   295  				nod2 = *l;
   296  			regalloc(&nod1, r, Z);
   297  			cgen(r, &nod1);
   298  		} else {
   299  			regalloc(&nod1, r, Z);
   300  			cgen(r, &nod1);
   301  			if(l->addable < INDEXED)
   302  				reglcgen(&nod2, l, Z);
   303  			else
   304  				nod2 = *l;
   305  		}
   306  
   307  		regalloc(&nod, n, nn);
   308  		gmove(&nod2, &nod);
   309  		gopcode(o, &nod1, Z, &nod);
   310  		gmove(&nod, &nod2);
   311  		if(nn != Z)
   312  			gopcode(OAS, &nod, Z, nn);
   313  		regfree(&nod);
   314  		regfree(&nod1);
   315  		if(l->addable < INDEXED)
   316  			regfree(&nod2);
   317  		break;
   318  
   319  	asbitop:
   320  		regalloc(&nod4, n, nn);
   321  		if(l->complex >= r->complex) {
   322  			bitload(l, &nod, &nod1, &nod2, &nod4);
   323  			regalloc(&nod3, r, Z);
   324  			cgen(r, &nod3);
   325  		} else {
   326  			regalloc(&nod3, r, Z);
   327  			cgen(r, &nod3);
   328  			bitload(l, &nod, &nod1, &nod2, &nod4);
   329  		}
   330  		gmove(&nod, &nod4);
   331  		gopcode(o, &nod3, Z, &nod4);
   332  		regfree(&nod3);
   333  		gmove(&nod4, &nod);
   334  		regfree(&nod4);
   335  		bitstore(l, &nod, &nod1, &nod2, nn);
   336  		break;
   337  
   338  	case OADDR:
   339  		if(nn == Z) {
   340  			nullwarn(l, Z);
   341  			break;
   342  		}
   343  		lcgen(l, nn);
   344  		break;
   345  
   346  	case OFUNC:
   347  		if(l->complex >= FNX) {
   348  			if(l->op != OIND)
   349  				diag(n, "bad function call");
   350  
   351  			regret(&nod, l->left, 0, 0);
   352  			cgen(l->left, &nod);
   353  			regsalloc(&nod1, l->left);
   354  			gopcode(OAS, &nod, Z, &nod1);
   355  			regfree(&nod);
   356  
   357  			nod = *n;
   358  			nod.left = &nod2;
   359  			nod2 = *l;
   360  			nod2.left = &nod1;
   361  			nod2.complex = 1;
   362  			cgen(&nod, nn);
   363  
   364  			return;
   365  		}
   366  		if(REGARG >= 0)
   367  			o = reg[REGARG];
   368  		gargs(r, &nod, &nod1);
   369  		if(l->addable < INDEXED) {
   370  			reglcgen(&nod, l, Z);
   371  			gopcode(OFUNC, Z, Z, &nod);
   372  			regfree(&nod);
   373  		} else
   374  			gopcode(OFUNC, Z, Z, l);
   375  		if(REGARG >= 0)
   376  			if(o != reg[REGARG])
   377  				reg[REGARG]--;
   378  		regret(&nod, n, l->type, 1);
   379  		if(nn != Z)
   380  			gmove(&nod, nn);
   381  		if(nod.op == OREGISTER)
   382  			regfree(&nod);
   383  		break;
   384  
   385  	case OIND:
   386  		if(nn == Z) {
   387  			nullwarn(l, Z);
   388  			break;
   389  		}
   390  		regialloc(&nod, n, nn);
   391  		r = l;
   392  		while(r->op == OADD)
   393  			r = r->right;
   394  		if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) {
   395  			v = r->vconst;
   396  			r->vconst = 0;
   397  			cgen(l, &nod);
   398  			nod.xoffset += v;
   399  			r->vconst = v;
   400  		} else
   401  			cgen(l, &nod);
   402  		regind(&nod, n);
   403  		gopcode(OAS, &nod, Z, nn);
   404  		regfree(&nod);
   405  		break;
   406  
   407  	case OEQ:
   408  	case ONE:
   409  	case OLE:
   410  	case OLT:
   411  	case OGE:
   412  	case OGT:
   413  	case OLO:
   414  	case OLS:
   415  	case OHI:
   416  	case OHS:
   417  		if(nn == Z) {
   418  			nullwarn(l, r);
   419  			break;
   420  		}
   421  		boolgen(n, 1, nn);
   422  		break;
   423  
   424  	case OANDAND:
   425  	case OOROR:
   426  		boolgen(n, 1, nn);
   427  		if(nn == Z)
   428  			patch(p, pc);
   429  		break;
   430  
   431  	case ONOT:
   432  		if(nn == Z) {
   433  			nullwarn(l, Z);
   434  			break;
   435  		}
   436  		boolgen(n, 1, nn);
   437  		break;
   438  
   439  	case OCOMMA:
   440  		cgen(l, Z);
   441  		cgen(r, nn);
   442  		break;
   443  
   444  	case OCAST:
   445  		if(nn == Z) {
   446  			nullwarn(l, Z);
   447  			break;
   448  		}
   449  		/*
   450  		 * convert from types l->n->nn
   451  		 */
   452  		if(nocast(l->type, n->type)) {
   453  			if(nocast(n->type, nn->type)) {
   454  				cgen(l, nn);
   455  				break;
   456  			}
   457  		}
   458  		regalloc(&nod, l, nn);
   459  		cgen(l, &nod);
   460  		regalloc(&nod1, n, &nod);
   461  		if(inrel)
   462  			gmover(&nod, &nod1);
   463  		else
   464  			gopcode(OAS, &nod, Z, &nod1);
   465  		gopcode(OAS, &nod1, Z, nn);
   466  		regfree(&nod1);
   467  		regfree(&nod);
   468  		break;
   469  
   470  	case ODOT:
   471  		sugen(l, nodrat, l->type->width);
   472  		if(nn != Z) {
   473  			warn(n, "non-interruptable temporary");
   474  			nod = *nodrat;
   475  			if(!r || r->op != OCONST) {
   476  				diag(n, "DOT and no offset");
   477  				break;
   478  			}
   479  			nod.xoffset += (int32)r->vconst;
   480  			nod.type = n->type;
   481  			cgen(&nod, nn);
   482  		}
   483  		break;
   484  
   485  	case OCOND:
   486  		bcgen(l, 1);
   487  		p1 = p;
   488  		cgen(r->left, nn);
   489  		gbranch(OGOTO);
   490  		patch(p1, pc);
   491  		p1 = p;
   492  		cgen(r->right, nn);
   493  		patch(p1, pc);
   494  		break;
   495  
   496  	case OPOSTINC:
   497  	case OPOSTDEC:
   498  		v = 1;
   499  		if(l->type->etype == TIND)
   500  			v = l->type->link->width;
   501  		if(o == OPOSTDEC)
   502  			v = -v;
   503  		if(l->op == OBIT)
   504  			goto bitinc;
   505  		if(nn == Z)
   506  			goto pre;
   507  
   508  		if(l->addable < INDEXED)
   509  			reglcgen(&nod2, l, Z);
   510  		else
   511  			nod2 = *l;
   512  
   513  		regalloc(&nod, l, nn);
   514  		gopcode(OAS, &nod2, Z, &nod);
   515  		regalloc(&nod1, l, Z);
   516  		if(typefd[l->type->etype]) {
   517  			regalloc(&nod3, l, Z);
   518  			if(v < 0) {
   519  				gopcode(OAS, nodfconst(-v), Z, &nod3);
   520  				gopcode(OSUB, &nod3, &nod, &nod1);
   521  			} else {
   522  				gopcode(OAS, nodfconst(v), Z, &nod3);
   523  				gopcode(OADD, &nod3, &nod, &nod1);
   524  			}
   525  			regfree(&nod3);
   526  		} else
   527  			gopcode(OADD, nodconst(v), &nod, &nod1);
   528  		gopcode(OAS, &nod1, Z, &nod2);
   529  
   530  		regfree(&nod);
   531  		regfree(&nod1);
   532  		if(l->addable < INDEXED)
   533  			regfree(&nod2);
   534  		break;
   535  
   536  	case OPREINC:
   537  	case OPREDEC:
   538  		v = 1;
   539  		if(l->type->etype == TIND)
   540  			v = l->type->link->width;
   541  		if(o == OPREDEC)
   542  			v = -v;
   543  		if(l->op == OBIT)
   544  			goto bitinc;
   545  
   546  	pre:
   547  		if(l->addable < INDEXED)
   548  			reglcgen(&nod2, l, Z);
   549  		else
   550  			nod2 = *l;
   551  
   552  		regalloc(&nod, l, nn);
   553  		gopcode(OAS, &nod2, Z, &nod);
   554  		if(typefd[l->type->etype]) {
   555  			regalloc(&nod3, l, Z);
   556  			if(v < 0) {
   557  				gopcode(OAS, nodfconst(-v), Z, &nod3);
   558  				gopcode(OSUB, &nod3, Z, &nod);
   559  			} else {
   560  				gopcode(OAS, nodfconst(v), Z, &nod3);
   561  				gopcode(OADD, &nod3, Z, &nod);
   562  			}
   563  			regfree(&nod3);
   564  		} else
   565  			gopcode(OADD, nodconst(v), Z, &nod);
   566  		gopcode(OAS, &nod, Z, &nod2);
   567  
   568  		regfree(&nod);
   569  		if(l->addable < INDEXED)
   570  			regfree(&nod2);
   571  		break;
   572  
   573  	bitinc:
   574  		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
   575  			bitload(l, &nod, &nod1, &nod2, Z);
   576  			gopcode(OAS, &nod, Z, nn);
   577  			gopcode(OADD, nodconst(v), Z, &nod);
   578  			bitstore(l, &nod, &nod1, &nod2, Z);
   579  			break;
   580  		}
   581  		bitload(l, &nod, &nod1, &nod2, nn);
   582  		gopcode(OADD, nodconst(v), Z, &nod);
   583  		bitstore(l, &nod, &nod1, &nod2, nn);
   584  		break;
   585  	}
   586  	cursafe = curs;
   587  	return;
   588  }
   589  
   590  void
   591  cgen(Node *n, Node *nn)
   592  {
   593  	_cgen(n, nn, 0);
   594  }
   595  
   596  void
   597  cgenrel(Node *n, Node *nn)
   598  {
   599  	_cgen(n, nn, 1);
   600  }
   601  
   602  void
   603  reglcgen(Node *t, Node *n, Node *nn)
   604  {
   605  	Node *r;
   606  	int32 v;
   607  
   608  	regialloc(t, n, nn);
   609  	if(n->op == OIND) {
   610  		r = n->left;
   611  		while(r->op == OADD)
   612  			r = r->right;
   613  		if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) {
   614  			v = r->vconst;
   615  			r->vconst = 0;
   616  			lcgen(n, t);
   617  			t->xoffset += v;
   618  			r->vconst = v;
   619  			regind(t, n);
   620  			return;
   621  		}
   622  	} else if(n->op == OINDREG) {
   623  		if((v = n->xoffset) > -4096 && v < 4096) {
   624  			n->op = OREGISTER;
   625  			cgen(n, t);
   626  			t->xoffset += v;
   627  			n->op = OINDREG;
   628  			regind(t, n);
   629  			return;
   630  		}
   631  	}
   632  	lcgen(n, t);
   633  	regind(t, n);
   634  }
   635  
   636  void
   637  reglpcgen(Node *n, Node *nn, int f)
   638  {
   639  	Type *t;
   640  
   641  	t = nn->type;
   642  	nn->type = types[TLONG];
   643  	if(f)
   644  		reglcgen(n, nn, Z);
   645  	else {
   646  		regialloc(n, nn, Z);
   647  		lcgen(nn, n);
   648  		regind(n, nn);
   649  	}
   650  	nn->type = t;
   651  }
   652  
   653  void
   654  lcgen(Node *n, Node *nn)
   655  {
   656  	Prog *p1;
   657  	Node nod;
   658  
   659  	if(debug['g']) {
   660  		prtree(nn, "lcgen lhs");
   661  		prtree(n, "lcgen");
   662  	}
   663  	if(n == Z || n->type == T)
   664  		return;
   665  	if(nn == Z) {
   666  		nn = &nod;
   667  		regalloc(&nod, n, Z);
   668  	}
   669  	switch(n->op) {
   670  	default:
   671  		if(n->addable < INDEXED) {
   672  			diag(n, "unknown op in lcgen: %O", n->op);
   673  			break;
   674  		}
   675  		nod = *n;
   676  		nod.op = OADDR;
   677  		nod.left = n;
   678  		nod.right = Z;
   679  		nod.type = types[TIND];
   680  		gopcode(OAS, &nod, Z, nn);
   681  		break;
   682  
   683  	case OCOMMA:
   684  		cgen(n->left, n->left);
   685  		lcgen(n->right, nn);
   686  		break;
   687  
   688  	case OIND:
   689  		cgen(n->left, nn);
   690  		break;
   691  
   692  	case OCOND:
   693  		bcgen(n->left, 1);
   694  		p1 = p;
   695  		lcgen(n->right->left, nn);
   696  		gbranch(OGOTO);
   697  		patch(p1, pc);
   698  		p1 = p;
   699  		lcgen(n->right->right, nn);
   700  		patch(p1, pc);
   701  		break;
   702  	}
   703  }
   704  
   705  void
   706  bcgen(Node *n, int true)
   707  {
   708  
   709  	if(n->type == T)
   710  		gbranch(OGOTO);
   711  	else
   712  		boolgen(n, true, Z);
   713  }
   714  
   715  void
   716  boolgen(Node *n, int true, Node *nn)
   717  {
   718  	int o;
   719  	Prog *p1, *p2;
   720  	Node *l, *r, nod, nod1;
   721  	int32 curs;
   722  
   723  	if(debug['g']) {
   724  		prtree(nn, "boolgen lhs");
   725  		prtree(n, "boolgen");
   726  	}
   727  	curs = cursafe;
   728  	l = n->left;
   729  	r = n->right;
   730  	switch(n->op) {
   731  
   732  	default:
   733  		regalloc(&nod, n, nn);
   734  		cgen(n, &nod);
   735  		o = ONE;
   736  		if(true)
   737  			o = comrel[relindex(o)];
   738  		if(typefd[n->type->etype]) {
   739  			gopcode(o, nodfconst(0), &nod, Z);
   740  		} else
   741  			gopcode(o, nodconst(0), &nod, Z);
   742  		regfree(&nod);
   743  		goto com;
   744  
   745  	case OCONST:
   746  		o = vconst(n);
   747  		if(!true)
   748  			o = !o;
   749  		gbranch(OGOTO);
   750  		if(o) {
   751  			p1 = p;
   752  			gbranch(OGOTO);
   753  			patch(p1, pc);
   754  		}
   755  		goto com;
   756  
   757  	case OCOMMA:
   758  		cgen(l, Z);
   759  		boolgen(r, true, nn);
   760  		break;
   761  
   762  	case ONOT:
   763  		boolgen(l, !true, nn);
   764  		break;
   765  
   766  	case OCOND:
   767  		bcgen(l, 1);
   768  		p1 = p;
   769  		bcgen(r->left, true);
   770  		p2 = p;
   771  		gbranch(OGOTO);
   772  		patch(p1, pc);
   773  		p1 = p;
   774  		bcgen(r->right, !true);
   775  		patch(p2, pc);
   776  		p2 = p;
   777  		gbranch(OGOTO);
   778  		patch(p1, pc);
   779  		patch(p2, pc);
   780  		goto com;
   781  
   782  	case OANDAND:
   783  		if(!true)
   784  			goto caseor;
   785  
   786  	caseand:
   787  		bcgen(l, true);
   788  		p1 = p;
   789  		bcgen(r, !true);
   790  		p2 = p;
   791  		patch(p1, pc);
   792  		gbranch(OGOTO);
   793  		patch(p2, pc);
   794  		goto com;
   795  
   796  	case OOROR:
   797  		if(!true)
   798  			goto caseand;
   799  
   800  	caseor:
   801  		bcgen(l, !true);
   802  		p1 = p;
   803  		bcgen(r, !true);
   804  		p2 = p;
   805  		gbranch(OGOTO);
   806  		patch(p1, pc);
   807  		patch(p2, pc);
   808  		goto com;
   809  
   810  	case OEQ:
   811  	case ONE:
   812  	case OLE:
   813  	case OLT:
   814  	case OGE:
   815  	case OGT:
   816  	case OHI:
   817  	case OHS:
   818  	case OLO:
   819  	case OLS:
   820  		o = n->op;
   821  		if(true)
   822  			o = comrel[relindex(o)];
   823  		if(l->complex >= FNX && r->complex >= FNX) {
   824  			regret(&nod, r, 0, 0);
   825  			cgenrel(r, &nod);
   826  			regsalloc(&nod1, r);
   827  			gopcode(OAS, &nod, Z, &nod1);
   828  			regfree(&nod);
   829  			nod = *n;
   830  			nod.right = &nod1;
   831  			boolgen(&nod, true, nn);
   832  			break;
   833  		}
   834  		if(sconst(l)) {
   835  			regalloc(&nod, r, nn);
   836  			cgenrel(r, &nod);
   837  			o = invrel[relindex(o)];
   838  			gopcode(o, l, &nod, Z);
   839  			regfree(&nod);
   840  			goto com;
   841  		}
   842  		if(sconst(r)) {
   843  			regalloc(&nod, l, nn);
   844  			cgenrel(l, &nod);
   845  			gopcode(o, r, &nod, Z);
   846  			regfree(&nod);
   847  			goto com;
   848  		}
   849  		if(l->complex >= r->complex) {
   850  			regalloc(&nod1, l, nn);
   851  			cgenrel(l, &nod1);
   852  			regalloc(&nod, r, Z);
   853  			cgenrel(r, &nod);
   854  		} else {
   855  			regalloc(&nod, r, nn);
   856  			cgenrel(r, &nod);
   857  			regalloc(&nod1, l, Z);
   858  			cgenrel(l, &nod1);
   859  		}
   860  		gopcode(o, &nod, &nod1, Z);
   861  		regfree(&nod);
   862  		regfree(&nod1);
   863  
   864  	com:
   865  		if(nn != Z) {
   866  			p1 = p;
   867  			gopcode(OAS, nodconst(1), Z, nn);
   868  			gbranch(OGOTO);
   869  			p2 = p;
   870  			patch(p1, pc);
   871  			gopcode(OAS, nodconst(0), Z, nn);
   872  			patch(p2, pc);
   873  		}
   874  		break;
   875  	}
   876  	cursafe = curs;
   877  }
   878  
   879  void
   880  sugen(Node *n, Node *nn, int32 w)
   881  {
   882  	Prog *p1;
   883  	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
   884  	Type *t;
   885  	int32 pc1;
   886  	int i, m, c;
   887  
   888  	if(n == Z || n->type == T)
   889  		return;
   890  	if(debug['g']) {
   891  		prtree(nn, "sugen lhs");
   892  		prtree(n, "sugen");
   893  	}
   894  	if(nn == nodrat)
   895  		if(w > nrathole)
   896  			nrathole = w;
   897  	switch(n->op) {
   898  	case OIND:
   899  		if(nn == Z) {
   900  			nullwarn(n->left, Z);
   901  			break;
   902  		}
   903  
   904  	default:
   905  		goto copy;
   906  
   907  	case OCONST:
   908  		if(n->type && typev[n->type->etype]) {
   909  			if(nn == Z) {
   910  				nullwarn(n->left, Z);
   911  				break;
   912  			}
   913  
   914  			t = nn->type;
   915  			nn->type = types[TLONG];
   916  			reglcgen(&nod1, nn, Z);
   917  			nn->type = t;
   918  
   919  			if(isbigendian)
   920  				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
   921  			else
   922  				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
   923  			nod1.xoffset += SZ_LONG;
   924  			if(isbigendian)
   925  				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
   926  			else
   927  				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
   928  
   929  			regfree(&nod1);
   930  			break;
   931  		}
   932  		goto copy;
   933  
   934  	case ODOT:
   935  		l = n->left;
   936  		sugen(l, nodrat, l->type->width);
   937  		if(nn != Z) {
   938  			warn(n, "non-interruptable temporary");
   939  			nod1 = *nodrat;
   940  			r = n->right;
   941  			if(!r || r->op != OCONST) {
   942  				diag(n, "DOT and no offset");
   943  				break;
   944  			}
   945  			nod1.xoffset += (int32)r->vconst;
   946  			nod1.type = n->type;
   947  			sugen(&nod1, nn, w);
   948  		}
   949  		break;
   950  
   951  	case OSTRUCT:
   952  		/*
   953  		 * rewrite so lhs has no side effect.
   954  		 */
   955  		if(nn != Z && side(nn)) {
   956  			nod1 = *n;
   957  			nod1.type = typ(TIND, n->type);
   958  			regret(&nod2, &nod1, 0, 0);
   959  			lcgen(nn, &nod2);
   960  			regsalloc(&nod0, &nod1);
   961  			gopcode(OAS, &nod2, Z, &nod0);
   962  			regfree(&nod2);
   963  
   964  			nod1 = *n;
   965  			nod1.op = OIND;
   966  			nod1.left = &nod0;
   967  			nod1.right = Z;
   968  			nod1.complex = 1;
   969  
   970  			sugen(n, &nod1, w);
   971  			return;
   972  		}
   973  
   974  		r = n->left;
   975  		for(t = n->type->link; t != T; t = t->down) {
   976  			l = r;
   977  			if(r->op == OLIST) {
   978  				l = r->left;
   979  				r = r->right;
   980  			}
   981  			if(nn == Z) {
   982  				cgen(l, nn);
   983  				continue;
   984  			}
   985  			/*
   986  			 * hand craft *(&nn + o) = l
   987  			 */
   988  			nod0 = znode;
   989  			nod0.op = OAS;
   990  			nod0.type = t;
   991  			nod0.left = &nod1;
   992  			nod0.right = l;
   993  
   994  			nod1 = znode;
   995  			nod1.op = OIND;
   996  			nod1.type = t;
   997  			nod1.left = &nod2;
   998  
   999  			nod2 = znode;
  1000  			nod2.op = OADD;
  1001  			nod2.type = typ(TIND, t);
  1002  			nod2.left = &nod3;
  1003  			nod2.right = &nod4;
  1004  
  1005  			nod3 = znode;
  1006  			nod3.op = OADDR;
  1007  			nod3.type = nod2.type;
  1008  			nod3.left = nn;
  1009  
  1010  			nod4 = znode;
  1011  			nod4.op = OCONST;
  1012  			nod4.type = nod2.type;
  1013  			nod4.vconst = t->offset;
  1014  
  1015  			ccom(&nod0);
  1016  			acom(&nod0);
  1017  			xcom(&nod0);
  1018  			nod0.addable = 0;
  1019  
  1020  			cgen(&nod0, Z);
  1021  		}
  1022  		break;
  1023  
  1024  	case OAS:
  1025  		if(nn == Z) {
  1026  			if(n->addable < INDEXED)
  1027  				sugen(n->right, n->left, w);
  1028  			break;
  1029  		}
  1030  		sugen(n->right, nodrat, w);
  1031  		warn(n, "non-interruptable temporary");
  1032  		sugen(nodrat, n->left, w);
  1033  		sugen(nodrat, nn, w);
  1034  		break;
  1035  
  1036  	case OFUNC:
  1037  		if(!hasdotdotdot(n->left->type)) {
  1038  			cgen(n, Z);
  1039  			if(nn != Z) {
  1040  				curarg -= n->type->width;
  1041  				regret(&nod1, n, n->left->type, 1);
  1042  				if(nn->complex >= FNX) {
  1043  					regsalloc(&nod2, n);
  1044  					cgen(&nod1, &nod2);
  1045  					nod1 = nod2;
  1046  				}
  1047  				cgen(&nod1, nn);
  1048  			}
  1049  			break;
  1050  		}
  1051  		if(nn == Z) {
  1052  			sugen(n, nodrat, w);
  1053  			break;
  1054  		}
  1055  		if(nn->op != OIND) {
  1056  			nn = new1(OADDR, nn, Z);
  1057  			nn->type = types[TIND];
  1058  			nn->addable = 0;
  1059  		} else
  1060  			nn = nn->left;
  1061  		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  1062  		n->type = types[TVOID];
  1063  		n->left->type = types[TVOID];
  1064  		cgen(n, Z);
  1065  		break;
  1066  
  1067  	case OCOND:
  1068  		bcgen(n->left, 1);
  1069  		p1 = p;
  1070  		sugen(n->right->left, nn, w);
  1071  		gbranch(OGOTO);
  1072  		patch(p1, pc);
  1073  		p1 = p;
  1074  		sugen(n->right->right, nn, w);
  1075  		patch(p1, pc);
  1076  		break;
  1077  
  1078  	case OCOMMA:
  1079  		cgen(n->left, Z);
  1080  		sugen(n->right, nn, w);
  1081  		break;
  1082  	}
  1083  	return;
  1084  
  1085  copy:
  1086  	if(nn == Z)
  1087  		return;
  1088  	if(n->complex >= FNX && nn->complex >= FNX) {
  1089  		t = nn->type;
  1090  		nn->type = types[TLONG];
  1091  		regialloc(&nod1, nn, Z);
  1092  		lcgen(nn, &nod1);
  1093  		regsalloc(&nod2, nn);
  1094  		nn->type = t;
  1095  
  1096  		gopcode(OAS, &nod1, Z, &nod2);
  1097  		regfree(&nod1);
  1098  
  1099  		nod2.type = typ(TIND, t);
  1100  
  1101  		nod1 = nod2;
  1102  		nod1.op = OIND;
  1103  		nod1.left = &nod2;
  1104  		nod1.right = Z;
  1105  		nod1.complex = 1;
  1106  		nod1.type = t;
  1107  
  1108  		sugen(n, &nod1, w);
  1109  		return;
  1110  	}
  1111  
  1112  	w /= SZ_LONG;
  1113  	if(w <= 2) {
  1114  		if(n->complex > nn->complex) {
  1115  			reglpcgen(&nod1, n, 1);
  1116  			reglpcgen(&nod2, nn, 1);
  1117  		} else {
  1118  			reglpcgen(&nod2, nn, 1);
  1119  			reglpcgen(&nod1, n, 1);
  1120  		}
  1121  		regalloc(&nod3, &regnode, Z);
  1122  		regalloc(&nod4, &regnode, Z);
  1123  		nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
  1124  		if(w == 2 && nod1.xoffset == 0)
  1125  			gmovm(&nod1, &nod0, 0);
  1126  		else {
  1127  			gmove(&nod1, &nod3);
  1128  			if(w == 2) {
  1129  				nod1.xoffset += SZ_LONG;
  1130  				gmove(&nod1, &nod4);
  1131  			}
  1132  		}
  1133  		if(w == 2 && nod2.xoffset == 0)
  1134  			gmovm(&nod0, &nod2, 0);
  1135  		else {
  1136  			gmove(&nod3, &nod2);
  1137  			if(w == 2) {
  1138  				nod2.xoffset += SZ_LONG;
  1139  				gmove(&nod4, &nod2);
  1140  			}
  1141  		}
  1142  		regfree(&nod1);
  1143  		regfree(&nod2);
  1144  		regfree(&nod3);
  1145  		regfree(&nod4);
  1146  		return;
  1147  	}
  1148  
  1149  	if(n->complex > nn->complex) {
  1150  		reglpcgen(&nod1, n, 0);
  1151  		reglpcgen(&nod2, nn, 0);
  1152  	} else {
  1153  		reglpcgen(&nod2, nn, 0);
  1154  		reglpcgen(&nod1, n, 0);
  1155  	}
  1156  
  1157  	m = 0;
  1158  	for(c = 0; c < w && c < 4; c++) {
  1159  		i = tmpreg();
  1160  		if (i == 0)
  1161  			break;
  1162  		reg[i]++;
  1163  		m |= 1<<i;
  1164  	}
  1165  	nod4 = *(nodconst(m));
  1166  	if(w < 3*c) {
  1167  		for (; w>c; w-=c) {
  1168  			gmovm(&nod1, &nod4, 1);
  1169  			gmovm(&nod4, &nod2, 1);
  1170  		}
  1171  		goto out;
  1172  	}
  1173  
  1174  	regalloc(&nod3, &regnode, Z);
  1175  	gopcode(OAS, nodconst(w/c), Z, &nod3);
  1176  	w %= c;
  1177  
  1178  	pc1 = pc;
  1179  	gmovm(&nod1, &nod4, 1);
  1180  	gmovm(&nod4, &nod2, 1);
  1181  
  1182  	gopcode(OSUB, nodconst(1), Z, &nod3);
  1183  	gopcode(OEQ, nodconst(0), &nod3, Z);
  1184  	p->as = ABGT;
  1185  	patch(p, pc1);
  1186  	regfree(&nod3);
  1187  
  1188  out:
  1189  	if (w) {
  1190  		i = 0;
  1191  		while (c>w) {
  1192  			while ((m&(1<<i)) == 0)
  1193  				i++;
  1194  			m &= ~(1<<i);
  1195  			reg[i] = 0;
  1196  			c--;
  1197  			i++;
  1198  		}
  1199  		nod4.vconst = m;
  1200  		gmovm(&nod1, &nod4, 0);
  1201  		gmovm(&nod4, &nod2, 0);
  1202  	}
  1203  	i = 0;
  1204  	do {
  1205  		while ((m&(1<<i)) == 0)
  1206  			i++;
  1207  		reg[i] = 0;
  1208  		c--;
  1209  		i++;
  1210  	} while (c>0);
  1211  	regfree(&nod1);
  1212  	regfree(&nod2);
  1213  }