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