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