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

     1  // Inferno utils/8c/sgen.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8c/sgen.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  
    33  Prog*
    34  gtext(Sym *s, int32 stkoff)
    35  {
    36  	int32 a;
    37  	
    38  	a = 0;
    39  	if(!(textflag & NOSPLIT))
    40  		a = argsize();
    41  	else if(stkoff >= 128)
    42  		yyerror("stack frame too large for NOSPLIT function");
    43  
    44  	gpseudo(ATEXT, s, nodconst(stkoff));
    45  	p->to.type = D_CONST2;
    46  	p->to.offset2 = a;
    47  	return p;
    48  }
    49  
    50  void
    51  noretval(int n)
    52  {
    53  
    54  	if(n & 1) {
    55  		gins(ANOP, Z, Z);
    56  		p->to.type = REGRET;
    57  	}
    58  	if(n & 2) {
    59  		gins(ANOP, Z, Z);
    60  		p->to.type = FREGRET;
    61  	}
    62  }
    63  
    64  /* welcome to commute */
    65  static void
    66  commute(Node *n)
    67  {
    68  	Node *l, *r;
    69  
    70  	l = n->left;
    71  	r = n->right;
    72  	if(r->complex > l->complex) {
    73  		n->left = r;
    74  		n->right = l;
    75  	}
    76  }
    77  
    78  void
    79  indexshift(Node *n)
    80  {
    81  	int g;
    82  
    83  	if(!typechlp[n->type->etype])
    84  		return;
    85  	simplifyshift(n);
    86  	if(n->op == OASHL && n->right->op == OCONST){
    87  		g = vconst(n->right);
    88  		if(g >= 0 && g < 4)
    89  			n->addable = 7;
    90  	}
    91  }
    92  
    93  /*
    94   *	calculate addressability as follows
    95   *		NAME ==> 10/11		name+value(SB/SP)
    96   *		REGISTER ==> 12		register
    97   *		CONST ==> 20		$value
    98   *		*(20) ==> 21		value
    99   *		&(10) ==> 13		$name+value(SB)
   100   *		&(11) ==> 1		$name+value(SP)
   101   *		(13) + (20) ==> 13	fold constants
   102   *		(1) + (20) ==> 1	fold constants
   103   *		*(13) ==> 10		back to name
   104   *		*(1) ==> 11		back to name
   105   *
   106   *		(20) * (X) ==> 7	multiplier in indexing
   107   *		(X,7) + (13,1) ==> 8	adder in indexing (addresses)
   108   *		(8) ==> &9(OINDEX)	index, almost addressable
   109   *		100					extern register
   110   *
   111   *	calculate complexity (number of registers)
   112   */
   113  void
   114  xcom(Node *n)
   115  {
   116  	Node *l, *r;
   117  	int g;
   118  
   119  	if(n == Z)
   120  		return;
   121  	l = n->left;
   122  	r = n->right;
   123  	n->complex = 0;
   124  	n->addable = 0;
   125  	switch(n->op) {
   126  	case OCONST:
   127  		n->addable = 20;
   128  		break;
   129  
   130  	case ONAME:
   131  		n->addable = 10;
   132  		if(n->class == CPARAM || n->class == CAUTO)
   133  			n->addable = 11;
   134  		break;
   135  
   136  	case OEXREG:
   137  		n->addable = 0;
   138  		break;
   139  
   140  	case OREGISTER:
   141  		n->addable = 12;
   142  		break;
   143  
   144  	case OINDREG:
   145  		n->addable = 12;
   146  		break;
   147  
   148  	case OADDR:
   149  		xcom(l);
   150  		if(l->addable == 10)
   151  			n->addable = 13;
   152  		else
   153  		if(l->addable == 11)
   154  			n->addable = 1;
   155  		break;
   156  
   157  	case OADD:
   158  		xcom(l);
   159  		xcom(r);
   160  		if(n->type->etype != TIND)
   161  			break;
   162  
   163  		switch(r->addable) {
   164  		case 20:
   165  			switch(l->addable) {
   166  			case 1:
   167  			case 13:
   168  			commadd:
   169  				l->type = n->type;
   170  				*n = *l;
   171  				l = new(0, Z, Z);
   172  				*l = *(n->left);
   173  				l->xoffset += r->vconst;
   174  				n->left = l;
   175  				r = n->right;
   176  				goto brk;
   177  			}
   178  			break;
   179  
   180  		case 1:
   181  		case 13:
   182  		case 10:
   183  		case 11:
   184  			/* l is the base, r is the index */
   185  			if(l->addable != 20)
   186  				n->addable = 8;
   187  			break;
   188  		}
   189  		switch(l->addable) {
   190  		case 20:
   191  			switch(r->addable) {
   192  			case 13:
   193  			case 1:
   194  				r = n->left;
   195  				l = n->right;
   196  				n->left = l;
   197  				n->right = r;
   198  				goto commadd;
   199  			}
   200  			break;
   201  
   202  		case 13:
   203  		case 1:
   204  		case 10:
   205  		case 11:
   206  			/* r is the base, l is the index */
   207  			if(r->addable != 20)
   208  				n->addable = 8;
   209  			break;
   210  		}
   211  		if(n->addable == 8 && !side(n)) {
   212  			indx(n);
   213  			l = new1(OINDEX, idx.basetree, idx.regtree);
   214  			l->scale = idx.scale;
   215  			l->addable = 9;
   216  			l->complex = l->right->complex;
   217  			l->type = l->left->type;
   218  			n->op = OADDR;
   219  			n->left = l;
   220  			n->right = Z;
   221  			n->addable = 8;
   222  			break;
   223  		}
   224  		break;
   225  
   226  	case OINDEX:
   227  		xcom(l);
   228  		xcom(r);
   229  		n->addable = 9;
   230  		break;
   231  
   232  	case OIND:
   233  		xcom(l);
   234  		if(l->op == OADDR) {
   235  			l = l->left;
   236  			l->type = n->type;
   237  			*n = *l;
   238  			return;
   239  		}
   240  		switch(l->addable) {
   241  		case 20:
   242  			n->addable = 21;
   243  			break;
   244  		case 1:
   245  			n->addable = 11;
   246  			break;
   247  		case 13:
   248  			n->addable = 10;
   249  			break;
   250  		}
   251  		break;
   252  
   253  	case OASHL:
   254  		xcom(l);
   255  		xcom(r);
   256  		indexshift(n);
   257  		break;
   258  
   259  	case OMUL:
   260  	case OLMUL:
   261  		xcom(l);
   262  		xcom(r);
   263  		g = vlog(l);
   264  		if(g >= 0) {
   265  			n->left = r;
   266  			n->right = l;
   267  			l = r;
   268  			r = n->right;
   269  		}
   270  		g = vlog(r);
   271  		if(g >= 0) {
   272  			n->op = OASHL;
   273  			r->vconst = g;
   274  			r->type = types[TINT];
   275  			indexshift(n);
   276  			break;
   277  		}
   278  commute(n);
   279  		break;
   280  
   281  	case OASLDIV:
   282  		xcom(l);
   283  		xcom(r);
   284  		g = vlog(r);
   285  		if(g >= 0) {
   286  			n->op = OASLSHR;
   287  			r->vconst = g;
   288  			r->type = types[TINT];
   289  		}
   290  		break;
   291  
   292  	case OLDIV:
   293  		xcom(l);
   294  		xcom(r);
   295  		g = vlog(r);
   296  		if(g >= 0) {
   297  			n->op = OLSHR;
   298  			r->vconst = g;
   299  			r->type = types[TINT];
   300  			indexshift(n);
   301  			break;
   302  		}
   303  		break;
   304  
   305  	case OASLMOD:
   306  		xcom(l);
   307  		xcom(r);
   308  		g = vlog(r);
   309  		if(g >= 0) {
   310  			n->op = OASAND;
   311  			r->vconst--;
   312  		}
   313  		break;
   314  
   315  	case OLMOD:
   316  		xcom(l);
   317  		xcom(r);
   318  		g = vlog(r);
   319  		if(g >= 0) {
   320  			n->op = OAND;
   321  			r->vconst--;
   322  		}
   323  		break;
   324  
   325  	case OASMUL:
   326  	case OASLMUL:
   327  		xcom(l);
   328  		xcom(r);
   329  		g = vlog(r);
   330  		if(g >= 0) {
   331  			n->op = OASASHL;
   332  			r->vconst = g;
   333  		}
   334  		break;
   335  
   336  	case OLSHR:
   337  	case OASHR:
   338  		xcom(l);
   339  		xcom(r);
   340  		indexshift(n);
   341  		break;
   342  
   343  	default:
   344  		if(l != Z)
   345  			xcom(l);
   346  		if(r != Z)
   347  			xcom(r);
   348  		break;
   349  	}
   350  brk:
   351  	if(n->addable >= 10)
   352  		return;
   353  	if(l != Z)
   354  		n->complex = l->complex;
   355  	if(r != Z) {
   356  		if(r->complex == n->complex)
   357  			n->complex = r->complex+1;
   358  		else
   359  		if(r->complex > n->complex)
   360  			n->complex = r->complex;
   361  	}
   362  	if(n->complex == 0)
   363  		n->complex++;
   364  
   365  	if(com64(n))
   366  		return;
   367  
   368  	switch(n->op) {
   369  
   370  	case OFUNC:
   371  		n->complex = FNX;
   372  		break;
   373  
   374  	case OLMOD:
   375  	case OMOD:
   376  	case OLMUL:
   377  	case OLDIV:
   378  	case OMUL:
   379  	case ODIV:
   380  	case OASLMUL:
   381  	case OASLDIV:
   382  	case OASLMOD:
   383  	case OASMUL:
   384  	case OASDIV:
   385  	case OASMOD:
   386  		if(r->complex >= l->complex) {
   387  			n->complex = l->complex + 3;
   388  			if(r->complex > n->complex)
   389  				n->complex = r->complex;
   390  		} else {
   391  			n->complex = r->complex + 3;
   392  			if(l->complex > n->complex)
   393  				n->complex = l->complex;
   394  		}
   395  		break;
   396  
   397  	case OLSHR:
   398  	case OASHL:
   399  	case OASHR:
   400  	case OASLSHR:
   401  	case OASASHL:
   402  	case OASASHR:
   403  		if(r->complex >= l->complex) {
   404  			n->complex = l->complex + 2;
   405  			if(r->complex > n->complex)
   406  				n->complex = r->complex;
   407  		} else {
   408  			n->complex = r->complex + 2;
   409  			if(l->complex > n->complex)
   410  				n->complex = l->complex;
   411  		}
   412  		break;
   413  
   414  	case OADD:
   415  	case OXOR:
   416  	case OAND:
   417  	case OOR:
   418  		/*
   419  		 * immediate operators, make const on right
   420  		 */
   421  		if(l->op == OCONST) {
   422  			n->left = r;
   423  			n->right = l;
   424  		}
   425  		break;
   426  
   427  	case OEQ:
   428  	case ONE:
   429  	case OLE:
   430  	case OLT:
   431  	case OGE:
   432  	case OGT:
   433  	case OHI:
   434  	case OHS:
   435  	case OLO:
   436  	case OLS:
   437  		/*
   438  		 * compare operators, make const on left
   439  		 */
   440  		if(r->op == OCONST) {
   441  			n->left = r;
   442  			n->right = l;
   443  			n->op = invrel[relindex(n->op)];
   444  		}
   445  		break;
   446  	}
   447  }
   448  
   449  void
   450  indx(Node *n)
   451  {
   452  	Node *l, *r;
   453  
   454  	if(debug['x'])
   455  		prtree(n, "indx");
   456  
   457  	l = n->left;
   458  	r = n->right;
   459  	if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
   460  		n->right = l;
   461  		n->left = r;
   462  		l = r;
   463  		r = n->right;
   464  	}
   465  	if(l->addable != 7) {
   466  		idx.regtree = l;
   467  		idx.scale = 1;
   468  	} else
   469  	if(l->right->addable == 20) {
   470  		idx.regtree = l->left;
   471  		idx.scale = 1 << l->right->vconst;
   472  	} else
   473  	if(l->left->addable == 20) {
   474  		idx.regtree = l->right;
   475  		idx.scale = 1 << l->left->vconst;
   476  	} else
   477  		diag(n, "bad index");
   478  
   479  	idx.basetree = r;
   480  	if(debug['x']) {
   481  		print("scale = %d\n", idx.scale);
   482  		prtree(idx.regtree, "index");
   483  		prtree(idx.basetree, "base");
   484  	}
   485  }