github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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 = argsize(1);
    39  	if((textflag & NOSPLIT) != 0 && stkoff >= 128)
    40  		yyerror("stack frame too large for NOSPLIT function");
    41  
    42  	gpseudo(ATEXT, s, nodconst(stkoff));
    43  	p->to.type = D_CONST2;
    44  	p->to.offset2 = a;
    45  	return p;
    46  }
    47  
    48  void
    49  noretval(int n)
    50  {
    51  
    52  	if(n & 1) {
    53  		gins(ANOP, Z, Z);
    54  		p->to.type = REGRET;
    55  	}
    56  	if(n & 2) {
    57  		gins(ANOP, Z, Z);
    58  		p->to.type = FREGRET;
    59  	}
    60  }
    61  
    62  /* welcome to commute */
    63  static void
    64  commute(Node *n)
    65  {
    66  	Node *l, *r;
    67  
    68  	l = n->left;
    69  	r = n->right;
    70  	if(r->complex > l->complex) {
    71  		n->left = r;
    72  		n->right = l;
    73  	}
    74  }
    75  
    76  void
    77  indexshift(Node *n)
    78  {
    79  	int g;
    80  
    81  	if(!typechlp[n->type->etype])
    82  		return;
    83  	simplifyshift(n);
    84  	if(n->op == OASHL && n->right->op == OCONST){
    85  		g = vconst(n->right);
    86  		if(g >= 0 && g < 4)
    87  			n->addable = 7;
    88  	}
    89  }
    90  
    91  /*
    92   *	calculate addressability as follows
    93   *		NAME ==> 10/11		name+value(SB/SP)
    94   *		REGISTER ==> 12		register
    95   *		CONST ==> 20		$value
    96   *		*(20) ==> 21		value
    97   *		&(10) ==> 13		$name+value(SB)
    98   *		&(11) ==> 1		$name+value(SP)
    99   *		(13) + (20) ==> 13	fold constants
   100   *		(1) + (20) ==> 1	fold constants
   101   *		*(13) ==> 10		back to name
   102   *		*(1) ==> 11		back to name
   103   *
   104   *		(20) * (X) ==> 7	multiplier in indexing
   105   *		(X,7) + (13,1) ==> 8	adder in indexing (addresses)
   106   *		(8) ==> &9(OINDEX)	index, almost addressable
   107   *		100					extern register
   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  		n->addable = 10;
   130  		if(n->class == CPARAM || n->class == CAUTO)
   131  			n->addable = 11;
   132  		break;
   133  
   134  	case OEXREG:
   135  		n->addable = 0;
   136  		break;
   137  
   138  	case OREGISTER:
   139  		n->addable = 12;
   140  		break;
   141  
   142  	case OINDREG:
   143  		n->addable = 12;
   144  		break;
   145  
   146  	case OADDR:
   147  		xcom(l);
   148  		if(l->addable == 10)
   149  			n->addable = 13;
   150  		else
   151  		if(l->addable == 11)
   152  			n->addable = 1;
   153  		break;
   154  
   155  	case OADD:
   156  		xcom(l);
   157  		xcom(r);
   158  		if(n->type->etype != TIND)
   159  			break;
   160  
   161  		switch(r->addable) {
   162  		case 20:
   163  			switch(l->addable) {
   164  			case 1:
   165  			case 13:
   166  			commadd:
   167  				l->type = n->type;
   168  				*n = *l;
   169  				l = new(0, Z, Z);
   170  				*l = *(n->left);
   171  				l->xoffset += r->vconst;
   172  				n->left = l;
   173  				r = n->right;
   174  				goto brk;
   175  			}
   176  			break;
   177  
   178  		case 1:
   179  		case 13:
   180  		case 10:
   181  		case 11:
   182  			/* l is the base, r is the index */
   183  			if(l->addable != 20)
   184  				n->addable = 8;
   185  			break;
   186  		}
   187  		switch(l->addable) {
   188  		case 20:
   189  			switch(r->addable) {
   190  			case 13:
   191  			case 1:
   192  				r = n->left;
   193  				l = n->right;
   194  				n->left = l;
   195  				n->right = r;
   196  				goto commadd;
   197  			}
   198  			break;
   199  
   200  		case 13:
   201  		case 1:
   202  		case 10:
   203  		case 11:
   204  			/* r is the base, l is the index */
   205  			if(r->addable != 20)
   206  				n->addable = 8;
   207  			break;
   208  		}
   209  		if(n->addable == 8 && !side(n)) {
   210  			indx(n);
   211  			l = new1(OINDEX, idx.basetree, idx.regtree);
   212  			l->scale = idx.scale;
   213  			l->addable = 9;
   214  			l->complex = l->right->complex;
   215  			l->type = l->left->type;
   216  			n->op = OADDR;
   217  			n->left = l;
   218  			n->right = Z;
   219  			n->addable = 8;
   220  			break;
   221  		}
   222  		break;
   223  
   224  	case OINDEX:
   225  		xcom(l);
   226  		xcom(r);
   227  		n->addable = 9;
   228  		break;
   229  
   230  	case OIND:
   231  		xcom(l);
   232  		if(l->op == OADDR) {
   233  			l = l->left;
   234  			l->type = n->type;
   235  			*n = *l;
   236  			return;
   237  		}
   238  		switch(l->addable) {
   239  		case 20:
   240  			n->addable = 21;
   241  			break;
   242  		case 1:
   243  			n->addable = 11;
   244  			break;
   245  		case 13:
   246  			n->addable = 10;
   247  			break;
   248  		}
   249  		break;
   250  
   251  	case OASHL:
   252  		xcom(l);
   253  		xcom(r);
   254  		indexshift(n);
   255  		break;
   256  
   257  	case OMUL:
   258  	case OLMUL:
   259  		xcom(l);
   260  		xcom(r);
   261  		g = vlog(l);
   262  		if(g >= 0) {
   263  			n->left = r;
   264  			n->right = l;
   265  			l = r;
   266  			r = n->right;
   267  		}
   268  		g = vlog(r);
   269  		if(g >= 0) {
   270  			n->op = OASHL;
   271  			r->vconst = g;
   272  			r->type = types[TINT];
   273  			indexshift(n);
   274  			break;
   275  		}
   276  commute(n);
   277  		break;
   278  
   279  	case OASLDIV:
   280  		xcom(l);
   281  		xcom(r);
   282  		g = vlog(r);
   283  		if(g >= 0) {
   284  			n->op = OASLSHR;
   285  			r->vconst = g;
   286  			r->type = types[TINT];
   287  		}
   288  		break;
   289  
   290  	case OLDIV:
   291  		xcom(l);
   292  		xcom(r);
   293  		g = vlog(r);
   294  		if(g >= 0) {
   295  			n->op = OLSHR;
   296  			r->vconst = g;
   297  			r->type = types[TINT];
   298  			indexshift(n);
   299  			break;
   300  		}
   301  		break;
   302  
   303  	case OASLMOD:
   304  		xcom(l);
   305  		xcom(r);
   306  		g = vlog(r);
   307  		if(g >= 0) {
   308  			n->op = OASAND;
   309  			r->vconst--;
   310  		}
   311  		break;
   312  
   313  	case OLMOD:
   314  		xcom(l);
   315  		xcom(r);
   316  		g = vlog(r);
   317  		if(g >= 0) {
   318  			n->op = OAND;
   319  			r->vconst--;
   320  		}
   321  		break;
   322  
   323  	case OASMUL:
   324  	case OASLMUL:
   325  		xcom(l);
   326  		xcom(r);
   327  		g = vlog(r);
   328  		if(g >= 0) {
   329  			n->op = OASASHL;
   330  			r->vconst = g;
   331  		}
   332  		break;
   333  
   334  	case OLSHR:
   335  	case OASHR:
   336  		xcom(l);
   337  		xcom(r);
   338  		indexshift(n);
   339  		break;
   340  
   341  	default:
   342  		if(l != Z)
   343  			xcom(l);
   344  		if(r != Z)
   345  			xcom(r);
   346  		break;
   347  	}
   348  brk:
   349  	if(n->addable >= 10)
   350  		return;
   351  	if(l != Z)
   352  		n->complex = l->complex;
   353  	if(r != Z) {
   354  		if(r->complex == n->complex)
   355  			n->complex = r->complex+1;
   356  		else
   357  		if(r->complex > n->complex)
   358  			n->complex = r->complex;
   359  	}
   360  	if(n->complex == 0)
   361  		n->complex++;
   362  
   363  	if(com64(n))
   364  		return;
   365  
   366  	switch(n->op) {
   367  
   368  	case OFUNC:
   369  		n->complex = FNX;
   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  }