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