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