1File: CANON.C                                                             Page       1
     1   /*
     2   	Copyright 1982
     3   	Alcyon Corporation
     4   	8716 Production Ave.
     5   	San Diego, Ca.  92121
     6   */
     7    
     8   #include "cgen.h"
     9   #include "cskel.h"
    10    
    11   /*
    12    * canon - expression canonicalization
    13    *		Top level tree canonicalization.  This fixes any bit field
    14    *		accesses, then loops on commute and optim until no more
    15    *		optimizations are done.
    16    */
    17   char *canon(tp)						/* returns pointer to tree*/
    18   struct tnode *tp;					/* pointer to tree to canonicalize*/
    19   {
    20   #ifndef NODEBUG
    21   	if ( oflag )
    22   		putexpr("pre-canon",tp);
    23   #endif
    24   	tp = fixbfield(tp);
    25   	do {
    26   		sucomp(tp,0,1);				/*need Sethy-Ullman's for commute*/
    27   		tp = commute(tp);			/*commute the tree*/
    28   	} while( optim(&tp) );			/*keep trying for optimizations*/
    29   #ifndef	NODEBUG
    30   	if( oflag )
    31   		putexpr("canon",tp);
    32   #endif
    33   	return(tp);
    34   }
    35    
    36   /* fixbfield - fix bit field operators*/
    37   /*		Fixes bit field assignment and normal usage*/
    38   char *fixbfield(tp)						/* returns pointer to fixed tree*/
    39   struct tnode *tp;						/* pointer to tree*/
    40   {
    41   	register struct tnode *btp, *stp;
    42   	register int foff, fmask, op, flen;
    43    
    44   	if( leafop(op=tp->t_op) )
    45   		return(tp);
    46   	if( asgop(op) && tp->t_left->t_op == BFIELD ) {
    47   		tp->t_right = fixbfield(tp->t_right);	/* [vlh] 4.0 */
    48   		btp = tp->t_left;				/*pointer to BFIELD node*/
    49   		stp = btp->t_left;				/*pointer to son of BFIELD node*/
    50   		foff = (btp->t_su>>8) & 0377;
    51   		flen = btp->t_su & 0377;
    52   		fmask = (1<<flen)-1;
    53   		if( tp->t_right->t_op == CINT && (op == ASSIGN || op == EQXOR) ) {
    54   			if( op == EQXOR ) {
    55   				tp->t_left = stp;
    56   				tp->t_right->t_value =<< foff;
    57   				return(tp);
    58   			}
    59   			if( !tp->t_right->t_value ) {
1File: CANON.C                                                             Page       2
    60   				tp->t_op = EQAND;
    61   				tp->t_left = stp;
    62   				tp->t_right->t_value = ~ (fmask << foff);
    63   				return(tp);
    64   			}
    65   			if( (tp->t_right->t_value & fmask) == fmask ) {
    66   				tp->t_op = EQOR;
    67   				tp->t_left = stp;
    68   				tp->t_right->t_value = fmask << foff;
    69   				return(tp);
    70   			}
    71   		}
    72   		if( fmask == -1 )
    73   			tp->t_left = stp;
    74   		else {
    75   			stp = tcopy(stp);
    76   			btp = fixbfield(btp);
    77   			op = tp->t_op;
    78   			tp = tp->t_right;				/*pointer to expression*/
    79   			if( op != ASSIGN )				/*=op operator?*/
    80   				tp = tnalloc(op-(EQADD-ADD),INT,0,0,btp,tp);
    81   			tp = tnalloc(AND,INT,0,0,tp,cnalloc(INT,fmask));
    82   			tp = tnalloc(LSH,INT,0,0,tp,cnalloc(INT,foff));
    83   			btp = tnalloc(AND,INT,0,0,tcopy(stp),
    84   					cnalloc(INT,~(fmask<<foff)));
    85   			tp = tnalloc(OR,INT,0,0,btp,tp);
    86   			tp = tnalloc(ASSIGN,INT,0,0,stp,tp);
    87   		}
    88   	}
    89   	else if( op == BFIELD ) {
    90   		foff = (tp->t_su>>8) & 0377;
    91   		fmask = (1<<(tp->t_su&0377))-1;
    92   		tp = tnalloc(RSH,INT,0,0,tp->t_left,cnalloc(INT,foff));
    93   		tp = tnalloc(AND,INT,0,0,tp,cnalloc(INT,fmask));
    94   	}
    95   	else {
    96   		tp->t_left = fixbfield(tp->t_left);
    97   		if( binop(op) )
    98   			tp->t_right = fixbfield(tp->t_right);
    99   	}
   100   	return(tp);
   101   }
   102    
   103   /*
   104    * optim - optimize expression tree
   105    *		This takes expression tree and performs the following
   106    *		translations:  folds auto names to accesses off the local
   107    *		environment pointer, performs mostly "machine-independent"
   108    *		optimizations, such as multiply by zero and one, etc.,
   109    *		turns field accesses into and's and or's, etc.
   110    *		[vlh] 4.0 added checks for divide/modulos long zero...
   111    *		[vlh] 4.0 optimize multiply/divide 1L, add/sub 0L...
   112    */
   113   optim(tpp)							/* returns pointer to new tree*/
   114   struct tnode **tpp;
   115   {
   116   	register struct tnode *ltp, *rtp, *tp;
   117   	register char *p;
   118   	register int i, cval, changes, op, lconst;
1File: CANON.C                                                             Page       3
   119   	long lcval;		/* [vlh] 4.0 simple long constant handling */
   120    
   121   	tp = *tpp;
   122   	if( tp->t_type & ~TYPE ) {
   123   		tp->t_type =& TYPE;
   124   		tp->t_type =| POINTER;
   125   	}
   126   	if( leafop(op=tp->t_op) )
   127   		return(0);
   128   	lconst = changes = 0;
   129   	if( binop(op) )
   130   		changes =+ optim(&tp->t_right);
   131   	changes =+ optim(&tp->t_left);
   132   	for( ; notleafop(op=tp->t_op); changes++ ) {
   133   #ifndef NODEBUG
   134   		if( oflag )
   135   			putexpr("optim",tp);
   136   #endif
   137   		*tpp = tp;
   138   		ltp = tp->t_left;
   139   		if( binop(op) ) {
   140   			rtp = tp->t_right;
   141   /*			if( tp->t_type == CHAR )	[vlh] 4.0 */
   142   /*				tp->t_type = INT;	[vlh] 4.0 */
   143   			if (!(p = constant(rtp)))
   144   				if (rtp->t_op == CLONG) {
   145   					lconst = 1;
   146   					lcval = rtp->t_lvalue;
   147   				}
   148   		}
   149   		else
   150   			if (!(p = constant(ltp)))
   151   				if (ltp->t_op == CLONG) {
   152   					lconst = 1;
   153   					lcval = ltp->t_lvalue;
   154   				}
   155   		if( p )
   156   			cval = p->t_value;
   157   		switch( op ) {
   158   	
   159   		case ADD:
   160   			if( p ) {
   161   				if( !cval ) {
   162   					tp = ltp;
   163   					continue;
   164   				}
   165   				if( ltp->t_op == ADDR ) {
   166   					ltp->t_left->t_offset =+ cval;
   167   					tp = ltp;
   168   					continue;
   169   				}
   170   			}
   171   			else
   172   				if (lconst && !lcval) {	/* [vlh] 4.0 plus long 0 */
   173   					tp = ltp;
   174   					continue;
   175   				}
   176   			break;
   177   	
1File: CANON.C                                                             Page       4
   178   		case ASSIGN:
   179   			if( rtp->t_op == ADD && indexreg(rtp->t_left) &&
   180   					rtp->t_right->t_op == CINT ) {
   181   				ltp = rtp->t_left;
   182   				ltp->t_sc = REGOFF;
   183   				ltp->t_offset =+ rtp->t_right->t_value;
   184   				tp->t_right = ltp;
   185   				tp->t_op = EQADDR;
   186   				continue;
   187   			}
   188   			break;
   189   	
   190   		case SUB:
   191   			if( p ) {
   192   				if( !cval ) {
   193   					tp = ltp;
   194   					continue;
   195   				}
   196   				tp->t_op = ADD;
   197   				p->t_value = -cval;
   198   				continue;
   199   			}
   200   			else
   201   				if (lconst && !lcval) {	/* [vlh] 4.0 minus long 0... */
   202   					tp = ltp;
   203   					continue;
   204   				}
   205   			if( (p=constant(ltp)) && !p->t_value ) {	/*0-X=-X*/
   206   				tp->t_op = UMINUS;
   207   				tp->t_left = ltp = rtp;
   208   				continue;
   209   			}
   210   			break;
   211   	
   212   		case DIV:
   213   		case EQDIV:
   214   			if( p ) {
   215   				if( !cval ) {		/*X/0->error*/
   216   					error("divide by zero");
   217   					tp = rtp;
   218   					continue;
   219   				}
   220   				if( cval == 1 ) {
   221   					tp = ltp;
   222   					continue;
   223   				}
   224   				if( cval == -1 ) {
   225   					tp->t_op = (tp->t_op == DIV ? UMINUS : EQNEG );
   226   					continue;
   227   				}
   228   			}
   229   			else
   230   				if (lconst) {	/* [vlh] 4.0 simple long expr */
   231   					if (!lcval) {
   232   						error("divide by zero");
   233   						tp = rtp;
   234   						continue;
   235   					}
   236   					if (lcval == 1L) {
1File: CANON.C                                                             Page       5
   237   						tp = ltp;
   238   						continue;
   239   					}
   240   				}
   241   			if( (p=constant(ltp)) && !p->t_value ) {
   242   				tp = ltp;
   243   				continue;
   244   			}
   245   			if( multop(tpp) ) {
   246   				tp = *tpp;
   247   				continue;
   248   			}
   249   			break;
   250   	
   251   		case EQMOD:
   252   		case MOD:
   253   			if( p ) {
   254   				if( !cval ) {		/*X%0->error*/
   255   					error("modulus by zero");
   256   					tp = rtp;
   257   					continue;
   258   				}
   259   				if( cval == 1 ) {		/*X%1->0*/
   260   					p->t_value = 0;
   261   					if (op == EQMOD)	/*[vlh] 4.0*/
   262   						tp->t_op = ASSIGN;
   263   					else
   264   						tp = rtp;
   265   					continue;
   266   				}
   267   			}
   268   			else	/* [vlh] 4.0 check for mod long 0 */
   269   				if (lconst) {
   270   					if(!lcval) {
   271   						error("modulus by zero");
   272   						tp = rtp;
   273   						continue;
   274   					}
   275   					if (lcval == 1L) {
   276   						rtp->t_lvalue = 0L;
   277   						if (op == EQMOD)
   278   							tp->t_op = ASSIGN;
   279   						else
   280   							tp = rtp;
   281   						continue;
   282   					}
   283   				}
   284   			if( (p=constant(ltp)) && !p->t_value ) {
   285   				tp = ltp;
   286   				continue;
   287   			}
   288   			if( multop(tpp) ) {
   289   				tp = *tpp;
   290   				continue;
   291   			}
   292   			break;
   293   	
   294   		case MULT:
   295   		case EQMULT:
1File: CANON.C                                                             Page       6
   296   			if( p ) {
   297   				if( !cval ) {
   298   					if (op == EQMULT)
   299   						tp->t_op = ASSIGN;
   300   					else
   301   						tp = rtp;
   302   					continue;
   303   				}
   304   				if( cval == 1 ) {
   305   					tp = ltp;
   306   					continue;
   307   				}
   308   				if( cval == -1 ) {
   309   					tp->t_op = (tp->t_op == MULT ? UMINUS : EQNEG);
   310   					continue;
   311   				}
   312   			}
   313   			else
   314   				if (lconst) {	/* [vlh] 4.0 simple long expr */
   315   					if (!lcval) {
   316   						if (op == EQMULT)
   317   							tp->t_op = ASSIGN;
   318   						else
   319   							tp = rtp;
   320   						continue;
   321   					}
   322   					if (lcval == 1L) {
   323   						tp = ltp;
   324   						continue;
   325   					}
   326   				}
   327   			if( multop(tpp) ) {
   328   				tp = *tpp;
   329   				continue;
   330   			}
   331   			break;
   332    
   333   		case EQUALS:
   334   		case NEQUALS:
   335   			if( p && (i=onebit(cval)) >= 0 && ltp->t_op == AND &&
   336   					(rtp=constant(ltp->t_right)) &&
   337   					i == onebit(rtp->t_value) ) {
   338   				tp->t_op = invrel[tp->t_op-EQUALS];
   339   				p->t_value = 0;
   340   				continue;
   341   			}
   342   			break;
   343   	
   344   		case GREATEQ:
   345   			if( p && !cval && unsign(ltp->t_type) ) {
   346   				p->t_value = 1;
   347   				tp = p;
   348   				continue;
   349   			}
   350   			break;
   351   	
   352   		case LESS:
   353   			if( p && !cval && unsign(ltp->t_type) ) {
   354   				tp = p;
1File: CANON.C                                                             Page       7
   355   				continue;
   356   			}
   357   			break;
   358   	
   359   		case AND:
   360   			if( p ) {
   361   				if( !cval ) {
   362   					tp = rtp;
   363   					continue;
   364   				}
   365   				if( cval == -1 ) {
   366   					tp = ltp;
   367   					continue;
   368   				}
   369   			}
   370   			break;
   371   	
   372   		case OR:
   373   			if( p ) {
   374   				if( !cval ) {
   375   					tp = ltp;
   376   					continue;
   377   				}
   378   				if( cval == -1 ) {
   379   					tp = rtp;
   380   					continue;
   381   				}
   382   			}
   383   			break;
   384   	
   385   		case EQXOR:
   386   		case XOR:
   387   			if( p ) {
   388   				if( !cval ) {
   389   					tp = ltp;
   390   					continue;
   391   				}
   392   				if( cval == -1 ) {
   393   					tp->t_op = (tp->t_op == XOR ? COMPL : EQNOT);
   394   					continue;
   395   				}
   396   			}
   397   			break;
   398   	
   399   		case LSH:
   400   		case EQLSH:
   401   			if( tp->t_type == LONG && rtp->t_op == INT2L &&
   402   					unsign(rtp->t_left) ) {
   403   				tp->t_right = rtp->t_left;
   404   				continue;
   405   			}
   406   		case RSH:
   407   		case EQRSH:
   408   			if( p ) {
   409   				if( !cval ) {
   410   					tp = ltp;
   411   					continue;
   412   				}
   413   				if( p != rtp ) {
1File: CANON.C                                                             Page       8
   414   					tp->t_right = p;
   415   					continue;
   416   				}
   417   			}
   418   			break;
   419   	
   420   		case ADDR:
   421   			if( ltp->t_op == INDR ) {
   422   				tp = ltp->t_left;
   423   				continue;
   424   			}
   425   			if( ltp->t_op == SYMBOL && ltp->t_sc == REGOFF ) {
   426   				tp->t_op = ADD;
   427   				tp->t_right = cnalloc(INT,ltp->t_offset);
   428   				ltp->t_type = tp->t_type;
   429   				ltp->t_sc = REGISTER;
   430   				ltp->t_offset = 0;
   431   				continue;
   432   			}
   433   			break;
   434   	
   435   		case INDR:
   436   			p = ltp->t_left;
   437   			switch( ltp->t_op ) {
   438    
   439   			case ADDR:
   440   				tp = p;
   441   				continue;
   442    
   443   			case CINT:
   444   				tp = snalloc(tp->t_type,CINDR,ltp->t_value,0,0);
   445   				continue;
   446    
   447   			case CLONG:
   448   				tp = snalloc(tp->t_type,CLINDR,ltp->t_lvalue.hiword,0,
   449   						ltp->t_lvalue.loword);
   450   				continue;
   451    
   452   			case CFLOAT:	/* [vlh] 3.4 */
   453   				tp = snalloc(tp->t_type,CFINDR,ltp->t_lvalue.hiword,0,
   454   						ltp->t_lvalue.loword);
   455   				continue;
   456    
   457   			case SYMBOL:
   458   				if( indexreg(ltp) ) {
   459   					ltp->t_sc = REGOFF;
   460   					ltp->t_type = tp->t_type;
   461   					ltp->t_offset = 0;
   462   					tp = ltp;
   463   					continue;
   464   				}
   465   				break;
   466    
   467   			case ADD:
   468   				if( p->t_op == SYMBOL && p->t_sc == REGOFF &&
   469   						(rtp=constant(ltp->t_right)) &&
   470   						notpointer(p->t_type) ) {
   471   					p->t_offset =+ rtp->t_value;
   472   					tp = p;
1File: CANON.C                                                             Page       9
   473   					continue;
   474   				}
   475   				if( indexreg(p) ) {
   476   					if( rtp = constant(ltp->t_right) ) {
   477   	/*
   478   	 * This combines an address register and a constant into a register
   479   	 * offset.  This relies on 68000 Addressing scheme somewhat.
   480   	 */
   481   						p->t_sc = REGOFF;
   482   						p->t_type = tp->t_type;
   483   						p->t_offset =+ rtp->t_value;
   484   						tp = p;
   485   						continue;
   486   					}
   487   					if( !lflag && ltp->t_right->t_op == ADDR ) {
   488   	/*
   489   	 * We can fold *(An+&expr) into *(&expr(An)), but note that &expr
   490   	 * must be 16 bits for 68000, hence we can only do this if short
   491   	 * addresses are enabled.  Note that the storage classes are mapped:
   492   	 * EXTERNAL->EXTOFF, STATIC->STATOFF, REGISTER->REGOFF
   493   	 */
   494   						ltp = ltp->t_right->t_left;
   495   						ltp->t_sc =+ (EXTOFF-EXTERNAL);
   496   						ltp->t_type = tp->t_type;
   497   						tp = ltp;
   498   						continue;
   499   					}
   500   				}
   501   				break;
   502   	/*
   503   	 * --X and X++ can be folded into -(An) and (An)+ 68000 instructions
   504   	 */
   505   			case PREDEC:
   506   			case POSTINC:
   507   				if( indexreg(p) && ltp->t_type == p->t_type ) {
   508   					p->t_op = (ltp->t_op == PREDEC ? AUTODEC : AUTOINC);
   509   					p->t_type = tp->t_type;
   510   					tp = p;
   511   					continue;
   512   				}
   513   			}
   514   			break;
   515   	
   516   		case NOT:
   517   			if( relop(ltp->t_op) ) {	/*!(X>Y)->X<=Y*/
   518   				tp = ltp;
   519   				tp->t_op = invrel[tp->t_op-EQUALS];
   520   				continue;
   521   			}
   522   			break;
   523   	
   524   		case UMINUS:
   525   		case COMPL:
   526   			if( tp->t_type == CHAR )
   527   				tp->t_type = INT;
   528   			if( tp->t_op == ltp->t_op ) {
   529   				tp = ltp->t_left;
   530   				continue;
   531   			}
1File: CANON.C                                                             Page      10
   532   			if( ltp->t_op == INT2L ) {	/*~(INT2L X)->INT2L (~X)*/
   533   				ltp->t_op = tp->t_op;
   534   				tp->t_op = INT2L;
   535   				ltp->t_type = INT;
   536   				continue;
   537   			}
   538   			break;
   539   	
   540   		case INT2L:
   541   			if( ltp->t_op == MULT ) {	/*INT2L (X*Y)->X*Y*/
   542   				ltp->t_type = (ltp->t_type&(~TYPE))|LONG;
   543   				tp = ltp;
   544   				continue;
   545   			}
   546   			break;
   547   		}
   548   		if(!ccexpr(tpp))
   549   			break;
   550   		tp = *tpp;
   551   	}
   552   	*tpp = tp;
   553   	return(changes);
   554   }
   555    
   556   /*
   557    * commute - commutes expression tree to canonical form
   558    *		This sorts commutable expression trees so that the most
   559    *		difficult expression is the left-most operand.  Note that
   560    *		canon assumes that commute has placed constant operands in
   561    *		the right sub-tree.  This also swaps relationals so that the
   562    *		most difficult expression is on the left.
   563    */
   564   char *commute(tp)					/* returns commuted expression tree*/
   565   struct tnode *tp;
   566   {
   567   	struct tnode *clist[20], *plist[19];
   568   	register struct tnode **p, **q, *s;
   569   	struct tnode **plp, **clp;
   570   	register int op;
   571    
   572   	if( relop(op=tp->t_op) ) {
   573   		s = tp->t_left;
   574   		if( harder(tp->t_right,s) ) {
   575   #ifndef	NODEBUG
   576   			if(oflag)
   577   				putexpr("swaprel",tp);
   578   #endif
   579   			tp->t_op = swaprel[op-EQUALS];
   580   			tp->t_left = tp->t_right;
   581   			tp->t_right = s;
   582   		}
   583   	}
   584   	if( commop(op) ) {
   585   #ifndef	NODEBUG
   586   		if(oflag)
   587   			putexpr("commute",tp);
   588   #endif
   589   		clp = clist;
   590   		plp = plist;
1File: CANON.C                                                             Page      11
   591   		addtree(tp,&clp,&plp);	/*collect comm. expressions*/
   592   	/*
   593   	 * see if any sub-trees can also be commuted (with different operator)
   594   	 */
   595   		clp--;
   596   		plp--;
   597   		for( p = clist; p <= clp; p++ )
   598   			*p = commute(*p);
   599   	/*
   600   	 * this sorts the expressions in decreasing order of Sethy-Ullman
   601   	 * values.
   602   	 */
   603   		for( p = clist; p <= clp; p++ ) {
   604   			for( q = p; q <= clp; q++ ) {
   605   				if( harder(*q,*p) ) {
   606   					s = *q;
   607   					*q = *p;
   608   					*p = s;
   609   				}
   610   			}
   611   		}
   612   	/*
   613   	 * Now, we start at the end of the list and collect any constants
   614   	 * if possible.
   615   	 */
   616   		for( q = clp, p = plp; p > plist; p-- ) {
   617   			s = *p;
   618   			s->t_right = *q;
   619   			s->t_left = *--q;
   620   			if( ccexpr(p) ) {
   621   				clp--;
   622   				plp--;
   623   				*q = *p;	/*[vlh]*/
   624   			}
   625   		}
   626   	/*
   627   	 * this takes the sorted sub-expression pointers and the pointers
   628   	 * to the commutable operator nodes (plist) and structures the
   629   	 * tree so that the left sub-expression is the most complex.  The
   630   	 * code generation scheme is very sensitive to this...
   631   	 */
   632   		q = clist;
   633   		p = plist;
   634   		s = *q++;
   635   		while( p <= plp ) {
   636   			(*p)->t_left = s;
   637   			s = *p++;
   638   			s->t_right = *q++;
   639   			if(!longorptr(s->t_type)) {
   640   				if( longorptr(s->t_right->t_type) )
   641   					s->t_type = s->t_right->t_type;
   642   				else if( longorptr(s->t_left->t_type) )
   643   					s->t_type = s->t_left->t_type;
   644   			}
   645   		}
   646   		tp = s;
   647   #ifndef	NODEBUG
   648   		if(oflag)
   649   			putexpr("after commute",tp);
1File: CANON.C                                                             Page      12
   650   #endif
   651   	}
   652   	else if( binop(op) ) {
   653   		tp->t_left = commute(tp->t_left);
   654   		tp->t_right = commute(tp->t_right);
   655   	}
   656   	else if( unaryop(op) )
   657   		tp->t_left = commute(tp->t_left);
   658   	return(tp);
   659   }
   660    
   661   /*
   662    * harder - test one sub-expression for being "harder" than another
   663    *		This requires some special finagling for registers.  The reason
   664    *		for this is that the code skeletons produce better code if the
   665    *		register is on the left.  Also note that allowing an address
   666    *		register on the right can have disastrous effects for AND and OR.
   667    *		The basic point is: don't mess with this routine unless you're
   668    *		100% sure you understand the ramifications...
   669    */
   670   harder(tp,ntp)							/* returns 1 if tp > ntp, else 0*/
   671   struct tnode *tp;
   672   struct tnode *ntp;
   673   {
   674   	if( ntp->t_su == SU_VHARD )
   675   		return(0);
   676   	if( tp->t_su == SU_VHARD )
   677   		return(1);
   678   	if( isreg(ntp) )
   679   		return(0);
   680   	if( isreg(tp) )
   681   		return(1);
   682   	if( constant(ntp) )
   683   		return(1);
   684   	if( constant(tp) )
   685   		return(0);
   686   	return( tp->t_su > ntp->t_su );
   687   }
   688    
   689   /*
   690    * addtree - collect commutable sub-trees for commute
   691    *		This recurses down the sub-trees looking for groups of
   692    *		commutable operators.  It collects the sub-trees and their
   693    *		parent nodes for commute.
   694    */
   695   addtree(tp,clist,plist)				/* returns pointer to clist*/
   696   struct tnode *tp;					/* pointer to tree*/
   697   struct tnode ***clist;				/* commutable sub-trees*/
   698   struct tnode ***plist;				/* parent nodes of sub-trees*/
   699   {
   700   	register struct tnode ***p, ***c;
   701    
   702   	c = clist;
   703   	p = plist;
   704   	if( tp->t_op == tp->t_left->t_op )
   705   		addtree(tp->t_left,c,p);
   706   	else
   707   		*(*c)++ = tp->t_left;
   708   	if( tp->t_op == tp->t_right->t_op )
1File: CANON.C                                                             Page      13
   709   		addtree(tp->t_right,c,p);
   710   	else
   711   		*(*c)++ = tp->t_right;
   712   	*(*p)++ = tp;
   713   }
   714    
   715   /* constant - test for tree being a constant node*/
   716   char *constant(tp)					/* returns 0 or ptr to const node*/
   717   struct tnode *tp;					/* pointer to tree*/
   718   {
   719   	if( tp->t_op == CINT )
   720   		return(tp);
   721   	if((tp->t_op==INT2L || tp->t_op==LONG2I) && tp->t_left->t_op==CINT )
   722   		return(tp->t_left);
   723   	return(0);
   724   }
   725    
   726   /* indexreg - returns whether node is an address register*/
   727   /*		For 68000, must be an A register*/
   728   indexreg(tp)						/* returns whether node is A reg*/
   729   struct tnode *tp;					/* pointer to tree*/
   730   {
   731   	if( tp->t_op == SYMBOL && tp->t_sc == REGISTER &&
   732   			!(isdreg(tp->t_reg)) )
   733   		return(1);
   734   	return(0);
   735   }
   736    
   737   /* ccexpr - compute constant expression*/
   738   /*		Evaluates constant expressions, including ?: and relationals*/
   739   ccexpr(tpp)							/* returns 1 if changes, 0 otherwise*/
   740   struct tnode **tpp;					/* pointer to tree*/
   741   {
   742   	register struct tnode *ltp, *rtp, *tp;
   743   	register int op, i, j, anylong, anyfloat;	/*[vlh] 3.4 anyfloat*/
   744   	register long rval, lval;
   745    
   746   	tp = *tpp;
   747   	op = tp->t_op;
   748   	if( leafop(op) )
   749   		return(0);
   750   	anylong = anyfloat = 0;
   751   	ltp = tp->t_left;
   752   	if( ltp->t_op == CLONG ) {
   753   		lval = ltp->t_lvalue;
   754   		anylong++;
   755   	}
   756   	else if ( ltp->t_op == CFLOAT) {	/* [vlh] 3.4 */
   757   		lval = ltp->t_lvalue;
   758   		anyfloat++;
   759   	}
   760   	else if( ltp = constant(ltp) )
   761   		lval = ltp->t_value;
   762   	else
   763   		return(0);
   764   	if( binop(op) ) {
   765   		rtp = tp->t_right;
   766   		if( op == QMARK ) {
   767   			ltp = rtp->t_left;
1File: CANON.C                                                             Page      14
   768   			rtp = rtp->t_right;
   769   			if( ltp->t_op != CINT || rtp->t_op != CINT )
   770   				return(0);
   771   			ltp->t_value = (lval?ltp->t_value:rtp->t_value);
   772   			*tpp = ltp;
   773   			return(1);
   774   		}
   775   		if( rtp->t_op == CLONG ) {
   776   			anylong++;
   777   			rval = rtp->t_lvalue;
   778   		}
   779   		else if (rtp->t_op == CFLOAT) {	/* [vlh] 3.4 */
   780   			anyfloat++;
   781   			rval = rtp->t_lvalue;
   782   		}
   783   		else if( rtp = constant(rtp) )
   784   			rval = rtp->t_value;
   785   		else
   786   			return(0);
   787   	}
   788   	i = lval;
   789   	j = rval;
   790   	switch( op ) {
   791    
   792   	case ADD:
   793   		lval =+ rval;
   794   		break;
   795    
   796   	case SUB:
   797   		lval =- rval;
   798   		break;
   799    
   800   	case MULT:
   801   	case DIV:
   802   	case MOD:
   803   	case LSH:
   804   	case RSH:
   805   	case XOR:
   806   		if( anylong || anyfloat )	/* [vlh] 3.4 float */
   807   			return(0);
   808   		switch( op ) {
   809    
   810   		case MULT:
   811   			lval = i * j;
   812   			break;
   813    
   814   		case DIV:
   815   			lval = i / j;
   816   			break;
   817    
   818   		case MOD:
   819   			lval = i % j;
   820   			break;
   821    
   822   		case RSH:
   823   			lval = i >> j;
   824   			break;
   825    
   826   		case LSH:
1File: CANON.C                                                             Page      15
   827   			lval = i << j;
   828   			break;
   829    
   830   		case XOR:
   831   			lval = i ^ j;
   832   			break;
   833   		}
   834   		break;
   835    
   836   	case GREAT:
   837   		lval = (lval>rval);
   838   		break;
   839    
   840   	case GREATEQ:
   841   		lval = (lval>=rval);
   842   		break;
   843    
   844   	case LESS:
   845   		lval = (lval<rval);
   846   		break;
   847    
   848   	case LESSEQ:
   849   		lval = (lval<=rval);
   850   		break;
   851    
   852   	case UMINUS:
   853   		lval = -lval;
   854   		break;
   855    
   856   	case COMPL:
   857   		lval = ~lval;
   858   		break;
   859    
   860   	case NOT:
   861   		lval = !lval;
   862   		break;
   863    
   864   	case OR:
   865   		lval =| rval;
   866   		break;
   867    
   868   	case AND:
   869   		lval =& rval;
   870   		break;
   871    
   872   	default:
   873   		return(0);
   874    
   875   	}
   876   	if( anylong )
   877   		ltp = lcnalloc(LONG,lval);
   878   	else if ( anyfloat )
   879   		ltp = fpcnalloc(FLOAT,lval);
   880   	else
   881   		ltp->t_value = lval;
   882   	*tpp = ltp;
   883   	return(1);
   884   }
   885    
1File: CANON.C                                                             Page      16
   886   /* power2 - do multiply and divide by powers of two*/
   887   /*		This changes multiplies and divides by constant powers of two*/
   888   /*		to shifts.*/
   889   power2(tpp)							/* returns 0 if not power of two*/
   890   struct tnode **tpp;					/* pointer to expression tree*/
   891   {
   892   	register char *p;
   893   	register int i, j, op;
   894   	register struct tnode *tp;
   895    
   896   	tp = *tpp;
   897   	if( p = constant(tp->t_right) ) {
   898   		if( (i=onebit(p->t_value)) < 0 )
   899   			return(0);
   900   		switch( op = tp->t_op ) {
   901    
   902   		case MULT:
   903   			op = LSH;
   904   			break;
   905    
   906   		case EQMULT:
   907   			op = EQLSH;
   908   			break;
   909    
   910   		case DIV:
   911   			op = RSH;
   912   			break;
   913    
   914   		case EQDIV:
   915   			op = EQRSH;
   916   			break;
   917    
   918   		case MOD:
   919   			op = AND;
   920   			i = p->t_value - 1;
   921   			break;
   922    
   923   		case EQMOD:
   924   			op = EQAND;
   925   			i = p->t_value - 1;
   926   			break;
   927    
   928   		default:
   929   			return(0);
   930   		}
   931   		tp->t_op = op;
   932   		p->t_value = i;
   933   		return(1);
   934   	}
   935   	return(0);
   936   }
   937    
   938   /* chklong - check for tree being a long*/
   939   chklong(tp)							/* returns 1 if long, 0 otherwise*/
   940   struct tnode *tp;					/* pointer to expression tree*/
   941   {
   942   	if( tp->t_op == INT2L && !(unsign(tp->t_left->t_type)) )
   943   		return(0);
   944   	if( tp->t_op == CLONG )
1File: CANON.C                                                             Page      17
   945   		return(1);
   946   	return( longorptr(tp->t_type) );
   947   }
   948    
   949   /* multop - handle multiplicative operators*/
   950   /*		This checks for powers of two optimizations, then for a hard*/
   951   /*		long operation.*/
   952   multop(tpp)							/* returns ptr to expression tree*/
   953   struct tnode **tpp;					/* pointer to expression tree*/
   954   {
   955   	register struct tnode *ltp, *tp, *rtp, *p;
   956   	register int change;
   957   	register long l;
   958    
   959   	tp = *tpp;
   960   	if( change = power2(tpp) )
   961   		tp = *tpp;
   962   	if( chklong(rtp=tp->t_right) || chklong(ltp=tp->t_left) ) {
   963   		switch( tp->t_op ) {
   964    
   965   		case MULT:
   966   			tp->t_op = LMULT;
   967   			break;
   968    
   969   		case DIV:
   970   		case MOD:
   971   			if( chklong(rtp) ) {		/*only hard if divisor is long*/
   972   				tp->t_op =+ (LMULT-MULT);
   973   				if( rtp->t_op == CLONG )
   974   					rtp->t_op = DCLONG;
   975   			}
   976   			break;
   977    
   978   		case EQDIV:
   979   		case EQMOD:
   980   			if( !chklong(rtp) )
   981   				break;
   982   			if( rtp->t_op == CLONG )
   983   				rtp->t_op = DCLONG;
   984   		case EQMULT:
   985   			tp->t_op =+ (LMULT-EQMULT);
   986   			*tpp = tnalloc(ASSIGN,tp->t_type,0,0,tcopy(ltp),tp);
   987   			change++;
   988   			break;
   989   		}
   990   	}
   991   	return(change);
   992   }
   993    
   994   /* onebit - returns whether constant is power of two (one bit on)*/
   995   onebit(val)							/* returns bit number or -1*/
   996   int val;							/* constant value to check*/
   997   {
   998   	register int i;
   999    
  1000   	for( i = 15; val != 0; val =<< 1, i-- )
  1001   		if( val & 0100000 )
  1002   			break;
  1003   	if (val != 0100000)
1File: CANON.C                                                             Page      18
  1004   		return(-1);
  1005   	return(i);
  1006   }
