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