847bc6f5bd256ebcb5d4ab822c2bc7aca9dc94ed
[fw/sdcc] / src / SDCCast.c
1 /*-------------------------------------------------------------------------
2   SDCCast.c - source file for parser support & all ast related routines
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19    
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!  
23 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26
27 int currLineno  = 0;
28 set *astList = NULL ;
29 set *operKeyReset = NULL;
30 ast *staticAutos = NULL;
31 int labelKey = 1 ;
32
33 #define LRVAL(x) x->left->rvalue
34 #define RRVAL(x) x->right->rvalue
35 #define TRVAL(x) x->rvalue
36 #define LLVAL(x) x->left->lvalue
37 #define RLVAL(x) x->right->lvalue
38 #define TLVAL(x) x->lvalue
39 #define RTYPE(x) x->right->ftype
40 #define RETYPE(x) x->right->etype
41 #define LTYPE(x) x->left->ftype
42 #define LETYPE(x) x->left->etype
43 #define TTYPE(x) x->ftype
44 #define TETYPE(x) x->etype
45 #define ALLOCATE 1
46 #define DEALLOCATE 2
47
48 char  buffer[1024];
49 int noLineno = 0;
50 int noAlloc = 0 ;
51 symbol *currFunc ;
52 ast  *createIval  (ast *, sym_link *, initList *, ast *);
53 ast *createIvalCharPtr (ast *, sym_link *, ast *);
54 ast *optimizeRRCRLC ( ast * );
55 ast *optimizeGetHbit(ast *);
56 ast *backPatchLabels (ast *,symbol *,symbol *);
57 int  inInitMode = 0;
58 FILE *codeOutFile ;
59 int ptt(ast *tree) {
60     printTypeChain(tree->ftype,stdout);
61     return 0;
62 }
63      
64
65 /*-----------------------------------------------------------------*/
66 /* newAst - creates a fresh node for an expression tree           */
67 /*-----------------------------------------------------------------*/
68 #if 0
69 ast  *newAst (int  type, void *op )
70 {
71     ast  *ex ;
72     static int oldLineno = 0 ;
73
74     ALLOC(ex,sizeof(ast));    
75     
76     ex->type = type ;           
77     ex->lineno = (noLineno ? oldLineno : yylineno);
78     ex->filename = currFname ;
79     ex->level = NestLevel ;
80     ex->block = currBlockno ;
81     ex->initMode = inInitMode;
82
83     /* depending on the type */
84     switch (type)   {
85     case  EX_VALUE :
86         ex->opval.val = (value *) op;
87         break ;
88     case EX_OP     :
89         ex->opval.op   = (long) op ;
90         break ;
91     case EX_LINK   :
92         ex->opval.lnk  = (sym_link *) op;
93         break ;
94     case EX_STMNT  :
95         ex->opval.stmnt= (unsigned) op;
96     }
97     
98     return ex;
99 }
100 #endif
101
102 static ast* newAst_(unsigned type)
103 {
104     ast  *ex ;
105     static int oldLineno = 0 ;
106
107     ALLOC(ex,sizeof(ast));    
108     
109     ex->type = type ;           
110     ex->lineno = (noLineno ? oldLineno : yylineno);
111     ex->filename = currFname ;
112     ex->level = NestLevel ;
113     ex->block = currBlockno ;
114     ex->initMode = inInitMode;
115     return ex;
116 }
117
118 ast* newAst_VALUE(value*val)
119 {
120       ast* ex = newAst_(EX_VALUE);
121       ex->opval.val = val;
122       return ex;
123 }
124
125 ast* newAst_OP(unsigned op)
126 {
127       ast*ex = newAst_(EX_OP);
128       ex->opval.op = op;
129       return ex;
130 }
131
132 ast* newAst_LINK(sym_link*val)
133 {
134       ast* ex = newAst_(EX_LINK);
135       ex->opval.lnk = val;
136       return ex;
137 }
138
139 ast* newAst_STMNT(unsigned val)
140 {
141       ast* ex = newAst_(EX_STMNT);
142       ex->opval.stmnt = val;
143       return ex;
144 }
145
146 /*-----------------------------------------------------------------*/
147 /* newNode - creates a new node                                    */
148 /*-----------------------------------------------------------------*/
149 ast  *newNode ( long op,   ast  *left, ast *right   )
150 {
151     ast  *ex ;
152     
153     ex = newAst_OP(op) ;
154     ex->left    = left ;
155     ex->right   = right;
156         
157     return ex ;
158 }
159
160 /*-----------------------------------------------------------------*/
161 /* newIfxNode - creates a new Ifx Node                             */
162 /*-----------------------------------------------------------------*/
163 ast *newIfxNode (ast *condAst, symbol *trueLabel, symbol *falseLabel)
164 {
165     ast *ifxNode ;
166     
167     /* if this is a literal then we already know the result */
168     if (condAst->etype && IS_LITERAL(condAst->etype)) {
169         
170         /* then depending on the expression value */
171         if ( floatFromVal(condAst->opval.val) )
172               ifxNode = newNode(GOTO,
173                                 newAst_VALUE(symbolVal(trueLabel)),
174                                 NULL);
175         else
176               ifxNode = newNode(GOTO,
177                                 newAst_VALUE(symbolVal(falseLabel)),
178                                 NULL);
179     }
180     else {
181         ifxNode = newNode(IFX,condAst,NULL);
182         ifxNode->trueLabel = trueLabel;
183         ifxNode->falseLabel= falseLabel;
184     }
185     
186     return ifxNode ;
187 }
188
189 /*-----------------------------------------------------------------*/
190 /* copyAstValues - copies value portion of ast if needed           */
191 /*-----------------------------------------------------------------*/
192 void copyAstValues (ast *dest,ast *src)
193 {
194     switch (src->opval.op) {
195     case BLOCK:
196         dest->values.sym     = copySymbolChain(src->values.sym);
197         break;
198         
199     case SWITCH:
200         dest->values.switchVals.swVals = 
201             copyValue(src->values.switchVals.swVals);
202         dest->values.switchVals.swDefault =
203             src->values.switchVals.swDefault ;
204         dest->values.switchVals.swNum  =
205             src->values.switchVals.swNum ;
206         break ;
207         
208     case INLINEASM:
209         ALLOC_ATOMIC(dest->values.inlineasm,strlen(src->values.inlineasm));
210         strcpy(dest->values.inlineasm,src->values.inlineasm);
211
212     case FOR:
213          AST_FOR(dest,trueLabel) = copySymbol(AST_FOR(src,trueLabel));
214          AST_FOR(dest,continueLabel) = copySymbol(AST_FOR(src,continueLabel));
215          AST_FOR(dest,falseLabel) =  copySymbol(AST_FOR(src,falseLabel));
216          AST_FOR(dest,condLabel)  =  copySymbol(AST_FOR(src,condLabel));
217          AST_FOR(dest,initExpr)   =  copyAst (AST_FOR(src,initExpr)) ;
218          AST_FOR(dest,condExpr)   =  copyAst (AST_FOR(src,condExpr)) ;
219          AST_FOR(dest,loopExpr)   =  copyAst (AST_FOR(src,loopExpr)) ;
220     }
221     
222 }
223
224 /*-----------------------------------------------------------------*/
225 /* copyAst - makes a copy of a given astession                     */
226 /*-----------------------------------------------------------------*/
227 ast  *copyAst (ast   *src)
228 {
229     ast  *dest;
230     
231     if (!src)  return NULL ;
232    
233     ALLOC(dest,sizeof(ast));
234     
235     dest->type = src->type  ;
236     dest->lineno = src->lineno ;
237     dest->level  = src->level  ;
238     dest->funcName = src->funcName;
239     dest->argSym = src->argSym;
240     
241     /* if this is a leaf */   
242     /* if value */
243     if (src->type == EX_VALUE)   {
244         dest->opval.val = copyValue(src->opval.val);
245         goto exit;
246     }
247     
248     /* if link */
249     if (src->type == EX_LINK)   {
250         dest->opval.lnk = copyLinkChain(src->opval.lnk);
251         goto exit ;
252     }
253     
254     dest->opval.op = src->opval.op ;
255     
256     /* if this is a node that has special values */
257     copyAstValues (dest,src);
258     
259     if ( src->ftype ) 
260         dest->etype = getSpec(dest->ftype = copyLinkChain(src->ftype)) ;
261     
262     dest->trueLabel = copySymbol (src->trueLabel);
263     dest->falseLabel= copySymbol (src->falseLabel);
264     dest->left = copyAst(src->left);
265     dest->right= copyAst(src->right);
266  exit:
267     return dest ;
268     
269 }
270
271 /*-----------------------------------------------------------------*/
272 /* hasSEFcalls - returns TRUE if tree has a function call          */
273 /*-----------------------------------------------------------------*/
274 bool hasSEFcalls ( ast *tree)
275 {
276     if (!tree)
277         return FALSE ;
278
279     if (tree->type == EX_OP && 
280         ( tree->opval.op == CALL  ||
281           tree->opval.op == PCALL ||
282           tree->opval.op == '='   ||
283           tree->opval.op == INC_OP ||
284           tree->opval.op == DEC_OP ))
285         return TRUE;
286
287     return ( hasSEFcalls(tree->left) |
288              hasSEFcalls(tree->right));
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* isAstEqual - compares two asts & returns 1 if they are equal    */
293 /*-----------------------------------------------------------------*/
294 int isAstEqual (ast *t1, ast *t2)
295 {
296     if (!t1 && !t2)
297         return 1;
298
299     if (!t1 || !t2)
300         return 0;
301
302     /* match type */
303     if (t1->type != t2->type)
304         return 0;
305
306     switch (t1->type) {
307     case EX_OP:
308         if (t1->opval.op != t2->opval.op)
309             return 0;
310         return ( isAstEqual(t1->left,t2->left) &&
311                  isAstEqual(t1->right,t2->right));
312         break;
313
314     case EX_VALUE:
315         if (t1->opval.val->sym) {
316             if (!t2->opval.val->sym)
317                 return 0;
318             else
319                 return isSymbolEqual(t1->opval.val->sym,
320                                      t2->opval.val->sym);
321         }
322         else {
323             if (t2->opval.val->sym)
324                 return 0;
325             else
326                 return (floatFromVal(t1->opval.val) ==
327                         floatFromVal(t2->opval.val));
328         }
329         break;
330
331         /* only compare these two types */
332     default :
333         return 0;
334     }
335
336     return 0;
337 }
338
339 /*-----------------------------------------------------------------*/
340 /* resolveSymbols - resolve symbols from the symbol table          */
341 /*-----------------------------------------------------------------*/
342 ast *resolveSymbols (ast *tree)
343 {
344     /* walk the entire tree and check for values */
345     /* with symbols if we find one then replace  */
346     /* symbol with that from the symbol table    */
347     
348     if ( tree == NULL )
349         return tree ;
350
351     /* print the line          */
352     /* if not block & function */
353     if ( tree->type == EX_OP && 
354          ( tree->opval.op != FUNCTION  &&
355            tree->opval.op != BLOCK     &&
356            tree->opval.op != NULLOP    )) {
357         filename = tree->filename ;
358         lineno = tree->lineno ;
359     }
360
361     /* make sure we resolve the true & false labels for ifx */
362     if (tree->type == EX_OP && tree->opval.op == IFX ) {
363         symbol *csym ;
364
365         if (tree->trueLabel) {
366             if (( csym = findSym(LabelTab,tree->trueLabel,
367                                  tree->trueLabel->name)))
368                 tree->trueLabel = csym ;
369             else
370                 werror(E_LABEL_UNDEF,tree->trueLabel->name);
371         }
372
373         if (tree->falseLabel) {
374             if (( csym = findSym(LabelTab,
375                                  tree->falseLabel,
376                                  tree->falseLabel->name)))
377                 tree->falseLabel = csym ;
378             else
379                 werror(E_LABEL_UNDEF,tree->falseLabel->name);       
380         }
381
382     }
383
384     /* if this is a label resolve it from the labelTab*/
385     if (IS_AST_VALUE(tree)   &&      
386         tree->opval.val->sym &&
387         tree->opval.val->sym->islbl) {
388         
389         symbol *csym = findSym (LabelTab, tree->opval.val->sym , 
390                                 tree->opval.val->sym->name);
391
392         if (!csym) 
393             werror (E_LABEL_UNDEF,tree->opval.val->sym->name);
394         else        
395             tree->opval.val->sym = csym ;       
396
397         goto resolveChildren ;
398     }
399
400     /* do only for leafs */
401     if (IS_AST_VALUE(tree)   && 
402         tree->opval.val->sym && 
403         ! tree->opval.val->sym->implicit ) {
404
405         symbol *csym = findSymWithLevel (SymbolTab,tree->opval.val->sym);
406         
407         /* if found in the symbol table & they r not the same */
408         if (csym && tree->opval.val->sym != csym ) {      
409             tree->opval.val->sym = csym ;          
410             tree->opval.val->type = csym->type;
411             tree->opval.val->etype = csym->etype;
412         }
413         
414         /* if not found in the symbol table */
415         /* mark it as undefined assume it is*/
416         /* an integer in data space         */
417         if (!csym && !tree->opval.val->sym->implicit) {
418             
419             /* if this is a function name then */
420             /* mark it as returning an int     */
421             if (tree->funcName) {
422                 tree->opval.val->sym->type = newLink();
423                 DCL_TYPE(tree->opval.val->sym->type) = FUNCTION;
424                 tree->opval.val->sym->type->next = 
425                     tree->opval.val->sym->etype = newIntLink();
426                 tree->opval.val->etype = tree->opval.val->etype;
427                 tree->opval.val->type = tree->opval.val->sym->type;
428                 werror(W_IMPLICIT_FUNC,tree->opval.val->sym->name);
429             } else {
430                 tree->opval.val->sym->undefined =1 ;
431                 tree->opval.val->type = 
432                     tree->opval.val->etype = newIntLink();
433                 tree->opval.val->sym->type = 
434                     tree->opval.val->sym->etype = newIntLink();
435             }
436         }       
437     }  
438
439  resolveChildren:    
440     resolveSymbols (tree->left);
441     resolveSymbols (tree->right);
442     
443     return tree;
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* setAstLineno - walks a ast tree & sets the line number          */
448 /*-----------------------------------------------------------------*/
449 int setAstLineno ( ast *tree, int lineno)
450 {
451     if (!tree)
452         return 0;
453
454     tree->lineno = lineno ;
455     setAstLineno ( tree->left, lineno);
456     setAstLineno ( tree->right, lineno);
457     return 0;
458 }
459
460 #if 0
461 /* this functions seems to be superfluous?! kmh */
462
463 /*-----------------------------------------------------------------*/
464 /* resolveFromTable - will return the symbal table value           */
465 /*-----------------------------------------------------------------*/
466 value *resolveFromTable (value *val)
467 {
468     symbol *csym ;
469
470     if (!val->sym)
471         return val;
472
473     csym = findSymWithLevel (SymbolTab,val->sym);
474             
475     /* if found in the symbol table & they r not the same */
476     if (csym && val->sym != csym && 
477         csym->level == val->sym->level &&
478         csym->_isparm &&
479         !csym->ismyparm) {
480       
481         val->sym = csym ;      
482         val->type = csym->type;
483         val->etype = csym->etype;
484     }  
485
486     return val;
487 }
488 #endif
489
490 /*-----------------------------------------------------------------*/
491 /* funcOfType :- function of type with name                        */
492 /*-----------------------------------------------------------------*/
493 symbol *funcOfType (char *name, sym_link *type, sym_link *argType, 
494                     int nArgs , int rent)
495 {
496     symbol *sym;    
497     int argStack = 0;   
498     /* create the symbol */
499     sym = newSymbol (name,0);
500         
501     /* if arguments required */
502     if (nArgs) {
503
504         value *args ;
505         args = sym->args = newValue();
506
507         while (nArgs--) {
508             argStack += getSize(type);
509             args->type = copyLinkChain(argType);
510             args->etype = getSpec(args->type);
511             if (!nArgs)
512                 break;
513             args = args->next = newValue();
514         }
515     }
516     
517     /* setup return value       */
518     sym->type = newLink();
519     DCL_TYPE(sym->type) = FUNCTION;
520     sym->type->next = copyLinkChain(type);
521     sym->etype = getSpec(sym->type);   
522     SPEC_RENT(sym->etype) = rent;
523     
524     /* save it */
525     addSymChain(sym);
526     sym->cdef = 1;
527     sym->argStack = (rent ? argStack : 0);
528     allocVariables (sym);
529     return sym;
530     
531 }
532
533 /*-----------------------------------------------------------------*/
534 /* reverseParms - will reverse a parameter tree                    */
535 /*-----------------------------------------------------------------*/
536 void reverseParms (ast *ptree)
537 {
538     ast *ttree;
539     if (!ptree)
540         return ;
541
542     /* top down if we find a nonParm tree then quit */
543     if (ptree->type == EX_OP && ptree->opval.op == PARAM ) {
544         ttree = ptree->left;
545         ptree->left = ptree->right;
546         ptree->right = ttree;
547         reverseParms(ptree->left);
548         reverseParms(ptree->right);
549     }
550
551     return ;
552 }
553
554 /*-----------------------------------------------------------------*/
555 /* processParms  - makes sure the parameters are okay and do some  */
556 /*                 processing with them                            */
557 /*-----------------------------------------------------------------*/
558 int processParms (ast *func, value *defParm, 
559                   ast *actParm, 
560                   int *parmNumber)
561 {
562     sym_link *fetype = func->etype;
563     
564     /* if none of them exist */
565     if ( !defParm && !actParm)
566         return 0;
567      
568     /* if the function is being called via a pointer &   */
569     /* it has not been defined a reentrant then we cannot*/
570     /* have parameters                                   */
571     if (func->type != EX_VALUE && !IS_RENT(fetype) && !options.stackAuto) {
572         werror (E_NONRENT_ARGS);  
573         return 1;
574     }
575     
576     /* if defined parameters ended but actual parameters */
577     /* exist and this is not defined as a variable arg   */
578     /* also check if statckAuto option is specified      */
579     if ((! defParm) && actParm && (!func->hasVargs ) && 
580         !options.stackAuto && !IS_RENT(fetype)) {
581         werror(E_TOO_MANY_PARMS);
582         return 1;
583     }
584     
585     /* if defined parameters present and actual paramters ended */
586     if ( defParm && ! actParm) {
587         werror(E_TO_FEW_PARMS);
588         return 1;
589     }
590         
591     /* if defined parameters ended but actual has not & */
592     /* has a variable argument list or statckAuto       */
593     if (! defParm && actParm && 
594         (func->hasVargs || options.stackAuto || IS_RENT(fetype)))
595         return 0;
596     
597     resolveSymbols(actParm);
598     /* if this is a PARAM node then match left & right */
599     if ( actParm->type == EX_OP && actParm->opval.op == PARAM) {
600         
601         return (processParms (func,defParm,actParm->left,parmNumber) ||
602                 processParms (func,defParm->next, actParm->right,parmNumber) );
603     }
604        
605     /* the parameter type must be atleast castable */
606     if (checkType(defParm->type,actParm->ftype) == 0) {
607         werror(E_TYPE_MISMATCH_PARM,*parmNumber);
608         werror(E_CONTINUE,"defined type ");
609         printTypeChain(defParm->type,stderr);fprintf(stderr,"\n");
610         werror(E_CONTINUE,"actual type ");
611         printTypeChain(actParm->ftype,stderr);fprintf(stderr,"\n");
612     }
613     
614     /* if the parameter is castable then add the cast */
615     if ( checkType (defParm->type,actParm->ftype) < 0) {
616         ast *pTree = resolveSymbols(copyAst(actParm));
617
618         /* now change the current one to a cast */      
619         actParm->type = EX_OP ;
620         actParm->opval.op = CAST ;
621         actParm->left = newAst_LINK(defParm->type);
622         actParm->right= pTree ;
623         actParm->etype= defParm->etype;
624         actParm->ftype= defParm->type;
625     }
626     
627 /*    actParm->argSym = resolveFromTable(defParm)->sym ; */
628     actParm->argSym = defParm->sym;
629     /* make a copy and change the regparm type to the defined parm */
630     actParm->etype = getSpec(actParm->ftype = copyLinkChain(actParm->ftype));
631     SPEC_REGPARM(actParm->etype) = SPEC_REGPARM(defParm->etype);
632     (*parmNumber)++;
633     return 0;
634 }
635 /*-----------------------------------------------------------------*/
636 /* createIvalType - generates ival for basic types                 */
637 /*-----------------------------------------------------------------*/
638 ast *createIvalType ( ast *sym,sym_link  *type, initList *ilist)
639 {
640     ast *iExpr;
641
642     /* if initList is deep */
643     if ( ilist->type == INIT_DEEP )
644         ilist =  ilist->init.deep  ;
645     
646     iExpr = decorateType(resolveSymbols(list2expr(ilist)));
647     return decorateType(newNode('=',sym,iExpr));
648 }
649
650 /*-----------------------------------------------------------------*/
651 /* createIvalStruct - generates initial value for structures       */
652 /*-----------------------------------------------------------------*/
653 ast *createIvalStruct (ast *sym,sym_link *type,initList *ilist)
654 {
655     ast *rast = NULL ;
656     symbol   *sflds  ;
657     initList *iloop  ;
658     
659     sflds = SPEC_STRUCT(type)->fields  ;
660     if (ilist->type != INIT_DEEP) {
661         werror(E_INIT_STRUCT,"");
662         return NULL ;
663     }
664     
665     iloop = ilist->init.deep;
666     
667     for ( ; sflds ; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL )) {
668         ast *lAst ;
669         
670         /* if we have come to end */
671         if (!iloop)
672             break;
673         sflds->implicit = 1;
674         lAst = newNode(PTR_OP,newNode('&',sym,NULL),newAst_VALUE(symbolVal(sflds)));
675         lAst = decorateType(resolveSymbols(lAst));
676         rast = decorateType(resolveSymbols(createIval (lAst, sflds->type, iloop,rast)));
677     }
678     return rast ;
679 }
680
681
682 /*-----------------------------------------------------------------*/
683 /* createIvalArray - generates code for array initialization       */
684 /*-----------------------------------------------------------------*/
685 ast *createIvalArray (ast  *sym, sym_link *type, initList *ilist)
686 {
687     ast *rast = NULL;
688     initList *iloop ;
689     int lcnt = 0, size =0 ;
690     
691     /* take care of the special   case  */
692     /* array of characters can be init  */
693     /* by a string                      */
694     if ( IS_CHAR(type->next) )
695         if ( (rast = createIvalCharPtr(sym,
696                                        type,
697                                        decorateType(resolveSymbols(list2expr(ilist))))))
698             
699             return decorateType(resolveSymbols(rast));
700     
701     /* not the special case             */
702     if (ilist->type != INIT_DEEP) {
703         werror(E_INIT_STRUCT,"");
704         return NULL;
705     }
706     
707     iloop = ilist->init.deep   ;
708     lcnt = DCL_ELEM(type);
709     
710     for (;;)  {
711         ast *aSym ;
712         size++ ;
713
714         aSym = newNode('[',sym,newAst_VALUE(valueFromLit(size-1)));
715         aSym = decorateType(resolveSymbols(aSym));
716         rast = createIval (aSym,type->next,iloop,rast)   ;
717         iloop = (iloop ? iloop->next : NULL) ;
718         if (!iloop)
719             break;
720         /* if not array limits given & we */
721         /* are out of initialisers then   */
722         if (!DCL_ELEM(type) && !iloop)
723             break ;
724         
725         /* no of elements given and we    */
726         /* have generated for all of them */
727         if (!--lcnt)
728             break ;
729     }
730     
731     /* if we have not been given a size  */
732     if (!DCL_ELEM(type))
733         DCL_ELEM(type) = size;
734     
735     return decorateType(resolveSymbols(rast));
736 }
737
738
739 /*-----------------------------------------------------------------*/
740 /* createIvalCharPtr - generates initial values for char pointers  */
741 /*-----------------------------------------------------------------*/
742 ast *createIvalCharPtr (ast *sym, sym_link *type, ast *iexpr)
743 {      
744     ast *rast = NULL ;
745
746     /* if this is a pointer & right is a literal array then */
747     /* just assignment will do                              */
748     if ( IS_PTR(type) && (( IS_LITERAL(iexpr->etype) || 
749           SPEC_SCLS(iexpr->etype) == S_CODE )
750                           && IS_ARRAY(iexpr->ftype))) 
751         return newNode('=',sym,iexpr);
752
753     /* left side is an array so we have to assign each */
754     /* element                                         */
755     if (( IS_LITERAL(iexpr->etype) || 
756           SPEC_SCLS(iexpr->etype) == S_CODE )
757         && IS_ARRAY(iexpr->ftype))  {
758
759         /* for each character generate an assignment */
760         /* to the array element */
761         char *s = SPEC_CVAL(iexpr->etype).v_char ;
762         int i = 0 ;
763         
764         while (*s) {        
765             rast = newNode(NULLOP,
766                            rast,
767                            newNode('=',
768                                    newNode('[', sym,
769                                            newAst_VALUE(valueFromLit(i))),
770                                    newAst_VALUE(valueFromLit(*s))));
771             i++;
772             s++;
773         }
774         rast = newNode(NULLOP,
775                            rast,
776                            newNode('=',
777                                    newNode('[', sym,
778                                            newAst_VALUE(valueFromLit(i))),
779                                    newAst_VALUE(valueFromLit(*s))));
780         return decorateType(resolveSymbols(rast));
781     }
782
783     return NULL ;
784 }
785
786 /*-----------------------------------------------------------------*/
787 /* createIvalPtr - generates initial value for pointers            */
788 /*-----------------------------------------------------------------*/
789 ast *createIvalPtr (ast *sym,sym_link *type,initList *ilist)
790 {    
791     ast *rast;
792     ast *iexpr ;
793
794     /* if deep then   */
795     if ( ilist->type == INIT_DEEP )
796         ilist = ilist->init.deep   ;
797            
798     iexpr = decorateType(resolveSymbols(list2expr(ilist)));
799
800     /* if character pointer */
801     if (IS_CHAR(type->next))
802         if ((rast = createIvalCharPtr (sym,type,iexpr)))
803             return rast;   
804
805     return newNode('=',sym,iexpr);          
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* createIval - generates code for initial value                   */
810 /*-----------------------------------------------------------------*/
811 ast  *createIval  (ast *sym, sym_link *type, initList *ilist, ast *wid)
812 {
813     ast *rast = NULL;  
814
815     if (!ilist)
816         return NULL ;   
817     
818     /* if structure then    */
819     if (IS_STRUCT(type)) 
820         rast =  createIvalStruct(sym, type,ilist);
821     else
822         /* if this is a pointer */
823         if (IS_PTR(type)) 
824             rast = createIvalPtr(sym, type,ilist);
825         else
826             /* if this is an array   */
827             if (IS_ARRAY(type))  
828                 rast = createIvalArray(sym, type,ilist); 
829             else
830                 /* if type is SPECIFIER */
831                 if (IS_SPEC(type))
832                     rast =  createIvalType (sym,type,ilist);
833     if ( wid )
834         return decorateType(resolveSymbols(newNode(NULLOP,wid,rast)));
835     else
836         return decorateType(resolveSymbols(rast)) ;
837 }
838
839 /*-----------------------------------------------------------------*/
840 /* initAggregates - initialises aggregate variables with initv     */
841 /*-----------------------------------------------------------------*/
842 ast *initAggregates ( symbol *sym, initList *ival, ast *wid)
843 {
844     return createIval (newAst_VALUE(symbolVal(sym)),sym->type,ival,wid);
845 }
846
847 /*-----------------------------------------------------------------*/
848 /* gatherAutoInit - creates assignment expressions for initial     */
849 /*      values                                                     */
850 /*-----------------------------------------------------------------*/
851 ast     *gatherAutoInit ( symbol *autoChain )
852 {
853     ast *init = NULL ;
854     ast *work ;
855     symbol      *sym;
856     
857     inInitMode =1;
858     for ( sym = autoChain ; sym ; sym = sym->next ) {
859         
860         /* resolve the symbols in the ival */
861         if (sym->ival)
862             resolveIvalSym(sym->ival);
863
864         /* if this is a static variable & has an */
865         /* initial value the code needs to be lifted */
866         /* here to the main portion since they can be */
867         /* initialised only once at the start    */
868         if ( IS_STATIC(sym->etype) && sym->ival &&
869              SPEC_SCLS(sym->etype) != S_CODE) {
870             symbol *newSym ;
871
872             /* insert the symbol into the symbol table */
873             /* with level = 0 & name = rname               */
874             newSym = copySymbol (sym);                      
875             addSym (SymbolTab,newSym,newSym->name,0,0);
876             
877             /* now lift the code to main */
878             if (IS_AGGREGATE(sym->type))
879                 work = initAggregates (sym, sym->ival,NULL);
880             else
881                 work = newNode('=' ,newAst_VALUE(symbolVal(newSym)),
882                                list2expr(sym->ival));
883             
884             setAstLineno(work,sym->lineDef);
885
886             sym->ival = NULL ;
887             if ( staticAutos )
888                 staticAutos = newNode(NULLOP,staticAutos,work);
889             else
890                 staticAutos = work ;
891             
892             continue;
893         }
894         
895         /* if there is an initial value */
896         if ( sym->ival && SPEC_SCLS(sym->etype)!=S_CODE) {
897             if (IS_AGGREGATE(sym->type)) 
898                 work = initAggregates (sym,sym->ival,NULL);
899             else
900                 work = newNode('=' ,newAst_VALUE(symbolVal(sym)),
901                                list2expr(sym->ival));
902             
903             setAstLineno (work,sym->lineDef);
904             sym->ival = NULL ;
905             if ( init )
906                 init = newNode(NULLOP,init,work);
907             else
908                 init = work ;
909         }
910     }
911     inInitMode = 0;
912     return init ;
913 }
914
915 /*-----------------------------------------------------------------*/
916 /* stringToSymbol - creates a symbol from a literal string         */
917 /*-----------------------------------------------------------------*/
918 static value *stringToSymbol (value *val)
919 {
920     char name[SDCC_NAME_MAX+1];
921     static int charLbl = 0;
922     symbol *sym ;
923     
924     sprintf(name,"_str_%d",charLbl++);
925     sym = newSymbol(name,0); /* make it @ level 0 */
926     strcpy(sym->rname,name);
927     
928     /* copy the type from the value passed */   
929     sym->type = copyLinkChain(val->type);
930     sym->etype = getSpec(sym->type);
931     /* change to storage class & output class */
932     SPEC_SCLS(sym->etype) = S_CODE ;
933     SPEC_CVAL(sym->etype).v_char = SPEC_CVAL(val->etype).v_char ;
934     SPEC_STAT(sym->etype) = 1;
935     /* make the level & block = 0 */
936     sym->block = sym->level = 0;
937     sym->isstrlit = 1;
938     /* create an ival */
939     sym->ival = newiList(INIT_NODE,newAst_VALUE(val));
940     if (noAlloc == 0) {
941         /* allocate it */
942         addSymChain(sym);
943         allocVariables(sym);
944     }
945     sym->ival = NULL;
946     return symbolVal(sym);
947     
948 }
949
950 /*-----------------------------------------------------------------*/
951 /* processBlockVars - will go thru the ast looking for block if    */
952 /*                    a block is found then will allocate the syms */
953 /*                    will also gather the auto inits present      */
954 /*-----------------------------------------------------------------*/
955 ast *processBlockVars ( ast *tree , int *stack, int action)
956 {
957     if (! tree)
958         return NULL ;
959     
960     /* if this is a block */
961     if (tree->type == EX_OP && tree->opval.op == BLOCK ) {
962         ast *autoInit ;
963         
964         if (action == ALLOCATE) {
965             autoInit = gatherAutoInit (tree->values.sym);
966             *stack += allocVariables (tree->values.sym);
967             
968             /* if there are auto inits then do them */
969             if (autoInit)
970                 tree->left = newNode(NULLOP,autoInit,tree->left);
971         } else /* action is deallocate */
972             deallocLocal (tree->values.sym) ;
973     }
974     
975     processBlockVars (tree->left, stack, action);
976     processBlockVars (tree->right, stack, action);
977     return tree ;
978 }
979
980 /*-----------------------------------------------------------------*/
981 /* constExprValue - returns the value of a constant expression     */
982 /*-----------------------------------------------------------------*/
983 value *constExprValue (ast *cexpr, int check)
984 {
985     cexpr = decorateType(resolveSymbols(cexpr));
986
987     /* if this is not a constant then */
988     if (!IS_LITERAL(cexpr->ftype)) {
989         /* then check if this is a literal array
990            in code segment */
991         if (SPEC_SCLS(cexpr->etype) == S_CODE &&
992             SPEC_CVAL(cexpr->etype).v_char    &&
993             IS_ARRAY(cexpr->ftype)) {
994             value *val = valFromType(cexpr->ftype);
995             SPEC_SCLS(val->etype) = S_LITERAL;
996             val->sym =cexpr->opval.val->sym ; 
997             val->sym->type = copyLinkChain(cexpr->ftype);
998             val->sym->etype = getSpec(val->sym->type);
999             strcpy(val->name,cexpr->opval.val->sym->rname);
1000             return val;
1001         }
1002         
1003         /* if we are casting a literal value then */
1004         if (IS_AST_OP(cexpr)        &&
1005             cexpr->opval.op == CAST &&
1006             IS_LITERAL(cexpr->left->ftype))
1007             return valCastLiteral(cexpr->ftype,
1008                                   floatFromVal(cexpr->left->opval.val));
1009
1010         if (IS_AST_VALUE(cexpr))
1011             return cexpr->opval.val;
1012         
1013         if (check)         
1014             werror(E_CONST_EXPECTED,"found expression");
1015
1016         return NULL ;
1017     }
1018     
1019     /* return the value */
1020     return cexpr->opval.val ;
1021     
1022 }
1023
1024 /*-----------------------------------------------------------------*/
1025 /* isLabelInAst - will return true if a given label is found       */
1026 /*-----------------------------------------------------------------*/
1027 bool isLabelInAst (symbol *label, ast *tree)
1028 {
1029     if (!tree  || IS_AST_VALUE(tree) || IS_AST_LINK(tree))
1030         return FALSE ;
1031
1032     if (IS_AST_OP(tree) &&
1033         tree->opval.op == LABEL &&
1034         isSymbolEqual(AST_SYMBOL(tree->left),label))
1035         return TRUE;
1036
1037     return isLabelInAst(label,tree->right) &&
1038         isLabelInAst(label,tree->left);
1039         
1040 }
1041
1042 /*-----------------------------------------------------------------*/
1043 /* isLoopCountable - return true if the loop count can be determi- */
1044 /* -ned at compile time .                                          */
1045 /*-----------------------------------------------------------------*/
1046 bool isLoopCountable (ast *initExpr, ast *condExpr, ast *loopExpr,
1047                       symbol **sym,ast **init, ast **end) 
1048 {
1049     
1050     /* the loop is considered countable if the following
1051        conditions are true :-
1052
1053        a) initExpr :- <sym> = <const>
1054        b) condExpr :- <sym> < <const1>
1055        c) loopExpr :- <sym> ++ 
1056     */
1057
1058     /* first check the initExpr */
1059     if ( IS_AST_OP(initExpr)       &&
1060          initExpr->opval.op == '=' && /* is assignment */
1061          IS_AST_SYM_VALUE(initExpr->left)) { /* left is a symbol */     
1062         
1063         *sym = AST_SYMBOL(initExpr->left);
1064         *init= initExpr->right;
1065     }
1066     else
1067         return FALSE;
1068     
1069     /* for now the symbol has to be of
1070        integral type */
1071     if (!IS_INTEGRAL((*sym)->type))
1072         return FALSE;
1073
1074     /* now check condExpr */
1075     if (IS_AST_OP(condExpr)) {
1076
1077         switch (condExpr->opval.op) {
1078         case '<':
1079             if (IS_AST_SYM_VALUE(condExpr->left) &&
1080                 isSymbolEqual (*sym,AST_SYMBOL(condExpr->left)) &&
1081                 IS_AST_LIT_VALUE(condExpr->right)) {
1082                 *end = condExpr->right;
1083                 break;
1084             }
1085             return FALSE;
1086             
1087         case '!':
1088             if (IS_AST_OP(condExpr->left) &&
1089                 condExpr->left->opval.op == '>' &&
1090                 IS_AST_LIT_VALUE(condExpr->left->right) &&
1091                 IS_AST_SYM_VALUE(condExpr->left->left)&&
1092                 isSymbolEqual (*sym,AST_SYMBOL(condExpr->left->left))) {
1093                 
1094                 *end = newNode('+', condExpr->left->right,
1095                                newAst_VALUE(constVal("1")));
1096                 break;
1097             }
1098             return FALSE ;
1099             
1100         default:
1101             return FALSE ;
1102         }       
1103         
1104     }          
1105
1106     /* check loop expression is of the form <sym>++ */
1107     if (!IS_AST_OP(loopExpr))
1108         return FALSE ;
1109
1110     /* check if <sym> ++ */
1111     if (loopExpr->opval.op == INC_OP) {
1112                 
1113         if (loopExpr->left) {
1114             /* pre */
1115             if (IS_AST_SYM_VALUE(loopExpr->left) &&
1116                 isSymbolEqual(*sym,AST_SYMBOL(loopExpr->left)))
1117                 return TRUE ;      
1118                 
1119         } else {
1120             /* post */
1121             if (IS_AST_SYM_VALUE(loopExpr->right) &&
1122                 isSymbolEqual(*sym,AST_SYMBOL(loopExpr->right)))
1123                 return TRUE ; 
1124         }
1125             
1126     } 
1127     else {
1128         /* check for += */
1129         if ( loopExpr->opval.op == ADD_ASSIGN ) {
1130
1131             if (IS_AST_SYM_VALUE(loopExpr->left) &&
1132                 isSymbolEqual(*sym,AST_SYMBOL(loopExpr->left)) &&
1133                 IS_AST_LIT_VALUE(loopExpr->right) &&
1134                 (int)AST_LIT_VALUE(loopExpr->right) != 1)
1135                 return TRUE ;
1136         }               
1137     }
1138     
1139     return FALSE;
1140 }
1141
1142 /*-----------------------------------------------------------------*/
1143 /* astHasVolatile - returns true if ast contains any volatile      */
1144 /*-----------------------------------------------------------------*/
1145 bool astHasVolatile (ast *tree)
1146 {
1147     if (!tree)
1148         return FALSE ;
1149
1150     if (TETYPE(tree) && IS_VOLATILE(TETYPE(tree)))
1151         return TRUE;
1152
1153     if (IS_AST_OP(tree))
1154         return astHasVolatile(tree->left) ||
1155             astHasVolatile(tree->right);
1156     else
1157         return FALSE ;
1158 }
1159
1160 /*-----------------------------------------------------------------*/
1161 /* astHasPointer - return true if the ast contains any ptr variable*/
1162 /*-----------------------------------------------------------------*/
1163 bool astHasPointer (ast *tree)
1164 {
1165     if (!tree)
1166         return FALSE ;
1167
1168     if (IS_AST_LINK(tree))
1169         return TRUE;
1170
1171     /* if we hit an array expression then check
1172        only the left side */
1173     if (IS_AST_OP(tree) && tree->opval.op == '[')
1174         return astHasPointer(tree->left);
1175
1176     if (IS_AST_VALUE(tree))
1177             return IS_PTR(tree->ftype) || IS_ARRAY(tree->ftype);
1178
1179     return astHasPointer(tree->left) ||
1180         astHasPointer(tree->right);
1181         
1182 }
1183
1184 /*-----------------------------------------------------------------*/
1185 /* astHasSymbol - return true if the ast has the given symbol      */
1186 /*-----------------------------------------------------------------*/
1187 bool astHasSymbol (ast *tree, symbol *sym)
1188 {
1189     if (!tree || IS_AST_LINK(tree))
1190         return FALSE ;   
1191
1192     if (IS_AST_VALUE(tree)) {
1193         if (IS_AST_SYM_VALUE(tree)) 
1194             return isSymbolEqual(AST_SYMBOL(tree),sym);
1195         else
1196             return FALSE;
1197     }
1198     
1199     return astHasSymbol(tree->left,sym) ||
1200         astHasSymbol(tree->right,sym);
1201 }
1202
1203 /*-----------------------------------------------------------------*/
1204 /* isConformingBody - the loop body has to conform to a set of rules */
1205 /* for the loop to be considered reversible read on for rules      */
1206 /*-----------------------------------------------------------------*/
1207 bool isConformingBody (ast *pbody, symbol *sym, ast *body)
1208 {
1209     
1210     /* we are going to do a pre-order traversal of the
1211        tree && check for the following conditions. (essentially
1212        a set of very shallow tests )
1213        a) the sym passed does not participate in
1214           any arithmetic operation
1215        b) There are no function calls
1216        c) all jumps are within the body 
1217        d) address of loop control variable not taken 
1218        e) if an assignment has a pointer on the
1219           left hand side make sure right does not have
1220           loop control variable */
1221
1222     /* if we reach the end or a leaf then true */
1223     if (!pbody ||  IS_AST_LINK(pbody) || IS_AST_VALUE(pbody))
1224         return TRUE ;
1225
1226
1227     /* if anything else is "volatile" */
1228     if (IS_VOLATILE(TETYPE(pbody)))
1229         return FALSE;
1230
1231     /* we will walk the body in a pre-order traversal for
1232        efficiency sake */
1233     switch (pbody->opval.op) {
1234         /*------------------------------------------------------------------*/
1235     case  '['   :       
1236         return isConformingBody (pbody->right,sym,body);
1237
1238         /*------------------------------------------------------------------*/
1239     case  PTR_OP:  
1240     case  '.'   :  
1241         return TRUE;
1242
1243         /*------------------------------------------------------------------*/
1244     case  INC_OP:  /* incerement operator unary so left only */
1245     case  DEC_OP:
1246         
1247         /* sure we are not sym is not modified */
1248         if (pbody->left                &&
1249             IS_AST_SYM_VALUE(pbody->left) &&
1250             isSymbolEqual(AST_SYMBOL(pbody->left),sym))
1251             return FALSE;
1252
1253         if (pbody->right                &&
1254             IS_AST_SYM_VALUE(pbody->right) &&
1255             isSymbolEqual(AST_SYMBOL(pbody->right),sym))
1256             return FALSE;
1257
1258         return TRUE;
1259
1260         /*------------------------------------------------------------------*/
1261
1262     case '*' :  /* can be unary  : if right is null then unary operation */
1263     case '+' :  
1264     case '-' :  
1265     case  '&':     
1266         
1267         /* if right is NULL then unary operation  */
1268         /*------------------------------------------------------------------*/
1269         /*----------------------------*/
1270         /*  address of                */
1271         /*----------------------------*/    
1272         if ( ! pbody->right ) { 
1273             if (IS_AST_SYM_VALUE(pbody->left) &&
1274                 isSymbolEqual(AST_SYMBOL(pbody->left),sym))
1275                 return FALSE;
1276             else
1277                 return isConformingBody(pbody->left,sym,body) ;
1278         } else {
1279             if (astHasSymbol(pbody->left,sym) ||
1280                 astHasSymbol(pbody->right,sym))
1281                 return FALSE;
1282         }
1283
1284         
1285         /*------------------------------------------------------------------*/
1286     case  '|':
1287     case  '^':
1288     case  '/':
1289     case  '%':
1290     case LEFT_OP:
1291     case RIGHT_OP:
1292         
1293         if (IS_AST_SYM_VALUE(pbody->left) &&
1294             isSymbolEqual(AST_SYMBOL(pbody->left),sym))
1295             return FALSE ;
1296
1297         if (IS_AST_SYM_VALUE(pbody->right) &&
1298             isSymbolEqual(AST_SYMBOL(pbody->right),sym))
1299             return FALSE ;
1300         
1301         return isConformingBody(pbody->left,sym,body) &&
1302             isConformingBody(pbody->right,sym,body);
1303         
1304     case '~' :
1305     case '!' :
1306     case RRC:
1307     case RLC:
1308     case GETHBIT:
1309         if (IS_AST_SYM_VALUE(pbody->left) &&
1310             isSymbolEqual(AST_SYMBOL(pbody->left),sym))
1311             return FALSE;
1312         return isConformingBody (pbody->left,sym,body);
1313         
1314         /*------------------------------------------------------------------*/
1315
1316     case AND_OP:
1317     case OR_OP:
1318     case '>' :
1319     case '<' :
1320     case LE_OP:
1321     case GE_OP:
1322     case EQ_OP:
1323     case NE_OP:
1324     case '?' :
1325     case ':' :
1326     case SIZEOF:  /* evaluate wihout code generation */
1327
1328         return isConformingBody(pbody->left,sym,body) &&
1329             isConformingBody(pbody->right,sym,body);    
1330
1331         /*------------------------------------------------------------------*/
1332     case '=' :
1333
1334         /* if left has a pointer & right has loop
1335            control variable then we cannot */
1336         if (astHasPointer(pbody->left) &&
1337             astHasSymbol (pbody->right,sym))
1338             return FALSE ;
1339         if (astHasVolatile(pbody->left))
1340             return FALSE ;
1341
1342         if (IS_AST_SYM_VALUE(pbody->left) &&
1343             isSymbolEqual(AST_SYMBOL(pbody->left),sym))
1344             return FALSE ;
1345         
1346         if (astHasVolatile(pbody->left))
1347             return FALSE;
1348
1349         return isConformingBody(pbody->left,sym,body) &&
1350             isConformingBody(pbody->right,sym,body);    
1351
1352     case MUL_ASSIGN:
1353     case DIV_ASSIGN:
1354     case AND_ASSIGN:
1355     case OR_ASSIGN:
1356     case XOR_ASSIGN:
1357     case RIGHT_ASSIGN:
1358     case LEFT_ASSIGN:
1359     case SUB_ASSIGN:
1360     case ADD_ASSIGN:
1361             assert("Parser should not have generated this\n");
1362         
1363         /*------------------------------------------------------------------*/
1364         /*----------------------------*/
1365         /*      comma operator        */
1366         /*----------------------------*/        
1367     case ',' :
1368         return isConformingBody(pbody->left,sym,body) &&
1369             isConformingBody(pbody->right,sym,body);    
1370         
1371         /*------------------------------------------------------------------*/
1372         /*----------------------------*/
1373         /*       function call        */
1374         /*----------------------------*/        
1375     case CALL:
1376         return FALSE;
1377
1378         /*------------------------------------------------------------------*/
1379         /*----------------------------*/
1380         /*     return statement       */
1381         /*----------------------------*/        
1382     case RETURN:
1383         return FALSE ;
1384
1385     case GOTO:
1386         if (isLabelInAst (AST_SYMBOL(pbody->left),body))
1387             return TRUE ;
1388         else
1389             return FALSE;
1390     case SWITCH:
1391         if (astHasSymbol(pbody->left,sym))
1392             return FALSE ;
1393
1394     default:
1395         break;
1396     }
1397
1398     return isConformingBody(pbody->left,sym,body) &&
1399         isConformingBody(pbody->right,sym,body);        
1400         
1401     
1402
1403 }
1404
1405 /*-----------------------------------------------------------------*/
1406 /* isLoopReversible - takes a for loop as input && returns true    */
1407 /* if the for loop is reversible. If yes will set the value of     */
1408 /* the loop control var & init value & termination value           */
1409 /*-----------------------------------------------------------------*/
1410 bool isLoopReversible (ast *loop, symbol **loopCntrl, 
1411                        ast **init, ast **end )
1412 {
1413     /* if option says don't do it then don't */
1414     if (optimize.noLoopReverse)
1415         return 0;
1416     /* there are several tests to determine this */
1417        
1418     /* for loop has to be of the form 
1419        for ( <sym> = <const1> ; 
1420              [<sym> < <const2>]  ;
1421              [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
1422              forBody */
1423     if (! isLoopCountable (AST_FOR(loop,initExpr),
1424                            AST_FOR(loop,condExpr),
1425                            AST_FOR(loop,loopExpr),
1426                            loopCntrl,init,end))
1427         return 0;
1428
1429     /* now do some serious checking on the body of the loop
1430      */
1431     
1432     return isConformingBody(loop->left,*loopCntrl,loop->left);
1433
1434 }
1435
1436 /*-----------------------------------------------------------------*/
1437 /* replLoopSym - replace the loop sym by loop sym -1               */
1438 /*-----------------------------------------------------------------*/
1439 static void replLoopSym ( ast *body, symbol *sym)
1440 {
1441     /* reached end */
1442     if (!body || IS_AST_LINK(body))
1443         return ;
1444
1445     if (IS_AST_SYM_VALUE(body)) {
1446         
1447         if (isSymbolEqual(AST_SYMBOL(body),sym)) {
1448             
1449             body->type = EX_OP;
1450             body->opval.op = '-';
1451             body->left = newAst_VALUE(symbolVal(sym));
1452             body->right= newAst_VALUE(constVal("1"));
1453
1454         }
1455             
1456         return;
1457         
1458     }
1459         
1460     replLoopSym(body->left,sym);
1461     replLoopSym(body->right,sym);
1462         
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* reverseLoop - do the actual loop reversal                       */
1467 /*-----------------------------------------------------------------*/
1468 ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end)
1469 {    
1470     ast *rloop ;  
1471         
1472     /* create the following tree 
1473                 <sym> = loopCount ;
1474          for_continue:
1475                 forbody
1476                 <sym> -= 1;
1477                 if (sym) goto for_continue ; 
1478                 <sym> = end */
1479     
1480     /* put it together piece by piece */
1481     rloop = newNode (NULLOP,
1482                      createIf(newAst_VALUE(symbolVal(sym)),
1483                               newNode(GOTO,
1484                                       newAst_VALUE(symbolVal(AST_FOR(loop,continueLabel))),
1485                                       NULL),NULL),
1486                      newNode('=',
1487                              newAst_VALUE(symbolVal(sym)),
1488                              end));
1489
1490     replLoopSym(loop->left, sym);
1491
1492     rloop = newNode(NULLOP,
1493                     newNode('=',
1494                             newAst_VALUE(symbolVal(sym)),
1495                             newNode('-',end,init)),
1496                     createLabel(AST_FOR(loop,continueLabel),
1497                                 newNode(NULLOP,
1498                                         loop->left,
1499                                         newNode(NULLOP,
1500                                                 newNode(SUB_ASSIGN,
1501                                                         newAst_VALUE(symbolVal(sym)),
1502                                                         newAst_VALUE(constVal("1"))),
1503                                                 rloop ))));
1504     
1505     return decorateType(rloop);
1506
1507 }
1508
1509 /*-----------------------------------------------------------------*/
1510 /* decorateType - compute type for this tree also does type cheking*/
1511 /*          this is done bottom up, since type have to flow upwards*/
1512 /*          it also does constant folding, and paramater checking  */
1513 /*-----------------------------------------------------------------*/
1514 ast *decorateType (ast *tree)
1515 {         
1516     int parmNumber ;
1517     sym_link *p;
1518     
1519     if ( ! tree )
1520         return tree ;
1521     
1522     /* if already has type then do nothing */
1523     if ( tree->decorated )
1524         return tree ;
1525     
1526     tree->decorated = 1;
1527     
1528     /* print the line          */
1529     /* if not block & function */
1530     if ( tree->type == EX_OP && 
1531          ( tree->opval.op != FUNCTION  &&
1532            tree->opval.op != BLOCK     &&
1533            tree->opval.op != NULLOP    )) {
1534         filename = tree->filename ;
1535         lineno = tree->lineno ;
1536     }
1537
1538     /* if any child is an error | this one is an error do nothing */
1539     if ( tree->isError ||
1540          ( tree->left && tree->left->isError) ||
1541          ( tree->right && tree->right->isError ))
1542         return tree ;
1543
1544     /*------------------------------------------------------------------*/
1545     /*----------------------------*/
1546     /*   leaf has been reached    */
1547     /*----------------------------*/        
1548     /* if this is of type value */
1549     /* just get the type        */
1550     if ( tree->type == EX_VALUE ) {
1551         
1552         if ( IS_LITERAL(tree->opval.val->etype) ) {
1553             
1554             /* if this is a character array then declare it */
1555             if (IS_ARRAY(tree->opval.val->type))
1556                 tree->opval.val = stringToSymbol(tree->opval.val);
1557             
1558             /* otherwise just copy the type information */
1559             COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.val->type);
1560             if (funcInChain(tree->opval.val->type)) {
1561                     tree->hasVargs = tree->opval.val->sym->hasVargs;
1562                     tree->args = copyValueChain(tree->opval.val->sym->args) ;
1563             }
1564             return tree ;
1565         }
1566         
1567         if ( tree->opval.val->sym ) {
1568             /* if the undefined flag is set then give error message */
1569                 if (tree->opval.val->sym->undefined ) {
1570                   werror(E_ID_UNDEF,tree->opval.val->sym->name) ;
1571                   /* assume int */
1572                   TTYPE(tree) = TETYPE(tree) =
1573                     tree->opval.val->type = tree->opval.val->sym->type = 
1574                     tree->opval.val->etype = tree->opval.val->sym->etype = 
1575                     copyLinkChain(INTTYPE);
1576                 }
1577                 else {
1578                   
1579                   /* if impilicit i.e. struct/union member then no type */
1580                   if (tree->opval.val->sym->implicit )
1581                     TTYPE(tree) = TETYPE(tree) = NULL ;
1582                   
1583                   else { 
1584                     
1585                                 /* else copy the type */
1586                     COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.val->type); 
1587                     
1588                                 /* and mark it as referenced */
1589                     tree->opval.val->sym->isref = 1;
1590                                 /* if this is of type function or function pointer */
1591                     if (funcInChain(tree->opval.val->type)) {
1592                       tree->hasVargs = tree->opval.val->sym->hasVargs;
1593                       tree->args = copyValueChain(tree->opval.val->sym->args) ;
1594                       
1595                     }
1596                   }
1597                 }
1598         }
1599         
1600         return tree ;
1601     }
1602     
1603     /* if type link for the case of cast */
1604     if ( tree->type == EX_LINK ) {
1605         COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.lnk);
1606         return tree ;
1607     } 
1608     
1609     {
1610         ast *dtl, *dtr;
1611         
1612         dtl = decorateType (tree->left);
1613         dtr = decorateType (tree->right);  
1614
1615         /* this is to take care of situations
1616            when the tree gets rewritten */
1617         if (dtl != tree->left)
1618             tree->left = dtl;
1619         if (dtr != tree->right)
1620             tree->right = dtr;
1621     }
1622     
1623     /* depending on type of operator do */
1624     
1625     switch   (tree->opval.op) {
1626         /*------------------------------------------------------------------*/
1627         /*----------------------------*/
1628         /*        array node          */
1629         /*----------------------------*/
1630     case  '['   :  
1631         
1632         /* determine which is the array & which the index */
1633         if ((IS_ARRAY(RTYPE(tree)) || IS_PTR(RTYPE(tree))) && IS_INTEGRAL(LTYPE(tree))) {
1634             
1635             ast *tempTree = tree->left ;
1636             tree->left = tree->right ;
1637             tree->right= tempTree ;
1638         }
1639
1640         /* first check if this is a array or a pointer */
1641         if ( (!IS_ARRAY(LTYPE(tree)))  && (!IS_PTR(LTYPE(tree)))) {
1642             werror(E_NEED_ARRAY_PTR,"[]");
1643             goto errorTreeReturn ;
1644         }       
1645         
1646         /* check if the type of the idx */
1647         if (!IS_INTEGRAL(RTYPE(tree))) {
1648             werror(E_IDX_NOT_INT);
1649             goto errorTreeReturn ;
1650         }
1651         
1652         /* if the left is an rvalue then error */
1653         if (LRVAL(tree)) {
1654             werror(E_LVALUE_REQUIRED,"array access");
1655             goto errorTreeReturn ;
1656         }
1657         RRVAL(tree) = 1;
1658         COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)->next);
1659         return tree;
1660         
1661         /*------------------------------------------------------------------*/
1662         /*----------------------------*/
1663         /*      struct/union          */
1664         /*----------------------------*/   
1665     case  '.'   :  
1666         /* if this is not a structure */
1667         if (!IS_STRUCT(LTYPE(tree))) {
1668             werror(E_STRUCT_UNION,".");
1669             goto errorTreeReturn ;
1670         }
1671         TTYPE(tree) = structElemType (LTYPE(tree), 
1672                                       (tree->right->type == EX_VALUE ?
1673                                        tree->right->opval.val : NULL ),&tree->args);
1674         TETYPE(tree) = getSpec(TTYPE(tree));
1675         return tree ;
1676         
1677         /*------------------------------------------------------------------*/
1678         /*----------------------------*/
1679         /*    struct/union pointer    */
1680         /*----------------------------*/
1681     case  PTR_OP:  
1682         /* if not pointer to a structure */
1683         if (!IS_PTR(LTYPE(tree)))  {
1684             werror(E_PTR_REQD);
1685             goto errorTreeReturn ;
1686         }
1687         
1688         if (!IS_STRUCT(LTYPE(tree)->next))  {
1689             werror(E_STRUCT_UNION,"->");
1690             goto errorTreeReturn ;
1691         }
1692         
1693         TTYPE(tree) = structElemType (LTYPE(tree)->next, 
1694                                       (tree->right->type == EX_VALUE ?
1695                                        tree->right->opval.val : NULL ),&tree->args);
1696         TETYPE(tree) = getSpec(TTYPE(tree));
1697         return tree ;
1698         
1699         /*------------------------------------------------------------------*/
1700         /*----------------------------*/
1701         /*  ++/-- operation           */
1702         /*----------------------------*/
1703     case  INC_OP:  /* incerement operator unary so left only */
1704     case  DEC_OP:
1705         {
1706             sym_link *ltc = (tree->right ? RTYPE(tree) : LTYPE(tree) );
1707             COPYTYPE(TTYPE(tree),TETYPE(tree),ltc);
1708             if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
1709                 werror(E_CODE_WRITE,"++/--");
1710             
1711             if (tree->right)
1712                 RLVAL(tree) = 1;
1713             else
1714                 LLVAL(tree) = 1;
1715             return tree ;
1716         }
1717         
1718         /*------------------------------------------------------------------*/
1719         /*----------------------------*/
1720         /*  bitwise and               */
1721         /*----------------------------*/
1722     case  '&':     /* can be unary   */
1723         /* if right is NULL then unary operation  */
1724         if ( tree->right ) /* not an unary operation */ {
1725             
1726             if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) {
1727                 werror(E_BITWISE_OP);
1728                 werror(E_CONTINUE,"left & right types are ");
1729                 printTypeChain(LTYPE(tree),stderr);
1730                 fprintf(stderr,",");
1731                 printTypeChain(RTYPE(tree),stderr);
1732                 fprintf(stderr,"\n");
1733                 goto errorTreeReturn ;
1734             }
1735             
1736             /* if they are both literal */
1737             if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
1738                 tree->type = EX_VALUE ;
1739                 tree->opval.val = valBitwise (valFromType(LETYPE(tree)),
1740                                               valFromType(RETYPE(tree)),'&');
1741                                        
1742                 tree->right = tree->left = NULL;
1743                 TETYPE(tree) = tree->opval.val->etype ;
1744                 TTYPE(tree) =  tree->opval.val->type;
1745                 return tree ;
1746             }
1747             
1748             /* see if this is a GETHBIT operation if yes
1749                then return that */
1750             {
1751                 ast *otree = optimizeGetHbit(tree);
1752                 
1753                 if (otree != tree)
1754                     return decorateType(otree);
1755             }
1756             
1757             /* if right or left is literal then result of that type*/
1758             if (IS_LITERAL(RTYPE(tree))) {
1759                 
1760                 TTYPE(tree) = copyLinkChain(RTYPE(tree));
1761                 TETYPE(tree) = getSpec(TTYPE(tree));
1762                 SPEC_SCLS(TETYPE(tree)) = S_AUTO;
1763             }
1764             else {
1765                 if (IS_LITERAL(LTYPE(tree))) {              
1766                     TTYPE(tree) = copyLinkChain(LTYPE(tree));
1767                     TETYPE(tree) = getSpec(TTYPE(tree));
1768                     SPEC_SCLS(TETYPE(tree)) = S_AUTO;
1769                     
1770                 }
1771                 else {
1772                     TTYPE(tree) = 
1773                         computeType (LTYPE(tree), RTYPE(tree));
1774                     TETYPE(tree) = getSpec(TTYPE(tree));
1775                 }
1776             }
1777             LRVAL(tree) = RRVAL(tree) = 1;
1778             return tree ;
1779         } 
1780         
1781         /*------------------------------------------------------------------*/
1782         /*----------------------------*/
1783         /*  address of                */
1784         /*----------------------------*/    
1785         p = newLink();
1786         p->class = DECLARATOR;
1787         /* if bit field then error */
1788         if (IS_BITVAR(tree->left->etype)) {
1789             werror (E_ILLEGAL_ADDR,"addrress of bit variable");
1790             goto errorTreeReturn ;
1791         }
1792         
1793         if (SPEC_SCLS(tree->left->etype)== S_REGISTER ) {
1794             werror (E_ILLEGAL_ADDR,"address of register variable");
1795             goto errorTreeReturn;
1796         }
1797         
1798         if (IS_FUNC(LTYPE(tree))) {
1799             werror(E_ILLEGAL_ADDR,"address of function");
1800             goto errorTreeReturn ;
1801         }
1802         
1803         if (LRVAL(tree)) {
1804             werror(E_LVALUE_REQUIRED,"address of");
1805             goto errorTreeReturn ;      
1806         }
1807         if (SPEC_SCLS(tree->left->etype) == S_CODE) {
1808             DCL_TYPE(p) = CPOINTER ;
1809             DCL_PTR_CONST(p) = port->mem.code_ro;
1810         }
1811         else
1812             if (SPEC_SCLS(tree->left->etype) == S_XDATA)
1813                 DCL_TYPE(p) = FPOINTER;
1814             else
1815                 if (SPEC_SCLS(tree->left->etype) == S_XSTACK )
1816                     DCL_TYPE(p) = PPOINTER ;
1817                 else
1818                     if (SPEC_SCLS(tree->left->etype) == S_IDATA)
1819                         DCL_TYPE(p) = IPOINTER ;
1820                     else
1821                         if (SPEC_SCLS(tree->left->etype) == S_EEPROM)
1822                             DCL_TYPE(p) = EEPPOINTER ;
1823                         else
1824                             DCL_TYPE(p) = POINTER ;
1825
1826         if (IS_AST_SYM_VALUE(tree->left)) {
1827             AST_SYMBOL(tree->left)->addrtaken = 1;
1828             AST_SYMBOL(tree->left)->allocreq = 1;
1829         }
1830
1831         p->next = LTYPE(tree);
1832         TTYPE(tree) = p;
1833         TETYPE(tree) = getSpec(TTYPE(tree));
1834         DCL_PTR_CONST(p) = SPEC_CONST(TETYPE(tree));
1835         DCL_PTR_VOLATILE(p) = SPEC_VOLATILE(TETYPE(tree));
1836         LLVAL(tree) = 1;
1837         TLVAL(tree) = 1;
1838         return tree ;
1839         
1840         /*------------------------------------------------------------------*/
1841         /*----------------------------*/
1842         /*  bitwise or                */
1843         /*----------------------------*/
1844     case  '|':
1845         /* if the rewrite succeeds then don't go any furthur */
1846         {
1847             ast *wtree = optimizeRRCRLC ( tree );
1848             if (wtree != tree) 
1849                 return decorateType(wtree) ;
1850         }
1851         /*------------------------------------------------------------------*/
1852         /*----------------------------*/
1853         /*  bitwise xor               */
1854         /*----------------------------*/
1855     case  '^':
1856         if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) {
1857             werror(E_BITWISE_OP);
1858             werror(E_CONTINUE,"left & right types are ");
1859             printTypeChain(LTYPE(tree),stderr);
1860             fprintf(stderr,",");
1861             printTypeChain(RTYPE(tree),stderr);
1862             fprintf(stderr,"\n");
1863             goto errorTreeReturn ;
1864         }
1865         
1866         /* if they are both literal then */
1867         /* rewrite the tree */
1868         if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
1869             tree->type = EX_VALUE ;
1870             tree->opval.val = valBitwise (valFromType(LETYPE(tree)),
1871                                           valFromType(RETYPE(tree)),
1872                                           tree->opval.op);                 
1873             tree->right = tree->left = NULL;
1874             TETYPE(tree) = tree->opval.val->etype;
1875             TTYPE(tree) = tree->opval.val->type;
1876             return tree ;
1877         }
1878         LRVAL(tree) = RRVAL(tree) = 1;
1879         TETYPE(tree) = getSpec (TTYPE(tree) = 
1880                                 computeType(LTYPE(tree),
1881                                             RTYPE(tree)));
1882         
1883         /*------------------------------------------------------------------*/
1884         /*----------------------------*/
1885         /*  division                  */
1886         /*----------------------------*/
1887     case  '/':
1888         if (!IS_ARITHMETIC(LTYPE(tree)) || !IS_ARITHMETIC(RTYPE(tree))) {
1889             werror(E_INVALID_OP,"divide");
1890             goto errorTreeReturn ;
1891         }
1892         /* if they are both literal then */
1893         /* rewrite the tree */
1894         if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
1895             tree->type = EX_VALUE ;
1896             tree->opval.val = valDiv (valFromType(LETYPE(tree)),
1897                                       valFromType(RETYPE(tree)));
1898             tree->right = tree->left = NULL;
1899             TETYPE(tree) = getSpec(TTYPE(tree) = 
1900                                    tree->opval.val->type);
1901             return tree ;
1902         }
1903         LRVAL(tree) = RRVAL(tree) = 1;
1904         TETYPE(tree) = getSpec (TTYPE(tree) = 
1905                                 computeType(LTYPE(tree),
1906                                             RTYPE(tree)));
1907         return tree;
1908         
1909         /*------------------------------------------------------------------*/
1910         /*----------------------------*/
1911         /*            modulus         */
1912         /*----------------------------*/
1913     case  '%':
1914         if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) {
1915             werror(E_BITWISE_OP);
1916             werror(E_CONTINUE,"left & right types are ");
1917             printTypeChain(LTYPE(tree),stderr);
1918             fprintf(stderr,",");
1919             printTypeChain(RTYPE(tree),stderr);
1920             fprintf(stderr,"\n");
1921             goto errorTreeReturn ;
1922         }
1923         /* if they are both literal then */
1924         /* rewrite the tree */
1925         if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
1926             tree->type = EX_VALUE ;
1927             tree->opval.val = valMod (valFromType(LETYPE(tree)),
1928                                       valFromType(RETYPE(tree)));                 
1929             tree->right = tree->left = NULL;
1930             TETYPE(tree) = getSpec(TTYPE(tree) = 
1931                                    tree->opval.val->type);
1932             return tree ;
1933         }
1934         LRVAL(tree) = RRVAL(tree) = 1;
1935         TETYPE(tree) = getSpec (TTYPE(tree) = 
1936                                 computeType(LTYPE(tree),
1937                                             RTYPE(tree)));
1938         return tree;
1939         
1940         /*------------------------------------------------------------------*/
1941         /*----------------------------*/
1942         /*  address dereference       */
1943         /*----------------------------*/
1944     case  '*':     /* can be unary  : if right is null then unary operation */
1945         if ( ! tree->right ) {
1946             if (!IS_PTR(LTYPE(tree)) && !IS_ARRAY(LTYPE(tree))) {
1947                 werror(E_PTR_REQD);
1948                 goto errorTreeReturn ;
1949             }
1950             
1951             if (LRVAL(tree)) {
1952                 werror(E_LVALUE_REQUIRED,"pointer deref");
1953                 goto errorTreeReturn ;  
1954             }
1955             TTYPE(tree) = copyLinkChain ((IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) ? 
1956                                          LTYPE(tree)->next : NULL );
1957             TETYPE(tree) = getSpec(TTYPE(tree));
1958             tree->args = tree->left->args ;
1959             tree->hasVargs = tree->left->hasVargs ;
1960             SPEC_CONST(TETYPE(tree)) = DCL_PTR_CONST(LTYPE(tree));
1961             return tree ;
1962         }
1963         
1964         /*------------------------------------------------------------------*/
1965         /*----------------------------*/
1966         /*      multiplication        */
1967         /*----------------------------*/
1968         if (!IS_ARITHMETIC(LTYPE(tree)) || !IS_ARITHMETIC(RTYPE(tree))) {
1969             werror(E_INVALID_OP,"multiplication");
1970             goto errorTreeReturn ;
1971         }
1972         
1973         /* if they are both literal then */
1974         /* rewrite the tree */
1975         if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
1976             tree->type = EX_VALUE ;
1977             tree->opval.val = valMult (valFromType(LETYPE(tree)),
1978                                        valFromType(RETYPE(tree)));                 
1979             tree->right = tree->left = NULL;
1980             TETYPE(tree) = getSpec(TTYPE(tree) = 
1981                                    tree->opval.val->type);
1982             return tree ;
1983         }
1984
1985         /* if left is a literal exchange left & right */
1986         if (IS_LITERAL(LTYPE(tree))) {
1987             ast *tTree = tree->left ;
1988             tree->left = tree->right ;
1989             tree->right= tTree ;
1990         }
1991                 
1992         LRVAL(tree) = RRVAL(tree) = 1;
1993         TETYPE(tree) = getSpec (TTYPE(tree) = 
1994                                 computeType(LTYPE(tree),
1995                                             RTYPE(tree)));                        
1996         return tree ;
1997         
1998         /*------------------------------------------------------------------*/
1999         /*----------------------------*/
2000         /*    unary '+' operator      */
2001         /*----------------------------*/
2002     case '+' :  
2003         /* if unary plus */
2004         if ( ! tree->right ) {
2005             if (!IS_INTEGRAL(LTYPE(tree))) {
2006                 werror(E_UNARY_OP,'+');
2007                 goto errorTreeReturn ;
2008             }
2009             
2010             /* if left is a literal then do it */
2011             if (IS_LITERAL(LTYPE(tree))) {
2012                 tree->type = EX_VALUE ;
2013                 tree->opval.val = valFromType(LETYPE(tree));          
2014                 tree->left = NULL ;
2015                 TETYPE(tree) = TTYPE(tree) = tree->opval.val->type;
2016                 return tree ;
2017             }
2018             LRVAL(tree) = 1;
2019             COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)); 
2020             return tree ;
2021         }
2022         
2023         /*------------------------------------------------------------------*/
2024         /*----------------------------*/
2025         /*      addition              */
2026         /*----------------------------*/
2027         
2028         /* this is not a unary operation */
2029         /* if both pointers then problem */
2030         if ((IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) &&
2031             (IS_PTR(RTYPE(tree)) || IS_ARRAY(RTYPE(tree)))) {
2032             werror(E_PTR_PLUS_PTR);
2033             goto errorTreeReturn ;
2034         }       
2035
2036         if (!IS_ARITHMETIC(LTYPE(tree)) && 
2037             !IS_PTR(LTYPE(tree)) && !IS_ARRAY(LTYPE(tree))) {
2038             werror(E_PLUS_INVALID,"+");
2039             goto errorTreeReturn ;
2040         }
2041         
2042         if (!IS_ARITHMETIC(RTYPE(tree)) && 
2043             !IS_PTR(RTYPE(tree)) && !IS_ARRAY(RTYPE(tree))) {
2044             werror(E_PLUS_INVALID,"+");
2045             goto errorTreeReturn;
2046         }
2047         /* if they are both literal then */
2048         /* rewrite the tree */
2049         if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
2050             tree->type = EX_VALUE ;
2051             tree->opval.val = valPlus (valFromType(LETYPE(tree)),
2052                                        valFromType(RETYPE(tree))); 
2053             tree->right = tree->left = NULL;
2054             TETYPE(tree) = getSpec(TTYPE(tree) = 
2055                                    tree->opval.val->type);
2056             return tree ;
2057         }
2058         
2059         /* if the right is a pointer or left is a literal 
2060            xchange left & right */
2061         if (IS_ARRAY(RTYPE(tree)) || 
2062             IS_PTR(RTYPE(tree))   || 
2063             IS_LITERAL(LTYPE(tree))) {
2064             ast *tTree = tree->left ;
2065             tree->left = tree->right ;
2066             tree->right= tTree ;
2067         }
2068
2069         LRVAL(tree) = RRVAL(tree) = 1;  
2070         /* if the left is a pointer */
2071         if (IS_PTR(LTYPE(tree)))      
2072             TETYPE(tree) = getSpec(TTYPE(tree) =
2073                                    LTYPE(tree));
2074         else
2075             TETYPE(tree) = getSpec(TTYPE(tree) = 
2076                                    computeType(LTYPE(tree),
2077                                                RTYPE(tree)));
2078         return tree ;
2079         
2080         /*------------------------------------------------------------------*/
2081         /*----------------------------*/
2082         /*      unary '-'             */
2083         /*----------------------------*/
2084     case '-' :  /* can be unary   */
2085         /* if right is null then unary */
2086         if ( ! tree->right ) {
2087             
2088             if (!IS_ARITHMETIC(LTYPE(tree))) {
2089                 werror(E_UNARY_OP,tree->opval.op);
2090                 goto errorTreeReturn ;
2091             }
2092             
2093             /* if left is a literal then do it */
2094             if (IS_LITERAL(LTYPE(tree))) {
2095                 tree->type = EX_VALUE ;
2096                 tree->opval.val = valUnaryPM(valFromType(LETYPE(tree)));
2097                 tree->left = NULL ;
2098                 TETYPE(tree) = TTYPE(tree) = tree->opval.val->type;
2099                 return tree ;
2100             }
2101             LRVAL(tree) = 1;
2102             TTYPE(tree) =  LTYPE(tree); 
2103             return tree ;
2104         }
2105         
2106         /*------------------------------------------------------------------*/
2107         /*----------------------------*/
2108         /*    subtraction             */
2109         /*----------------------------*/
2110         
2111         if (!(IS_PTR(LTYPE(tree)) || 
2112               IS_ARRAY(LTYPE(tree)) || 
2113               IS_ARITHMETIC(LTYPE(tree)))) {
2114             werror(E_PLUS_INVALID,"-");
2115             goto errorTreeReturn ;
2116         }
2117         
2118         if (!(IS_PTR(RTYPE(tree)) || 
2119               IS_ARRAY(RTYPE(tree)) || 
2120               IS_ARITHMETIC(RTYPE(tree)))) {
2121             werror(E_PLUS_INVALID,"-");
2122             goto errorTreeReturn ;
2123         }
2124         
2125         if ( (IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) &&
2126             ! (IS_PTR(RTYPE(tree)) || IS_ARRAY(RTYPE(tree)) || 
2127                IS_INTEGRAL(RTYPE(tree)))   ) {
2128             werror(E_PLUS_INVALID,"-");
2129             goto errorTreeReturn ;
2130         }
2131
2132         /* if they are both literal then */
2133         /* rewrite the tree */
2134         if (IS_LITERAL(RTYPE(tree)) &&  IS_LITERAL(LTYPE(tree))) {
2135             tree->type = EX_VALUE ;
2136             tree->opval.val = valMinus (valFromType(LETYPE(tree)),
2137                                         valFromType(RETYPE(tree)));  
2138             tree->right = tree->left = NULL;
2139             TETYPE(tree) = getSpec(TTYPE(tree) = 
2140                                    tree->opval.val->type);
2141             return tree ;
2142         }
2143         
2144         /* if the left & right are equal then zero */
2145         if (isAstEqual(tree->left,tree->right)) {
2146             tree->type = EX_VALUE;
2147             tree->left = tree->right = NULL;
2148             tree->opval.val = constVal("0");
2149             TETYPE(tree) = TTYPE(tree) = tree->opval.val->type;
2150             return tree;
2151         }
2152
2153         /* if both of them are pointers or arrays then */
2154         /* the result is going to be an integer        */
2155         if (( IS_ARRAY(LTYPE(tree)) || IS_PTR(LTYPE(tree))) &&
2156             ( IS_ARRAY(RTYPE(tree)) || IS_PTR(RTYPE(tree)))) 
2157             TETYPE(tree) = TTYPE(tree) = newIntLink();
2158         else 
2159             /* if only the left is a pointer */
2160             /* then result is a pointer      */
2161             if (IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) 
2162                 TETYPE(tree) = getSpec(TTYPE(tree) =
2163                                        LTYPE(tree));
2164             else
2165                 TETYPE(tree) = getSpec (TTYPE(tree) = 
2166                                         computeType(LTYPE(tree),
2167                                                     RTYPE(tree))); 
2168         LRVAL(tree) = RRVAL(tree) = 1;
2169         return tree ;  
2170         
2171         /*------------------------------------------------------------------*/
2172         /*----------------------------*/
2173         /*    compliment              */
2174         /*----------------------------*/
2175     case '~' :
2176         /* can be only integral type */
2177         if (!IS_INTEGRAL(LTYPE(tree))) {
2178             werror(E_UNARY_OP,tree->opval.op);
2179             goto errorTreeReturn ;
2180         } 
2181         
2182         /* if left is a literal then do it */
2183         if (IS_LITERAL(LTYPE(tree))) {
2184             tree->type = EX_VALUE ;
2185             tree->opval.val = valComplement(valFromType(LETYPE(tree)));     
2186             tree->left = NULL ;
2187             TETYPE(tree) = TTYPE(tree) = tree->opval.val->type;
2188             return tree ;
2189         }
2190         LRVAL(tree) = 1;
2191         COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree));
2192         return tree ;
2193         
2194         /*------------------------------------------------------------------*/
2195         /*----------------------------*/
2196         /*           not              */
2197         /*----------------------------*/
2198     case '!' :
2199         /* can be pointer */
2200         if (!IS_ARITHMETIC(LTYPE(tree)) && 
2201             !IS_PTR(LTYPE(tree))        && 
2202             !IS_ARRAY(LTYPE(tree))) {
2203             werror(E_UNARY_OP,tree->opval.op);
2204             goto errorTreeReturn ;
2205         }
2206         
2207         /* if left is a literal then do it */
2208         if (IS_LITERAL(LTYPE(tree))) {
2209             tree->type = EX_VALUE ;
2210             tree->opval.val = valNot(valFromType(LETYPE(tree)));           
2211             tree->left = NULL ;
2212             TETYPE(tree) = TTYPE(tree) = tree->opval.val->type;
2213             return tree ;
2214         }
2215         LRVAL(tree) = 1;
2216         TTYPE(tree) = TETYPE(tree) = newCharLink();
2217         return tree ;
2218         
2219         /*------------------------------------------------------------------*/
2220         /*----------------------------*/
2221         /*           shift            */
2222         /*----------------------------*/
2223     case RRC:
2224     case RLC:
2225         TTYPE(tree) = LTYPE(tree);
2226         TETYPE(tree) = LETYPE(tree);
2227         return tree ;
2228         
2229     case GETHBIT:
2230         TTYPE(tree) = TETYPE(tree) = newCharLink();       
2231         return tree;
2232
2233     case LEFT_OP:
2234     case RIGHT_OP:
2235         if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(tree->left->etype)) {  
2236             werror(E_SHIFT_OP_INVALID);
2237             werror(E_CONTINUE,"left & right types are ");
2238             printTypeChain(LTYPE(tree),stderr);
2239             fprintf(stderr,",");
2240             printTypeChain(RTYPE(tree),stderr);
2241             fprintf(stderr,"\n");
2242             goto errorTreeReturn ;
2243         }
2244
2245         /* if they are both literal then */
2246         /* rewrite the tree */
2247         if (IS_LITERAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))) {
2248             tree->type = EX_VALUE ;
2249             tree->opval.val = valShift (valFromType(LETYPE(tree)),
2250                                         valFromType(RETYPE(tree)),
2251                                         (tree->opval.op == LEFT_OP ? 1 : 0));             
2252             tree->right = tree->left = NULL;
2253             TETYPE(tree) = getSpec(TTYPE(tree) = 
2254                                    tree->opval.val->type);
2255             return tree ;
2256         }
2257         /* if only the right side is a literal & we are
2258            shifting more than size of the left operand then zero */
2259         if (IS_LITERAL(RTYPE(tree)) && 
2260             ((int)floatFromVal( valFromType(RETYPE(tree)))) >=
2261             (getSize(LTYPE(tree))*8)) {
2262             werror(W_SHIFT_CHANGED, 
2263                    (tree->opval.op == LEFT_OP ? "left" : "right"));
2264             tree->type = EX_VALUE;
2265             tree->left = tree->right = NULL;
2266             tree->opval.val = constVal("0");
2267             TETYPE(tree) = TTYPE(tree) = tree->opval.val->type;
2268             return tree;
2269         }
2270         LRVAL(tree) = RRVAL(tree) = 1;
2271         if (IS_LITERAL(LTYPE(tree)) && !IS_LITERAL(RTYPE(tree))) {          
2272             COPYTYPE(TTYPE(tree),TETYPE(tree),RTYPE(tree));     
2273         } else {
2274             COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree));
2275         }
2276         return tree ;
2277         
2278         /*------------------------------------------------------------------*/
2279         /*----------------------------*/
2280         /*         casting            */
2281         /*----------------------------*/
2282     case CAST:  /* change the type   */
2283         /* cannot cast to an aggregate type */
2284         if (IS_AGGREGATE(LTYPE(tree))) {
2285             werror(E_CAST_ILLEGAL);
2286             goto errorTreeReturn ;
2287         }
2288         
2289         /* if the right is a literal replace the tree */
2290         if (IS_LITERAL(RETYPE(tree)) && !IS_PTR(LTYPE(tree))) {
2291             tree->type = EX_VALUE ;
2292             tree->opval.val = 
2293                 valCastLiteral(LTYPE(tree),
2294                                floatFromVal(valFromType(RETYPE(tree))));
2295             tree->left = NULL;
2296             tree->right = NULL;
2297             TTYPE(tree) = tree->opval.val->type;            
2298         }
2299         else {
2300             TTYPE(tree) = LTYPE(tree);
2301             LRVAL(tree) = 1;
2302         }
2303
2304         TETYPE(tree) = getSpec(TTYPE(tree)); 
2305         
2306         return tree;
2307         
2308         /*------------------------------------------------------------------*/
2309         /*----------------------------*/
2310         /*       logical &&, ||       */
2311         /*----------------------------*/
2312     case AND_OP:
2313     case OR_OP:
2314         /* each must me arithmetic type or be a pointer */
2315         if (!IS_PTR(LTYPE(tree)) && 
2316             !IS_ARRAY(LTYPE(tree)) && 
2317             !IS_INTEGRAL(LTYPE(tree))) {
2318             werror(E_COMPARE_OP);
2319             goto errorTreeReturn ;
2320         }
2321         
2322         if (!IS_PTR(RTYPE(tree)) &&     
2323             !IS_ARRAY(RTYPE(tree)) && 
2324             !IS_INTEGRAL(RTYPE(tree))) {
2325             werror(E_COMPARE_OP);
2326             goto errorTreeReturn ;
2327         }
2328         /* if they are both literal then */
2329         /* rewrite the tree */
2330         if (IS_LITERAL(RTYPE(tree)) &&
2331             IS_LITERAL(LTYPE(tree))) {
2332             tree->type = EX_VALUE ;
2333             tree->opval.val = valLogicAndOr (valFromType(LETYPE(tree)),
2334                                              valFromType(RETYPE(tree)),
2335                                              tree->opval.op);               
2336             tree->right = tree->left = NULL;
2337             TETYPE(tree) = getSpec(TTYPE(tree) = 
2338                                    tree->opval.val->type);
2339             return tree ;
2340         }
2341         LRVAL(tree) = RRVAL(tree) = 1;
2342         TTYPE(tree) = TETYPE(tree) = newCharLink();
2343         return tree ;
2344         
2345         /*------------------------------------------------------------------*/
2346         /*----------------------------*/
2347         /*     comparison operators   */
2348         /*----------------------------*/    
2349     case '>' :
2350     case '<' :
2351     case LE_OP :
2352     case GE_OP :
2353     case EQ_OP :
2354     case NE_OP :
2355         {
2356             ast *lt = optimizeCompare(tree);
2357             
2358             if ( tree != lt )
2359                 return lt;
2360         }
2361
2362         /* if they are pointers they must be castable */
2363         if ( IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree))) {
2364             if (checkType(LTYPE(tree),RTYPE(tree)) == 0) {
2365                 werror(E_COMPARE_OP);
2366                 fprintf(stderr,"comparing type ");
2367                 printTypeChain(LTYPE(tree),stderr);
2368                 fprintf(stderr,"to type ");
2369                 printTypeChain(RTYPE(tree),stderr);
2370                 fprintf(stderr,"\n");
2371                 goto errorTreeReturn ;
2372             }
2373         } 
2374         /* else they should be promotable to one another */
2375         else {
2376             if (!(  ( IS_PTR(LTYPE(tree)) && IS_LITERAL(RTYPE(tree))) ||
2377                     ( IS_PTR(RTYPE(tree)) && IS_LITERAL(LTYPE(tree))))) 
2378                 
2379                 if (checkType (LTYPE(tree),RTYPE(tree)) == 0 ) {
2380                     werror(E_COMPARE_OP);
2381                     fprintf(stderr,"comparing type ");
2382                     printTypeChain(LTYPE(tree),stderr);
2383                     fprintf(stderr,"to type ");
2384                     printTypeChain(RTYPE(tree),stderr);
2385                     fprintf(stderr,"\n");
2386                     goto errorTreeReturn ;
2387                 }
2388         }
2389         
2390         /* if they are both literal then */
2391         /* rewrite the tree */
2392         if (IS_LITERAL(RTYPE(tree)) &&
2393             IS_LITERAL(LTYPE(tree))) {
2394             tree->type = EX_VALUE ;
2395             tree->opval.val = valCompare (valFromType(LETYPE(tree)),
2396                                           valFromType(RETYPE(tree)),
2397                                           tree->opval.op);                 
2398             tree->right = tree->left = NULL;
2399             TETYPE(tree) = getSpec(TTYPE(tree) = 
2400                                    tree->opval.val->type);
2401             return tree ;
2402         }
2403         LRVAL(tree) = RRVAL(tree) = 1;
2404         TTYPE(tree) = TETYPE(tree) = newCharLink();
2405         return tree ;
2406         
2407         /*------------------------------------------------------------------*/
2408         /*----------------------------*/
2409         /*             sizeof         */
2410         /*----------------------------*/    
2411     case SIZEOF :  /* evaluate wihout code generation */
2412         /* change the type to a integer */
2413         tree->type = EX_VALUE;
2414         sprintf(buffer,"%d",(getSize(tree->right->ftype)));
2415         tree->opval.val = constVal(buffer);
2416         tree->right = tree->left = NULL;
2417         TETYPE(tree) = getSpec(TTYPE(tree) = 
2418                                tree->opval.val->type);
2419         return tree;     
2420         
2421         /*------------------------------------------------------------------*/
2422         /*----------------------------*/
2423         /* conditional operator  '?'  */
2424         /*----------------------------*/    
2425     case '?' :
2426         /* the type is one on the left */
2427         TTYPE(tree) = LTYPE(tree);
2428         TETYPE(tree)= getSpec (TTYPE(tree));
2429         return tree ;
2430         
2431     case ':' :
2432         /* if they don't match we have a problem */
2433         if (checkType( LTYPE(tree), RTYPE(tree)) == 0) {
2434             werror(E_TYPE_MISMATCH,"conditional operator"," ");
2435             goto errorTreeReturn ;
2436         }
2437         
2438         TTYPE(tree) = computeType(LTYPE(tree),RTYPE(tree));
2439         TETYPE(tree)= getSpec(TTYPE(tree));
2440         return tree ;
2441         
2442         
2443         /*------------------------------------------------------------------*/
2444         /*----------------------------*/
2445         /*    assignment operators    */
2446         /*----------------------------*/    
2447     case MUL_ASSIGN:
2448     case DIV_ASSIGN:
2449         /* for these it must be both must be integral */
2450         if (!IS_ARITHMETIC(LTYPE(tree)) ||
2451             !IS_ARITHMETIC(RTYPE(tree))) {
2452             werror (E_OPS_INTEGRAL);
2453             goto errorTreeReturn ;
2454         }
2455         RRVAL(tree) = 1;
2456         TETYPE(tree) = getSpec(TTYPE(tree) = LTYPE(tree));
2457
2458         if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
2459             werror(E_CODE_WRITE," ");
2460
2461         if (LRVAL(tree)) {
2462             werror(E_LVALUE_REQUIRED,"*= or /=");
2463             goto errorTreeReturn ;      
2464         }
2465         LLVAL(tree) = 1;
2466         return tree ;
2467
2468     case AND_ASSIGN:
2469     case OR_ASSIGN:
2470     case XOR_ASSIGN:
2471     case RIGHT_ASSIGN:
2472     case LEFT_ASSIGN:
2473         /* for these it must be both must be integral */
2474         if (!IS_INTEGRAL(LTYPE(tree)) ||
2475             !IS_INTEGRAL(RTYPE(tree))) {
2476             werror (E_OPS_INTEGRAL);
2477             goto errorTreeReturn ;
2478         }
2479         RRVAL(tree) = 1;
2480         TETYPE(tree) = getSpec(TTYPE(tree) = LTYPE(tree));
2481
2482         if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
2483             werror(E_CODE_WRITE," ");
2484
2485         if (LRVAL(tree)) {
2486             werror(E_LVALUE_REQUIRED,"&= or |= or ^= or >>= or <<=");
2487             goto errorTreeReturn ;      
2488         }
2489         LLVAL(tree) = 1;
2490         return tree ;
2491         
2492         /*------------------------------------------------------------------*/
2493         /*----------------------------*/
2494         /*    -= operator             */
2495         /*----------------------------*/    
2496     case SUB_ASSIGN:
2497         if (!(IS_PTR(LTYPE(tree))   ||
2498               IS_ARITHMETIC(LTYPE(tree)))) {
2499             werror(E_PLUS_INVALID,"-=");
2500             goto errorTreeReturn ;
2501         }
2502         
2503         if (!(IS_PTR(RTYPE(tree))   ||
2504               IS_ARITHMETIC(RTYPE(tree)))) {
2505             werror(E_PLUS_INVALID,"-=");
2506             goto errorTreeReturn ;
2507         }
2508         RRVAL(tree) = 1;
2509         TETYPE(tree) = getSpec (TTYPE(tree) = 
2510                                 computeType(LTYPE(tree),
2511                                             RTYPE(tree)));  
2512
2513         if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
2514             werror(E_CODE_WRITE," ");
2515
2516         if (LRVAL(tree)) {
2517             werror(E_LVALUE_REQUIRED,"-=");
2518             goto errorTreeReturn ;      
2519         }
2520         LLVAL(tree) = 1;
2521         return tree;
2522         
2523         /*------------------------------------------------------------------*/
2524         /*----------------------------*/
2525         /*          += operator       */
2526         /*----------------------------*/    
2527     case ADD_ASSIGN:
2528         /* this is not a unary operation */
2529         /* if both pointers then problem */
2530         if (IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree)) ) {
2531             werror(E_PTR_PLUS_PTR);
2532             goto errorTreeReturn ;
2533         }
2534         
2535         if (!IS_ARITHMETIC(LTYPE(tree)) && !IS_PTR(LTYPE(tree)))  {
2536             werror(E_PLUS_INVALID,"+=");
2537             goto errorTreeReturn ;
2538         }
2539         
2540         if (!IS_ARITHMETIC(RTYPE(tree)) && !IS_PTR(RTYPE(tree)))  {
2541             werror(E_PLUS_INVALID,"+=");
2542             goto errorTreeReturn;
2543         }
2544         RRVAL(tree) = 1;
2545         TETYPE(tree) = getSpec (TTYPE(tree) = 
2546                                 computeType(LTYPE(tree),
2547                                             RTYPE(tree)));  
2548
2549         if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
2550             werror(E_CODE_WRITE," ");
2551
2552         if (LRVAL(tree)) {
2553             werror(E_LVALUE_REQUIRED,"+=");
2554             goto errorTreeReturn ;      
2555         }
2556
2557         tree->right = decorateType(newNode('+',copyAst(tree->left),tree->right));
2558         tree->opval.op = '=';       
2559         return tree;
2560         
2561         /*------------------------------------------------------------------*/
2562         /*----------------------------*/
2563         /*      straight assignemnt   */
2564         /*----------------------------*/    
2565     case '=' :
2566         /* cannot be an aggregate */
2567         if (IS_AGGREGATE(LTYPE(tree))) {
2568             werror(E_AGGR_ASSIGN);
2569             goto errorTreeReturn;
2570         }
2571             
2572         /* they should either match or be castable */
2573         if (checkType (LTYPE(tree),RTYPE(tree)) == 0) {
2574             werror(E_TYPE_MISMATCH,"assignment"," ");
2575             fprintf(stderr,"type --> '"); 
2576             printTypeChain (RTYPE(tree),stderr); fprintf(stderr,"' ");
2577             fprintf(stderr,"assigned to type --> '"); 
2578             printTypeChain (LTYPE(tree),stderr); fprintf(stderr,"'\n");
2579             goto errorTreeReturn ;
2580         }
2581
2582         /* if the left side of the tree is of type void
2583            then report error */
2584         if (IS_VOID(LTYPE(tree))) {
2585             werror(E_CAST_ZERO);
2586             fprintf(stderr,"type --> '"); 
2587             printTypeChain (RTYPE(tree),stderr); fprintf(stderr,"' ");
2588             fprintf(stderr,"assigned to type --> '"); 
2589             printTypeChain (LTYPE(tree),stderr); fprintf(stderr,"'\n");
2590         }
2591
2592         /* extra checks for pointer types */
2593         if (IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree)) &&
2594             !IS_GENPTR(LTYPE(tree))) {
2595           if (DCL_TYPE(LTYPE(tree)) != DCL_TYPE(RTYPE(tree)))
2596             werror(W_PTR_ASSIGN);
2597         }
2598
2599         TETYPE(tree) = getSpec(TTYPE(tree) = 
2600                                LTYPE(tree));
2601         RRVAL(tree) = 1;
2602         LLVAL(tree) = 1;
2603         if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
2604             werror(E_CODE_WRITE," ");
2605
2606         if (LRVAL(tree)) {
2607             werror(E_LVALUE_REQUIRED,"=");
2608             goto errorTreeReturn ;      
2609         }
2610
2611         return tree ;
2612         
2613         /*------------------------------------------------------------------*/
2614         /*----------------------------*/
2615         /*      comma operator        */
2616         /*----------------------------*/        
2617     case ',' :
2618         TETYPE(tree) = getSpec(TTYPE(tree) =  RTYPE(tree));
2619         return tree ;    
2620         
2621         /*------------------------------------------------------------------*/
2622         /*----------------------------*/
2623         /*       function call        */
2624         /*----------------------------*/        
2625     case CALL   :
2626         parmNumber = 1;
2627
2628
2629         if (processParms (tree->left,
2630                           tree->left->args,
2631                           tree->right,&parmNumber)) 
2632             goto errorTreeReturn ;    
2633
2634         if (options.stackAuto || IS_RENT(LETYPE(tree))) {
2635                 tree->left->args = reverseVal(tree->left->args); 
2636                 reverseParms(tree->right);
2637         }
2638
2639         tree->args = tree->left->args ;
2640         TETYPE(tree) = getSpec (TTYPE(tree) = LTYPE(tree)->next);
2641         return tree;
2642
2643         /*------------------------------------------------------------------*/
2644         /*----------------------------*/
2645         /*     return statement       */
2646         /*----------------------------*/        
2647     case RETURN :
2648         if (!tree->right)
2649             goto voidcheck ;
2650
2651         if (checkType(currFunc->type->next,RTYPE(tree)) == 0) {
2652             werror(E_RETURN_MISMATCH);
2653             goto errorTreeReturn ;
2654         }
2655
2656         if (IS_VOID(currFunc->type->next) 
2657             && tree->right && 
2658             !IS_VOID(RTYPE(tree))) {
2659             werror(E_FUNC_VOID);
2660             goto errorTreeReturn ;
2661         }
2662         
2663         /* if there is going to be a casing required then add it */
2664         if (checkType(currFunc->type->next,RTYPE(tree)) < 0 ) {
2665             tree->right = 
2666                 decorateType(newNode(CAST,
2667                                      newAst_LINK(copyLinkChain(currFunc->type->next)),
2668                                      tree->right));
2669         }
2670         
2671         RRVAL(tree) = 1;
2672         return tree;
2673
2674         voidcheck :
2675
2676         if (!IS_VOID(currFunc->type->next) && tree->right == NULL ) {
2677             werror(E_VOID_FUNC,currFunc->name);
2678             goto errorTreeReturn ;
2679         }               
2680
2681         TTYPE(tree) = TETYPE(tree) = NULL ;
2682         return tree ;    
2683
2684         /*------------------------------------------------------------------*/
2685         /*----------------------------*/
2686         /*     switch statement       */
2687         /*----------------------------*/        
2688     case SWITCH:
2689         /* the switch value must be an integer */
2690         if (!IS_INTEGRAL(LTYPE(tree))) {
2691             werror (E_SWITCH_NON_INTEGER);
2692             goto errorTreeReturn ;
2693         }
2694         LRVAL(tree) = 1;
2695         TTYPE(tree) = TETYPE(tree) = NULL ;
2696         return tree ;
2697
2698         /*------------------------------------------------------------------*/
2699         /*----------------------------*/
2700         /* ifx Statement              */
2701         /*----------------------------*/
2702     case IFX:
2703         tree->left = backPatchLabels(tree->left,
2704                                      tree->trueLabel,
2705                                      tree->falseLabel);
2706         TTYPE(tree) = TETYPE(tree) = NULL;
2707         return tree;
2708
2709         /*------------------------------------------------------------------*/
2710         /*----------------------------*/
2711         /* for Statement              */
2712         /*----------------------------*/
2713     case FOR:              
2714
2715         decorateType(resolveSymbols(AST_FOR(tree,initExpr)));
2716         decorateType(resolveSymbols(AST_FOR(tree,condExpr)));
2717         decorateType(resolveSymbols(AST_FOR(tree,loopExpr)));
2718         
2719         /* if the for loop is reversible then 
2720            reverse it otherwise do what we normally
2721            do */
2722         {
2723             symbol *sym ;
2724             ast *init, *end;
2725
2726             if (isLoopReversible (tree,&sym,&init,&end))
2727                 return reverseLoop (tree,sym,init,end);
2728             else
2729                 return decorateType(createFor ( AST_FOR(tree,trueLabel), 
2730                                                 AST_FOR(tree,continueLabel) ,
2731                                                 AST_FOR(tree,falseLabel) ,
2732                                                 AST_FOR(tree,condLabel)  ,
2733                                                 AST_FOR(tree,initExpr)   , 
2734                                                 AST_FOR(tree,condExpr)   , 
2735                                                 AST_FOR(tree,loopExpr),
2736                                                 tree->left ) );
2737         }
2738     default :
2739         TTYPE(tree) = TETYPE(tree) = NULL ;
2740         return tree ;    
2741     }
2742     
2743     /* some error found this tree will be killed */
2744     errorTreeReturn :     
2745         TTYPE(tree) = TETYPE(tree) = newCharLink();
2746     tree->opval.op = NULLOP ;
2747     tree->isError = 1;
2748     
2749     return tree ;
2750 }
2751
2752 /*-----------------------------------------------------------------*/
2753 /* sizeofOp - processes size of operation                          */
2754 /*-----------------------------------------------------------------*/
2755 value  *sizeofOp( sym_link  *type)
2756 {
2757         char buff[10];
2758
2759         /* get the size and convert it to character  */
2760         sprintf (buff,"%d", getSize(type));
2761
2762         /* now convert into value  */
2763         return  constVal (buff);      
2764 }
2765
2766
2767 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
2768 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
2769 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
2770 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
2771 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
2772 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
2773 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
2774
2775 /*-----------------------------------------------------------------*/
2776 /* backPatchLabels - change and or not operators to flow control    */
2777 /*-----------------------------------------------------------------*/
2778 ast *backPatchLabels (ast *tree, symbol *trueLabel, symbol *falseLabel )
2779 {  
2780     
2781     if ( ! tree )
2782         return NULL ;
2783     
2784     if ( ! (IS_ANDORNOT(tree)))
2785         return tree ;
2786     
2787     /* if this an and */
2788     if (IS_AND(tree)) {
2789         static int localLbl = 0 ;
2790         symbol *localLabel ;
2791         
2792         sprintf (buffer,"_and_%d",localLbl++);
2793         localLabel = newSymbol(buffer,NestLevel);
2794         
2795         tree->left = backPatchLabels (tree->left, localLabel,falseLabel);    
2796         
2797         /* if left is already a IFX then just change the if true label in that */
2798         if (!IS_IFX(tree->left)) 
2799             tree->left = newIfxNode(tree->left,localLabel,falseLabel);
2800         
2801         tree->right = backPatchLabels(tree->right,trueLabel,falseLabel);    
2802         /* right is a IFX then just join */
2803         if (IS_IFX(tree->right))
2804             return newNode(NULLOP,tree->left,createLabel(localLabel,tree->right));
2805         
2806         tree->right = createLabel(localLabel,tree->right);
2807         tree->right = newIfxNode(tree->right,trueLabel,falseLabel);
2808         
2809         return newNode(NULLOP,tree->left,tree->right);
2810     }
2811     
2812     /* if this is an or operation */
2813     if (IS_OR(tree)) {
2814         static int localLbl = 0 ;
2815         symbol *localLabel ;
2816         
2817         sprintf (buffer,"_or_%d",localLbl++);
2818         localLabel = newSymbol(buffer,NestLevel);
2819         
2820         tree->left = backPatchLabels (tree->left, trueLabel,localLabel);    
2821         
2822         /* if left is already a IFX then just change the if true label in that */
2823         if (!IS_IFX(tree->left))                
2824             tree->left = newIfxNode(tree->left,trueLabel,localLabel);
2825         
2826         tree->right = backPatchLabels(tree->right,trueLabel,falseLabel);    
2827         /* right is a IFX then just join */
2828         if (IS_IFX(tree->right))
2829             return newNode(NULLOP,tree->left,createLabel(localLabel,tree->right));
2830         
2831         tree->right = createLabel(localLabel,tree->right);
2832         tree->right = newIfxNode(tree->right,trueLabel,falseLabel);
2833         
2834         return newNode(NULLOP,tree->left,tree->right);
2835     }
2836     
2837     /* change not */
2838     if (IS_NOT(tree)) {
2839         int wasnot = IS_NOT(tree->left);
2840         tree->left = backPatchLabels (tree->left,falseLabel,trueLabel);
2841         
2842         /* if the left is already a IFX */
2843         if ( ! IS_IFX(tree->left) ) 
2844             tree->left = newNode (IFX,tree->left,NULL);
2845         
2846         if (wasnot) {
2847             tree->left->trueLabel = trueLabel ;
2848             tree->left->falseLabel= falseLabel ;
2849         } else {
2850             tree->left->trueLabel = falseLabel ;
2851             tree->left->falseLabel= trueLabel ;
2852         }
2853         return tree->left ;
2854     }
2855     
2856     if (IS_IFX(tree)) {
2857         tree->trueLabel = trueLabel ;
2858         tree->falseLabel= falseLabel;
2859     }
2860     
2861     return tree ;    
2862 }
2863
2864
2865 /*-----------------------------------------------------------------*/
2866 /* createBlock - create expression tree for block                  */
2867 /*-----------------------------------------------------------------*/
2868 ast  *createBlock   ( symbol *decl,   ast  *body )
2869 {
2870     ast *ex ;
2871     
2872     /* if the block has nothing */
2873     if (!body)
2874         return NULL;
2875
2876     ex = newNode(BLOCK,NULL,body);
2877     ex->values.sym = decl ;
2878     
2879     ex->right = ex->right ;
2880     ex->level++ ;
2881     ex->lineno = 0 ;
2882     return ex;
2883 }
2884
2885 /*-----------------------------------------------------------------*/
2886 /* createLabel - creates the expression tree for labels            */
2887 /*-----------------------------------------------------------------*/
2888 ast  *createLabel  ( symbol  *label,  ast  *stmnt  )
2889 {
2890     symbol *csym;
2891     char        name[SDCC_NAME_MAX+1];
2892     ast   *rValue ;
2893     
2894     /* must create fresh symbol if the symbol name  */
2895     /* exists in the symbol table, since there can  */
2896     /* be a variable with the same name as the labl */
2897     if ((csym = findSym (SymbolTab,NULL,label->name)) &&
2898         (csym->level == label->level))
2899         label = newSymbol(label->name,label->level);
2900     
2901     /* change the name before putting it in add _*/
2902     sprintf (name,"%s",label->name);
2903     
2904     /* put the label in the LabelSymbol table    */
2905     /* but first check if a label of the same    */
2906     /* name exists                               */
2907     if ( (csym = findSym(LabelTab,NULL,name)))
2908         werror(E_DUPLICATE_LABEL,label->name);
2909     else
2910         addSym (LabelTab, label, name,label->level,0);
2911     
2912     label->islbl = 1;
2913     label->key = labelKey++ ;
2914     rValue =  newNode (LABEL,newAst_VALUE(symbolVal(label)),stmnt);  
2915     rValue->lineno = 0;
2916     
2917     return rValue ;
2918 }
2919
2920 /*-----------------------------------------------------------------*/
2921 /* createCase - generates the parsetree for a case statement       */
2922 /*-----------------------------------------------------------------*/
2923 ast  *createCase (ast *swStat, ast *caseVal, ast *stmnt   )
2924 {
2925     char caseLbl[SDCC_NAME_MAX+1];
2926     ast *rexpr;
2927     value *val;
2928     
2929     /* if the switch statement does not exist */
2930     /* then case is out of context            */
2931     if (!swStat) {
2932         werror(E_CASE_CONTEXT);
2933         return NULL ;
2934     }
2935     
2936     caseVal = decorateType(resolveSymbols(caseVal));
2937     /* if not a constant then error  */
2938     if (!IS_LITERAL(caseVal->ftype)) {
2939         werror(E_CASE_CONSTANT);
2940         return NULL ;
2941     }
2942     
2943     /* if not a integer than error */
2944     if (!IS_INTEGRAL(caseVal->ftype)) {
2945         werror(E_CASE_NON_INTEGER);
2946         return NULL;
2947     }
2948
2949     /* find the end of the switch values chain   */
2950     if (!(val = swStat->values.switchVals.swVals))
2951         swStat->values.switchVals.swVals = caseVal->opval.val ;
2952     else {
2953         /* also order the cases according to value */
2954         value *pval = NULL;
2955         int cVal = (int) floatFromVal(caseVal->opval.val);
2956         while (val && (int) floatFromVal(val) < cVal) {
2957             pval = val;
2958             val = val->next ;
2959         }
2960        
2961         /* if we reached the end then */
2962         if (!val) {
2963             pval->next =  caseVal->opval.val;
2964         } else {
2965             /* we found a value greater than */
2966             /* the current value we must add this */
2967             /* before the value */
2968             caseVal->opval.val->next = val;
2969
2970             /* if this was the first in chain */
2971             if (swStat->values.switchVals.swVals == val)
2972                 swStat->values.switchVals.swVals = 
2973                     caseVal->opval.val;
2974             else
2975                 pval->next =  caseVal->opval.val;
2976         }
2977             
2978     }
2979     
2980     /* create the case label   */
2981     sprintf(caseLbl,"_case_%d_%d",
2982             swStat->values.switchVals.swNum,
2983             (int) floatFromVal(caseVal->opval.val));
2984     
2985     rexpr = createLabel(newSymbol(caseLbl,0),stmnt);
2986     rexpr->lineno = 0;
2987     return rexpr;
2988 }
2989
2990 /*-----------------------------------------------------------------*/
2991 /* createDefault - creates the parse tree for the default statement*/
2992 /*-----------------------------------------------------------------*/
2993 ast  *createDefault (ast *swStat, ast *stmnt)
2994 {
2995     char  defLbl[SDCC_NAME_MAX+1];
2996     
2997     /* if the switch statement does not exist */
2998     /* then case is out of context            */
2999     if (!swStat) {
3000         werror(E_CASE_CONTEXT);
3001         return NULL ;
3002     }
3003     
3004     /* turn on the default flag   */
3005     swStat->values.switchVals.swDefault = 1   ;
3006     
3007     /* create the label  */
3008     sprintf (defLbl,"_default_%d",swStat->values.switchVals.swNum);
3009     return createLabel(newSymbol(defLbl,0),stmnt);   
3010 }
3011
3012 /*-----------------------------------------------------------------*/
3013 /* createIf - creates the parsetree for the if statement           */
3014 /*-----------------------------------------------------------------*/
3015 ast *createIf ( ast *condAst, ast *ifBody, ast *elseBody )
3016 {
3017     static int Lblnum = 0 ;
3018     ast *ifTree ;
3019     symbol *ifTrue , *ifFalse, *ifEnd ;
3020     
3021     /* if neither exists */
3022     if (! elseBody && !ifBody)
3023         return condAst ;
3024     
3025     /* create the labels */
3026     sprintf (buffer,"_iffalse_%d",Lblnum);
3027     ifFalse = newSymbol (buffer,NestLevel);
3028     /* if no else body then end == false */
3029     if ( ! elseBody ) 
3030         ifEnd = ifFalse ;
3031     else {
3032         sprintf (buffer,"_ifend_%d",Lblnum);
3033         ifEnd = newSymbol (buffer,NestLevel);
3034     }
3035
3036     sprintf (buffer,"_iftrue_%d",Lblnum);
3037     ifTrue = newSymbol (buffer,NestLevel);
3038         
3039     Lblnum++ ;
3040
3041     /* attach the ifTrue label to the top of it body */
3042     ifBody = createLabel(ifTrue,ifBody);
3043     /* attach a goto end to the ifBody if else is present */
3044     if ( elseBody ) {
3045         ifBody = newNode(NULLOP,ifBody,
3046                          newNode(GOTO,
3047                                  newAst_VALUE(symbolVal(ifEnd)),
3048                                  NULL));
3049         /* put the elseLabel on the else body */
3050         elseBody = createLabel (ifFalse,elseBody);
3051         /* out the end at the end of the body */
3052         elseBody = newNode(NULLOP,
3053                            elseBody,
3054                            createLabel(ifEnd,NULL));
3055     }
3056     else {
3057         ifBody = newNode(NULLOP,ifBody,
3058                          createLabel(ifFalse,NULL));
3059     }
3060     condAst = backPatchLabels (condAst,ifTrue,ifFalse);
3061     if (IS_IFX(condAst))
3062         ifTree = condAst;
3063     else 
3064         ifTree = newIfxNode(condAst,ifTrue,ifFalse);
3065     
3066     return newNode(NULLOP,ifTree,
3067                    newNode(NULLOP,ifBody,elseBody));
3068     
3069 }
3070
3071 /*-----------------------------------------------------------------*/
3072 /* createDo - creates parse tree for do                            */
3073 /*        _dobody_n:                                               */
3074 /*            statements                                           */
3075 /*        _docontinue_n:                                           */
3076 /*            condition_expression +-> trueLabel -> _dobody_n      */
3077 /*                                 |                               */
3078 /*                                 +-> falseLabel-> _dobreak_n     */
3079 /*        _dobreak_n:                                              */
3080 /*-----------------------------------------------------------------*/
3081 ast *createDo ( symbol *trueLabel, symbol *continueLabel,
3082                 symbol *falseLabel, ast *condAst, ast *doBody )
3083 {
3084     ast *doTree ;
3085     
3086     
3087     /* if the body does not exist then it is simple */
3088     if ( ! doBody ) {
3089         condAst = backPatchLabels(condAst,continueLabel,NULL);
3090         doTree = (IS_IFX(condAst) ? createLabel(continueLabel,condAst) 
3091                   : newNode(IFX,createLabel(continueLabel,condAst),NULL));
3092         doTree->trueLabel = continueLabel ;
3093         doTree->falseLabel= NULL ;
3094         return doTree ;
3095     }
3096     
3097     /* otherwise we have a body */
3098     condAst = backPatchLabels(condAst,trueLabel,falseLabel);
3099     
3100     /* attach the body label to the top */
3101     doBody = createLabel(trueLabel,doBody);
3102     /* attach the continue label to end of body */
3103     doBody = newNode(NULLOP, doBody, 
3104                      createLabel(continueLabel,NULL));
3105     
3106     /* now put the break label at the end */
3107     if (IS_IFX(condAst))
3108         doTree = condAst;
3109     else 
3110         doTree = newIfxNode(condAst,trueLabel,falseLabel);
3111     
3112     doTree = newNode(NULLOP,doTree,createLabel(falseLabel,NULL));
3113     
3114     /* putting it together */
3115     return newNode(NULLOP,doBody,doTree);
3116 }
3117
3118 /*-----------------------------------------------------------------*/
3119 /* createFor - creates parse tree for 'for' statement              */
3120 /*        initExpr                                                 */
3121 /*   _forcond_n:                                                   */
3122 /*        condExpr  +-> trueLabel -> _forbody_n                    */
3123 /*                  |                                              */
3124 /*                  +-> falseLabel-> _forbreak_n                   */
3125 /*   _forbody_n:                                                   */
3126 /*        statements                                               */
3127 /*   _forcontinue_n:                                               */
3128 /*        loopExpr                                                 */
3129 /*        goto _forcond_n ;                                        */
3130 /*   _forbreak_n:                                                  */
3131 /*-----------------------------------------------------------------*/
3132 ast *createFor ( symbol *trueLabel, symbol *continueLabel ,
3133                  symbol *falseLabel,symbol *condLabel     ,
3134                  ast *initExpr, ast *condExpr, ast *loopExpr,
3135                  ast *forBody )
3136 {
3137     ast *forTree ;      
3138
3139     /* if loopexpression not present then we can generate it */
3140     /* the same way as a while */
3141     if ( ! loopExpr ) 
3142         return newNode(NULLOP,initExpr,
3143                        createWhile (trueLabel, continueLabel, 
3144                                     falseLabel,condExpr, forBody ));
3145     /* vanilla for statement */
3146     condExpr = backPatchLabels(condExpr,trueLabel,falseLabel);
3147     
3148     if (condExpr && !IS_IFX(condExpr)) 
3149         condExpr = newIfxNode(condExpr,trueLabel,falseLabel);
3150     
3151     
3152     /* attach condition label to condition */
3153     condExpr = createLabel(condLabel,condExpr);
3154     
3155     /* attach body label to body */
3156     forBody = createLabel(trueLabel,forBody);
3157     
3158     /* attach continue to forLoop expression & attach */
3159     /* goto the forcond @ and of loopExpression       */
3160     loopExpr = createLabel(continueLabel,
3161                            newNode(NULLOP,
3162                                    loopExpr,
3163                                    newNode(GOTO,
3164                                            newAst_VALUE(symbolVal(condLabel)),
3165                                            NULL)));
3166     /* now start putting them together */
3167     forTree = newNode(NULLOP,initExpr,condExpr);
3168     forTree = newNode(NULLOP,forTree,forBody);
3169     forTree = newNode(NULLOP,forTree,loopExpr);
3170     /* finally add the break label */
3171     forTree = newNode(NULLOP,forTree,
3172                       createLabel(falseLabel,NULL));
3173     return forTree ;
3174 }
3175
3176 /*-----------------------------------------------------------------*/
3177 /* createWhile - creates parse tree for while statement            */
3178 /*               the while statement will be created as follows    */
3179 /*                                                                 */
3180 /*      _while_continue_n:                                         */
3181 /*            condition_expression +-> trueLabel -> _while_boby_n  */
3182 /*                                 |                               */
3183 /*                                 +-> falseLabel -> _while_break_n*/
3184 /*      _while_body_n:                                             */
3185 /*            statements                                           */
3186 /*            goto _while_continue_n                               */
3187 /*      _while_break_n:                                            */
3188 /*-----------------------------------------------------------------*/
3189 ast *createWhile (symbol *trueLabel, symbol *continueLabel, 
3190                    symbol *falseLabel,ast *condExpr, ast *whileBody )
3191 {
3192     ast *whileTree ;
3193         
3194     /* put the continue label */
3195     condExpr = backPatchLabels (condExpr,trueLabel,falseLabel);
3196     condExpr = createLabel(continueLabel,condExpr);
3197     condExpr->lineno = 0;
3198     
3199     /* put the body label in front of the body */
3200     whileBody = createLabel(trueLabel,whileBody);
3201     whileBody->lineno = 0;
3202     /* put a jump to continue at the end of the body */
3203     /* and put break label at the end of the body */
3204     whileBody = newNode(NULLOP,
3205                         whileBody,
3206                         newNode(GOTO,
3207                                 newAst_VALUE(symbolVal(continueLabel)),
3208                                 createLabel(falseLabel,NULL)));
3209     
3210     /* put it all together */
3211     if ( IS_IFX(condExpr) )
3212         whileTree = condExpr ;
3213     else {
3214         whileTree = newNode (IFX, condExpr,NULL );      
3215         /* put the true & false labels in place */
3216         whileTree->trueLabel = trueLabel ;
3217         whileTree->falseLabel= falseLabel;
3218     }
3219     
3220     return newNode(NULLOP,whileTree,whileBody );
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* optimizeGetHbit - get highest order bit of the expression       */
3225 /*-----------------------------------------------------------------*/
3226 ast *optimizeGetHbit (ast *tree)
3227 {
3228     int i,j;
3229     /* if this is not a bit and */
3230     if (!IS_BITAND(tree))
3231         return tree;
3232     
3233     /* will look for tree of the form
3234        ( expr >> ((sizeof expr) -1) ) & 1 */
3235     if (!IS_AST_LIT_VALUE(tree->right))
3236         return tree;
3237
3238     if (AST_LIT_VALUE(tree->right) != 1)
3239         return tree;
3240
3241     if (!IS_RIGHT_OP(tree->left))
3242         return tree;
3243
3244     if (!IS_AST_LIT_VALUE(tree->left->right))
3245         return tree;
3246
3247     if ((i = AST_LIT_VALUE(tree->left->right)) !=
3248         ( j = (getSize(TTYPE(tree->left->left))*8 - 1)))
3249         return tree;
3250
3251     return decorateType(newNode(GETHBIT,tree->left->left,NULL));
3252         
3253 }
3254
3255 /*-----------------------------------------------------------------*/
3256 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
3257 /*-----------------------------------------------------------------*/
3258 ast *optimizeRRCRLC ( ast *root )
3259 {
3260     /* will look for trees of the form
3261        (?expr << 1) | (?expr >> 7) or
3262        (?expr >> 7) | (?expr << 1) will make that
3263        into a RLC : operation ..
3264        Will also look for 
3265        (?expr >> 1) | (?expr << 7) or
3266        (?expr << 7) | (?expr >> 1) will make that
3267        into a RRC operation 
3268        note : by 7 I mean (number of bits required to hold the
3269        variable -1 ) */
3270     /* if the root operations is not a | operation the not */
3271     if (!IS_BITOR(root))
3272         return root ;
3273
3274     /* I have to think of a better way to match patterns this sucks */
3275     /* that aside let start looking for the first case : I use a the
3276        negative check a lot to improve the efficiency */
3277     /* (?expr << 1) | (?expr >> 7) */
3278     if (IS_LEFT_OP(root->left)    && 
3279         IS_RIGHT_OP(root->right)  ) {   
3280         
3281         if (!SPEC_USIGN(TETYPE(root->left->left)))
3282             return root;
3283
3284         if (!IS_AST_LIT_VALUE(root->left->right) ||
3285             !IS_AST_LIT_VALUE(root->right->right))
3286             goto tryNext0;
3287
3288         /* make sure it is the same expression */
3289         if (!isAstEqual(root->left->left,
3290                         root->right->left))
3291             goto tryNext0;
3292         
3293         if (AST_LIT_VALUE(root->left->right) != 1 )
3294             goto tryNext0 ;
3295         
3296         if (AST_LIT_VALUE(root->right->right) !=
3297             (getSize(TTYPE(root->left->left))*8 - 1))
3298             goto tryNext0 ;
3299
3300         /* whew got the first case : create the AST */
3301         return  newNode(RLC,root->left->left,NULL);     
3302     }
3303
3304  tryNext0:
3305     /* check for second case */
3306     /* (?expr >> 7) | (?expr << 1) */
3307     if (IS_LEFT_OP(root->right)    && 
3308         IS_RIGHT_OP(root->left)  ) {     
3309
3310         if (!SPEC_USIGN(TETYPE(root->left->left)))
3311             return root;
3312         
3313         if (!IS_AST_LIT_VALUE(root->left->right) ||
3314             !IS_AST_LIT_VALUE(root->right->right))
3315             goto tryNext1 ;
3316         
3317         /* make sure it is the same symbol */
3318         if (!isAstEqual(root->left->left,
3319                         root->right->left))
3320             goto tryNext1 ;
3321         
3322         if (AST_LIT_VALUE(root->right->right) != 1 )
3323             goto tryNext1 ;
3324         
3325         if (AST_LIT_VALUE(root->left->right) !=
3326             (getSize(TTYPE(root->left->left))*8 - 1))
3327             goto tryNext1 ;
3328
3329         /* whew got the first case : create the AST */
3330         return  newNode(RLC,root->left->left,NULL);
3331         
3332     }
3333
3334  tryNext1:
3335     /* third case for RRC */
3336     /*  (?symbol >> 1) | (?symbol << 7) */
3337     if (IS_LEFT_OP(root->right)    && 
3338         IS_RIGHT_OP(root->left)  ) {    
3339
3340         if (!SPEC_USIGN(TETYPE(root->left->left)))
3341             return root;
3342         
3343         if (!IS_AST_LIT_VALUE(root->left->right) ||
3344             !IS_AST_LIT_VALUE(root->right->right))
3345             goto tryNext2;
3346         
3347         /* make sure it is the same symbol */
3348         if (!isAstEqual(root->left->left,
3349                         root->right->left))
3350             goto tryNext2;
3351         
3352         if (AST_LIT_VALUE(root->left->right) != 1 )
3353             goto tryNext2;
3354         
3355         if (AST_LIT_VALUE(root->right->right) !=
3356             (getSize(TTYPE(root->left->left))*8 - 1))
3357             goto tryNext2;
3358
3359         /* whew got the first case : create the AST */
3360         return newNode(RRC,root->left->left,NULL);
3361         
3362     }
3363  tryNext2:
3364     /* fourth and last case for now */
3365     /* (?symbol << 7) | (?symbol >> 1) */
3366     if (IS_RIGHT_OP(root->right)    && 
3367         IS_LEFT_OP(root->left)  ) {     
3368
3369         if (!SPEC_USIGN(TETYPE(root->left->left)))
3370             return root;
3371         
3372         if (!IS_AST_LIT_VALUE(root->left->right) ||
3373             !IS_AST_LIT_VALUE(root->right->right))
3374             return root;
3375
3376         /* make sure it is the same symbol */
3377         if (!isAstEqual(root->left->left,
3378                         root->right->left))
3379             return root;
3380         
3381         if (AST_LIT_VALUE(root->right->right) != 1 )
3382             return root ;
3383         
3384         if (AST_LIT_VALUE(root->left->right) !=
3385             (getSize(TTYPE(root->left->left))*8 - 1))
3386             return root ;
3387
3388         /* whew got the first case : create the AST */
3389         return  newNode(RRC,root->left->left,NULL);
3390         
3391     }
3392
3393     /* not found return root */
3394     return root;
3395 }
3396
3397 /*-----------------------------------------------------------------*/
3398 /* optimizeCompare - otimizes compares for bit variables           */
3399 /*-----------------------------------------------------------------*/
3400 ast  *optimizeCompare ( ast *root )
3401 {
3402     ast *optExpr = NULL;
3403     value       *vleft;
3404     value       *vright;
3405     unsigned int litValue ;
3406     
3407     /* if nothing then return nothing */
3408     if (!root)
3409         return NULL ;
3410     
3411     /* if not a compare op then do leaves */
3412     if (!IS_COMPARE_OP(root)) {
3413         root->left = optimizeCompare (root->left);
3414         root->right= optimizeCompare (root->right);
3415         return root ;
3416     }
3417     
3418     /* if left & right are the same then depending 
3419        of the operation do */
3420     if (isAstEqual(root->left,root->right)) {
3421         switch (root->opval.op) {
3422         case '>' :
3423         case '<' :
3424         case NE_OP :
3425             optExpr = newAst_VALUE(constVal("0"));
3426             break;
3427         case GE_OP :
3428         case LE_OP :
3429         case EQ_OP :
3430             optExpr = newAst_VALUE(constVal("1"));
3431             break;
3432         }
3433
3434         return decorateType(optExpr);
3435     }
3436
3437     vleft = (root->left->type == EX_VALUE ?
3438              root->left->opval.val : NULL );
3439     
3440     vright = (root->right->type == EX_VALUE ?
3441               root->right->opval.val : NULL);
3442     
3443     /* if left is a BITVAR in BITSPACE */
3444     /* and right is a LITERAL then opt-*/
3445     /* imize else do nothing               */
3446     if (vleft && vright                   &&
3447         IS_BITVAR(vleft->etype)           && 
3448         IN_BITSPACE(SPEC_OCLS(vleft->etype))  &&
3449         IS_LITERAL(vright->etype)) {
3450         
3451         /* if right side > 1 then comparison may never succeed */
3452         if ( (litValue = (int) floatFromVal(vright)) > 1 ) {
3453             werror(W_BAD_COMPARE);
3454             goto noOptimize ;
3455         }
3456         
3457         if ( litValue ) {
3458             switch (root->opval.op) {
3459             case '>' :  /* bit value greater than 1 cannot be */
3460                 werror(W_BAD_COMPARE);
3461                 goto noOptimize ;
3462                 break;
3463                 
3464             case '<' : /* bit value < 1 means 0 */
3465             case NE_OP :
3466                 optExpr = newNode('!',newAst_VALUE(vleft),NULL);
3467                 break;
3468                 
3469             case LE_OP : /* bit value <= 1 means no check */
3470                 optExpr = newAst_VALUE(vright);         
3471                 break;
3472                 
3473             case GE_OP : /* bit value >= 1 means only check for = */
3474             case EQ_OP :
3475                 optExpr = newAst_VALUE(vleft);          
3476                 break;
3477             }
3478         } else { /* literal is zero */
3479             switch (root->opval.op) {
3480             case '<' :  /* bit value < 0 cannot be */
3481                 werror(W_BAD_COMPARE);
3482                 goto noOptimize ;
3483                 break;
3484                 
3485             case '>' : /* bit value > 0 means 1 */
3486             case NE_OP :
3487                 optExpr = newAst_VALUE(vleft);       
3488                 break;
3489                 
3490             case LE_OP : /* bit value <= 0 means no check */
3491             case GE_OP : /* bit value >= 0 means no check */
3492                 werror(W_BAD_COMPARE);
3493                 goto noOptimize ;
3494                 break;
3495                 
3496             case EQ_OP : /* bit == 0 means ! of bit */
3497                 optExpr = newNode('!',newAst_VALUE(vleft),NULL);              
3498                 break;
3499             }
3500         }                      
3501         return decorateType(resolveSymbols(optExpr)); 
3502     }   /* end-of-if of BITVAR */
3503     
3504     noOptimize :
3505         return root;
3506 }
3507 /*-----------------------------------------------------------------*/
3508 /* addSymToBlock : adds the symbol to the first block we find      */
3509 /*-----------------------------------------------------------------*/
3510 void addSymToBlock (symbol *sym, ast *tree)
3511 {
3512     /* reached end of tree or a leaf */
3513     if (!tree || IS_AST_LINK(tree) || IS_AST_VALUE(tree))
3514         return ;
3515
3516     /* found a block */
3517     if (IS_AST_OP(tree) &&
3518         tree->opval.op == BLOCK ) {
3519         
3520         symbol *lsym = copySymbol(sym);
3521         
3522         lsym->next = AST_VALUES(tree,sym);
3523         AST_VALUES(tree,sym) = lsym ;
3524         return ;
3525     }
3526     
3527     addSymToBlock(sym,tree->left);
3528     addSymToBlock(sym,tree->right);
3529 }
3530
3531 /*-----------------------------------------------------------------*/
3532 /* processRegParms - do processing for register parameters         */
3533 /*-----------------------------------------------------------------*/
3534 static void processRegParms (value *args, ast *body)
3535 {
3536     while (args) {
3537         if (IS_REGPARM(args->etype))
3538             addSymToBlock(args->sym,body);
3539         args = args->next;
3540     }
3541 }
3542
3543 /*-----------------------------------------------------------------*/
3544 /* resetParmKey - resets the operandkeys for the symbols           */
3545 /*-----------------------------------------------------------------*/
3546 DEFSETFUNC(resetParmKey)
3547 {
3548     symbol *sym = item;
3549
3550     sym->key = 0 ;
3551     sym->defs = NULL ;
3552     sym->uses = NULL ;
3553     sym->remat= 0;
3554     return 1;
3555 }
3556
3557 /*-----------------------------------------------------------------*/
3558 /* createFunction - This is the key node that calls the iCode for  */
3559 /*                  generating the code for a function. Note code  */
3560 /*                  is generated function by function, later when  */
3561 /*                  add inter-procedural analysis this will change */
3562 /*-----------------------------------------------------------------*/
3563 ast  *createFunction   (symbol  *name,   ast  *body )
3564 {
3565     ast  *ex ;
3566     symbol *csym;
3567     int stack = 0 ;
3568     sym_link *fetype;       
3569     iCode *piCode = NULL;
3570     
3571     /* if check function return 0 then some problem */
3572     if (checkFunction (name) == 0)
3573         return NULL;
3574     
3575     /* create a dummy block if none exists */
3576     if (!body)
3577         body = newNode(BLOCK,NULL,NULL);
3578
3579     noLineno++ ;
3580    
3581     /* check if the function name already in the symbol table */
3582     if ((csym = findSym (SymbolTab,NULL,name->name))) {
3583         name = csym ;     
3584         /* special case for compiler defined functions
3585            we need to add the name to the publics list : this
3586            actually means we are now compiling the compiler
3587            support routine */
3588         if (name->cdef) {
3589             addSet(&publics,name);
3590         }
3591     }
3592     else {
3593         addSymChain(name);
3594         allocVariables(name);
3595     }
3596     name->lastLine = yylineno;
3597     currFunc = name ;
3598     processFuncArgs(currFunc,0);
3599     
3600     /* set the stack pointer */
3601     /* PENDING: check this for the mcs51 */
3602     stackPtr = -port->stack.direction * port->stack.call_overhead;
3603     if (IS_ISR(name->etype))
3604         stackPtr -= port->stack.direction * port->stack.isr_overhead;
3605     if (IS_RENT(name->etype) || options.stackAuto)
3606         stackPtr -= port->stack.direction * port->stack.reent_overhead;
3607
3608     xstackPtr = -port->stack.direction * port->stack.call_overhead;
3609     
3610     fetype = getSpec(name->type); /* get the specifier for the function */
3611     /* if this is a reentrant function then */
3612     if (IS_RENT(fetype))
3613         reentrant++ ;
3614         
3615     allocParms (name->args);           /* allocate the parameters */
3616
3617     /* do processing for parameters that are passed in registers */
3618     processRegParms (name->args,body); 
3619
3620    /* set the stack pointer */
3621     stackPtr = 0;
3622     xstackPtr= -1;
3623     
3624     /* allocate & autoinit the block variables */
3625     processBlockVars (body, &stack,ALLOCATE); 
3626     
3627     /* save the stack information */
3628     if (options.useXstack)
3629         name->xstack = SPEC_STAK(fetype) = stack;
3630     else
3631         name->stack = SPEC_STAK(fetype) = stack;
3632     
3633     /* name needs to be mangled */
3634     sprintf (name->rname,"%s%s", port->fun_prefix, name->name);
3635     
3636     body = resolveSymbols(body); /* resolve the symbols */
3637     body = decorateType (body);  /* propagateType & do semantic checks */
3638     
3639     ex = newAst_VALUE(symbolVal(name));    /* create name       */
3640     ex = newNode (FUNCTION,ex,body);
3641     ex->values.args = name->args ;
3642     
3643     if (fatalError) {
3644         werror(E_FUNC_NO_CODE,name->name);
3645         goto skipall ;
3646     }
3647         
3648     /* create the node & generate intermediate code */  
3649     codeOutFile = code->oFile;
3650     piCode = iCodeFromAst(ex);
3651
3652      if (fatalError) {
3653          werror(E_FUNC_NO_CODE,name->name);
3654          goto skipall ;
3655      }
3656      
3657      eBBlockFromiCode(piCode);
3658                     
3659     /* if there are any statics then do them */
3660     if (staticAutos) {
3661         codeOutFile = statsg->oFile;
3662         eBBlockFromiCode (iCodeFromAst (decorateType(resolveSymbols(staticAutos))));
3663         staticAutos = NULL;
3664     }
3665     
3666  skipall:
3667     
3668     /* dealloc the block variables */
3669     processBlockVars(body, &stack,DEALLOCATE);
3670     /* deallocate paramaters */
3671     deallocParms(name->args);
3672     
3673     if (IS_RENT(fetype))
3674         reentrant-- ;
3675     
3676     /* we are done freeup memory & cleanup */
3677     noLineno-- ;
3678     labelKey = 1 ;
3679     name->key = 0;
3680     name->fbody = 1;
3681     addSet(&operKeyReset,name);
3682     applyToSet(operKeyReset,resetParmKey);
3683        
3684     if (options.debug && !options.nodebug)
3685         cdbStructBlock(1,cdbFile);
3686
3687     cleanUpLevel(LabelTab,0);
3688     cleanUpBlock(StructTab,1);
3689     cleanUpBlock(TypedefTab,1);
3690
3691     xstack->syms = NULL;
3692     istack->syms = NULL;
3693     return NULL ;
3694 }
3695
3696