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

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