github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/cc/scon.c (about)

     1  // Inferno utils/cc/scon.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.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 <u.h>
    32  #include "cc.h"
    33  
    34  static Node*
    35  acast(Type *t, Node *n)
    36  {
    37  	if(n->type->etype != t->etype || n->op == OBIT) {
    38  		n = new1(OCAST, n, Z);
    39  		if(nocast(n->left->type, t))
    40  			*n = *n->left;
    41  		n->type = t;
    42  	}
    43  	return n;
    44  }
    45  
    46  
    47  void
    48  evconst(Node *n)
    49  {
    50  	Node *l, *r;
    51  	int et, isf;
    52  	vlong v;
    53  	double d;
    54  
    55  	if(n == Z || n->type == T)
    56  		return;
    57  
    58  	et = n->type->etype;
    59  	isf = typefd[et];
    60  
    61  	l = n->left;
    62  	r = n->right;
    63  
    64  	d = 0;
    65  	v = 0;
    66  
    67  	switch(n->op) {
    68  	default:
    69  		return;
    70  
    71  	case ONEG:
    72  		if(isf)
    73  			d = -l->fconst;
    74  		else
    75  			v = -l->vconst;
    76  		break;
    77  
    78  	case OCOM:
    79  		v = ~l->vconst;
    80  		break;
    81  
    82  	case OCAST:
    83  		if(et == TVOID)
    84  			return;
    85  		et = l->type->etype;
    86  		if(isf) {
    87  			if(typefd[et])
    88  				d = l->fconst;
    89  			else
    90  				d = l->vconst;
    91  		} else {
    92  			if(typefd[et])
    93  				v = l->fconst;
    94  			else
    95  				v = convvtox(l->vconst, n->type->etype);
    96  		}
    97  		break;
    98  
    99  	case OCONST:
   100  		break;
   101  
   102  	case OADD:
   103  		if(isf)
   104  			d = l->fconst + r->fconst;
   105  		else {
   106  			v = l->vconst + r->vconst;
   107  		}
   108  		break;
   109  
   110  	case OSUB:
   111  		if(isf)
   112  			d = l->fconst - r->fconst;
   113  		else
   114  			v = l->vconst - r->vconst;
   115  		break;
   116  
   117  	case OMUL:
   118  		if(isf)
   119  			d = l->fconst * r->fconst;
   120  		else {
   121  			v = l->vconst * r->vconst;
   122  		}
   123  		break;
   124  
   125  	case OLMUL:
   126  		v = (uvlong)l->vconst * (uvlong)r->vconst;
   127  		break;
   128  
   129  
   130  	case ODIV:
   131  		if(vconst(r) == 0) {
   132  			warn(n, "divide by zero");
   133  			return;
   134  		}
   135  		if(isf)
   136  			d = l->fconst / r->fconst;
   137  		else
   138  			v = l->vconst / r->vconst;
   139  		break;
   140  
   141  	case OLDIV:
   142  		if(vconst(r) == 0) {
   143  			warn(n, "divide by zero");
   144  			return;
   145  		}
   146  		v = (uvlong)l->vconst / (uvlong)r->vconst;
   147  		break;
   148  
   149  	case OMOD:
   150  		if(vconst(r) == 0) {
   151  			warn(n, "modulo by zero");
   152  			return;
   153  		}
   154  		v = l->vconst % r->vconst;
   155  		break;
   156  
   157  	case OLMOD:
   158  		if(vconst(r) == 0) {
   159  			warn(n, "modulo by zero");
   160  			return;
   161  		}
   162  		v = (uvlong)l->vconst % (uvlong)r->vconst;
   163  		break;
   164  
   165  	case OAND:
   166  		v = l->vconst & r->vconst;
   167  		break;
   168  
   169  	case OOR:
   170  		v = l->vconst | r->vconst;
   171  		break;
   172  
   173  	case OXOR:
   174  		v = l->vconst ^ r->vconst;
   175  		break;
   176  
   177  	case OLSHR:
   178  		if(l->type->width != sizeof(uvlong))
   179  			v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst;
   180  		else
   181  			v = (uvlong)l->vconst >> r->vconst;
   182  		break;
   183  
   184  	case OASHR:
   185  		v = l->vconst >> r->vconst;
   186  		break;
   187  
   188  	case OASHL:
   189  		v = l->vconst << r->vconst;
   190  		break;
   191  
   192  	case OLO:
   193  		v = (uvlong)l->vconst < (uvlong)r->vconst;
   194  		break;
   195  
   196  	case OLT:
   197  		if(typefd[l->type->etype])
   198  			v = l->fconst < r->fconst;
   199  		else
   200  			v = l->vconst < r->vconst;
   201  		break;
   202  
   203  	case OHI:
   204  		v = (uvlong)l->vconst > (uvlong)r->vconst;
   205  		break;
   206  
   207  	case OGT:
   208  		if(typefd[l->type->etype])
   209  			v = l->fconst > r->fconst;
   210  		else
   211  			v = l->vconst > r->vconst;
   212  		break;
   213  
   214  	case OLS:
   215  		v = (uvlong)l->vconst <= (uvlong)r->vconst;
   216  		break;
   217  
   218  	case OLE:
   219  		if(typefd[l->type->etype])
   220  			v = l->fconst <= r->fconst;
   221  		else
   222  			v = l->vconst <= r->vconst;
   223  		break;
   224  
   225  	case OHS:
   226  		v = (uvlong)l->vconst >= (uvlong)r->vconst;
   227  		break;
   228  
   229  	case OGE:
   230  		if(typefd[l->type->etype])
   231  			v = l->fconst >= r->fconst;
   232  		else
   233  			v = l->vconst >= r->vconst;
   234  		break;
   235  
   236  	case OEQ:
   237  		if(typefd[l->type->etype])
   238  			v = l->fconst == r->fconst;
   239  		else
   240  			v = l->vconst == r->vconst;
   241  		break;
   242  
   243  	case ONE:
   244  		if(typefd[l->type->etype])
   245  			v = l->fconst != r->fconst;
   246  		else
   247  			v = l->vconst != r->vconst;
   248  		break;
   249  
   250  	case ONOT:
   251  		if(typefd[l->type->etype])
   252  			v = !l->fconst;
   253  		else
   254  			v = !l->vconst;
   255  		break;
   256  
   257  	case OANDAND:
   258  		if(typefd[l->type->etype])
   259  			v = l->fconst && r->fconst;
   260  		else
   261  			v = l->vconst && r->vconst;
   262  		break;
   263  
   264  	case OOROR:
   265  		if(typefd[l->type->etype])
   266  			v = l->fconst || r->fconst;
   267  		else
   268  			v = l->vconst || r->vconst;
   269  		break;
   270  	}
   271  	if(isf) {
   272  		n->fconst = d;
   273  	} else {
   274  		n->vconst = convvtox(v, n->type->etype);
   275  	}
   276  	n->oldop = n->op;
   277  	n->op = OCONST;
   278  }
   279  
   280  void
   281  acom(Node *n)
   282  {
   283  	Type *t;
   284  	Node *l, *r;
   285  	int i;
   286  
   287  	switch(n->op)
   288  	{
   289  
   290  	case ONAME:
   291  	case OCONST:
   292  	case OSTRING:
   293  	case OINDREG:
   294  	case OREGISTER:
   295  		return;
   296  
   297  	case ONEG:
   298  		l = n->left;
   299  		if(addo(n) && addo(l))
   300  			break;
   301  		acom(l);
   302  		return;
   303  
   304  	case OADD:
   305  	case OSUB:
   306  	case OMUL:
   307  		l = n->left;
   308  		r = n->right;
   309  		if(addo(n)) {
   310  			if(addo(r))
   311  				break;
   312  			if(addo(l))
   313  				break;
   314  		}
   315  		acom(l);
   316  		acom(r);
   317  		return;
   318  
   319  	default:
   320  		l = n->left;
   321  		r = n->right;
   322  		if(l != Z)
   323  			acom(l);
   324  		if(r != Z)
   325  			acom(r);
   326  		return;
   327  	}
   328  
   329  	/* bust terms out */
   330  	t = n->type;
   331  	term[0].mult = 0;
   332  	term[0].node = Z;
   333  	nterm = 1;
   334  	acom1(1, n);
   335  	if(debug['m'])
   336  	for(i=0; i<nterm; i++) {
   337  		print("%d %3lld ", i, term[i].mult);
   338  		prtree1(term[i].node, 1, 0);
   339  	}
   340  	if(nterm < NTERM)
   341  		acom2(n, t);
   342  	n->type = t;
   343  }
   344  
   345  int
   346  acomcmp1(const void *a1, const void *a2)
   347  {
   348  	vlong c1, c2;
   349  	Term *t1, *t2;
   350  
   351  	t1 = (Term*)a1;
   352  	t2 = (Term*)a2;
   353  	c1 = t1->mult;
   354  	if(c1 < 0)
   355  		c1 = -c1;
   356  	c2 = t2->mult;
   357  	if(c2 < 0)
   358  		c2 = -c2;
   359  	if(c1 > c2)
   360  		return 1;
   361  	if(c1 < c2)
   362  		return -1;
   363  	c1 = 1;
   364  	if(t1->mult < 0)
   365  		c1 = 0;
   366  	c2 = 1;
   367  	if(t2->mult < 0)
   368  		c2 = 0;
   369  	if(c2 -= c1)
   370  		return c2;
   371  	if(t2 > t1)
   372  		return 1;
   373  	return -1;
   374  }
   375  
   376  int
   377  acomcmp2(const void *a1, const void *a2)
   378  {
   379  	vlong c1, c2;
   380  	Term *t1, *t2;
   381  
   382  	t1 = (Term*)a1;
   383  	t2 = (Term*)a2;
   384  	c1 = t1->mult;
   385  	c2 = t2->mult;
   386  	if(c1 > c2)
   387  		return 1;
   388  	if(c1 < c2)
   389  		return -1;
   390  	if(t2 > t1)
   391  		return 1;
   392  	return -1;
   393  }
   394  
   395  void
   396  acom2(Node *n, Type *t)
   397  {
   398  	Node *l, *r;
   399  	Term trm[NTERM];
   400  	int et, nt, i, j;
   401  	vlong c1, c2;
   402  
   403  	/*
   404  	 * copy into automatic
   405  	 */
   406  	c2 = 0;
   407  	nt = nterm;
   408  	for(i=0; i<nt; i++)
   409  		trm[i] = term[i];
   410  	/*
   411  	 * recur on subtrees
   412  	 */
   413  	j = 0;
   414  	for(i=1; i<nt; i++) {
   415  		c1 = trm[i].mult;
   416  		if(c1 == 0)
   417  			continue;
   418  		l = trm[i].node;
   419  		if(l != Z) {
   420  			j = 1;
   421  			acom(l);
   422  		}
   423  	}
   424  	c1 = trm[0].mult;
   425  	if(j == 0) {
   426  		n->oldop = n->op;
   427  		n->op = OCONST;
   428  		n->vconst = c1;
   429  		return;
   430  	}
   431  	et = t->etype;
   432  
   433  	/*
   434  	 * prepare constant term,
   435  	 * combine it with an addressing term
   436  	 */
   437  	if(c1 != 0) {
   438  		l = new1(OCONST, Z, Z);
   439  		l->type = t;
   440  		l->vconst = c1;
   441  		trm[0].mult = 1;
   442  		for(i=1; i<nt; i++) {
   443  			if(trm[i].mult != 1)
   444  				continue;
   445  			r = trm[i].node;
   446  			if(r->op != OADDR)
   447  				continue;
   448  			r->type = t;
   449  			l = new1(OADD, r, l);
   450  			l->type = t;
   451  			trm[i].mult = 0;
   452  			break;
   453  		}
   454  		trm[0].node = l;
   455  	}
   456  	/*
   457  	 * look for factorable terms
   458  	 * c1*i + c1*c2*j -> c1*(i + c2*j)
   459  	 */
   460  	qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
   461  	for(i=nt-1; i>=0; i--) {
   462  		c1 = trm[i].mult;
   463  		if(c1 < 0)
   464  			c1 = -c1;
   465  		if(c1 <= 1)
   466  			continue;
   467  		for(j=i+1; j<nt; j++) {
   468  			c2 = trm[j].mult;
   469  			if(c2 < 0)
   470  				c2 = -c2;
   471  			if(c2 <= 1)
   472  				continue;
   473  			if(c2 % c1)
   474  				continue;
   475  			r = trm[j].node;
   476  			if(r->type->etype != et)
   477  				r = acast(t, r);
   478  			c2 = trm[j].mult/trm[i].mult;
   479  			if(c2 != 1 && c2 != -1) {
   480  				r = new1(OMUL, r, new(OCONST, Z, Z));
   481  				r->type = t;
   482  				r->right->type = t;
   483  				r->right->vconst = c2;
   484  			}
   485  			l = trm[i].node;
   486  			if(l->type->etype != et)
   487  				l = acast(t, l);
   488  			r = new1(OADD, l, r);
   489  			r->type = t;
   490  			if(c2 == -1)
   491  				r->op = OSUB;
   492  			trm[i].node = r;
   493  			trm[j].mult = 0;
   494  		}
   495  	}
   496  	if(debug['m']) {
   497  		print("\n");
   498  		for(i=0; i<nt; i++) {
   499  			print("%d %3lld ", i, trm[i].mult);
   500  			prtree1(trm[i].node, 1, 0);
   501  		}
   502  	}
   503  
   504  	/*
   505  	 * put it all back together
   506  	 */
   507  	qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
   508  	l = Z;
   509  	for(i=nt-1; i>=0; i--) {
   510  		c1 = trm[i].mult;
   511  		if(c1 == 0)
   512  			continue;
   513  		r = trm[i].node;
   514  		if(r->type->etype != et || r->op == OBIT)
   515  			r = acast(t, r);
   516  		if(c1 != 1 && c1 != -1) {
   517  			r = new1(OMUL, r, new(OCONST, Z, Z));
   518  			r->type = t;
   519  			r->right->type = t;
   520  			if(c1 < 0) {
   521  				r->right->vconst = -c1;
   522  				c1 = -1;
   523  			} else {
   524  				r->right->vconst = c1;
   525  				c1 = 1;
   526  			}
   527  		}
   528  		if(l == Z) {
   529  			l = r;
   530  			c2 = c1;
   531  			continue;
   532  		}
   533  		if(c1 < 0)
   534  			if(c2 < 0)
   535  				l = new1(OADD, l, r);
   536  			else
   537  				l = new1(OSUB, l, r);
   538  		else
   539  			if(c2 < 0) {
   540  				l = new1(OSUB, r, l);
   541  				c2 = 1;
   542  			} else
   543  				l = new1(OADD, l, r);
   544  		l->type = t;
   545  	}
   546  	if(c2 < 0) {
   547  		r = new1(OCONST, 0, 0);
   548  		r->vconst = 0;
   549  		r->type = t;
   550  		l = new1(OSUB, r, l);
   551  		l->type = t;
   552  	}
   553  	*n = *l;
   554  }
   555  
   556  void
   557  acom1(vlong v, Node *n)
   558  {
   559  	Node *l, *r;
   560  
   561  	if(v == 0 || nterm >= NTERM)
   562  		return;
   563  	if(!addo(n)) {
   564  		if(n->op == OCONST)
   565  		if(!typefd[n->type->etype]) {
   566  			term[0].mult += v*n->vconst;
   567  			return;
   568  		}
   569  		term[nterm].mult = v;
   570  		term[nterm].node = n;
   571  		nterm++;
   572  		return;
   573  	}
   574  	switch(n->op) {
   575  
   576  	case OCAST:
   577  		acom1(v, n->left);
   578  		break;
   579  
   580  	case ONEG:
   581  		acom1(-v, n->left);
   582  		break;
   583  
   584  	case OADD:
   585  		acom1(v, n->left);
   586  		acom1(v, n->right);
   587  		break;
   588  
   589  	case OSUB:
   590  		acom1(v, n->left);
   591  		acom1(-v, n->right);
   592  		break;
   593  
   594  	case OMUL:
   595  		l = n->left;
   596  		r = n->right;
   597  		if(l->op == OCONST)
   598  		if(!typefd[n->type->etype]) {
   599  			acom1(v*l->vconst, r);
   600  			break;
   601  		}
   602  		if(r->op == OCONST)
   603  		if(!typefd[n->type->etype]) {
   604  			acom1(v*r->vconst, l);
   605  			break;
   606  		}
   607  		break;
   608  
   609  	default:
   610  		diag(n, "not addo");
   611  	}
   612  }
   613  
   614  int
   615  addo(Node *n)
   616  {
   617  
   618  	if(n != Z)
   619  	if(!typefd[n->type->etype])
   620  	if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
   621  	switch(n->op) {
   622  
   623  	case OCAST:
   624  		if(nilcast(n->left->type, n->type))
   625  			return 1;
   626  		break;
   627  
   628  	case ONEG:
   629  	case OADD:
   630  	case OSUB:
   631  		return 1;
   632  
   633  	case OMUL:
   634  		if(n->left->op == OCONST)
   635  			return 1;
   636  		if(n->right->op == OCONST)
   637  			return 1;
   638  	}
   639  	return 0;
   640  }