github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 "../../pkg/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]) {
    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);
    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);
   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);
   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  		gpcdata(PCDATA_ArgSize, curarg);
   370  		if(l->addable < INDEXED) {
   371  			reglcgen(&nod, l, Z);
   372  			gopcode(OFUNC, Z, Z, &nod);
   373  			regfree(&nod);
   374  		} else
   375  			gopcode(OFUNC, Z, Z, l);
   376  		gpcdata(PCDATA_ArgSize, -1);
   377  		if(REGARG >= 0)
   378  			if(o != reg[REGARG])
   379  				reg[REGARG]--;
   380  		if(nn != Z) {
   381  			regret(&nod, n);
   382  			gopcode(OAS, &nod, Z, nn);
   383  			regfree(&nod);
   384  		}
   385  		break;
   386  
   387  	case OIND:
   388  		if(nn == Z) {
   389  			nullwarn(l, Z);
   390  			break;
   391  		}
   392  		regialloc(&nod, n, nn);
   393  		r = l;
   394  		while(r->op == OADD)
   395  			r = r->right;
   396  		if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) {
   397  			v = r->vconst;
   398  			r->vconst = 0;
   399  			cgen(l, &nod);
   400  			nod.xoffset += v;
   401  			r->vconst = v;
   402  		} else
   403  			cgen(l, &nod);
   404  		regind(&nod, n);
   405  		gopcode(OAS, &nod, Z, nn);
   406  		regfree(&nod);
   407  		break;
   408  
   409  	case OEQ:
   410  	case ONE:
   411  	case OLE:
   412  	case OLT:
   413  	case OGE:
   414  	case OGT:
   415  	case OLO:
   416  	case OLS:
   417  	case OHI:
   418  	case OHS:
   419  		if(nn == Z) {
   420  			nullwarn(l, r);
   421  			break;
   422  		}
   423  		boolgen(n, 1, nn);
   424  		break;
   425  
   426  	case OANDAND:
   427  	case OOROR:
   428  		boolgen(n, 1, nn);
   429  		if(nn == Z)
   430  			patch(p, pc);
   431  		break;
   432  
   433  	case ONOT:
   434  		if(nn == Z) {
   435  			nullwarn(l, Z);
   436  			break;
   437  		}
   438  		boolgen(n, 1, nn);
   439  		break;
   440  
   441  	case OCOMMA:
   442  		cgen(l, Z);
   443  		cgen(r, nn);
   444  		break;
   445  
   446  	case OCAST:
   447  		if(nn == Z) {
   448  			nullwarn(l, Z);
   449  			break;
   450  		}
   451  		/*
   452  		 * convert from types l->n->nn
   453  		 */
   454  		if(nocast(l->type, n->type)) {
   455  			if(nocast(n->type, nn->type)) {
   456  				cgen(l, nn);
   457  				break;
   458  			}
   459  		}
   460  		regalloc(&nod, l, nn);
   461  		cgen(l, &nod);
   462  		regalloc(&nod1, n, &nod);
   463  		if(inrel)
   464  			gmover(&nod, &nod1);
   465  		else
   466  			gopcode(OAS, &nod, Z, &nod1);
   467  		gopcode(OAS, &nod1, Z, nn);
   468  		regfree(&nod1);
   469  		regfree(&nod);
   470  		break;
   471  
   472  	case ODOT:
   473  		sugen(l, nodrat, l->type->width);
   474  		if(nn != Z) {
   475  			warn(n, "non-interruptable temporary");
   476  			nod = *nodrat;
   477  			if(!r || r->op != OCONST) {
   478  				diag(n, "DOT and no offset");
   479  				break;
   480  			}
   481  			nod.xoffset += (int32)r->vconst;
   482  			nod.type = n->type;
   483  			cgen(&nod, nn);
   484  		}
   485  		break;
   486  
   487  	case OCOND:
   488  		bcgen(l, 1);
   489  		p1 = p;
   490  		cgen(r->left, nn);
   491  		gbranch(OGOTO);
   492  		patch(p1, pc);
   493  		p1 = p;
   494  		cgen(r->right, nn);
   495  		patch(p1, pc);
   496  		break;
   497  
   498  	case OPOSTINC:
   499  	case OPOSTDEC:
   500  		v = 1;
   501  		if(l->type->etype == TIND)
   502  			v = l->type->link->width;
   503  		if(o == OPOSTDEC)
   504  			v = -v;
   505  		if(l->op == OBIT)
   506  			goto bitinc;
   507  		if(nn == Z)
   508  			goto pre;
   509  
   510  		if(l->addable < INDEXED)
   511  			reglcgen(&nod2, l, Z);
   512  		else
   513  			nod2 = *l;
   514  
   515  		regalloc(&nod, l, nn);
   516  		gopcode(OAS, &nod2, Z, &nod);
   517  		regalloc(&nod1, l, Z);
   518  		if(typefd[l->type->etype]) {
   519  			regalloc(&nod3, l, Z);
   520  			if(v < 0) {
   521  				gopcode(OAS, nodfconst(-v), Z, &nod3);
   522  				gopcode(OSUB, &nod3, &nod, &nod1);
   523  			} else {
   524  				gopcode(OAS, nodfconst(v), Z, &nod3);
   525  				gopcode(OADD, &nod3, &nod, &nod1);
   526  			}
   527  			regfree(&nod3);
   528  		} else
   529  			gopcode(OADD, nodconst(v), &nod, &nod1);
   530  		gopcode(OAS, &nod1, Z, &nod2);
   531  
   532  		regfree(&nod);
   533  		regfree(&nod1);
   534  		if(l->addable < INDEXED)
   535  			regfree(&nod2);
   536  		break;
   537  
   538  	case OPREINC:
   539  	case OPREDEC:
   540  		v = 1;
   541  		if(l->type->etype == TIND)
   542  			v = l->type->link->width;
   543  		if(o == OPREDEC)
   544  			v = -v;
   545  		if(l->op == OBIT)
   546  			goto bitinc;
   547  
   548  	pre:
   549  		if(l->addable < INDEXED)
   550  			reglcgen(&nod2, l, Z);
   551  		else
   552  			nod2 = *l;
   553  
   554  		regalloc(&nod, l, nn);
   555  		gopcode(OAS, &nod2, Z, &nod);
   556  		if(typefd[l->type->etype]) {
   557  			regalloc(&nod3, l, Z);
   558  			if(v < 0) {
   559  				gopcode(OAS, nodfconst(-v), Z, &nod3);
   560  				gopcode(OSUB, &nod3, Z, &nod);
   561  			} else {
   562  				gopcode(OAS, nodfconst(v), Z, &nod3);
   563  				gopcode(OADD, &nod3, Z, &nod);
   564  			}
   565  			regfree(&nod3);
   566  		} else
   567  			gopcode(OADD, nodconst(v), Z, &nod);
   568  		gopcode(OAS, &nod, Z, &nod2);
   569  
   570  		regfree(&nod);
   571  		if(l->addable < INDEXED)
   572  			regfree(&nod2);
   573  		break;
   574  
   575  	bitinc:
   576  		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
   577  			bitload(l, &nod, &nod1, &nod2, Z);
   578  			gopcode(OAS, &nod, Z, nn);
   579  			gopcode(OADD, nodconst(v), Z, &nod);
   580  			bitstore(l, &nod, &nod1, &nod2, Z);
   581  			break;
   582  		}
   583  		bitload(l, &nod, &nod1, &nod2, nn);
   584  		gopcode(OADD, nodconst(v), Z, &nod);
   585  		bitstore(l, &nod, &nod1, &nod2, nn);
   586  		break;
   587  	}
   588  	cursafe = curs;
   589  	return;
   590  }
   591  
   592  void
   593  cgen(Node *n, Node *nn)
   594  {
   595  	_cgen(n, nn, 0);
   596  }
   597  
   598  void
   599  cgenrel(Node *n, Node *nn)
   600  {
   601  	_cgen(n, nn, 1);
   602  }
   603  
   604  void
   605  reglcgen(Node *t, Node *n, Node *nn)
   606  {
   607  	Node *r;
   608  	int32 v;
   609  
   610  	regialloc(t, n, nn);
   611  	if(n->op == OIND) {
   612  		r = n->left;
   613  		while(r->op == OADD)
   614  			r = r->right;
   615  		if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) {
   616  			v = r->vconst;
   617  			r->vconst = 0;
   618  			lcgen(n, t);
   619  			t->xoffset += v;
   620  			r->vconst = v;
   621  			regind(t, n);
   622  			return;
   623  		}
   624  	} else if(n->op == OINDREG) {
   625  		if((v = n->xoffset) > -4096 && v < 4096) {
   626  			n->op = OREGISTER;
   627  			cgen(n, t);
   628  			t->xoffset += v;
   629  			n->op = OINDREG;
   630  			regind(t, n);
   631  			return;
   632  		}
   633  	}
   634  	lcgen(n, t);
   635  	regind(t, n);
   636  }
   637  
   638  void
   639  reglpcgen(Node *n, Node *nn, int f)
   640  {
   641  	Type *t;
   642  
   643  	t = nn->type;
   644  	nn->type = types[TLONG];
   645  	if(f)
   646  		reglcgen(n, nn, Z);
   647  	else {
   648  		regialloc(n, nn, Z);
   649  		lcgen(nn, n);
   650  		regind(n, nn);
   651  	}
   652  	nn->type = t;
   653  }
   654  
   655  void
   656  lcgen(Node *n, Node *nn)
   657  {
   658  	Prog *p1;
   659  	Node nod;
   660  
   661  	if(debug['g']) {
   662  		prtree(nn, "lcgen lhs");
   663  		prtree(n, "lcgen");
   664  	}
   665  	if(n == Z || n->type == T)
   666  		return;
   667  	if(nn == Z) {
   668  		nn = &nod;
   669  		regalloc(&nod, n, Z);
   670  	}
   671  	switch(n->op) {
   672  	default:
   673  		if(n->addable < INDEXED) {
   674  			diag(n, "unknown op in lcgen: %O", n->op);
   675  			break;
   676  		}
   677  		nod = *n;
   678  		nod.op = OADDR;
   679  		nod.left = n;
   680  		nod.right = Z;
   681  		nod.type = types[TIND];
   682  		gopcode(OAS, &nod, Z, nn);
   683  		break;
   684  
   685  	case OCOMMA:
   686  		cgen(n->left, n->left);
   687  		lcgen(n->right, nn);
   688  		break;
   689  
   690  	case OIND:
   691  		cgen(n->left, nn);
   692  		break;
   693  
   694  	case OCOND:
   695  		bcgen(n->left, 1);
   696  		p1 = p;
   697  		lcgen(n->right->left, nn);
   698  		gbranch(OGOTO);
   699  		patch(p1, pc);
   700  		p1 = p;
   701  		lcgen(n->right->right, nn);
   702  		patch(p1, pc);
   703  		break;
   704  	}
   705  }
   706  
   707  void
   708  bcgen(Node *n, int true)
   709  {
   710  
   711  	if(n->type == T)
   712  		gbranch(OGOTO);
   713  	else
   714  		boolgen(n, true, Z);
   715  }
   716  
   717  void
   718  boolgen(Node *n, int true, Node *nn)
   719  {
   720  	int o;
   721  	Prog *p1, *p2;
   722  	Node *l, *r, nod, nod1;
   723  	int32 curs;
   724  
   725  	if(debug['g']) {
   726  		prtree(nn, "boolgen lhs");
   727  		prtree(n, "boolgen");
   728  	}
   729  	curs = cursafe;
   730  	l = n->left;
   731  	r = n->right;
   732  	switch(n->op) {
   733  
   734  	default:
   735  		regalloc(&nod, n, nn);
   736  		cgen(n, &nod);
   737  		o = ONE;
   738  		if(true)
   739  			o = comrel[relindex(o)];
   740  		if(typefd[n->type->etype]) {
   741  			gopcode(o, nodfconst(0), &nod, Z);
   742  		} else
   743  			gopcode(o, nodconst(0), &nod, Z);
   744  		regfree(&nod);
   745  		goto com;
   746  
   747  	case OCONST:
   748  		o = vconst(n);
   749  		if(!true)
   750  			o = !o;
   751  		gbranch(OGOTO);
   752  		if(o) {
   753  			p1 = p;
   754  			gbranch(OGOTO);
   755  			patch(p1, pc);
   756  		}
   757  		goto com;
   758  
   759  	case OCOMMA:
   760  		cgen(l, Z);
   761  		boolgen(r, true, nn);
   762  		break;
   763  
   764  	case ONOT:
   765  		boolgen(l, !true, nn);
   766  		break;
   767  
   768  	case OCOND:
   769  		bcgen(l, 1);
   770  		p1 = p;
   771  		bcgen(r->left, true);
   772  		p2 = p;
   773  		gbranch(OGOTO);
   774  		patch(p1, pc);
   775  		p1 = p;
   776  		bcgen(r->right, !true);
   777  		patch(p2, pc);
   778  		p2 = p;
   779  		gbranch(OGOTO);
   780  		patch(p1, pc);
   781  		patch(p2, pc);
   782  		goto com;
   783  
   784  	case OANDAND:
   785  		if(!true)
   786  			goto caseor;
   787  
   788  	caseand:
   789  		bcgen(l, true);
   790  		p1 = p;
   791  		bcgen(r, !true);
   792  		p2 = p;
   793  		patch(p1, pc);
   794  		gbranch(OGOTO);
   795  		patch(p2, pc);
   796  		goto com;
   797  
   798  	case OOROR:
   799  		if(!true)
   800  			goto caseand;
   801  
   802  	caseor:
   803  		bcgen(l, !true);
   804  		p1 = p;
   805  		bcgen(r, !true);
   806  		p2 = p;
   807  		gbranch(OGOTO);
   808  		patch(p1, pc);
   809  		patch(p2, pc);
   810  		goto com;
   811  
   812  	case OEQ:
   813  	case ONE:
   814  	case OLE:
   815  	case OLT:
   816  	case OGE:
   817  	case OGT:
   818  	case OHI:
   819  	case OHS:
   820  	case OLO:
   821  	case OLS:
   822  		o = n->op;
   823  		if(true)
   824  			o = comrel[relindex(o)];
   825  		if(l->complex >= FNX && r->complex >= FNX) {
   826  			regret(&nod, r);
   827  			cgenrel(r, &nod);
   828  			regsalloc(&nod1, r);
   829  			gopcode(OAS, &nod, Z, &nod1);
   830  			regfree(&nod);
   831  			nod = *n;
   832  			nod.right = &nod1;
   833  			boolgen(&nod, true, nn);
   834  			break;
   835  		}
   836  		if(sconst(l)) {
   837  			regalloc(&nod, r, nn);
   838  			cgenrel(r, &nod);
   839  			o = invrel[relindex(o)];
   840  			gopcode(o, l, &nod, Z);
   841  			regfree(&nod);
   842  			goto com;
   843  		}
   844  		if(sconst(r)) {
   845  			regalloc(&nod, l, nn);
   846  			cgenrel(l, &nod);
   847  			gopcode(o, r, &nod, Z);
   848  			regfree(&nod);
   849  			goto com;
   850  		}
   851  		if(l->complex >= r->complex) {
   852  			regalloc(&nod1, l, nn);
   853  			cgenrel(l, &nod1);
   854  			regalloc(&nod, r, Z);
   855  			cgenrel(r, &nod);
   856  		} else {
   857  			regalloc(&nod, r, nn);
   858  			cgenrel(r, &nod);
   859  			regalloc(&nod1, l, Z);
   860  			cgenrel(l, &nod1);
   861  		}
   862  		gopcode(o, &nod, &nod1, Z);
   863  		regfree(&nod);
   864  		regfree(&nod1);
   865  
   866  	com:
   867  		if(nn != Z) {
   868  			p1 = p;
   869  			gopcode(OAS, nodconst(1), Z, nn);
   870  			gbranch(OGOTO);
   871  			p2 = p;
   872  			patch(p1, pc);
   873  			gopcode(OAS, nodconst(0), Z, nn);
   874  			patch(p2, pc);
   875  		}
   876  		break;
   877  	}
   878  	cursafe = curs;
   879  }
   880  
   881  void
   882  sugen(Node *n, Node *nn, int32 w)
   883  {
   884  	Prog *p1;
   885  	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
   886  	Type *t;
   887  	int32 pc1;
   888  	int i, m, c;
   889  
   890  	if(n == Z || n->type == T)
   891  		return;
   892  	if(debug['g']) {
   893  		prtree(nn, "sugen lhs");
   894  		prtree(n, "sugen");
   895  	}
   896  	if(nn == nodrat)
   897  		if(w > nrathole)
   898  			nrathole = w;
   899  	switch(n->op) {
   900  	case OIND:
   901  		if(nn == Z) {
   902  			nullwarn(n->left, Z);
   903  			break;
   904  		}
   905  
   906  	default:
   907  		goto copy;
   908  
   909  	case OCONST:
   910  		if(n->type && typev[n->type->etype]) {
   911  			if(nn == Z) {
   912  				nullwarn(n->left, Z);
   913  				break;
   914  			}
   915  
   916  			t = nn->type;
   917  			nn->type = types[TLONG];
   918  			reglcgen(&nod1, nn, Z);
   919  			nn->type = t;
   920  
   921  			if(isbigendian)
   922  				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
   923  			else
   924  				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
   925  			nod1.xoffset += SZ_LONG;
   926  			if(isbigendian)
   927  				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
   928  			else
   929  				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
   930  
   931  			regfree(&nod1);
   932  			break;
   933  		}
   934  		goto copy;
   935  
   936  	case ODOT:
   937  		l = n->left;
   938  		sugen(l, nodrat, l->type->width);
   939  		if(nn != Z) {
   940  			warn(n, "non-interruptable temporary");
   941  			nod1 = *nodrat;
   942  			r = n->right;
   943  			if(!r || r->op != OCONST) {
   944  				diag(n, "DOT and no offset");
   945  				break;
   946  			}
   947  			nod1.xoffset += (int32)r->vconst;
   948  			nod1.type = n->type;
   949  			sugen(&nod1, nn, w);
   950  		}
   951  		break;
   952  
   953  	case OSTRUCT:
   954  		/*
   955  		 * rewrite so lhs has no side effect.
   956  		 */
   957  		if(nn != Z && side(nn)) {
   958  			nod1 = *n;
   959  			nod1.type = typ(TIND, n->type);
   960  			regret(&nod2, &nod1);
   961  			lcgen(nn, &nod2);
   962  			regsalloc(&nod0, &nod1);
   963  			gopcode(OAS, &nod2, Z, &nod0);
   964  			regfree(&nod2);
   965  
   966  			nod1 = *n;
   967  			nod1.op = OIND;
   968  			nod1.left = &nod0;
   969  			nod1.right = Z;
   970  			nod1.complex = 1;
   971  
   972  			sugen(n, &nod1, w);
   973  			return;
   974  		}
   975  
   976  		r = n->left;
   977  		for(t = n->type->link; t != T; t = t->down) {
   978  			l = r;
   979  			if(r->op == OLIST) {
   980  				l = r->left;
   981  				r = r->right;
   982  			}
   983  			if(nn == Z) {
   984  				cgen(l, nn);
   985  				continue;
   986  			}
   987  			/*
   988  			 * hand craft *(&nn + o) = l
   989  			 */
   990  			nod0 = znode;
   991  			nod0.op = OAS;
   992  			nod0.type = t;
   993  			nod0.left = &nod1;
   994  			nod0.right = l;
   995  
   996  			nod1 = znode;
   997  			nod1.op = OIND;
   998  			nod1.type = t;
   999  			nod1.left = &nod2;
  1000  
  1001  			nod2 = znode;
  1002  			nod2.op = OADD;
  1003  			nod2.type = typ(TIND, t);
  1004  			nod2.left = &nod3;
  1005  			nod2.right = &nod4;
  1006  
  1007  			nod3 = znode;
  1008  			nod3.op = OADDR;
  1009  			nod3.type = nod2.type;
  1010  			nod3.left = nn;
  1011  
  1012  			nod4 = znode;
  1013  			nod4.op = OCONST;
  1014  			nod4.type = nod2.type;
  1015  			nod4.vconst = t->offset;
  1016  
  1017  			ccom(&nod0);
  1018  			acom(&nod0);
  1019  			xcom(&nod0);
  1020  			nod0.addable = 0;
  1021  
  1022  			cgen(&nod0, Z);
  1023  		}
  1024  		break;
  1025  
  1026  	case OAS:
  1027  		if(nn == Z) {
  1028  			if(n->addable < INDEXED)
  1029  				sugen(n->right, n->left, w);
  1030  			break;
  1031  		}
  1032  		sugen(n->right, nodrat, w);
  1033  		warn(n, "non-interruptable temporary");
  1034  		sugen(nodrat, n->left, w);
  1035  		sugen(nodrat, nn, w);
  1036  		break;
  1037  
  1038  	case OFUNC:
  1039  		if(nn == Z) {
  1040  			sugen(n, nodrat, w);
  1041  			break;
  1042  		}
  1043  		if(nn->op != OIND) {
  1044  			nn = new1(OADDR, nn, Z);
  1045  			nn->type = types[TIND];
  1046  			nn->addable = 0;
  1047  		} else
  1048  			nn = nn->left;
  1049  		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  1050  		n->type = types[TVOID];
  1051  		n->left->type = types[TVOID];
  1052  		cgen(n, Z);
  1053  		break;
  1054  
  1055  	case OCOND:
  1056  		bcgen(n->left, 1);
  1057  		p1 = p;
  1058  		sugen(n->right->left, nn, w);
  1059  		gbranch(OGOTO);
  1060  		patch(p1, pc);
  1061  		p1 = p;
  1062  		sugen(n->right->right, nn, w);
  1063  		patch(p1, pc);
  1064  		break;
  1065  
  1066  	case OCOMMA:
  1067  		cgen(n->left, Z);
  1068  		sugen(n->right, nn, w);
  1069  		break;
  1070  	}
  1071  	return;
  1072  
  1073  copy:
  1074  	if(nn == Z)
  1075  		return;
  1076  	if(n->complex >= FNX && nn->complex >= FNX) {
  1077  		t = nn->type;
  1078  		nn->type = types[TLONG];
  1079  		regialloc(&nod1, nn, Z);
  1080  		lcgen(nn, &nod1);
  1081  		regsalloc(&nod2, nn);
  1082  		nn->type = t;
  1083  
  1084  		gopcode(OAS, &nod1, Z, &nod2);
  1085  		regfree(&nod1);
  1086  
  1087  		nod2.type = typ(TIND, t);
  1088  
  1089  		nod1 = nod2;
  1090  		nod1.op = OIND;
  1091  		nod1.left = &nod2;
  1092  		nod1.right = Z;
  1093  		nod1.complex = 1;
  1094  		nod1.type = t;
  1095  
  1096  		sugen(n, &nod1, w);
  1097  		return;
  1098  	}
  1099  
  1100  	w /= SZ_LONG;
  1101  	if(w <= 2) {
  1102  		if(n->complex > nn->complex) {
  1103  			reglpcgen(&nod1, n, 1);
  1104  			reglpcgen(&nod2, nn, 1);
  1105  		} else {
  1106  			reglpcgen(&nod2, nn, 1);
  1107  			reglpcgen(&nod1, n, 1);
  1108  		}
  1109  		regalloc(&nod3, &regnode, Z);
  1110  		regalloc(&nod4, &regnode, Z);
  1111  		nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
  1112  		if(w == 2 && nod1.xoffset == 0)
  1113  			gmovm(&nod1, &nod0, 0);
  1114  		else {
  1115  			gmove(&nod1, &nod3);
  1116  			if(w == 2) {
  1117  				nod1.xoffset += SZ_LONG;
  1118  				gmove(&nod1, &nod4);
  1119  			}
  1120  		}
  1121  		if(w == 2 && nod2.xoffset == 0)
  1122  			gmovm(&nod0, &nod2, 0);
  1123  		else {
  1124  			gmove(&nod3, &nod2);
  1125  			if(w == 2) {
  1126  				nod2.xoffset += SZ_LONG;
  1127  				gmove(&nod4, &nod2);
  1128  			}
  1129  		}
  1130  		regfree(&nod1);
  1131  		regfree(&nod2);
  1132  		regfree(&nod3);
  1133  		regfree(&nod4);
  1134  		return;
  1135  	}
  1136  
  1137  	if(n->complex > nn->complex) {
  1138  		reglpcgen(&nod1, n, 0);
  1139  		reglpcgen(&nod2, nn, 0);
  1140  	} else {
  1141  		reglpcgen(&nod2, nn, 0);
  1142  		reglpcgen(&nod1, n, 0);
  1143  	}
  1144  
  1145  	m = 0;
  1146  	for(c = 0; c < w && c < 4; c++) {
  1147  		i = tmpreg();
  1148  		if (i == 0)
  1149  			break;
  1150  		reg[i]++;
  1151  		m |= 1<<i;
  1152  	}
  1153  	nod4 = *(nodconst(m));
  1154  	if(w < 3*c) {
  1155  		for (; w>c; w-=c) {
  1156  			gmovm(&nod1, &nod4, 1);
  1157  			gmovm(&nod4, &nod2, 1);
  1158  		}
  1159  		goto out;
  1160  	}
  1161  
  1162  	regalloc(&nod3, &regnode, Z);
  1163  	gopcode(OAS, nodconst(w/c), Z, &nod3);
  1164  	w %= c;
  1165  
  1166  	pc1 = pc;
  1167  	gmovm(&nod1, &nod4, 1);
  1168  	gmovm(&nod4, &nod2, 1);
  1169  
  1170  	gopcode(OSUB, nodconst(1), Z, &nod3);
  1171  	gopcode(OEQ, nodconst(0), &nod3, Z);
  1172  	p->as = ABGT;
  1173  	patch(p, pc1);
  1174  	regfree(&nod3);
  1175  
  1176  out:
  1177  	if (w) {
  1178  		i = 0;
  1179  		while (c>w) {
  1180  			while ((m&(1<<i)) == 0)
  1181  				i++;
  1182  			m &= ~(1<<i);
  1183  			reg[i] = 0;
  1184  			c--;
  1185  			i++;
  1186  		}
  1187  		nod4.vconst = m;
  1188  		gmovm(&nod1, &nod4, 0);
  1189  		gmovm(&nod4, &nod2, 0);
  1190  	}
  1191  	i = 0;
  1192  	do {
  1193  		while ((m&(1<<i)) == 0)
  1194  			i++;
  1195  		reg[i] = 0;
  1196  		c--;
  1197  		i++;
  1198  	} while (c>0);
  1199  	regfree(&nod1);
  1200  	regfree(&nod2);
  1201  }