* src/SDCCsymt.h,
[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 #define DEBUG_CF(x) /* puts(x); */
26
27 #include "common.h"
28
29 int currLineno = 0;
30 set *astList = NULL;
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
33 int labelKey = 1;
34
35 #define LRVAL(x) x->left->rvalue
36 #define RRVAL(x) x->right->rvalue
37 #define TRVAL(x) x->rvalue
38 #define LLVAL(x) x->left->lvalue
39 #define RLVAL(x) x->right->lvalue
40 #define TLVAL(x) x->lvalue
41 #define RTYPE(x) x->right->ftype
42 #define RETYPE(x) x->right->etype
43 #define LTYPE(x) x->left->ftype
44 #define LETYPE(x) x->left->etype
45 #define TTYPE(x) x->ftype
46 #define TETYPE(x) x->etype
47 #define ALLOCATE 1
48 #define DEALLOCATE 2
49
50 int noLineno = 0;
51 int noAlloc = 0;
52 symbol *currFunc=NULL;
53 static ast *createIval (ast *, sym_link *, initList *, ast *);
54 static ast *createIvalCharPtr (ast *, sym_link *, ast *);
55 static ast *optimizeCompare (ast *);
56 ast *optimizeRRCRLC (ast *);
57 ast *optimizeSWAP (ast *);
58 ast *optimizeGetHbit (ast *);
59 ast *backPatchLabels (ast *, symbol *, symbol *);
60 void PA(ast *t);
61 int inInitMode = 0;
62 memmap *GcurMemmap=NULL;  /* points to the memmap that's currently active */
63 FILE *codeOutFile;
64 int 
65 ptt (ast * tree)
66 {
67   printTypeChain (tree->ftype, stdout);
68   return 0;
69 }
70
71
72 /*-----------------------------------------------------------------*/
73 /* newAst - creates a fresh node for an expression tree            */
74 /*-----------------------------------------------------------------*/
75 static ast *
76 newAst_ (unsigned type)
77 {
78   ast *ex;
79   static int oldLineno = 0;
80
81   ex = Safe_alloc ( sizeof (ast));
82
83   ex->type = type;
84   ex->lineno = (noLineno ? oldLineno : mylineno);
85   ex->filename = currFname;
86   ex->level = NestLevel;
87   ex->block = currBlockno;
88   ex->initMode = inInitMode;
89   ex->seqPoint = seqPointNo;
90   return ex;
91 }
92
93 ast *
94 newAst_VALUE (value * val)
95 {
96   ast *ex = newAst_ (EX_VALUE);
97   ex->opval.val = val;
98   return ex;
99 }
100
101 ast *
102 newAst_OP (unsigned op)
103 {
104   ast *ex = newAst_ (EX_OP);
105   ex->opval.op = op;
106   return ex;
107 }
108
109 ast *
110 newAst_LINK (sym_link * val)
111 {
112   ast *ex = newAst_ (EX_LINK);
113   ex->opval.lnk = val;
114   return ex;
115 }
116
117 /*-----------------------------------------------------------------*/
118 /* newNode - creates a new node                                    */
119 /*-----------------------------------------------------------------*/
120 ast *
121 newNode (long op, ast * left, ast * right)
122 {
123   ast *ex;
124
125   ex = newAst_OP (op);
126   ex->left = left;
127   ex->right = right;
128
129   return ex;
130 }
131
132 /*-----------------------------------------------------------------*/
133 /* newIfxNode - creates a new Ifx Node                             */
134 /*-----------------------------------------------------------------*/
135 ast *
136 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
137 {
138   ast *ifxNode;
139
140   /* if this is a literal then we already know the result */
141   if (condAst->etype && IS_LITERAL (condAst->etype))
142     {
143       /* then depending on the expression value */
144       if (floatFromVal (condAst->opval.val))
145         ifxNode = newNode (GOTO,
146                            newAst_VALUE (symbolVal (trueLabel)),
147                            NULL);
148       else
149         ifxNode = newNode (GOTO,
150                            newAst_VALUE (symbolVal (falseLabel)),
151                            NULL);
152     }
153   else
154     {
155       ifxNode = newNode (IFX, condAst, NULL);
156       ifxNode->trueLabel = trueLabel;
157       ifxNode->falseLabel = falseLabel;
158     }
159
160   return ifxNode;
161 }
162
163 /*-----------------------------------------------------------------*/
164 /* copyAstValues - copies value portion of ast if needed     */
165 /*-----------------------------------------------------------------*/
166 void
167 copyAstValues (ast * dest, ast * src)
168 {
169   switch (src->opval.op)
170     {
171     case BLOCK:
172       dest->values.sym = copySymbolChain (src->values.sym);
173       break;
174
175     case SWITCH:
176       dest->values.switchVals.swVals =
177         copyValue (src->values.switchVals.swVals);
178       dest->values.switchVals.swDefault =
179         src->values.switchVals.swDefault;
180       dest->values.switchVals.swNum =
181         src->values.switchVals.swNum;
182       break;
183
184     case INLINEASM:
185       dest->values.inlineasm =  Safe_strdup(src->values.inlineasm);
186       break;
187
188     case ARRAYINIT:
189         dest->values.constlist = copyLiteralList(src->values.constlist);
190         break;
191
192     case FOR:
193       AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
194       AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
195       AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
196       AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
197       AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
198       AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
199       AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
200     }
201
202 }
203
204 /*-----------------------------------------------------------------*/
205 /* copyAst - makes a copy of a given astession                     */
206 /*-----------------------------------------------------------------*/
207 ast *
208 copyAst (ast * src)
209 {
210   ast *dest;
211
212   if (!src)
213     return NULL;
214
215   dest = Safe_alloc ( sizeof (ast));
216
217   dest->type = src->type;
218   dest->lineno = src->lineno;
219   dest->level = src->level;
220   dest->funcName = src->funcName;
221
222   if (src->ftype)
223     dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
224
225   /* if this is a leaf */
226   /* if value */
227   if (src->type == EX_VALUE)
228     {
229       dest->opval.val = copyValue (src->opval.val);
230       goto exit;
231     }
232
233   /* if link */
234   if (src->type == EX_LINK)
235     {
236       dest->opval.lnk = copyLinkChain (src->opval.lnk);
237       goto exit;
238     }
239
240   dest->opval.op = src->opval.op;
241
242   /* if this is a node that has special values */
243   copyAstValues (dest, src);
244
245   dest->trueLabel = copySymbol (src->trueLabel);
246   dest->falseLabel = copySymbol (src->falseLabel);
247   dest->left = copyAst (src->left);
248   dest->right = copyAst (src->right);
249 exit:
250   return dest;
251
252 }
253
254 /*-----------------------------------------------------------------*/
255 /* removeIncDecOps: remove for side effects in *_ASSIGN's          */
256 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
257 /*-----------------------------------------------------------------*/
258 ast *removeIncDecOps (ast * tree) {
259
260   // traverse the tree and remove inc/dec ops
261
262   if (!tree)
263     return NULL;
264
265   if (tree->type == EX_OP &&
266       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
267     if (tree->left)
268       tree=tree->left;
269     else
270       tree=tree->right;
271   }
272
273   tree->left=removeIncDecOps(tree->left);
274   tree->right=removeIncDecOps(tree->right);
275
276  return tree;
277 }
278
279 /*-----------------------------------------------------------------*/
280 /* removePreIncDecOps: remove for side effects in *_ASSIGN's       */
281 /*                  "*++s += 3" -> "*++s = *++s + 3"               */
282 /*-----------------------------------------------------------------*/
283 ast *removePreIncDecOps (ast * tree) {
284
285   // traverse the tree and remove pre-inc/dec ops
286
287   if (!tree)
288     return NULL;
289
290   if (tree->type == EX_OP &&
291       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
292     if (tree->right)
293       tree=tree->right;
294   }
295
296   tree->left=removePreIncDecOps(tree->left);
297   tree->right=removePreIncDecOps(tree->right);
298
299  return tree;
300 }
301
302 /*-----------------------------------------------------------------*/
303 /* removePostIncDecOps: remove for side effects in *_ASSIGN's      */
304 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
305 /*-----------------------------------------------------------------*/
306 ast *removePostIncDecOps (ast * tree) {
307
308   // traverse the tree and remove pre-inc/dec ops
309
310   if (!tree)
311     return NULL;
312
313   if (tree->type == EX_OP &&
314       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
315     if (tree->left)
316       tree=tree->left;
317   }
318
319   tree->left=removePostIncDecOps(tree->left);
320   tree->right=removePostIncDecOps(tree->right);
321
322  return tree;
323 }
324
325 /*-----------------------------------------------------------------*/
326 /* hasSEFcalls - returns TRUE if tree has a function call          */
327 /*-----------------------------------------------------------------*/
328 bool
329 hasSEFcalls (ast * tree)
330 {
331   if (!tree)
332     return FALSE;
333
334   if (tree->type == EX_OP &&
335       (tree->opval.op == CALL ||
336        tree->opval.op == PCALL ||
337        tree->opval.op == '=' ||
338        tree->opval.op == INC_OP ||
339        tree->opval.op == DEC_OP))
340     return TRUE;
341
342   return (hasSEFcalls (tree->left) |
343           hasSEFcalls (tree->right));
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* isAstEqual - compares two asts & returns 1 if they are equal    */
348 /*-----------------------------------------------------------------*/
349 static int
350 isAstEqual (ast * t1, ast * t2)
351 {
352   if (!t1 && !t2)
353     return 1;
354
355   if (!t1 || !t2)
356     return 0;
357
358   /* match type */
359   if (t1->type != t2->type)
360     return 0;
361
362   switch (t1->type)
363     {
364     case EX_OP:
365       if (t1->opval.op != t2->opval.op)
366         return 0;
367       return (isAstEqual (t1->left, t2->left) &&
368               isAstEqual (t1->right, t2->right));
369       break;
370
371     case EX_VALUE:
372       if (t1->opval.val->sym)
373         {
374           if (!t2->opval.val->sym)
375             return 0;
376           else
377             return isSymbolEqual (t1->opval.val->sym,
378                                   t2->opval.val->sym);
379         }
380       else
381         {
382           if (t2->opval.val->sym)
383             return 0;
384           else
385             return (floatFromVal (t1->opval.val) ==
386                     floatFromVal (t2->opval.val));
387         }
388       break;
389
390       /* only compare these two types */
391     default:
392       return 0;
393     }
394
395   return 0;
396 }
397
398 /*-----------------------------------------------------------------*/
399 /* resolveSymbols - resolve symbols from the symbol table          */
400 /*-----------------------------------------------------------------*/
401 ast *
402 resolveSymbols (ast * tree)
403 {
404   /* walk the entire tree and check for values */
405   /* with symbols if we find one then replace  */
406   /* symbol with that from the symbol table    */
407
408   if (tree == NULL)
409     return tree;
410
411 #if 0
412   /* print the line          */
413   /* if not block & function */
414   if (tree->type == EX_OP &&
415       (tree->opval.op != FUNCTION &&
416        tree->opval.op != BLOCK &&
417        tree->opval.op != NULLOP))
418     {
419       filename = tree->filename;
420       lineno = tree->lineno;
421     }
422 #endif
423
424   /* make sure we resolve the true & false labels for ifx */
425   if (tree->type == EX_OP && tree->opval.op == IFX)
426     {
427       symbol *csym;
428
429       if (tree->trueLabel)
430         {
431           if ((csym = findSym (LabelTab, tree->trueLabel,
432                                tree->trueLabel->name)))
433             tree->trueLabel = csym;
434           else
435             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
436                       tree->trueLabel->name);
437         }
438
439       if (tree->falseLabel)
440         {
441           if ((csym = findSym (LabelTab,
442                                tree->falseLabel,
443                                tree->falseLabel->name)))
444             tree->falseLabel = csym;
445           else
446             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
447                       tree->falseLabel->name);
448         }
449
450     }
451
452   /* if this is a label resolve it from the labelTab */
453   if (IS_AST_VALUE (tree) &&
454       tree->opval.val->sym &&
455       tree->opval.val->sym->islbl)
456     {
457
458       symbol *csym = findSym (LabelTab, tree->opval.val->sym,
459                               tree->opval.val->sym->name);
460
461       if (!csym)
462         werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
463                   tree->opval.val->sym->name);
464       else
465         tree->opval.val->sym = csym;
466
467       goto resolveChildren;
468     }
469
470   /* do only for leafs */
471   if (IS_AST_VALUE (tree) &&
472       tree->opval.val->sym &&
473       !tree->opval.val->sym->implicit)
474     {
475
476       symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
477
478       /* if found in the symbol table & they r not the same */
479       if (csym && tree->opval.val->sym != csym)
480         {
481           tree->opval.val->sym = csym;
482           tree->opval.val->type = csym->type;
483           tree->opval.val->etype = csym->etype;
484         }
485
486       /* if not found in the symbol table */
487       /* mark it as undefined assume it is */
488       /* an integer in data space         */
489       if (!csym && !tree->opval.val->sym->implicit)
490         {
491
492           /* if this is a function name then */
493           /* mark it as returning an int     */
494           if (tree->funcName)
495             {
496               tree->opval.val->sym->type = newLink (DECLARATOR);
497               DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
498               tree->opval.val->sym->type->next =
499                 tree->opval.val->sym->etype = newIntLink ();
500               tree->opval.val->etype = tree->opval.val->etype;
501               tree->opval.val->type = tree->opval.val->sym->type;
502               werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
503                         tree->opval.val->sym->name);
504               //tree->opval.val->sym->undefined = 1;
505               allocVariables (tree->opval.val->sym);
506             }
507           else
508             {
509               tree->opval.val->sym->undefined = 1;
510               tree->opval.val->type =
511                 tree->opval.val->etype = newIntLink ();
512               tree->opval.val->sym->type =
513                 tree->opval.val->sym->etype = newIntLink ();
514             }
515         }
516     }
517
518 resolveChildren:
519   resolveSymbols (tree->left);
520   resolveSymbols (tree->right);
521
522   return tree;
523 }
524
525 /*-----------------------------------------------------------------*/
526 /* setAstLineno - walks a ast tree & sets the line number          */
527 /*-----------------------------------------------------------------*/
528 int setAstLineno (ast * tree, int lineno)
529 {
530   if (!tree)
531     return 0;
532
533   tree->lineno = lineno;
534   setAstLineno (tree->left, lineno);
535   setAstLineno (tree->right, lineno);
536   return 0;
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* funcOfType :- function of type with name                        */
541 /*-----------------------------------------------------------------*/
542 symbol *
543 funcOfType (char *name, sym_link * type, sym_link * argType,
544             int nArgs, int rent)
545 {
546   symbol *sym;
547   /* create the symbol */
548   sym = newSymbol (name, 0);
549
550   /* setup return value */
551   sym->type = newLink (DECLARATOR);
552   DCL_TYPE (sym->type) = FUNCTION;
553   sym->type->next = copyLinkChain (type);
554   sym->etype = getSpec (sym->type);
555   FUNC_ISREENT(sym->type) = rent ? 1 : 0;
556
557   /* if arguments required */
558   if (nArgs)
559     {
560       value *args;
561       args = FUNC_ARGS(sym->type) = newValue ();
562
563       while (nArgs--)
564         {
565           args->type = copyLinkChain (argType);
566           args->etype = getSpec (args->type);
567           SPEC_EXTR(args->etype)=1;
568           if (!nArgs)
569             break;
570           args = args->next = newValue ();
571         }
572     }
573
574   /* save it */
575   addSymChain (sym);
576   sym->cdef = 1;
577   allocVariables (sym);
578   return sym;
579
580 }
581
582 /*-----------------------------------------------------------------*/
583 /* funcOfTypeVarg :- function of type with name and argtype        */
584 /*-----------------------------------------------------------------*/
585 symbol *
586 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
587 {
588   
589     symbol *sym;
590     int i ;
591     /* create the symbol */
592     sym = newSymbol (name, 0);
593     
594     /* setup return value */
595     sym->type = newLink (DECLARATOR);
596     DCL_TYPE (sym->type) = FUNCTION;
597     sym->type->next = typeFromStr(rtype);
598     sym->etype = getSpec (sym->type);
599     
600     /* if arguments required */
601     if (nArgs) {
602         value *args;
603         args = FUNC_ARGS(sym->type) = newValue ();
604         
605         for ( i = 0 ; i < nArgs ; i++ ) {
606             args->type = typeFromStr(atypes[i]);
607             args->etype = getSpec (args->type);
608             SPEC_EXTR(args->etype)=1;
609             if ((i + 1) == nArgs) break;
610             args = args->next = newValue ();
611         }
612     }
613
614     /* save it */
615     addSymChain (sym);
616     sym->cdef = 1;
617     allocVariables (sym);
618     return sym;
619
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* reverseParms - will reverse a parameter tree                    */
624 /*-----------------------------------------------------------------*/
625 static void
626 reverseParms (ast * ptree)
627 {
628   ast *ttree;
629   if (!ptree)
630     return;
631
632   /* top down if we find a nonParm tree then quit */
633   if (ptree->type == EX_OP && ptree->opval.op == PARAM)
634     {
635       ttree = ptree->left;
636       ptree->left = ptree->right;
637       ptree->right = ttree;
638       reverseParms (ptree->left);
639       reverseParms (ptree->right);
640     }
641
642   return;
643 }
644
645 /*-----------------------------------------------------------------*/
646 /* processParms  - makes sure the parameters are okay and do some  */
647 /*                 processing with them                            */
648 /*-----------------------------------------------------------------*/
649 static int
650 processParms (ast *func,
651               value *defParm,
652               ast **actParm,
653               int *parmNumber, /* unused, although updated */
654               bool rightmost)
655 {
656   RESULT_TYPE resultType;
657   sym_link *functype;
658   
659   /* if none of them exist */
660   if (!defParm && !*actParm)
661     return 0;
662
663   if (defParm)
664     {
665       if (getenv("DEBUG_SANITY"))
666         {
667           fprintf (stderr, "processParms: %s ", defParm->name);
668         }
669       /* make sure the type is complete and sane */
670       checkTypeSanity(defParm->etype, defParm->name);
671     }
672
673   if (IS_CODEPTR (func->ftype))
674     functype = func->ftype->next;
675   else
676     functype = func->ftype;
677     
678   /* if the function is being called via a pointer &   */
679   /* it has not been defined a reentrant then we cannot */
680   /* have parameters                                   */
681   if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
682     {
683       werror (W_NONRENT_ARGS);
684       fatalError++;
685       return 1;
686     }
687
688   /* if defined parameters ended but actual parameters */
689   /* exist and this is not defined as a variable arg   */
690   if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
691     {
692       werror (E_TOO_MANY_PARMS);
693       return 1;
694     }
695
696   /* if defined parameters present but no actual parameters */
697   if (defParm && !*actParm)
698     {
699       werror (E_TOO_FEW_PARMS);
700       return 1;
701     }
702
703   /* if this is a PARAM node then match left & right */
704   if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
705     {
706       (*actParm)->decorated = 1;
707       return (processParms (func, defParm,
708                             &(*actParm)->left,  parmNumber, FALSE) ||
709               processParms (func, defParm ? defParm->next : NULL,
710                             &(*actParm)->right, parmNumber, rightmost));
711     }
712   else if (defParm) /* not vararg */
713     {
714       /* If we have found a value node by following only right-hand links,
715        * then we know that there are no more values after us.
716        *
717        * Therefore, if there are more defined parameters, the caller didn't
718        * supply enough.
719        */
720       if (rightmost && defParm->next)
721         {
722           werror (E_TOO_FEW_PARMS);
723           return 1;
724         }
725     }
726
727   /* decorate parameter */
728   resultType = defParm ? getResultTypeFromType (defParm->etype) :
729                          RESULT_TYPE_NONE;
730   *actParm = decorateType (*actParm, resultType);
731
732   if (IS_VOID((*actParm)->ftype))
733     {
734       werror (E_VOID_VALUE_USED);
735       return 1;
736     }
737
738   /* If this is a varargs function... */
739   if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
740     {
741       ast *newType = NULL;
742       sym_link *ftype;
743
744       if (IS_CAST_OP (*actParm)
745           || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
746         {
747           /* Parameter was explicitly typecast; don't touch it. */
748           return 0;
749         }
750
751       ftype = (*actParm)->ftype;
752
753       /* If it's a char, upcast to int. */
754       if (IS_INTEGRAL (ftype)
755           && (getSize (ftype) < (unsigned) INTSIZE))
756         {
757           newType = newAst_LINK(INTTYPE);  
758         }
759
760       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
761         {
762           newType = newAst_LINK (copyLinkChain(ftype));
763           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
764         }
765
766       if (IS_AGGREGATE (ftype))
767         {
768           newType = newAst_LINK (copyLinkChain (ftype));
769           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
770         }
771       
772       if (newType)
773         {
774           /* cast required; change this op to a cast. */
775           (*actParm)->decorated = 0;
776            *actParm = newNode (CAST, newType, *actParm);
777           (*actParm)->lineno = (*actParm)->right->lineno;
778           
779           decorateType (*actParm, RESULT_TYPE_NONE);
780         }
781       return 0;
782     } /* vararg */
783
784   /* if defined parameters ended but actual has not & */
785   /* reentrant */
786   if (!defParm && *actParm &&
787       (options.stackAuto || IFFUNC_ISREENT (functype)))
788     return 0;
789
790   resolveSymbols (*actParm);
791   
792   /* the parameter type must be at least castable */
793   if (compareType (defParm->type, (*actParm)->ftype) == 0)
794     {
795       werror (E_INCOMPAT_TYPES);
796       printFromToType ((*actParm)->ftype, defParm->type);
797       return 1;
798     }
799
800   /* if the parameter is castable then add the cast */
801   if (compareType (defParm->type, (*actParm)->ftype) < 0)
802     {
803       ast *pTree;
804
805       resultType = getResultTypeFromType (defParm->etype);
806       pTree = resolveSymbols (copyAst (*actParm));
807       
808       /* now change the current one to a cast */
809       (*actParm)->type = EX_OP;
810       (*actParm)->opval.op = CAST;
811       (*actParm)->left = newAst_LINK (defParm->type);
812       (*actParm)->right = pTree;
813       (*actParm)->decorated = 0; /* force typechecking */
814       decorateType (*actParm, resultType);
815     }
816
817   /* make a copy and change the regparm type to the defined parm */
818   (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
819   SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
820   SPEC_ARGREG  ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
821   (*parmNumber)++;
822   return 0;
823 }
824
825 /*-----------------------------------------------------------------*/
826 /* createIvalType - generates ival for basic types                 */
827 /*-----------------------------------------------------------------*/
828 static ast *
829 createIvalType (ast * sym, sym_link * type, initList * ilist)
830 {
831   ast *iExpr;
832
833   /* if initList is deep */
834   if (ilist->type == INIT_DEEP)
835     ilist = ilist->init.deep;
836
837   iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
838   return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
839 }
840
841 /*-----------------------------------------------------------------*/
842 /* createIvalStruct - generates initial value for structures       */
843 /*-----------------------------------------------------------------*/
844 static ast *
845 createIvalStruct (ast * sym, sym_link * type, initList * ilist)
846 {
847   ast *rast = NULL;
848   ast *lAst;
849   symbol *sflds;
850   initList *iloop;
851
852   sflds = SPEC_STRUCT (type)->fields;
853   if (ilist->type != INIT_DEEP)
854     {
855       werror (E_INIT_STRUCT, "");
856       return NULL;
857     }
858
859   iloop = ilist->init.deep;
860
861   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
862     {
863       /* if we have come to end */
864       if (!iloop)
865         break;
866       sflds->implicit = 1;
867       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
868       lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
869       rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
870     }
871
872   if (iloop) {
873     werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
874               W_EXCESS_INITIALIZERS, "struct", 
875               sym->opval.val->sym->name);
876   }
877
878   return rast;
879 }
880
881
882 /*-----------------------------------------------------------------*/
883 /* createIvalArray - generates code for array initialization       */
884 /*-----------------------------------------------------------------*/
885 static ast *
886 createIvalArray (ast * sym, sym_link * type, initList * ilist)
887 {
888   ast *rast = NULL;
889   initList *iloop;
890   int lcnt = 0, size = 0;
891   literalList *literalL;
892
893   /* take care of the special   case  */
894   /* array of characters can be init  */
895   /* by a string                      */
896   if (IS_CHAR (type->next))
897     if ((rast = createIvalCharPtr (sym,
898                                    type,
899                         decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
900
901       return decorateType (resolveSymbols (rast), RESULT_CHECK);
902
903     /* not the special case             */
904     if (ilist->type != INIT_DEEP)
905     {
906         werror (E_INIT_STRUCT, "");
907         return NULL;
908     }
909
910     iloop = ilist->init.deep;
911     lcnt = DCL_ELEM (type);
912
913     if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
914     {
915         ast *aSym;
916
917         aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
918         
919         rast = newNode(ARRAYINIT, aSym, NULL);
920         rast->values.constlist = literalL;
921         
922         // Make sure size is set to length of initializer list.
923         while (iloop)
924         {
925             size++;
926             iloop = iloop->next;
927         }
928         
929         if (lcnt && size > lcnt)
930         {
931             // Array size was specified, and we have more initializers than needed.
932             char *name=sym->opval.val->sym->name;
933             int lineno=sym->opval.val->sym->lineDef;
934             char *filename=sym->opval.val->sym->fileDef;
935             
936             werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
937         }
938     }
939     else
940     {
941         for (;;)
942         {
943             ast *aSym;
944             
945             aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
946             aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
947             rast = createIval (aSym, type->next, iloop, rast);
948             iloop = (iloop ? iloop->next : NULL);
949             if (!iloop)
950             {
951                 break;
952             }
953             
954             /* no of elements given and we    */
955             /* have generated for all of them */
956             if (!--lcnt) 
957             {
958                 // is this a better way? at least it won't crash
959                 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
960                 int lineno = iloop->lineno;
961                 char *filename = iloop->filename;
962                 werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
963                 
964                 break;
965             }
966         }
967     }
968
969     /* if we have not been given a size  */
970     if (!DCL_ELEM (type))
971     {
972         /* but this still updates the typedef instead of the instance ! see bug 770487 */
973         DCL_ELEM (type) = size;
974     }
975
976     return decorateType (resolveSymbols (rast), RESULT_CHECK);
977 }
978
979
980 /*-----------------------------------------------------------------*/
981 /* createIvalCharPtr - generates initial values for char pointers  */
982 /*-----------------------------------------------------------------*/
983 static ast *
984 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
985 {
986   ast *rast = NULL;
987
988   /* if this is a pointer & right is a literal array then */
989   /* just assignment will do                              */
990   if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
991                          SPEC_SCLS (iexpr->etype) == S_CODE)
992                         && IS_ARRAY (iexpr->ftype)))
993     return newNode ('=', sym, iexpr);
994
995   /* left side is an array so we have to assign each */
996   /* element                                         */
997   if ((IS_LITERAL (iexpr->etype) ||
998        SPEC_SCLS (iexpr->etype) == S_CODE)
999       && IS_ARRAY (iexpr->ftype))
1000     {
1001       /* for each character generate an assignment */
1002       /* to the array element */
1003       char *s = SPEC_CVAL (iexpr->etype).v_char;
1004       int i = 0;
1005       int size = getSize (iexpr->ftype);
1006       int symsize = getSize (type);
1007       
1008       if (size>symsize)
1009         {
1010           if (size>(symsize+1))
1011             werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1012                       "string", sym->opval.val->sym->name);
1013           size = symsize;
1014         }
1015
1016       for (i=0;i<size;i++)
1017         {
1018           rast = newNode (NULLOP,
1019                           rast,
1020                           newNode ('=',
1021                                    newNode ('[', sym,
1022                                    newAst_VALUE (valueFromLit ((float) i))),
1023                                    newAst_VALUE (valueFromLit (*s))));
1024           s++;
1025         }
1026
1027       // now WE don't need iexpr's symbol anymore
1028       freeStringSymbol(AST_SYMBOL(iexpr));
1029
1030       return decorateType (resolveSymbols (rast), RESULT_CHECK);
1031     }
1032
1033   return NULL;
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /* createIvalPtr - generates initial value for pointers            */
1038 /*-----------------------------------------------------------------*/
1039 static ast *
1040 createIvalPtr (ast * sym, sym_link * type, initList * ilist)
1041 {
1042   ast *rast;
1043   ast *iexpr;
1044
1045   /* if deep then   */
1046   if (ilist->type == INIT_DEEP)
1047     ilist = ilist->init.deep;
1048
1049   iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
1050
1051   /* if character pointer */
1052   if (IS_CHAR (type->next))
1053     if ((rast = createIvalCharPtr (sym, type, iexpr)))
1054       return rast;
1055
1056   return newNode ('=', sym, iexpr);
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* createIval - generates code for initial value                   */
1061 /*-----------------------------------------------------------------*/
1062 static ast *
1063 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
1064 {
1065   ast *rast = NULL;
1066
1067   if (!ilist)
1068     return NULL;
1069
1070   /* if structure then    */
1071   if (IS_STRUCT (type))
1072     rast = createIvalStruct (sym, type, ilist);
1073   else
1074     /* if this is a pointer */
1075   if (IS_PTR (type))
1076     rast = createIvalPtr (sym, type, ilist);
1077   else
1078     /* if this is an array   */
1079   if (IS_ARRAY (type))
1080     rast = createIvalArray (sym, type, ilist);
1081   else
1082     /* if type is SPECIFIER */
1083   if (IS_SPEC (type))
1084     rast = createIvalType (sym, type, ilist);
1085
1086   if (wid)
1087     return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
1088   else
1089     return decorateType (resolveSymbols (rast), RESULT_CHECK);
1090 }
1091
1092 /*-----------------------------------------------------------------*/
1093 /* initAggregates - initialises aggregate variables with initv     */
1094 /*-----------------------------------------------------------------*/
1095 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1096   return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
1097 }
1098
1099 /*-----------------------------------------------------------------*/
1100 /* gatherAutoInit - creates assignment expressions for initial     */
1101 /*    values                 */
1102 /*-----------------------------------------------------------------*/
1103 static ast *
1104 gatherAutoInit (symbol * autoChain)
1105 {
1106   ast *init = NULL;
1107   ast *work;
1108   symbol *sym;
1109
1110   inInitMode = 1;
1111   for (sym = autoChain; sym; sym = sym->next)
1112     {
1113
1114       /* resolve the symbols in the ival */
1115       if (sym->ival)
1116         resolveIvalSym (sym->ival, sym->type);
1117
1118       /* if this is a static variable & has an */
1119       /* initial value the code needs to be lifted */
1120       /* here to the main portion since they can be */
1121       /* initialised only once at the start    */
1122       if (IS_STATIC (sym->etype) && sym->ival &&
1123           SPEC_SCLS (sym->etype) != S_CODE)
1124         {
1125           symbol *newSym;
1126           
1127           /* insert the symbol into the symbol table */
1128           /* with level = 0 & name = rname       */
1129           newSym = copySymbol (sym);
1130           addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1131
1132           /* now lift the code to main */
1133           if (IS_AGGREGATE (sym->type)) {
1134             work = initAggregates (sym, sym->ival, NULL);
1135           } else {
1136             if (getNelements(sym->type, sym->ival)>1) {
1137               werrorfl (sym->fileDef, sym->lineDef,
1138                         W_EXCESS_INITIALIZERS, "scalar", 
1139                         sym->name);
1140             }
1141             work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1142                             list2expr (sym->ival));
1143           }
1144
1145           setAstLineno (work, sym->lineDef);
1146
1147           sym->ival = NULL;
1148           if (staticAutos)
1149             staticAutos = newNode (NULLOP, staticAutos, work);
1150           else
1151             staticAutos = work;
1152
1153           continue;
1154         }
1155
1156       /* if there is an initial value */
1157       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1158         {
1159           initList *ilist=sym->ival;
1160           
1161           while (ilist->type == INIT_DEEP) {
1162             ilist = ilist->init.deep;
1163           }
1164
1165           /* update lineno for error msg */
1166           lineno=sym->lineDef;
1167           setAstLineno (ilist->init.node, lineno);
1168           
1169           if (IS_AGGREGATE (sym->type)) {
1170             work = initAggregates (sym, sym->ival, NULL);
1171           } else {
1172             if (getNelements(sym->type, sym->ival)>1) {
1173               werrorfl (sym->fileDef, sym->lineDef,
1174                         W_EXCESS_INITIALIZERS, "scalar", 
1175                         sym->name);
1176             }
1177             work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1178                             list2expr (sym->ival));
1179           }
1180           
1181           // just to be sure
1182           setAstLineno (work, sym->lineDef);
1183
1184           sym->ival = NULL;
1185           if (init)
1186             init = newNode (NULLOP, init, work);
1187           else
1188             init = work;
1189         }
1190     }
1191   inInitMode = 0;
1192   return init;
1193 }
1194
1195 /*-----------------------------------------------------------------*/
1196 /* freeStringSymbol - delete a literal string if no more usage     */
1197 /*-----------------------------------------------------------------*/
1198 void freeStringSymbol(symbol *sym) {
1199   /* make sure this is a literal string */
1200   assert (sym->isstrlit);
1201   if (--sym->isstrlit == 0) { // lower the usage count
1202     memmap *segment=SPEC_OCLS(sym->etype);
1203     if (segment) {
1204       deleteSetItem(&segment->syms, sym);
1205     }
1206   }
1207 }
1208   
1209 /*-----------------------------------------------------------------*/
1210 /* stringToSymbol - creates a symbol from a literal string         */
1211 /*-----------------------------------------------------------------*/
1212 static value *
1213 stringToSymbol (value * val)
1214 {
1215   char name[SDCC_NAME_MAX + 1];
1216   static int charLbl = 0;
1217   symbol *sym;
1218   set *sp;
1219   unsigned int size;
1220
1221   // have we heard this before?
1222   for (sp=statsg->syms; sp; sp=sp->next) {
1223     sym=sp->item;
1224     size = getSize (sym->type);
1225     if (sym->isstrlit && size == getSize (val->type) &&
1226         !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
1227       // yes, this is old news. Don't publish it again.
1228       sym->isstrlit++; // but raise the usage count
1229       return symbolVal(sym);
1230     }
1231   }
1232
1233   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1234   sym = newSymbol (name, 0);    /* make it @ level 0 */
1235   strncpyz (sym->rname, name, SDCC_NAME_MAX);
1236
1237   /* copy the type from the value passed */
1238   sym->type = copyLinkChain (val->type);
1239   sym->etype = getSpec (sym->type);
1240   /* change to storage class & output class */
1241   SPEC_SCLS (sym->etype) = S_CODE;
1242   SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1243   SPEC_STAT (sym->etype) = 1;
1244   /* make the level & block = 0 */
1245   sym->block = sym->level = 0;
1246   sym->isstrlit = 1;
1247   /* create an ival */
1248   sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1249   if (noAlloc == 0)
1250     {
1251       /* allocate it */
1252       addSymChain (sym);
1253       allocVariables (sym);
1254     }
1255   sym->ival = NULL;
1256   return symbolVal (sym);
1257
1258 }
1259
1260 /*-----------------------------------------------------------------*/
1261 /* processBlockVars - will go thru the ast looking for block if    */
1262 /*                    a block is found then will allocate the syms */
1263 /*                    will also gather the auto inits present      */
1264 /*-----------------------------------------------------------------*/
1265 ast *
1266 processBlockVars (ast * tree, int *stack, int action)
1267 {
1268   if (!tree)
1269     return NULL;
1270
1271   /* if this is a block */
1272   if (tree->type == EX_OP && tree->opval.op == BLOCK)
1273     {
1274       ast *autoInit;
1275
1276       if (action == ALLOCATE)
1277         {
1278           *stack += allocVariables (tree->values.sym);
1279           autoInit = gatherAutoInit (tree->values.sym);
1280         
1281           /* if there are auto inits then do them */
1282           if (autoInit)
1283             tree->left = newNode (NULLOP, autoInit, tree->left);
1284         }
1285       else                      /* action is deallocate */
1286         deallocLocal (tree->values.sym);
1287     }
1288
1289   processBlockVars (tree->left, stack, action);
1290   processBlockVars (tree->right, stack, action);
1291   return tree;
1292 }
1293
1294
1295 /*-------------------------------------------------------------*/
1296 /* constExprTree - returns TRUE if this tree is a constant     */
1297 /*                 expression                                  */
1298 /*-------------------------------------------------------------*/
1299 bool constExprTree (ast *cexpr) {
1300
1301   if (!cexpr) {
1302     return TRUE;
1303   }
1304
1305   cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
1306
1307   switch (cexpr->type) 
1308     {
1309     case EX_VALUE:
1310       if (IS_AST_LIT_VALUE(cexpr)) {
1311         // this is a literal
1312         return TRUE;
1313       }
1314       if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1315         // a function's address will never change
1316         return TRUE;
1317       }
1318       if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1319         // an array's address will never change
1320         return TRUE;
1321       }
1322       if (IS_AST_SYM_VALUE(cexpr) && 
1323           IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1324         // a symbol in code space will never change
1325         // This is only for the 'char *s="hallo"' case and will have to leave
1326         //printf(" code space symbol");
1327         return TRUE;
1328       }
1329       return FALSE;
1330     case EX_LINK:
1331       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1332               "unexpected link in expression tree\n");
1333       return FALSE;
1334     case EX_OP:
1335       if (cexpr->opval.op==ARRAYINIT) {
1336         // this is a list of literals
1337         return TRUE;
1338       }
1339       if (cexpr->opval.op=='=') {
1340         return constExprTree(cexpr->right);
1341       }
1342       if (cexpr->opval.op==CAST) {
1343         // cast ignored, maybe we should throw a warning here?
1344         return constExprTree(cexpr->right);
1345       }
1346       if (cexpr->opval.op=='&') { 
1347         return TRUE;
1348       }
1349       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1350         return FALSE;
1351       }
1352       if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1353         return TRUE;
1354       }
1355       return FALSE;
1356     case EX_OPERAND:
1357       return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1358     }
1359   return FALSE;
1360 }
1361     
1362 /*-----------------------------------------------------------------*/
1363 /* constExprValue - returns the value of a constant expression     */
1364 /*                  or NULL if it is not a constant expression     */
1365 /*-----------------------------------------------------------------*/
1366 value *
1367 constExprValue (ast * cexpr, int check)
1368 {
1369   cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
1370
1371   /* if this is not a constant then */
1372   if (!IS_LITERAL (cexpr->ftype))
1373     {
1374       /* then check if this is a literal array
1375          in code segment */
1376       if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1377           SPEC_CVAL (cexpr->etype).v_char &&
1378           IS_ARRAY (cexpr->ftype))
1379         {
1380           value *val = valFromType (cexpr->ftype);
1381           SPEC_SCLS (val->etype) = S_LITERAL;
1382           val->sym = cexpr->opval.val->sym;
1383           val->sym->type = copyLinkChain (cexpr->ftype);
1384           val->sym->etype = getSpec (val->sym->type);
1385           strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1386           return val;
1387         }
1388
1389       /* if we are casting a literal value then */
1390       if (IS_AST_OP (cexpr) &&
1391           cexpr->opval.op == CAST &&
1392           IS_LITERAL (cexpr->right->ftype))
1393         {
1394         return valCastLiteral (cexpr->ftype,
1395                                floatFromVal (cexpr->right->opval.val));
1396         }
1397
1398       if (IS_AST_VALUE (cexpr))
1399         {
1400         return cexpr->opval.val;
1401         }
1402
1403       if (check)
1404         werror (E_CONST_EXPECTED, "found expression");
1405
1406       return NULL;
1407     }
1408
1409   /* return the value */
1410   return cexpr->opval.val;
1411
1412 }
1413
1414 /*-----------------------------------------------------------------*/
1415 /* isLabelInAst - will return true if a given label is found       */
1416 /*-----------------------------------------------------------------*/
1417 bool 
1418 isLabelInAst (symbol * label, ast * tree)
1419 {
1420   if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1421     return FALSE;
1422
1423   if (IS_AST_OP (tree) &&
1424       tree->opval.op == LABEL &&
1425       isSymbolEqual (AST_SYMBOL (tree->left), label))
1426     return TRUE;
1427
1428   return isLabelInAst (label, tree->right) &&
1429     isLabelInAst (label, tree->left);
1430
1431 }
1432
1433 /*-----------------------------------------------------------------*/
1434 /* isLoopCountable - return true if the loop count can be determi- */
1435 /* -ned at compile time .                                          */
1436 /*-----------------------------------------------------------------*/
1437 bool 
1438 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1439                  symbol ** sym, ast ** init, ast ** end)
1440 {
1441
1442   /* the loop is considered countable if the following
1443      conditions are true :-
1444
1445      a) initExpr :- <sym> = <const>
1446      b) condExpr :- <sym> < <const1>
1447      c) loopExpr :- <sym> ++
1448    */
1449
1450   /* first check the initExpr */
1451   if (IS_AST_OP (initExpr) &&
1452       initExpr->opval.op == '=' &&      /* is assignment */
1453       IS_AST_SYM_VALUE (initExpr->left))
1454     {                           /* left is a symbol */
1455
1456       *sym = AST_SYMBOL (initExpr->left);
1457       *init = initExpr->right;
1458     }
1459   else
1460     return FALSE;
1461
1462   /* for now the symbol has to be of
1463      integral type */
1464   if (!IS_INTEGRAL ((*sym)->type))
1465     return FALSE;
1466
1467   /* now check condExpr */
1468   if (IS_AST_OP (condExpr))
1469     {
1470
1471       switch (condExpr->opval.op)
1472         {
1473         case '<':
1474           if (IS_AST_SYM_VALUE (condExpr->left) &&
1475               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1476               IS_AST_LIT_VALUE (condExpr->right))
1477             {
1478               *end = condExpr->right;
1479               break;
1480             }
1481           return FALSE;
1482
1483         case '!':
1484           if (IS_AST_OP (condExpr->left) &&
1485               condExpr->left->opval.op == '>' &&
1486               IS_AST_LIT_VALUE (condExpr->left->right) &&
1487               IS_AST_SYM_VALUE (condExpr->left->left) &&
1488               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1489             {
1490
1491               *end = newNode ('+', condExpr->left->right,
1492                               newAst_VALUE (constVal ("1")));
1493               break;
1494             }
1495           return FALSE;
1496
1497         default:
1498           return FALSE;
1499         }
1500
1501     }
1502
1503   /* check loop expression is of the form <sym>++ */
1504   if (!IS_AST_OP (loopExpr))
1505     return FALSE;
1506
1507   /* check if <sym> ++ */
1508   if (loopExpr->opval.op == INC_OP)
1509     {
1510
1511       if (loopExpr->left)
1512         {
1513           /* pre */
1514           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1515               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1516             return TRUE;
1517
1518         }
1519       else
1520         {
1521           /* post */
1522           if (IS_AST_SYM_VALUE (loopExpr->right) &&
1523               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1524             return TRUE;
1525         }
1526
1527     }
1528   else
1529     {
1530       /* check for += */
1531       if (loopExpr->opval.op == ADD_ASSIGN)
1532         {
1533
1534           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1535               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1536               IS_AST_LIT_VALUE (loopExpr->right) &&
1537               (int) AST_LIT_VALUE (loopExpr->right) != 1)
1538             return TRUE;
1539         }
1540     }
1541
1542   return FALSE;
1543 }
1544
1545 /*-----------------------------------------------------------------*/
1546 /* astHasVolatile - returns true if ast contains any volatile      */
1547 /*-----------------------------------------------------------------*/
1548 bool 
1549 astHasVolatile (ast * tree)
1550 {
1551   if (!tree)
1552     return FALSE;
1553
1554   if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1555     return TRUE;
1556
1557   if (IS_AST_OP (tree))
1558     return astHasVolatile (tree->left) ||
1559       astHasVolatile (tree->right);
1560   else
1561     return FALSE;
1562 }
1563
1564 /*-----------------------------------------------------------------*/
1565 /* astHasPointer - return true if the ast contains any ptr variable */
1566 /*-----------------------------------------------------------------*/
1567 bool 
1568 astHasPointer (ast * tree)
1569 {
1570   if (!tree)
1571     return FALSE;
1572
1573   if (IS_AST_LINK (tree))
1574     return TRUE;
1575
1576   /* if we hit an array expression then check
1577      only the left side */
1578   if (IS_AST_OP (tree) && tree->opval.op == '[')
1579     return astHasPointer (tree->left);
1580
1581   if (IS_AST_VALUE (tree))
1582     return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1583
1584   return astHasPointer (tree->left) ||
1585     astHasPointer (tree->right);
1586
1587 }
1588
1589 /*-----------------------------------------------------------------*/
1590 /* astHasSymbol - return true if the ast has the given symbol      */
1591 /*-----------------------------------------------------------------*/
1592 bool 
1593 astHasSymbol (ast * tree, symbol * sym)
1594 {
1595   if (!tree || IS_AST_LINK (tree))
1596     return FALSE;
1597
1598   if (IS_AST_VALUE (tree))
1599     {
1600       if (IS_AST_SYM_VALUE (tree))
1601         return isSymbolEqual (AST_SYMBOL (tree), sym);
1602       else
1603         return FALSE;
1604     }
1605
1606   return astHasSymbol (tree->left, sym) ||
1607     astHasSymbol (tree->right, sym);
1608 }
1609
1610 /*-----------------------------------------------------------------*/
1611 /* astHasDeref - return true if the ast has an indirect access     */
1612 /*-----------------------------------------------------------------*/
1613 static bool 
1614 astHasDeref (ast * tree)
1615 {
1616   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1617     return FALSE;
1618
1619   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1620   
1621   return astHasDeref (tree->left) || astHasDeref (tree->right);
1622 }
1623
1624 /*-----------------------------------------------------------------*/
1625 /* isConformingBody - the loop body has to conform to a set of rules */
1626 /* for the loop to be considered reversible read on for rules      */
1627 /*-----------------------------------------------------------------*/
1628 bool 
1629 isConformingBody (ast * pbody, symbol * sym, ast * body)
1630 {
1631
1632   /* we are going to do a pre-order traversal of the
1633      tree && check for the following conditions. (essentially
1634      a set of very shallow tests )
1635      a) the sym passed does not participate in
1636      any arithmetic operation
1637      b) There are no function calls
1638      c) all jumps are within the body
1639      d) address of loop control variable not taken
1640      e) if an assignment has a pointer on the
1641      left hand side make sure right does not have
1642      loop control variable */
1643
1644   /* if we reach the end or a leaf then true */
1645   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1646     return TRUE;
1647   
1648   /* if anything else is "volatile" */
1649   if (IS_VOLATILE (TETYPE (pbody)))
1650     return FALSE;
1651
1652   /* we will walk the body in a pre-order traversal for
1653      efficiency sake */
1654   switch (pbody->opval.op)
1655     {
1656 /*------------------------------------------------------------------*/
1657     case '[':
1658       // if the loopvar is used as an index
1659       /* array op is commutative -- must check both left & right */
1660       if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1661         return FALSE;
1662       }
1663       return isConformingBody (pbody->right, sym, body)
1664               && isConformingBody (pbody->left, sym, body);
1665
1666 /*------------------------------------------------------------------*/
1667     case PTR_OP:
1668     case '.':
1669       return TRUE;
1670
1671 /*------------------------------------------------------------------*/
1672     case INC_OP:
1673     case DEC_OP:
1674
1675       /* sure we are not sym is not modified */
1676       if (pbody->left &&
1677           IS_AST_SYM_VALUE (pbody->left) &&
1678           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1679         return FALSE;
1680
1681       if (pbody->right &&
1682           IS_AST_SYM_VALUE (pbody->right) &&
1683           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1684         return FALSE;
1685
1686       return TRUE;
1687
1688 /*------------------------------------------------------------------*/
1689
1690     case '*':                   /* can be unary  : if right is null then unary operation */
1691     case '+':
1692     case '-':
1693     case '&':
1694
1695       /* if right is NULL then unary operation  */
1696 /*------------------------------------------------------------------*/
1697 /*----------------------------*/
1698       /*  address of                */
1699 /*----------------------------*/
1700       if (!pbody->right)
1701         {
1702           if (IS_AST_SYM_VALUE (pbody->left) &&
1703               isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1704             return FALSE;
1705           else
1706             return isConformingBody (pbody->left, sym, body);
1707         }
1708       else
1709         {
1710           if (astHasSymbol (pbody->left, sym) ||
1711               astHasSymbol (pbody->right, sym))
1712             return FALSE;
1713         }
1714
1715
1716 /*------------------------------------------------------------------*/
1717     case '|':
1718     case '^':
1719     case '/':
1720     case '%':
1721     case LEFT_OP:
1722     case RIGHT_OP:
1723
1724       if (IS_AST_SYM_VALUE (pbody->left) &&
1725           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1726         return FALSE;
1727
1728       if (IS_AST_SYM_VALUE (pbody->right) &&
1729           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1730         return FALSE;
1731
1732       return isConformingBody (pbody->left, sym, body) &&
1733         isConformingBody (pbody->right, sym, body);
1734
1735     case '~':
1736     case '!':
1737     case RRC:
1738     case RLC:
1739     case GETHBIT:
1740     case SWAP:
1741       if (IS_AST_SYM_VALUE (pbody->left) &&
1742           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1743         return FALSE;
1744       return isConformingBody (pbody->left, sym, body);
1745
1746 /*------------------------------------------------------------------*/
1747
1748     case AND_OP:
1749     case OR_OP:
1750     case '>':
1751     case '<':
1752     case LE_OP:
1753     case GE_OP:
1754     case EQ_OP:
1755     case NE_OP:
1756     case '?':
1757     case ':':
1758     case SIZEOF:                /* evaluate wihout code generation */
1759
1760       if (IS_AST_SYM_VALUE (pbody->left) &&
1761           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1762         return FALSE;
1763
1764       if (IS_AST_SYM_VALUE (pbody->right) &&
1765           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1766         return FALSE;
1767
1768       return isConformingBody (pbody->left, sym, body) &&
1769         isConformingBody (pbody->right, sym, body);
1770
1771 /*------------------------------------------------------------------*/
1772     case '=':
1773
1774       /* if left has a pointer & right has loop
1775          control variable then we cannot */
1776       if (astHasPointer (pbody->left) &&
1777           astHasSymbol (pbody->right, sym))
1778         return FALSE;
1779       if (astHasVolatile (pbody->left))
1780         return FALSE;
1781
1782       if (IS_AST_SYM_VALUE (pbody->left)) {
1783         // if the loopvar has an assignment
1784         if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1785           return FALSE;
1786         // if the loopvar is used in another (maybe conditional) block
1787         if (astHasSymbol (pbody->right, sym) &&
1788             (pbody->level >= body->level)) {
1789           return FALSE;
1790         }
1791       }
1792
1793       if (astHasVolatile (pbody->left))
1794         return FALSE;
1795
1796       if (astHasDeref(pbody->right)) return FALSE;
1797
1798       return isConformingBody (pbody->left, sym, body) &&
1799         isConformingBody (pbody->right, sym, body);
1800
1801     case MUL_ASSIGN:
1802     case DIV_ASSIGN:
1803     case AND_ASSIGN:
1804     case OR_ASSIGN:
1805     case XOR_ASSIGN:
1806     case RIGHT_ASSIGN:
1807     case LEFT_ASSIGN:
1808     case SUB_ASSIGN:
1809     case ADD_ASSIGN:
1810       assert ("Parser should not have generated this\n");
1811
1812 /*------------------------------------------------------------------*/
1813 /*----------------------------*/
1814       /*      comma operator        */
1815 /*----------------------------*/
1816     case ',':
1817       return isConformingBody (pbody->left, sym, body) &&
1818         isConformingBody (pbody->right, sym, body);
1819
1820 /*------------------------------------------------------------------*/
1821 /*----------------------------*/
1822       /*       function call        */
1823 /*----------------------------*/
1824     case CALL:
1825         /* if local & not passed as paramater then ok */
1826         if (sym->level && !astHasSymbol(pbody->right,sym)) 
1827             return TRUE;
1828       return FALSE;
1829
1830 /*------------------------------------------------------------------*/
1831 /*----------------------------*/
1832       /*     return statement       */
1833 /*----------------------------*/
1834     case RETURN:
1835       return FALSE;
1836
1837     case GOTO:
1838       if (isLabelInAst (AST_SYMBOL (pbody->left), body))
1839         return TRUE;
1840       else
1841         return FALSE;
1842     case SWITCH:
1843       if (astHasSymbol (pbody->left, sym))
1844         return FALSE;
1845
1846     default:
1847       break;
1848     }
1849
1850   return isConformingBody (pbody->left, sym, body) &&
1851     isConformingBody (pbody->right, sym, body);
1852
1853
1854
1855 }
1856
1857 /*-----------------------------------------------------------------*/
1858 /* isLoopReversible - takes a for loop as input && returns true    */
1859 /* if the for loop is reversible. If yes will set the value of     */
1860 /* the loop control var & init value & termination value           */
1861 /*-----------------------------------------------------------------*/
1862 bool
1863 isLoopReversible (ast * loop, symbol ** loopCntrl,
1864                   ast ** init, ast ** end)
1865 {
1866   /* if option says don't do it then don't */
1867   if (optimize.noLoopReverse)
1868     return 0;
1869   /* there are several tests to determine this */
1870
1871   /* for loop has to be of the form
1872      for ( <sym> = <const1> ;
1873      [<sym> < <const2>]  ;
1874      [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
1875      forBody */
1876   if (!isLoopCountable (AST_FOR (loop, initExpr),
1877                         AST_FOR (loop, condExpr),
1878                         AST_FOR (loop, loopExpr),
1879                         loopCntrl, init, end))
1880     return 0;
1881
1882   /* now do some serious checking on the body of the loop
1883    */
1884
1885   return isConformingBody (loop->left, *loopCntrl, loop->left);
1886
1887 }
1888
1889 /*-----------------------------------------------------------------*/
1890 /* replLoopSym - replace the loop sym by loop sym -1               */
1891 /*-----------------------------------------------------------------*/
1892 static void 
1893 replLoopSym (ast * body, symbol * sym)
1894 {
1895   /* reached end */
1896   if (!body || IS_AST_LINK (body))
1897     return;
1898
1899   if (IS_AST_SYM_VALUE (body))
1900     {
1901
1902       if (isSymbolEqual (AST_SYMBOL (body), sym))
1903         {
1904
1905           body->type = EX_OP;
1906           body->opval.op = '-';
1907           body->left = newAst_VALUE (symbolVal (sym));
1908           body->right = newAst_VALUE (constVal ("1"));
1909
1910         }
1911
1912       return;
1913
1914     }
1915
1916   replLoopSym (body->left, sym);
1917   replLoopSym (body->right, sym);
1918
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* reverseLoop - do the actual loop reversal                       */
1923 /*-----------------------------------------------------------------*/
1924 ast *
1925 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
1926 {
1927   ast *rloop;
1928
1929   /* create the following tree
1930      <sym> = loopCount ;
1931      for_continue:
1932      forbody
1933      <sym> -= 1;
1934      if (sym) goto for_continue ;
1935      <sym> = end */
1936
1937   /* put it together piece by piece */
1938   rloop = newNode (NULLOP,
1939                    createIf (newAst_VALUE (symbolVal (sym)),
1940                              newNode (GOTO,
1941                                       newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
1942                                       NULL), NULL),
1943                    newNode ('=',
1944                             newAst_VALUE (symbolVal (sym)),
1945                             end));
1946
1947   replLoopSym (loop->left, sym);
1948   setAstLineno (rloop, init->lineno);
1949
1950   rloop = newNode (NULLOP,
1951                    newNode ('=',
1952                             newAst_VALUE (symbolVal (sym)),
1953                             newNode ('-', end, init)),
1954                    createLabel (AST_FOR (loop, continueLabel),
1955                                 newNode (NULLOP,
1956                                          loop->left,
1957                                          newNode (NULLOP,
1958                                                   newNode (SUB_ASSIGN,
1959                                                            newAst_VALUE (symbolVal (sym)),
1960                                                            newAst_VALUE (constVal ("1"))),
1961                                                   rloop))));
1962
1963   rloop->lineno=init->lineno;
1964   return decorateType (rloop, RESULT_CHECK);
1965
1966 }
1967
1968 /*-----------------------------------------------------------------*/
1969 /* searchLitOp - search tree (*ops only) for an ast with literal */
1970 /*-----------------------------------------------------------------*/
1971 static ast *
1972 searchLitOp (ast *tree, ast **parent, const char *ops)
1973 {
1974   ast *ret;
1975
1976   if (tree && optimize.global_cse)
1977     {
1978       /* is there a literal operand? */
1979       if (tree->right &&
1980           IS_AST_OP(tree->right) &&
1981           tree->right->right &&
1982           (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
1983         {
1984           if (IS_LITERAL (RTYPE (tree->right)) !=
1985               IS_LITERAL (LTYPE (tree->right)))
1986             {
1987               tree->right->decorated = 0;
1988               tree->decorated = 0;
1989               *parent = tree;
1990               return tree->right;
1991             }
1992           ret = searchLitOp (tree->right, parent, ops);
1993           if (ret)
1994             return ret;
1995         }
1996       if (tree->left &&
1997           IS_AST_OP(tree->left) &&
1998           tree->left->right &&
1999           (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
2000         {
2001           if (IS_LITERAL (RTYPE (tree->left)) !=
2002               IS_LITERAL (LTYPE (tree->left)))
2003             {
2004               tree->left->decorated = 0;
2005               tree->decorated = 0;
2006               *parent = tree;
2007               return tree->left;
2008             }
2009           ret = searchLitOp (tree->left, parent, ops);
2010           if (ret)
2011             return ret;
2012         }
2013     }
2014   return NULL;
2015 }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* getResultFromType                                               */
2019 /*-----------------------------------------------------------------*/
2020 RESULT_TYPE
2021 getResultTypeFromType (sym_link *type)
2022 {
2023   /* type = getSpec (type); */
2024   if (IS_BIT (type))
2025     return RESULT_TYPE_BIT;
2026   if (IS_BITFIELD (type))
2027     {
2028       int blen = SPEC_BLEN (type);
2029       
2030       if (blen <= 1)
2031         return RESULT_TYPE_BIT;
2032       if (blen <= 8)
2033         return RESULT_TYPE_CHAR;
2034       return RESULT_TYPE_INT;
2035     }
2036   if (IS_CHAR (type))
2037     return RESULT_TYPE_CHAR;
2038   if (   IS_INT (type)
2039       && !IS_LONG (type))
2040     return RESULT_TYPE_INT;
2041   return RESULT_TYPE_OTHER;
2042 }
2043
2044 /*-----------------------------------------------------------------*/
2045 /* addCast - adds casts to a type specified by RESULT_TYPE         */
2046 /*-----------------------------------------------------------------*/
2047 static ast *
2048 addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
2049 {
2050   sym_link *newLink;
2051   bool upCasted = FALSE;
2052   
2053   switch (resultType)
2054     {
2055       case RESULT_TYPE_NONE:
2056         /* char: promote to int */
2057         if (!upcast ||
2058             getSize (tree->etype) >= INTSIZE)
2059           return tree;
2060         newLink = newIntLink();
2061         upCasted = TRUE;
2062         break;
2063       case RESULT_TYPE_CHAR:
2064         if (IS_CHAR (tree->etype) ||
2065             IS_FLOAT(tree->etype))
2066           return tree;
2067         newLink = newCharLink();
2068         break;
2069       case RESULT_TYPE_INT:
2070 #if 0
2071         if (getSize (tree->etype) > INTSIZE)
2072           {
2073             /* warn ("Loosing significant digits"); */
2074             return;
2075           }
2076 #endif
2077         /* char: promote to int */
2078         if (!upcast ||
2079             getSize (tree->etype) >= INTSIZE)
2080           return tree;
2081         newLink = newIntLink();
2082         upCasted = TRUE;
2083         break;
2084       case RESULT_TYPE_OTHER:
2085         if (!upcast)
2086           return tree;
2087         /* return type is long, float: promote char to int */
2088         if (getSize (tree->etype) >= INTSIZE)
2089           return tree;
2090         newLink = newIntLink();
2091         upCasted = TRUE;
2092         break;
2093       default:
2094         return tree;
2095     }
2096   tree->decorated = 0;
2097   tree = newNode (CAST, newAst_LINK (newLink), tree);
2098   tree->lineno = tree->right->lineno;
2099   /* keep unsigned type during cast to smaller type,
2100      but not when promoting from char to int */
2101   if (!upCasted)
2102     SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2103   return decorateType (tree, resultType);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* resultTypePropagate - decides if resultType can be propagated   */
2108 /*-----------------------------------------------------------------*/
2109 static RESULT_TYPE
2110 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2111 {
2112   switch (tree->opval.op)
2113     {
2114       case '=':
2115       case '?':
2116       case ':':
2117       case '|':
2118       case '^':
2119       case '~':
2120       case '*':
2121       case '+':
2122       case '-':
2123       case LABEL:
2124         return resultType;
2125       case '&':
2126         if (!tree->right)
2127           /* can be unary */
2128           return RESULT_TYPE_NONE;
2129         else
2130           return resultType;
2131       case IFX:
2132         return RESULT_TYPE_IFX;
2133       default:
2134         return RESULT_TYPE_NONE;
2135     }
2136 }
2137
2138 /*-----------------------------------------------------------------*/
2139 /* getLeftResultType - gets type from left branch for propagation  */
2140 /*-----------------------------------------------------------------*/
2141 static RESULT_TYPE
2142 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2143 {
2144   switch (tree->opval.op)
2145     {
2146       case '=':
2147       case CAST:
2148         if (IS_PTR (LTYPE (tree)))
2149           return RESULT_TYPE_NONE;
2150         else
2151           return getResultTypeFromType (LETYPE (tree));
2152       case RETURN:
2153         if (IS_PTR (currFunc->type->next))
2154           return RESULT_TYPE_NONE;
2155         else
2156           return getResultTypeFromType (currFunc->type->next);
2157       case '[':
2158         if (!IS_ARRAY (LTYPE (tree)))
2159           return resultType;
2160         if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
2161           return RESULT_TYPE_CHAR;
2162         return resultType;
2163       default:
2164         return resultType;
2165     }
2166 }
2167
2168 /*--------------------------------------------------------------------*/
2169 /* decorateType - compute type for this tree, also does type checking.*/
2170 /* This is done bottom up, since type has to flow upwards.            */
2171 /* resultType flows top-down and forces e.g. char-arithmetik, if the  */
2172 /* result is a char and the operand(s) are int's.                     */
2173 /* It also does constant folding, and parameter checking.             */
2174 /*--------------------------------------------------------------------*/
2175 ast *
2176 decorateType (ast * tree, RESULT_TYPE resultType)
2177 {
2178   int parmNumber;
2179   sym_link *p;
2180   RESULT_TYPE resultTypeProp;
2181
2182   if (!tree)
2183     return tree;
2184
2185   /* if already has type then do nothing */
2186   if (tree->decorated)
2187     return tree;
2188
2189   tree->decorated = 1;
2190
2191 #if 0
2192   /* print the line          */
2193   /* if not block & function */
2194   if (tree->type == EX_OP &&
2195       (tree->opval.op != FUNCTION &&
2196        tree->opval.op != BLOCK &&
2197        tree->opval.op != NULLOP))
2198     {
2199       filename = tree->filename;
2200       lineno = tree->lineno;
2201     }
2202 #endif
2203
2204   /* if any child is an error | this one is an error do nothing */
2205   if (tree->isError ||
2206       (tree->left && tree->left->isError) ||
2207       (tree->right && tree->right->isError))
2208     return tree;
2209
2210 /*------------------------------------------------------------------*/
2211 /*----------------------------*/
2212 /*   leaf has been reached    */
2213 /*----------------------------*/
2214   lineno=tree->lineno;
2215   /* if this is of type value */
2216   /* just get the type        */
2217   if (tree->type == EX_VALUE)
2218     {
2219
2220       if (IS_LITERAL (tree->opval.val->etype))
2221         {
2222
2223           /* if this is a character array then declare it */
2224           if (IS_ARRAY (tree->opval.val->type))
2225             tree->opval.val = stringToSymbol (tree->opval.val);
2226
2227           /* otherwise just copy the type information */
2228           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2229           return tree;
2230         }
2231
2232       if (tree->opval.val->sym)
2233         {
2234           /* if the undefined flag is set then give error message */
2235           if (tree->opval.val->sym->undefined)
2236             {
2237               werror (E_ID_UNDEF, tree->opval.val->sym->name);
2238               /* assume int */
2239               TTYPE (tree) = TETYPE (tree) =
2240                 tree->opval.val->type = tree->opval.val->sym->type =
2241                 tree->opval.val->etype = tree->opval.val->sym->etype =
2242                 copyLinkChain (INTTYPE);
2243             }
2244           else
2245             {
2246
2247               /* if impilicit i.e. struct/union member then no type */
2248               if (tree->opval.val->sym->implicit)
2249                 TTYPE (tree) = TETYPE (tree) = NULL;
2250
2251               else
2252                 {
2253
2254                   /* else copy the type */
2255                   COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2256
2257                   /* and mark it as referenced */
2258                   tree->opval.val->sym->isref = 1;
2259                 }
2260             }
2261         }
2262
2263       return tree;
2264     }
2265
2266   /* if type link for the case of cast */
2267   if (tree->type == EX_LINK)
2268     {
2269       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2270       return tree;
2271     }
2272
2273   {
2274     ast *dtl, *dtr;
2275
2276     #if 0
2277     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2278       {
2279         if (tree->left && tree->left->type == EX_OPERAND
2280             && (tree->left->opval.op == INC_OP
2281                 || tree->left->opval.op == DEC_OP)
2282             && tree->left->left)
2283           {
2284             tree->left->right = tree->left->left;
2285             tree->left->left = NULL;
2286           }
2287         if (tree->right && tree->right->type == EX_OPERAND
2288             && (tree->right->opval.op == INC_OP
2289                 || tree->right->opval.op == DEC_OP)
2290             && tree->right->left)
2291           {
2292             tree->right->right = tree->right->left;
2293             tree->right->left = NULL;
2294           }
2295       }
2296     #endif
2297
2298     /* Before decorating the left branch we've to decide in dependence
2299        upon tree->opval.op, if resultType can be propagated */
2300     resultTypeProp = resultTypePropagate (tree, resultType);
2301
2302     if (tree->opval.op == '?')
2303       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2304     else
2305       dtl = decorateType (tree->left, resultTypeProp);
2306
2307     /* if an array node, we may need to swap branches */
2308     if (tree->opval.op == '[')
2309       {
2310         /* determine which is the array & which the index */
2311         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2312             IS_INTEGRAL (LTYPE (tree)))
2313           {
2314             ast *tempTree = tree->left;
2315             tree->left = tree->right;
2316             tree->right = tempTree;
2317           }
2318       }
2319
2320     /* After decorating the left branch there's type information available
2321        in tree->left->?type. If the op is e.g. '=' we extract the type
2322        information from there and propagate it to the right branch. */
2323     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2324     
2325     switch (tree->opval.op)
2326       {
2327         case '?':
2328           /* delay right side for '?' operator since conditional macro
2329              expansions might rely on this */
2330           dtr = tree->right;
2331           break;
2332         case CALL: 
2333           /* decorate right side for CALL (parameter list) in processParms();
2334              there is resultType available */
2335           dtr = tree->right;
2336           break;
2337         default:     
2338           dtr = decorateType (tree->right, resultTypeProp);
2339           break;
2340       }
2341
2342     /* this is to take care of situations
2343        when the tree gets rewritten */
2344     if (dtl != tree->left)
2345       tree->left = dtl;
2346     if (dtr != tree->right)
2347       tree->right = dtr;
2348     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2349       return tree;
2350   }
2351
2352   /* depending on type of operator do */
2353
2354   switch (tree->opval.op)
2355     {
2356         /*------------------------------------------------------------------*/
2357         /*----------------------------*/
2358         /*        array node          */
2359         /*----------------------------*/
2360     case '[':
2361
2362       /* first check if this is a array or a pointer */
2363       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2364         {
2365           werror (E_NEED_ARRAY_PTR, "[]");
2366           goto errorTreeReturn;
2367         }
2368
2369       /* check if the type of the idx */
2370       if (!IS_INTEGRAL (RTYPE (tree)))
2371         {
2372           werror (E_IDX_NOT_INT);
2373           goto errorTreeReturn;
2374         }
2375
2376       /* if the left is an rvalue then error */
2377       if (LRVAL (tree))
2378         {
2379           werror (E_LVALUE_REQUIRED, "array access");
2380           goto errorTreeReturn;
2381         }
2382
2383       if (IS_LITERAL (RTYPE (tree)))
2384         {
2385           int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
2386           int arraySize = DCL_ELEM (LTYPE (tree));
2387           if (arraySize && arrayIndex >= arraySize)
2388             {
2389               werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2390             }
2391         }
2392
2393       RRVAL (tree) = 1;
2394       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2395       return tree;
2396
2397       /*------------------------------------------------------------------*/
2398       /*----------------------------*/
2399       /*      struct/union          */
2400       /*----------------------------*/
2401     case '.':
2402       /* if this is not a structure */
2403       if (!IS_STRUCT (LTYPE (tree)))
2404         {
2405           werror (E_STRUCT_UNION, ".");
2406           goto errorTreeReturn;
2407         }
2408       TTYPE (tree) = structElemType (LTYPE (tree),
2409                                      (tree->right->type == EX_VALUE ?
2410                                tree->right->opval.val : NULL));
2411       TETYPE (tree) = getSpec (TTYPE (tree));
2412       return tree;
2413
2414       /*------------------------------------------------------------------*/
2415       /*----------------------------*/
2416       /*    struct/union pointer    */
2417       /*----------------------------*/
2418     case PTR_OP:
2419       /* if not pointer to a structure */
2420       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2421         {
2422           werror (E_PTR_REQD);
2423           goto errorTreeReturn;
2424         }
2425
2426       if (!IS_STRUCT (LTYPE (tree)->next))
2427         {
2428           werror (E_STRUCT_UNION, "->");
2429           goto errorTreeReturn;
2430         }
2431
2432       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2433                                      (tree->right->type == EX_VALUE ?
2434                                tree->right->opval.val : NULL));
2435       TETYPE (tree) = getSpec (TTYPE (tree));
2436
2437       /* adjust the storage class */
2438       switch (DCL_TYPE(tree->left->ftype)) {
2439       case POINTER:
2440         SPEC_SCLS(TETYPE(tree)) = S_DATA; 
2441         break;
2442       case FPOINTER:
2443         SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2444         break;
2445       case CPOINTER:
2446         SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2447         break;
2448       case GPOINTER:
2449         SPEC_SCLS (TETYPE (tree)) = 0;
2450         break;
2451       case PPOINTER:
2452         SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2453         break;
2454       case IPOINTER:
2455         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2456         break;
2457       case EEPPOINTER:
2458         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2459         break;
2460       case UPOINTER:
2461         SPEC_SCLS (TETYPE (tree)) = 0;
2462         break;
2463       case ARRAY:
2464       case FUNCTION:
2465         break;
2466       }
2467       
2468       /* This breaks with extern declarations, bitfields, and perhaps other */
2469       /* cases (gcse). Let's leave this optimization disabled for now and   */
2470       /* ponder if there's a safe way to do this. -- EEP                    */
2471       #if 0
2472       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2473           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2474         {
2475             /* If defined    struct type at addr var
2476                then rewrite  (&struct var)->member
2477                as            temp
2478                and define    membertype at (addr+offsetof(struct var,member)) temp
2479             */
2480             symbol *sym;
2481             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2482                                                 AST_SYMBOL(tree->right));
2483
2484             sym = newSymbol(genSymName (0), 0);
2485             sym->type = TTYPE (tree);
2486             sym->etype = getSpec(sym->type);
2487             sym->lineDef = tree->lineno;
2488             sym->cdef = 1;
2489             sym->isref = 1;
2490             SPEC_STAT (sym->etype) = 1;
2491             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2492                                      + element->offset;
2493             SPEC_ABSA(sym->etype) = 1;
2494             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2495             allocGlobal (sym);
2496             
2497             AST_VALUE (tree) = symbolVal(sym);
2498             TLVAL (tree) = 1;
2499             TRVAL (tree) = 0;
2500             tree->type = EX_VALUE;
2501             tree->left = NULL;
2502             tree->right = NULL;
2503         }
2504       #endif
2505       
2506       return tree;
2507
2508       /*------------------------------------------------------------------*/
2509       /*----------------------------*/
2510       /*  ++/-- operation           */
2511       /*----------------------------*/
2512     case INC_OP:
2513     case DEC_OP:
2514       {
2515         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2516         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2517         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2518           werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2519
2520         if (tree->right)
2521           RLVAL (tree) = 1;
2522         else
2523           LLVAL (tree) = 1;
2524         return tree;
2525       }
2526
2527       /*------------------------------------------------------------------*/
2528       /*----------------------------*/
2529       /*  bitwise and               */
2530       /*----------------------------*/
2531     case '&':                   /* can be unary   */
2532       /* if right is NULL then unary operation  */
2533       if (tree->right)          /* not an unary operation */
2534         {
2535
2536           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2537             {
2538               werror (E_BITWISE_OP);
2539               werror (W_CONTINUE, "left & right types are ");
2540               printTypeChain (LTYPE (tree), stderr);
2541               fprintf (stderr, ",");
2542               printTypeChain (RTYPE (tree), stderr);
2543               fprintf (stderr, "\n");
2544               goto errorTreeReturn;
2545             }
2546
2547           /* if they are both literal */
2548           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2549             {
2550               tree->type = EX_VALUE;
2551               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2552                                           valFromType (RETYPE (tree)), '&');
2553
2554               tree->right = tree->left = NULL;
2555               TETYPE (tree) = tree->opval.val->etype;
2556               TTYPE (tree) = tree->opval.val->type;
2557               return tree;
2558             }
2559
2560           /* see if this is a GETHBIT operation if yes
2561              then return that */
2562           {
2563             ast *otree = optimizeGetHbit (tree);
2564
2565             if (otree != tree)
2566               return decorateType (otree, RESULT_CHECK);
2567           }
2568
2569           /* if left is a literal exchange left & right */
2570           if (IS_LITERAL (LTYPE (tree)))
2571             {
2572               ast *tTree = tree->left;
2573               tree->left = tree->right;
2574               tree->right = tTree;
2575             }
2576
2577           /* if right is a literal and */
2578           /* we can find a 2nd literal in an and-tree then */
2579           /* rearrange the tree */
2580           if (IS_LITERAL (RTYPE (tree)))
2581             {
2582               ast *parent;
2583               ast *litTree = searchLitOp (tree, &parent, "&");
2584               if (litTree)
2585                 {
2586                   DEBUG_CF("&")
2587                   ast *tTree = litTree->left;
2588                   litTree->left = tree->right;
2589                   tree->right = tTree;
2590                   /* both operands in litTree are literal now */
2591                   decorateType (parent, resultType);
2592                 }
2593             }
2594
2595           LRVAL (tree) = RRVAL (tree) = 1;
2596           
2597           TTYPE (tree) = computeType (LTYPE (tree),
2598                                       RTYPE (tree),
2599                                       resultType,
2600                                       tree->opval.op);
2601           TETYPE (tree) = getSpec (TTYPE (tree));
2602
2603           return tree;
2604         }
2605
2606       /*------------------------------------------------------------------*/
2607       /*----------------------------*/
2608       /*  address of                */
2609       /*----------------------------*/
2610       p = newLink (DECLARATOR);
2611       /* if bit field then error */
2612       if (IS_BITVAR (tree->left->etype))
2613         {
2614           werror (E_ILLEGAL_ADDR, "address of bit variable");
2615           goto errorTreeReturn;
2616         }
2617
2618       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2619         {
2620           werror (E_ILLEGAL_ADDR, "address of register variable");
2621           goto errorTreeReturn;
2622         }
2623
2624       if (IS_FUNC (LTYPE (tree)))
2625         {
2626           // this ought to be ignored
2627           return (tree->left);
2628         }
2629
2630       if (IS_LITERAL(LTYPE(tree)))
2631         {
2632           werror (E_ILLEGAL_ADDR, "address of literal");
2633           goto errorTreeReturn;
2634         }
2635
2636      if (LRVAL (tree))
2637         {
2638           werror (E_LVALUE_REQUIRED, "address of");
2639           goto errorTreeReturn;
2640         }
2641       if (!LETYPE (tree))
2642         DCL_TYPE (p) = POINTER;
2643       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2644         DCL_TYPE (p) = CPOINTER;
2645       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2646         DCL_TYPE (p) = FPOINTER;
2647       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2648         DCL_TYPE (p) = PPOINTER;
2649       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2650         DCL_TYPE (p) = IPOINTER;
2651       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2652         DCL_TYPE (p) = EEPPOINTER;
2653       else if (SPEC_OCLS(tree->left->etype))
2654           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2655       else
2656           DCL_TYPE (p) = POINTER;
2657
2658       if (IS_AST_SYM_VALUE (tree->left))
2659         {
2660           AST_SYMBOL (tree->left)->addrtaken = 1;
2661           AST_SYMBOL (tree->left)->allocreq = 1;
2662         }
2663
2664       p->next = LTYPE (tree);
2665       TTYPE (tree) = p;
2666       TETYPE (tree) = getSpec (TTYPE (tree));
2667       LLVAL (tree) = 1;
2668       TLVAL (tree) = 1;
2669
2670       #if 0
2671       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2672           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2673         {
2674           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2675                                       AST_SYMBOL(tree->left->right));
2676           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2677                                     valueFromLit(element->offset));
2678           tree->left = NULL;
2679           tree->right = NULL;
2680           tree->type = EX_VALUE;
2681           tree->values.literalFromCast = 1;
2682         }
2683       #endif
2684
2685       return tree;
2686
2687       /*------------------------------------------------------------------*/
2688       /*----------------------------*/
2689       /*  bitwise or                */
2690       /*----------------------------*/
2691     case '|':
2692       /* if the rewrite succeeds then don't go any furthur */
2693       {
2694         ast *wtree = optimizeRRCRLC (tree);
2695         if (wtree != tree)
2696           return decorateType (wtree, RESULT_CHECK);
2697         
2698         wtree = optimizeSWAP (tree);
2699         if (wtree != tree)
2700           return decorateType (wtree, RESULT_CHECK);
2701       }
2702
2703       /* if left is a literal exchange left & right */
2704       if (IS_LITERAL (LTYPE (tree)))
2705         {
2706           ast *tTree = tree->left;
2707           tree->left = tree->right;
2708           tree->right = tTree;
2709         }
2710
2711       /* if right is a literal and */
2712       /* we can find a 2nd literal in an or-tree then */
2713       /* rearrange the tree */
2714       if (IS_LITERAL (RTYPE (tree)))
2715         {
2716           ast *parent;
2717           ast *litTree = searchLitOp (tree, &parent, "|");
2718           if (litTree)
2719             {
2720               DEBUG_CF("|")
2721               ast *tTree = litTree->left;
2722               litTree->left = tree->right;
2723               tree->right = tTree;
2724               /* both operands in tTree are literal now */
2725               decorateType (parent, resultType);
2726             }
2727         }
2728       /* fall through */
2729
2730       /*------------------------------------------------------------------*/
2731       /*----------------------------*/
2732       /*  bitwise xor               */
2733       /*----------------------------*/
2734     case '^':
2735       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2736         {
2737           werror (E_BITWISE_OP);
2738           werror (W_CONTINUE, "left & right types are ");
2739           printTypeChain (LTYPE (tree), stderr);
2740           fprintf (stderr, ",");
2741           printTypeChain (RTYPE (tree), stderr);
2742           fprintf (stderr, "\n");
2743           goto errorTreeReturn;
2744         }
2745
2746       /* if they are both literal then rewrite the tree */
2747       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2748         {
2749           tree->type = EX_VALUE;
2750           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2751                                         valFromType (RETYPE (tree)),
2752                                         tree->opval.op);
2753           tree->right = tree->left = NULL;
2754           TETYPE (tree) = tree->opval.val->etype;
2755           TTYPE (tree) = tree->opval.val->type;
2756           return tree;
2757         }
2758
2759       /* if left is a literal exchange left & right */
2760       if (IS_LITERAL (LTYPE (tree)))
2761         {
2762           ast *tTree = tree->left;
2763           tree->left = tree->right;
2764           tree->right = tTree;
2765         }
2766
2767       /* if right is a literal and */
2768       /* we can find a 2nd literal in a xor-tree then */
2769       /* rearrange the tree */
2770       if (IS_LITERAL (RTYPE (tree)) &&
2771           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
2772         {
2773           ast *parent;
2774           ast *litTree = searchLitOp (tree, &parent, "^");
2775           if (litTree)
2776             {
2777               DEBUG_CF("^")
2778               ast *tTree = litTree->left;
2779               litTree->left = tree->right;
2780               tree->right = tTree;
2781               /* both operands in litTree are literal now */
2782               decorateType (parent, resultType);
2783             }
2784         }
2785
2786       LRVAL (tree) = RRVAL (tree) = 1;
2787
2788       TTYPE (tree) = computeType (LTYPE (tree),
2789                                   RTYPE (tree),
2790                                   resultType,
2791                                   tree->opval.op);
2792       TETYPE (tree) = getSpec (TTYPE (tree));
2793
2794       return tree;
2795
2796       /*------------------------------------------------------------------*/
2797       /*----------------------------*/
2798       /*  division                  */
2799       /*----------------------------*/
2800     case '/':
2801       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2802         {
2803           werror (E_INVALID_OP, "divide");
2804           goto errorTreeReturn;
2805         }
2806       /* if they are both literal then */
2807       /* rewrite the tree */
2808       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2809         {
2810           tree->type = EX_VALUE;
2811           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
2812                                     valFromType (RETYPE (tree)));
2813           tree->right = tree->left = NULL;
2814           TETYPE (tree) = getSpec (TTYPE (tree) =
2815                                    tree->opval.val->type);
2816           return tree;
2817         }
2818
2819       LRVAL (tree) = RRVAL (tree) = 1;
2820
2821       TETYPE (tree) = getSpec (TTYPE (tree) =
2822                                computeType (LTYPE (tree),
2823                                             RTYPE (tree),
2824                                             resultType,
2825                                             tree->opval.op));
2826
2827       /* if right is a literal and */
2828       /* left is also a division by a literal then */
2829       /* rearrange the tree */
2830       if (IS_LITERAL (RTYPE (tree))
2831           /* avoid infinite loop */
2832           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
2833         {
2834           ast *parent;
2835           ast *litTree = searchLitOp (tree, &parent, "/");
2836           if (litTree)
2837             {
2838               if (IS_LITERAL (RTYPE (litTree)))
2839                 {
2840                   /* foo_div */
2841                   DEBUG_CF("div r")
2842                   litTree->right = newNode ('*',
2843                                             litTree->right,
2844                                             copyAst (tree->right));
2845                   litTree->right->lineno = tree->lineno;
2846
2847                   tree->right->opval.val = constVal ("1");
2848                   decorateType (parent, resultType);
2849                 }
2850               else
2851                 {
2852                   /* litTree->left is literal: no gcse possible.
2853                      We can't call decorateType(parent, RESULT_CHECK), because
2854                      this would cause an infinit loop. */
2855                   parent->decorated = 1;
2856                   decorateType (litTree, resultType);
2857                 }
2858             }
2859         }
2860
2861       return tree;
2862
2863       /*------------------------------------------------------------------*/
2864       /*----------------------------*/
2865       /*            modulus         */
2866       /*----------------------------*/
2867     case '%':
2868       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2869         {
2870           werror (E_BITWISE_OP);
2871           werror (W_CONTINUE, "left & right types are ");
2872           printTypeChain (LTYPE (tree), stderr);
2873           fprintf (stderr, ",");
2874           printTypeChain (RTYPE (tree), stderr);
2875           fprintf (stderr, "\n");
2876           goto errorTreeReturn;
2877         }
2878       /* if they are both literal then */
2879       /* rewrite the tree */
2880       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2881         {
2882           tree->type = EX_VALUE;
2883           tree->opval.val = valMod (valFromType (LETYPE (tree)),
2884                                     valFromType (RETYPE (tree)));
2885           tree->right = tree->left = NULL;
2886           TETYPE (tree) = getSpec (TTYPE (tree) =
2887                                    tree->opval.val->type);
2888           return tree;
2889         }
2890       LRVAL (tree) = RRVAL (tree) = 1;
2891       TETYPE (tree) = getSpec (TTYPE (tree) =
2892                                computeType (LTYPE (tree),
2893                                             RTYPE (tree),
2894                                             resultType,
2895                                             tree->opval.op));
2896       return tree;
2897
2898       /*------------------------------------------------------------------*/
2899       /*----------------------------*/
2900       /*  address dereference       */
2901       /*----------------------------*/
2902     case '*':                   /* can be unary  : if right is null then unary operation */
2903       if (!tree->right)
2904         {
2905           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2906             {
2907               werror (E_PTR_REQD);
2908               goto errorTreeReturn;
2909             }
2910
2911           if (LRVAL (tree))
2912             {
2913               werror (E_LVALUE_REQUIRED, "pointer deref");
2914               goto errorTreeReturn;
2915             }
2916           if (IS_ADDRESS_OF_OP(tree->left))
2917             {
2918               /* replace *&obj with obj */
2919               return tree->left->left;
2920             }
2921           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
2922           TETYPE (tree) = getSpec (TTYPE (tree));
2923           /* adjust the storage class */
2924           switch (DCL_TYPE(tree->left->ftype)) {
2925             case POINTER:
2926               SPEC_SCLS(TETYPE(tree)) = S_DATA;
2927               break;
2928             case FPOINTER:
2929               SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2930               break;
2931             case CPOINTER:
2932               SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2933               break;
2934             case GPOINTER:
2935               SPEC_SCLS (TETYPE (tree)) = 0;
2936               break;
2937             case PPOINTER:
2938               SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2939               break;
2940             case IPOINTER:
2941               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2942               break;
2943             case EEPPOINTER:
2944               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2945               break;
2946             case UPOINTER:
2947               SPEC_SCLS (TETYPE (tree)) = 0;
2948               break;
2949             case ARRAY:
2950             case FUNCTION:
2951               break;
2952           }
2953           return tree;
2954         }
2955
2956       /*------------------------------------------------------------------*/
2957       /*----------------------------*/
2958       /*      multiplication        */
2959       /*----------------------------*/
2960       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2961         {
2962           werror (E_INVALID_OP, "multiplication");
2963           goto errorTreeReturn;
2964         }
2965
2966       /* if they are both literal then */
2967       /* rewrite the tree */
2968       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2969         {
2970           tree->type = EX_VALUE;
2971           tree->opval.val = valMult (valFromType (LETYPE (tree)),
2972                                      valFromType (RETYPE (tree)));
2973           tree->right = tree->left = NULL;
2974           TETYPE (tree) = getSpec (TTYPE (tree) =
2975                                    tree->opval.val->type);
2976           return tree;
2977         }
2978
2979       /* if left is a literal exchange left & right */
2980       if (IS_LITERAL (LTYPE (tree)))
2981         {
2982           ast *tTree = tree->left;
2983           tree->left = tree->right;
2984           tree->right = tTree;
2985         }
2986
2987       /* if right is a literal and */
2988       /* we can find a 2nd literal in a mul-tree then */
2989       /* rearrange the tree */
2990       if (IS_LITERAL (RTYPE (tree)))
2991         {
2992           ast *parent;
2993           ast *litTree = searchLitOp (tree, &parent, "*");
2994           if (litTree)
2995             {
2996               DEBUG_CF("mul")
2997               ast *tTree = litTree->left;
2998               litTree->left = tree->right;
2999               tree->right = tTree;
3000               /* both operands in litTree are literal now */
3001               decorateType (parent, resultType);
3002             }
3003         }
3004
3005       LRVAL (tree) = RRVAL (tree) = 1;
3006       tree->left  = addCast (tree->left,  resultType, FALSE);
3007       tree->right = addCast (tree->right, resultType, FALSE);
3008       TETYPE (tree) = getSpec (TTYPE (tree) =
3009                                    computeType (LTYPE (tree),
3010                                                 RTYPE (tree),
3011                                                 resultType,
3012                                                 tree->opval.op));
3013
3014       return tree;
3015
3016       /*------------------------------------------------------------------*/
3017       /*----------------------------*/
3018       /*    unary '+' operator      */
3019       /*----------------------------*/
3020     case '+':
3021       /* if unary plus */
3022       if (!tree->right)
3023         {
3024           if (!IS_ARITHMETIC (LTYPE (tree)))
3025             {
3026               werror (E_UNARY_OP, '+');
3027               goto errorTreeReturn;
3028             }
3029
3030           /* if left is a literal then do it */
3031           if (IS_LITERAL (LTYPE (tree)))
3032             {
3033               tree->type = EX_VALUE;
3034               tree->opval.val = valFromType (LETYPE (tree));
3035               tree->left = NULL;
3036               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3037               return tree;
3038             }
3039           LRVAL (tree) = 1;
3040           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3041           return tree;
3042         }
3043
3044       /*------------------------------------------------------------------*/
3045       /*----------------------------*/
3046       /*      addition              */
3047       /*----------------------------*/
3048
3049       /* this is not a unary operation */
3050       /* if both pointers then problem */
3051       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3052           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3053         {
3054           werror (E_PTR_PLUS_PTR);
3055           goto errorTreeReturn;
3056         }
3057
3058       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3059           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3060         {
3061           werror (E_PLUS_INVALID, "+");
3062           goto errorTreeReturn;
3063         }
3064
3065       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3066           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3067         {
3068           werror (E_PLUS_INVALID, "+");
3069           goto errorTreeReturn;
3070         }
3071       /* if they are both literal then */
3072       /* rewrite the tree */
3073       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3074         {
3075           tree->type = EX_VALUE;
3076           tree->left  = addCast (tree->left,  resultType, TRUE);
3077           tree->right = addCast (tree->right, resultType, TRUE);
3078           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3079                                      valFromType (RETYPE (tree)));
3080           tree->right = tree->left = NULL;
3081           TETYPE (tree) = getSpec (TTYPE (tree) =
3082                                    tree->opval.val->type);
3083           return tree;
3084         }
3085
3086       /* if the right is a pointer or left is a literal
3087          xchange left & right */
3088       if (IS_ARRAY (RTYPE (tree)) ||
3089           IS_PTR (RTYPE (tree)) ||
3090           IS_LITERAL (LTYPE (tree)))
3091         {
3092           ast *tTree = tree->left;
3093           tree->left = tree->right;
3094           tree->right = tTree;
3095         }
3096
3097       /* if right is a literal and */
3098       /* left is also an addition/subtraction with a literal then */
3099       /* rearrange the tree */
3100       if (IS_LITERAL (RTYPE (tree)))
3101         {
3102           ast *litTree, *parent;
3103           litTree = searchLitOp (tree, &parent, "+-");
3104           if (litTree)
3105             {
3106               if (litTree->opval.op == '+')
3107                 {
3108                   /* foo_aa */
3109                   DEBUG_CF("+ 1 AA")
3110                   ast *tTree = litTree->left;
3111                   litTree->left = tree->right;
3112                   tree->right = tree->left;
3113                   tree->left = tTree;
3114                 }
3115               else if (litTree->opval.op == '-')
3116                 {
3117                   if (IS_LITERAL (RTYPE (litTree)))
3118                     {
3119                       DEBUG_CF("+ 2 ASR")
3120                       /* foo_asr */
3121                       ast *tTree = litTree->left;
3122                       litTree->left = tree->right;
3123                       tree->right = tTree;
3124                     }
3125                   else
3126                     {
3127                       DEBUG_CF("+ 3 ASL")
3128                       /* foo_asl */
3129                       ast *tTree = litTree->right;
3130                       litTree->right = tree->right;
3131                       tree->right = tTree;
3132                       litTree->opval.op = '+';
3133                       tree->opval.op = '-';
3134                     }
3135                 }
3136               decorateType (parent, resultType);
3137             }
3138         }
3139
3140       LRVAL (tree) = RRVAL (tree) = 1;
3141       /* if the left is a pointer */
3142       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3143         TETYPE (tree) = getSpec (TTYPE (tree) =
3144                                  LTYPE (tree));
3145       else
3146         {
3147           tree->left  = addCast (tree->left,  resultType, TRUE);
3148           tree->right = addCast (tree->right, resultType, TRUE);
3149           TETYPE (tree) = getSpec (TTYPE (tree) =
3150                                      computeType (LTYPE (tree),
3151                                                   RTYPE (tree),
3152                                                   resultType,
3153                                                   tree->opval.op));
3154         }
3155         
3156       return tree;
3157
3158       /*------------------------------------------------------------------*/
3159       /*----------------------------*/
3160       /*      unary '-'             */
3161       /*----------------------------*/
3162     case '-':                   /* can be unary   */
3163       /* if right is null then unary */
3164       if (!tree->right)
3165         {
3166
3167           if (!IS_ARITHMETIC (LTYPE (tree)))
3168             {
3169               werror (E_UNARY_OP, tree->opval.op);
3170               goto errorTreeReturn;
3171             }
3172
3173           /* if left is a literal then do it */
3174           if (IS_LITERAL (LTYPE (tree)))
3175             {
3176               tree->type = EX_VALUE;
3177               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3178               tree->left = NULL;
3179               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3180               SPEC_USIGN(TETYPE(tree)) = 0;
3181               return tree;
3182             }
3183           LRVAL (tree) = 1;
3184           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3185           return tree;
3186         }
3187
3188       /*------------------------------------------------------------------*/
3189       /*----------------------------*/
3190       /*    subtraction             */
3191       /*----------------------------*/
3192
3193       if (!(IS_PTR (LTYPE (tree)) ||
3194             IS_ARRAY (LTYPE (tree)) ||
3195             IS_ARITHMETIC (LTYPE (tree))))
3196         {
3197           werror (E_PLUS_INVALID, "-");
3198           goto errorTreeReturn;
3199         }
3200
3201       if (!(IS_PTR (RTYPE (tree)) ||
3202             IS_ARRAY (RTYPE (tree)) ||
3203             IS_ARITHMETIC (RTYPE (tree))))
3204         {
3205           werror (E_PLUS_INVALID, "-");
3206           goto errorTreeReturn;
3207         }
3208
3209       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3210           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3211             IS_INTEGRAL (RTYPE (tree))))
3212         {
3213           werror (E_PLUS_INVALID, "-");
3214           goto errorTreeReturn;
3215         }
3216
3217       /* if they are both literal then */
3218       /* rewrite the tree */
3219       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3220         {
3221           tree->type = EX_VALUE;
3222           tree->left  = addCast (tree->left,  resultType, TRUE);
3223           tree->right = addCast (tree->right, resultType, TRUE);
3224           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3225                                       valFromType (RETYPE (tree)));
3226           tree->right = tree->left = NULL;
3227           TETYPE (tree) = getSpec (TTYPE (tree) =
3228                                    tree->opval.val->type);
3229           return tree;
3230         }
3231
3232       /* if the left & right are equal then zero */
3233       if (isAstEqual (tree->left, tree->right))
3234         {
3235           tree->type = EX_VALUE;
3236           tree->left = tree->right = NULL;
3237           tree->opval.val = constVal ("0");
3238           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3239           return tree;
3240         }
3241
3242       /* if both of them are pointers or arrays then */
3243       /* the result is going to be an integer        */
3244       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3245           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3246         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3247       else
3248         /* if only the left is a pointer */
3249         /* then result is a pointer      */
3250       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3251         TETYPE (tree) = getSpec (TTYPE (tree) =
3252                                  LTYPE (tree));
3253       else
3254         {
3255           tree->left  = addCast (tree->left,  resultType, TRUE);
3256           tree->right = addCast (tree->right, resultType, TRUE);
3257
3258           TETYPE (tree) = getSpec (TTYPE (tree) =
3259                                      computeType (LTYPE (tree),
3260                                                   RTYPE (tree),
3261                                                   resultType,
3262                                                   tree->opval.op));
3263         }
3264
3265       LRVAL (tree) = RRVAL (tree) = 1;
3266
3267       /* if right is a literal and */
3268       /* left is also an addition/subtraction with a literal then */
3269       /* rearrange the tree */
3270       if (IS_LITERAL (RTYPE (tree))
3271           /* avoid infinite loop */
3272           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
3273         {
3274           ast *litTree, *litParent;
3275           litTree = searchLitOp (tree, &litParent, "+-");
3276           if (litTree)
3277             {
3278               if (litTree->opval.op == '+')
3279                 {
3280                   /* foo_sa */
3281                   DEBUG_CF("- 1 SA")
3282                   ast *tTree = litTree->left;
3283                   litTree->left = litTree->right;
3284                   litTree->right = tree->right;
3285                   tree->right = tTree;
3286                   tree->opval.op = '+';
3287                   litTree->opval.op = '-';
3288                 }
3289               else if (litTree->opval.op == '-')
3290                 {
3291                   if (IS_LITERAL (RTYPE (litTree)))
3292                     {
3293                       /* foo_ssr */
3294                       DEBUG_CF("- 2 SSR")
3295                       ast *tTree = litTree->left;
3296                       litTree->left = tree->right;
3297                       tree->right = litParent->left;
3298                       litParent->left = tTree;
3299                       litTree->opval.op = '+';
3300                       
3301                       tree->decorated = 0;
3302                       decorateType (tree, resultType);
3303                     }
3304                   else
3305                     {
3306                       /* foo_ssl */
3307                       DEBUG_CF("- 3 SSL")
3308                       ast *tTree = litTree->right;
3309                       litTree->right = tree->right;
3310                       tree->right = tTree;
3311                     }
3312                 }
3313               decorateType (litParent, resultType);
3314             }
3315         }
3316       return tree;
3317
3318       /*------------------------------------------------------------------*/
3319       /*----------------------------*/
3320       /*    complement              */
3321       /*----------------------------*/
3322     case '~':
3323       /* can be only integral type */
3324       if (!IS_INTEGRAL (LTYPE (tree)))
3325         {
3326           werror (E_UNARY_OP, tree->opval.op);
3327           goto errorTreeReturn;
3328         }
3329
3330       /* if left is a literal then do it */
3331       if (IS_LITERAL (LTYPE (tree)))
3332         {
3333           tree->type = EX_VALUE;
3334           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3335           tree->left = NULL;
3336           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3337           return addCast (tree, resultType, TRUE);
3338         }
3339       tree->left = addCast (tree->left, resultType, TRUE);
3340       LRVAL (tree) = 1;
3341       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3342       return tree;
3343
3344       /*------------------------------------------------------------------*/
3345       /*----------------------------*/
3346       /*           not              */
3347       /*----------------------------*/
3348     case '!':
3349       /* can be pointer */
3350       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3351           !IS_PTR (LTYPE (tree)) &&
3352           !IS_ARRAY (LTYPE (tree)))
3353         {
3354           werror (E_UNARY_OP, tree->opval.op);
3355           goto errorTreeReturn;
3356         }
3357
3358       /* if left is a literal then do it */
3359       if (IS_LITERAL (LTYPE (tree)))
3360         {
3361           tree->type = EX_VALUE;
3362           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3363           tree->left = NULL;
3364           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3365           return tree;
3366         }
3367       LRVAL (tree) = 1;
3368       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3369       return tree;
3370
3371       /*------------------------------------------------------------------*/
3372       /*----------------------------*/
3373       /*           shift            */
3374       /*----------------------------*/
3375     case RRC:
3376     case RLC:
3377     case SWAP:
3378       TTYPE (tree) = LTYPE (tree);
3379       TETYPE (tree) = LETYPE (tree);
3380       return tree;
3381
3382     case GETHBIT:
3383       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3384       return tree;
3385
3386     case LEFT_OP:
3387     case RIGHT_OP:
3388       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3389         {
3390           werror (E_SHIFT_OP_INVALID);
3391           werror (W_CONTINUE, "left & right types are ");
3392           printTypeChain (LTYPE (tree), stderr);
3393           fprintf (stderr, ",");
3394           printTypeChain (RTYPE (tree), stderr);
3395           fprintf (stderr, "\n");
3396           goto errorTreeReturn;
3397         }
3398
3399       /* make smaller type only if it's a LEFT_OP */
3400       if (tree->opval.op == LEFT_OP)
3401         tree->left = addCast (tree->left, resultType, TRUE);
3402       
3403       /* if they are both literal then */
3404       /* rewrite the tree */
3405       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3406         {
3407           tree->type = EX_VALUE;
3408           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3409                                       valFromType (RETYPE (tree)),
3410                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3411           tree->right = tree->left = NULL;
3412           TETYPE (tree) = getSpec (TTYPE (tree) =
3413                                    tree->opval.val->type);
3414           return tree;
3415         }
3416
3417       LRVAL (tree) = RRVAL (tree) = 1;
3418       if (tree->opval.op == LEFT_OP)
3419         {
3420           TETYPE (tree) = getSpec (TTYPE (tree) =
3421                                        computeType (LTYPE (tree),
3422                                                     NULL,
3423                                                     resultType,
3424                                                     tree->opval.op));
3425         }
3426       else /* RIGHT_OP */
3427         {
3428           /* no promotion necessary */
3429           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3430           if (IS_LITERAL (TTYPE (tree)))
3431             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3432         }
3433
3434       /* if only the right side is a literal & we are
3435          shifting more than size of the left operand then zero */
3436       if (IS_LITERAL (RTYPE (tree)) &&
3437           ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
3438           (getSize (TETYPE (tree)) * 8))
3439         {
3440           if (tree->opval.op==LEFT_OP ||
3441               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3442             {
3443               lineno=tree->lineno;
3444               werror (W_SHIFT_CHANGED,
3445                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3446               tree->type = EX_VALUE;
3447               tree->left = tree->right = NULL;
3448               tree->opval.val = constVal ("0");
3449               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3450               return tree;
3451             }
3452         }
3453
3454       return tree;
3455
3456       /*------------------------------------------------------------------*/
3457       /*----------------------------*/
3458       /*         casting            */
3459       /*----------------------------*/
3460     case CAST:                  /* change the type   */
3461       /* cannot cast to an aggregate type */
3462       if (IS_AGGREGATE (LTYPE (tree)))
3463         {
3464           werror (E_CAST_ILLEGAL);
3465           goto errorTreeReturn;
3466         }
3467
3468       /* make sure the type is complete and sane */
3469       changePointer(LTYPE(tree));
3470       checkTypeSanity(LETYPE(tree), "(cast)");
3471
3472       /* If code memory is read only, then pointers to code memory */
3473       /* implicitly point to constants -- make this explicit       */
3474       {
3475         sym_link *t = LTYPE(tree);
3476         while (t && t->next)
3477           {
3478             if (IS_CODEPTR(t) && port->mem.code_ro)
3479               {
3480                 if (IS_SPEC(t->next))
3481                   SPEC_CONST (t->next) = 1;
3482                 else
3483                   DCL_PTR_CONST (t->next) = 1;
3484               }
3485             t = t->next;
3486           }
3487       }
3488
3489 #if 0
3490       /* if the right is a literal replace the tree */
3491       if (IS_LITERAL (RETYPE (tree))) {
3492               if (!IS_PTR (LTYPE (tree))) {
3493                       tree->type = EX_VALUE;
3494                       tree->opval.val =
3495                               valCastLiteral (LTYPE (tree),
3496                                               floatFromVal (valFromType (RETYPE (tree))));
3497                       tree->left = NULL;
3498                       tree->right = NULL;
3499                       TTYPE (tree) = tree->opval.val->type;
3500                       tree->values.literalFromCast = 1;
3501               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3502                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3503                       sym_link *rest = LTYPE(tree)->next;
3504                       werror(W_LITERAL_GENERIC);
3505                       TTYPE(tree) = newLink(DECLARATOR);
3506                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3507                       TTYPE(tree)->next = rest;
3508                       tree->left->opval.lnk = TTYPE(tree);
3509                       LRVAL (tree) = 1;
3510               } else {
3511                       TTYPE (tree) = LTYPE (tree);
3512                       LRVAL (tree) = 1;
3513               }
3514       } else {
3515               TTYPE (tree) = LTYPE (tree);
3516               LRVAL (tree) = 1;
3517       }
3518 #else
3519 #if 0 // this is already checked, now this could be explicit
3520       /* if pointer to struct then check names */
3521       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3522           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3523           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3524         {
3525           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3526                  SPEC_STRUCT(LETYPE(tree))->tag);
3527         }
3528 #endif
3529       if (IS_ADDRESS_OF_OP(tree->right)
3530           && IS_AST_SYM_VALUE (tree->right->left)
3531           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3532
3533         tree->type = EX_VALUE;
3534         tree->opval.val =
3535           valCastLiteral (LTYPE (tree),
3536                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3537         TTYPE (tree) = tree->opval.val->type;
3538         TETYPE (tree) = getSpec (TTYPE (tree));
3539         tree->left = NULL;
3540         tree->right = NULL;
3541         tree->values.literalFromCast = 1;
3542         return tree;
3543       }
3544
3545       /* handle offsetof macro:            */
3546       /* #define offsetof(TYPE, MEMBER) \  */
3547       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3548       if (IS_ADDRESS_OF_OP(tree->right)
3549           && IS_AST_OP (tree->right->left)
3550           && tree->right->left->opval.op == PTR_OP
3551           && IS_AST_OP (tree->right->left->left)
3552           && tree->right->left->left->opval.op == CAST
3553           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3554
3555         symbol *element = getStructElement (
3556           SPEC_STRUCT (LETYPE(tree->right->left)),
3557           AST_SYMBOL(tree->right->left->right)
3558         );
3559
3560         if (element) {
3561           tree->type = EX_VALUE;
3562           tree->opval.val = valCastLiteral (
3563             LTYPE (tree),
3564             element->offset
3565             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3566           );
3567
3568           TTYPE (tree) = tree->opval.val->type;
3569           TETYPE (tree) = getSpec (TTYPE (tree));
3570           tree->left = NULL;
3571           tree->right = NULL;
3572           return tree;
3573         }
3574       }
3575
3576       /* if the right is a literal replace the tree */
3577       if (IS_LITERAL (RETYPE (tree))) {
3578         #if 0
3579         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3580           /* rewrite      (type *)litaddr
3581              as           &temp
3582              and define   type at litaddr temp
3583              (but only if type's storage class is not generic)
3584           */
3585           ast *newTree = newNode ('&', NULL, NULL);
3586           symbol *sym;
3587
3588           TTYPE (newTree) = LTYPE (tree);
3589           TETYPE (newTree) = getSpec(LTYPE (tree));
3590
3591           /* define a global symbol at the casted address*/
3592           sym = newSymbol(genSymName (0), 0);
3593           sym->type = LTYPE (tree)->next;
3594           if (!sym->type)
3595             sym->type = newLink (V_VOID);
3596           sym->etype = getSpec(sym->type);
3597           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3598           sym->lineDef = tree->lineno;
3599           sym->cdef = 1;
3600           sym->isref = 1;
3601           SPEC_STAT (sym->etype) = 1;
3602           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3603           SPEC_ABSA(sym->etype) = 1;
3604           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3605           allocGlobal (sym);
3606
3607           newTree->left = newAst_VALUE(symbolVal(sym));
3608           newTree->left->lineno = tree->lineno;
3609           LTYPE (newTree) = sym->type;
3610           LETYPE (newTree) = sym->etype;
3611           LLVAL (newTree) = 1;
3612           LRVAL (newTree) = 0;
3613           TLVAL (newTree) = 1;
3614           return newTree;
3615         }
3616         #endif
3617         if (!IS_PTR (LTYPE (tree))) {
3618           tree->type = EX_VALUE;
3619           tree->opval.val =
3620           valCastLiteral (LTYPE (tree),
3621                           floatFromVal (valFromType (RTYPE (tree))));
3622           TTYPE (tree) = tree->opval.val->type;
3623           tree->left = NULL;
3624           tree->right = NULL;
3625           tree->values.literalFromCast = 1;
3626           TETYPE (tree) = getSpec (TTYPE (tree));
3627           return tree;
3628         }
3629       }
3630       TTYPE (tree) = LTYPE (tree);
3631       LRVAL (tree) = 1;
3632
3633 #endif
3634       TETYPE (tree) = getSpec (TTYPE (tree));
3635
3636       return tree;
3637
3638       /*------------------------------------------------------------------*/
3639       /*----------------------------*/
3640       /*       logical &&, ||       */
3641       /*----------------------------*/
3642     case AND_OP:
3643     case OR_OP:
3644       /* each must be arithmetic type or be a pointer */
3645       if (!IS_PTR (LTYPE (tree)) &&
3646           !IS_ARRAY (LTYPE (tree)) &&
3647           !IS_INTEGRAL (LTYPE (tree)))
3648         {
3649           werror (E_COMPARE_OP);
3650           goto errorTreeReturn;
3651         }
3652
3653       if (!IS_PTR (RTYPE (tree)) &&
3654           !IS_ARRAY (RTYPE (tree)) &&
3655           !IS_INTEGRAL (RTYPE (tree)))
3656         {
3657           werror (E_COMPARE_OP);
3658           goto errorTreeReturn;
3659         }
3660       /* if they are both literal then */
3661       /* rewrite the tree */
3662       if (IS_LITERAL (RTYPE (tree)) &&
3663           IS_LITERAL (LTYPE (tree)))
3664         {
3665           tree->type = EX_VALUE;
3666           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
3667                                            valFromType (RTYPE (tree)),
3668                                            tree->opval.op);
3669           tree->right = tree->left = NULL;
3670           TETYPE (tree) = getSpec (TTYPE (tree) =
3671                                    tree->opval.val->type);
3672           return tree;
3673         }
3674       LRVAL (tree) = RRVAL (tree) = 1;
3675       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3676       return tree;
3677
3678       /*------------------------------------------------------------------*/
3679       /*----------------------------*/
3680       /*     comparison operators   */
3681       /*----------------------------*/
3682     case '>':
3683     case '<':
3684     case LE_OP:
3685     case GE_OP:
3686     case EQ_OP:
3687     case NE_OP:
3688       {
3689         ast *lt = optimizeCompare (tree);
3690
3691         if (tree != lt)
3692           return lt;
3693       }
3694
3695       /* if they are pointers they must be castable */
3696       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3697         {
3698           if (tree->opval.op==EQ_OP &&
3699               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3700             // we cannot cast a gptr to a !gptr: switch the leaves
3701             struct ast *s=tree->left;
3702             tree->left=tree->right;
3703             tree->right=s;
3704           }
3705           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3706             {
3707               werror (E_COMPARE_OP);
3708               fprintf (stderr, "comparing type ");
3709               printTypeChain (LTYPE (tree), stderr);
3710               fprintf (stderr, "to type ");
3711               printTypeChain (RTYPE (tree), stderr);
3712               fprintf (stderr, "\n");
3713               goto errorTreeReturn;
3714             }
3715         }
3716       /* else they should be promotable to one another */
3717       else
3718         {
3719           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3720                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3721
3722             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3723               {
3724                 werror (E_COMPARE_OP);
3725                 fprintf (stderr, "comparing type ");
3726                 printTypeChain (LTYPE (tree), stderr);
3727                 fprintf (stderr, "to type ");
3728                 printTypeChain (RTYPE (tree), stderr);
3729                 fprintf (stderr, "\n");
3730                 goto errorTreeReturn;
3731               }
3732         }
3733       /* if unsigned value < 0  then always false */
3734       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
3735       if (SPEC_USIGN(LETYPE(tree)) &&
3736           !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
3737           IS_LITERAL(RTYPE(tree))  &&
3738           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
3739         {
3740           if (tree->opval.op == '<')
3741             {
3742               return tree->right;
3743             }
3744           if (tree->opval.op == '>')
3745             {
3746               if (resultType == RESULT_TYPE_IFX)
3747                 {
3748                   /* the parent is an ifx: */
3749                   /* if (unsigned value) */
3750                   return tree->left;
3751                 }
3752               
3753               /* (unsigned value) ? 1 : 0 */
3754               tree->opval.op = '?';
3755               tree->right = newNode (':',
3756                                      newAst_VALUE (constVal ("1")),
3757                                      tree->right); /* val 0 */
3758               tree->right->lineno = tree->lineno;
3759               tree->right->left->lineno = tree->lineno;
3760               decorateType (tree->right, RESULT_CHECK);
3761             }
3762         }
3763       /* if they are both literal then */
3764       /* rewrite the tree */
3765       if (IS_LITERAL (RTYPE (tree)) &&
3766           IS_LITERAL (LTYPE (tree)))
3767         {
3768           tree->type = EX_VALUE;
3769           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3770                                         valFromType (RETYPE (tree)),
3771                                         tree->opval.op);
3772           tree->right = tree->left = NULL;
3773           TETYPE (tree) = getSpec (TTYPE (tree) =
3774                                    tree->opval.val->type);
3775           return tree;
3776         }
3777       LRVAL (tree) = RRVAL (tree) = 1;
3778       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3779       return tree;
3780
3781       /*------------------------------------------------------------------*/
3782       /*----------------------------*/
3783       /*             sizeof         */
3784       /*----------------------------*/
3785     case SIZEOF:                /* evaluate wihout code generation */
3786       /* change the type to a integer */
3787       {
3788         int size = getSize (tree->right->ftype);
3789         SNPRINTF(buffer, sizeof(buffer), "%d", size);
3790         if (!size && !IS_VOID(tree->right->ftype))
3791           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
3792       }
3793       tree->type = EX_VALUE;
3794       tree->opval.val = constVal (buffer);
3795       tree->right = tree->left = NULL;
3796       TETYPE (tree) = getSpec (TTYPE (tree) =
3797                                tree->opval.val->type);
3798       return tree;
3799
3800       /*------------------------------------------------------------------*/
3801       /*----------------------------*/
3802       /*             typeof         */
3803       /*----------------------------*/
3804     case TYPEOF:
3805         /* return typeof enum value */
3806         tree->type = EX_VALUE;
3807         {
3808             int typeofv = 0;
3809             if (IS_SPEC(tree->right->ftype)) {
3810                 switch (SPEC_NOUN(tree->right->ftype)) {
3811                 case V_INT:
3812                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3813                     else typeofv = TYPEOF_INT;
3814                     break;
3815                 case V_FLOAT:
3816                     typeofv = TYPEOF_FLOAT;
3817                     break;
3818                 case V_CHAR:
3819                     typeofv = TYPEOF_CHAR;
3820                     break;
3821                 case V_VOID:
3822                     typeofv = TYPEOF_VOID;
3823                     break;
3824                 case V_STRUCT:
3825                     typeofv = TYPEOF_STRUCT;
3826                     break;
3827                 case V_BITFIELD:
3828                     typeofv = TYPEOF_BITFIELD;
3829                     break;
3830                 case V_BIT:
3831                     typeofv = TYPEOF_BIT;
3832                     break;
3833                 case V_SBIT:
3834                     typeofv = TYPEOF_SBIT;
3835                     break;
3836                 default:
3837                     break;
3838                 }
3839             } else {
3840                 switch (DCL_TYPE(tree->right->ftype)) {
3841                 case POINTER:
3842                     typeofv = TYPEOF_POINTER;
3843                     break;
3844                 case FPOINTER:
3845                     typeofv = TYPEOF_FPOINTER;
3846                     break;
3847                 case CPOINTER:
3848                     typeofv = TYPEOF_CPOINTER;
3849                     break;
3850                 case GPOINTER:
3851                     typeofv = TYPEOF_GPOINTER;
3852                     break;
3853                 case PPOINTER:
3854                     typeofv = TYPEOF_PPOINTER;
3855                     break;
3856                 case IPOINTER:
3857                     typeofv = TYPEOF_IPOINTER;
3858                     break;
3859                 case ARRAY:
3860                     typeofv = TYPEOF_ARRAY;
3861                     break;
3862                 case FUNCTION:
3863                     typeofv = TYPEOF_FUNCTION;
3864                     break;
3865                 default:
3866                     break;
3867                 }
3868             }
3869             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3870             tree->opval.val = constVal (buffer);
3871             tree->right = tree->left = NULL;
3872             TETYPE (tree) = getSpec (TTYPE (tree) =
3873                                      tree->opval.val->type);
3874         }
3875         return tree;
3876       /*------------------------------------------------------------------*/
3877       /*----------------------------*/
3878       /* conditional operator  '?'  */
3879       /*----------------------------*/
3880     case '?':
3881       /* the type is value of the colon operator (on the right) */
3882       assert (IS_COLON_OP (tree->right));
3883       /* if already known then replace the tree : optimizer will do it
3884          but faster to do it here */
3885       if (IS_LITERAL (LTYPE (tree)))
3886         {
3887           if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
3888             return decorateType (tree->right->left, resultTypeProp);
3889           else
3890             return decorateType (tree->right->right, resultTypeProp);
3891         }
3892       else
3893         {
3894           tree->right = decorateType (tree->right, resultTypeProp);
3895           TTYPE (tree) = RTYPE (tree);
3896           TETYPE (tree) = getSpec (TTYPE (tree));
3897         }
3898       return tree;
3899
3900     case ':':
3901       /* if they don't match we have a problem */
3902       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3903         {
3904           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3905           goto errorTreeReturn;
3906         }
3907
3908       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
3909                                   resultType, tree->opval.op);
3910       TETYPE (tree) = getSpec (TTYPE (tree));
3911       return tree;
3912
3913
3914 #if 0 // assignment operators are converted by the parser
3915       /*------------------------------------------------------------------*/
3916       /*----------------------------*/
3917       /*    assignment operators    */
3918       /*----------------------------*/
3919     case MUL_ASSIGN:
3920     case DIV_ASSIGN:
3921       /* for these it must be both must be integral */
3922       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3923           !IS_ARITHMETIC (RTYPE (tree)))
3924         {
3925           werror (E_OPS_INTEGRAL);
3926           goto errorTreeReturn;
3927         }
3928       RRVAL (tree) = 1;
3929       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3930
3931       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3932         werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3933
3934       if (LRVAL (tree))
3935         {
3936           werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3937           goto errorTreeReturn;
3938         }
3939       LLVAL (tree) = 1;
3940
3941       return tree;
3942
3943     case AND_ASSIGN:
3944     case OR_ASSIGN:
3945     case XOR_ASSIGN:
3946     case RIGHT_ASSIGN:
3947     case LEFT_ASSIGN:
3948       /* for these it must be both must be integral */
3949       if (!IS_INTEGRAL (LTYPE (tree)) ||
3950           !IS_INTEGRAL (RTYPE (tree)))
3951         {
3952           werror (E_OPS_INTEGRAL);
3953           goto errorTreeReturn;
3954         }
3955       RRVAL (tree) = 1;
3956       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3957
3958       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3959         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3960
3961       if (LRVAL (tree))
3962         {
3963           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3964           goto errorTreeReturn;
3965         }
3966       LLVAL (tree) = 1;
3967
3968       return tree;
3969
3970       /*------------------------------------------------------------------*/
3971       /*----------------------------*/
3972       /*    -= operator             */
3973       /*----------------------------*/
3974     case SUB_ASSIGN:
3975       if (!(IS_PTR (LTYPE (tree)) ||
3976             IS_ARITHMETIC (LTYPE (tree))))
3977         {
3978           werror (E_PLUS_INVALID, "-=");
3979           goto errorTreeReturn;
3980         }
3981
3982       if (!(IS_PTR (RTYPE (tree)) ||
3983             IS_ARITHMETIC (RTYPE (tree))))
3984         {
3985           werror (E_PLUS_INVALID, "-=");
3986           goto errorTreeReturn;
3987         }
3988       RRVAL (tree) = 1;
3989       TETYPE (tree) = getSpec (TTYPE (tree) =
3990                                computeType (LTYPE (tree),
3991                                             RTYPE (tree),
3992                                             RESULT_TYPE_NOPROM,
3993                                             tree->opval.op));
3994
3995       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3996         werror (E_CODE_WRITE, "-=");
3997
3998       if (LRVAL (tree))
3999         {
4000           werror (E_LVALUE_REQUIRED, "-=");
4001           goto errorTreeReturn;
4002         }
4003       LLVAL (tree) = 1;
4004
4005       return tree;
4006
4007       /*------------------------------------------------------------------*/
4008       /*----------------------------*/
4009       /*          += operator       */
4010       /*----------------------------*/
4011     case ADD_ASSIGN:
4012       /* this is not a unary operation */
4013       /* if both pointers then problem */
4014       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4015         {
4016           werror (E_PTR_PLUS_PTR);
4017           goto errorTreeReturn;
4018         }
4019
4020       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4021         {
4022           werror (E_PLUS_INVALID, "+=");
4023           goto errorTreeReturn;
4024         }
4025
4026       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4027         {
4028           werror (E_PLUS_INVALID, "+=");
4029           goto errorTreeReturn;
4030         }
4031       RRVAL (tree) = 1;
4032       TETYPE (tree) = getSpec (TTYPE (tree) =
4033                                computeType (LTYPE (tree),
4034                                             RTYPE (tree),
4035                                             RESULT_TYPE_NOPROM,
4036                                             tree->opval.op));
4037
4038       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4039         werror (E_CODE_WRITE, "+=");
4040
4041       if (LRVAL (tree))
4042         {
4043           werror (E_LVALUE_REQUIRED, "+=");
4044           goto errorTreeReturn;
4045         }
4046
4047       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
4048       tree->opval.op = '=';
4049
4050       return tree;
4051 #endif
4052
4053       /*------------------------------------------------------------------*/
4054       /*----------------------------*/
4055       /*      straight assignemnt   */
4056       /*----------------------------*/
4057     case '=':
4058       /* cannot be an aggregate */
4059       if (IS_AGGREGATE (LTYPE (tree)))
4060         {
4061           werror (E_AGGR_ASSIGN);
4062           goto errorTreeReturn;
4063         }
4064
4065       /* they should either match or be castable */
4066       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4067         {
4068           werror (E_TYPE_MISMATCH, "assignment", " ");
4069           printFromToType(RTYPE(tree),LTYPE(tree));
4070         }
4071
4072       /* if the left side of the tree is of type void
4073          then report error */
4074       if (IS_VOID (LTYPE (tree)))
4075         {
4076           werror (E_CAST_ZERO);
4077           printFromToType(RTYPE(tree), LTYPE(tree));
4078         }
4079
4080       TETYPE (tree) = getSpec (TTYPE (tree) =
4081                                LTYPE (tree));
4082       RRVAL (tree) = 1;
4083       LLVAL (tree) = 1;
4084       if (!tree->initMode ) {
4085         if (IS_CONSTANT(LTYPE(tree)))
4086           werror (E_CODE_WRITE, "=");
4087       }
4088       if (LRVAL (tree))
4089         {
4090           werror (E_LVALUE_REQUIRED, "=");
4091           goto errorTreeReturn;
4092         }
4093
4094       return tree;
4095
4096       /*------------------------------------------------------------------*/
4097       /*----------------------------*/
4098       /*      comma operator        */
4099       /*----------------------------*/
4100     case ',':
4101       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4102       return tree;
4103
4104       /*------------------------------------------------------------------*/
4105       /*----------------------------*/
4106       /*       function call        */
4107       /*----------------------------*/
4108     case CALL:
4109       
4110       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4111       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4112         {
4113           if (tree->left->opval.op == '*' && !tree->left->right)
4114             tree->left = tree->left->left;
4115         }
4116
4117       /* require a function or pointer to function */
4118       if (!IS_FUNC (LTYPE (tree))
4119           && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
4120         {
4121           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4122           goto errorTreeReturn;
4123         }
4124
4125       /* if there are parms, make sure that
4126          parms are decorate / process / reverse only once */
4127       if (!tree->right ||
4128           !tree->right->decorated)
4129         {
4130           sym_link *functype;      
4131           parmNumber = 1;
4132
4133           if (IS_CODEPTR(LTYPE(tree)))
4134             functype = LTYPE (tree)->next;
4135           else
4136             functype = LTYPE (tree);
4137
4138           if (processParms (tree->left, FUNC_ARGS(functype),
4139                             &tree->right, &parmNumber, TRUE))
4140             {
4141               goto errorTreeReturn;
4142             }
4143         
4144           if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
4145              !IFFUNC_ISBUILTIN(functype))
4146             {
4147               reverseParms (tree->right);
4148             }
4149
4150            TTYPE (tree) = functype->next;
4151            TETYPE (tree) = getSpec (TTYPE (tree));
4152         }
4153       return tree;
4154
4155       /*------------------------------------------------------------------*/
4156       /*----------------------------*/
4157       /*     return statement       */
4158       /*----------------------------*/
4159     case RETURN:
4160       if (!tree->right)
4161         goto voidcheck;
4162
4163       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4164         {
4165           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4166           printFromToType (RTYPE(tree), currFunc->type->next);
4167           goto errorTreeReturn;
4168         }
4169
4170       if (IS_VOID (currFunc->type->next)
4171           && tree->right &&
4172           !IS_VOID (RTYPE (tree)))
4173         {
4174           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4175           goto errorTreeReturn;
4176         }
4177
4178       /* if there is going to be a casting required then add it */
4179       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4180         {
4181           tree->right =
4182             decorateType (newNode (CAST,
4183                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4184                                         tree->right),
4185                           RESULT_CHECK);
4186         }
4187
4188       RRVAL (tree) = 1;
4189       return tree;
4190
4191     voidcheck:
4192
4193       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4194         {
4195           werror (W_VOID_FUNC, currFunc->name);
4196           goto errorTreeReturn;
4197         }
4198
4199       TTYPE (tree) = TETYPE (tree) = NULL;
4200       return tree;
4201
4202       /*------------------------------------------------------------------*/
4203       /*----------------------------*/
4204       /*     switch statement       */
4205       /*----------------------------*/
4206     case SWITCH:
4207       /* the switch value must be an integer */
4208       if (!IS_INTEGRAL (LTYPE (tree)))
4209         {
4210           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4211           goto errorTreeReturn;
4212         }
4213       LRVAL (tree) = 1;
4214       TTYPE (tree) = TETYPE (tree) = NULL;
4215       return tree;
4216
4217       /*------------------------------------------------------------------*/
4218       /*----------------------------*/
4219       /* ifx Statement              */
4220       /*----------------------------*/
4221     case IFX:
4222       tree->left = backPatchLabels (tree->left,
4223                                     tree->trueLabel,
4224                                     tree->falseLabel);
4225       TTYPE (tree) = TETYPE (tree) = NULL;
4226       return tree;
4227
4228       /*------------------------------------------------------------------*/
4229       /*----------------------------*/
4230       /* for Statement              */
4231       /*----------------------------*/
4232     case FOR:
4233
4234       decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
4235       decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
4236       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
4237
4238       /* if the for loop is reversible then
4239          reverse it otherwise do what we normally
4240          do */
4241       {
4242         symbol *sym;
4243         ast *init, *end;
4244
4245         if (isLoopReversible (tree, &sym, &init, &end))
4246           return reverseLoop (tree, sym, init, end);
4247         else
4248           return decorateType (createFor (AST_FOR (tree, trueLabel),
4249                                           AST_FOR (tree, continueLabel),
4250                                           AST_FOR (tree, falseLabel),
4251                                           AST_FOR (tree, condLabel),
4252                                           AST_FOR (tree, initExpr),
4253                                           AST_FOR (tree, condExpr),
4254                                           AST_FOR (tree, loopExpr),
4255                                           tree->left), RESULT_CHECK);
4256       }
4257     case PARAM:
4258       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4259               "node PARAM shouldn't be processed here");
4260               /* but in processParams() */
4261       return tree;
4262     default:
4263       TTYPE (tree) = TETYPE (tree) = NULL;
4264       return tree;
4265     }
4266
4267   /* some error found this tree will be killed */
4268 errorTreeReturn:
4269   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4270   tree->opval.op = NULLOP;
4271   tree->isError = 1;
4272
4273   return tree;
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* sizeofOp - processes size of operation                          */
4278 /*-----------------------------------------------------------------*/
4279 value *
4280 sizeofOp (sym_link * type)
4281 {
4282   char buff[10];
4283   int size;
4284
4285   /* make sure the type is complete and sane */
4286   checkTypeSanity(type, "(sizeof)");
4287
4288   /* get the size and convert it to character  */
4289   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4290   if (!size && !IS_VOID(type))
4291     werror (E_SIZEOF_INCOMPLETE_TYPE);
4292
4293   /* now convert into value  */
4294   return constVal (buff);
4295 }
4296
4297
4298 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4299 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4300 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4301 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4302 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4303 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4304 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4305
4306 /*-----------------------------------------------------------------*/
4307 /* backPatchLabels - change and or not operators to flow control    */
4308 /*-----------------------------------------------------------------*/
4309 ast *
4310 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4311 {
4312
4313   if (!tree)
4314     return NULL;
4315
4316   if (!(IS_ANDORNOT (tree)))
4317     return tree;
4318
4319   /* if this an and */
4320   if (IS_AND (tree))
4321     {
4322       static int localLbl = 0;
4323       symbol *localLabel;
4324
4325       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4326       localLabel = newSymbol (buffer, NestLevel);
4327
4328       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4329
4330       /* if left is already a IFX then just change the if true label in that */
4331       if (!IS_IFX (tree->left))
4332         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4333
4334       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4335       /* right is a IFX then just join */
4336       if (IS_IFX (tree->right))
4337         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4338
4339       tree->right = createLabel (localLabel, tree->right);
4340       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4341
4342       return newNode (NULLOP, tree->left, tree->right);
4343     }
4344
4345   /* if this is an or operation */
4346   if (IS_OR (tree))
4347     {
4348       static int localLbl = 0;
4349       symbol *localLabel;
4350
4351       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4352       localLabel = newSymbol (buffer, NestLevel);
4353
4354       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4355
4356       /* if left is already a IFX then just change the if true label in that */
4357       if (!IS_IFX (tree->left))
4358         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4359
4360       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4361       /* right is a IFX then just join */
4362       if (IS_IFX (tree->right))
4363         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4364
4365       tree->right = createLabel (localLabel, tree->right);
4366       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4367
4368       return newNode (NULLOP, tree->left, tree->right);
4369     }
4370
4371   /* change not */
4372   if (IS_NOT (tree))
4373     {
4374       int wasnot = IS_NOT (tree->left);
4375       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4376
4377       /* if the left is already a IFX */
4378       if (!IS_IFX (tree->left))
4379         tree->left = newNode (IFX, tree->left, NULL);
4380
4381       if (wasnot)
4382         {
4383           tree->left->trueLabel = trueLabel;
4384           tree->left->falseLabel = falseLabel;
4385         }
4386       else
4387         {
4388           tree->left->trueLabel = falseLabel;
4389           tree->left->falseLabel = trueLabel;
4390         }
4391       return tree->left;
4392     }
4393
4394   if (IS_IFX (tree))
4395     {
4396       tree->trueLabel = trueLabel;
4397       tree->falseLabel = falseLabel;
4398     }
4399
4400   return tree;
4401 }
4402
4403
4404 /*-----------------------------------------------------------------*/
4405 /* createBlock - create expression tree for block                  */
4406 /*-----------------------------------------------------------------*/
4407 ast *
4408 createBlock (symbol * decl, ast * body)
4409 {
4410   ast *ex;
4411
4412   /* if the block has nothing */
4413   if (!body && !decl)
4414     return NULL;
4415
4416   ex = newNode (BLOCK, NULL, body);
4417   ex->values.sym = decl;
4418   
4419   ex->right = ex->right;
4420   ex->level++;
4421   ex->lineno = 0;
4422   return ex;
4423 }
4424
4425 /*-----------------------------------------------------------------*/
4426 /* createLabel - creates the expression tree for labels            */
4427 /*-----------------------------------------------------------------*/
4428 ast *
4429 createLabel (symbol * label, ast * stmnt)
4430 {
4431   symbol *csym;
4432   char name[SDCC_NAME_MAX + 1];
4433   ast *rValue;
4434
4435   /* must create fresh symbol if the symbol name  */
4436   /* exists in the symbol table, since there can  */
4437   /* be a variable with the same name as the labl */
4438   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4439       (csym->level == label->level))
4440     label = newSymbol (label->name, label->level);
4441
4442   /* change the name before putting it in add _ */
4443   SNPRINTF(name, sizeof(name), "%s", label->name);
4444
4445   /* put the label in the LabelSymbol table    */
4446   /* but first check if a label of the same    */
4447   /* name exists                               */
4448   if ((csym = findSym (LabelTab, NULL, name)))
4449     werror (E_DUPLICATE_LABEL, label->name);
4450   else
4451     addSym (LabelTab, label, name, label->level, 0, 0);
4452
4453   label->isitmp = 1;
4454   label->islbl = 1;
4455   label->key = labelKey++;
4456   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4457   rValue->lineno = 0;
4458
4459   return rValue;
4460 }
4461
4462 /*-----------------------------------------------------------------*/
4463 /* createCase - generates the parsetree for a case statement       */
4464 /*-----------------------------------------------------------------*/
4465 ast *
4466 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4467 {
4468   char caseLbl[SDCC_NAME_MAX + 1];
4469   ast *rexpr;
4470   value *val;
4471
4472   /* if the switch statement does not exist */
4473   /* then case is out of context            */
4474   if (!swStat)
4475     {
4476       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4477       return NULL;
4478     }
4479
4480   caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
4481   /* if not a constant then error  */
4482   if (!IS_LITERAL (caseVal->ftype))
4483     {
4484       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4485       return NULL;
4486     }
4487
4488   /* if not a integer than error */
4489   if (!IS_INTEGRAL (caseVal->ftype))
4490     {
4491       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4492       return NULL;
4493     }
4494
4495   /* find the end of the switch values chain   */
4496   if (!(val = swStat->values.switchVals.swVals))
4497     swStat->values.switchVals.swVals = caseVal->opval.val;
4498   else
4499     {
4500       /* also order the cases according to value */
4501       value *pval = NULL;
4502       int cVal = (int) floatFromVal (caseVal->opval.val);
4503       while (val && (int) floatFromVal (val) < cVal)
4504         {
4505           pval = val;
4506           val = val->next;
4507         }
4508
4509       /* if we reached the end then */
4510       if (!val)
4511         {
4512           pval->next = caseVal->opval.val;
4513         }
4514       else if ((int) floatFromVal (val) == cVal)
4515         {
4516           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4517                     "case");
4518           return NULL;
4519         }
4520       else
4521         {
4522           /* we found a value greater than */
4523           /* the current value we must add this */
4524           /* before the value */
4525           caseVal->opval.val->next = val;
4526
4527           /* if this was the first in chain */
4528           if (swStat->values.switchVals.swVals == val)
4529             swStat->values.switchVals.swVals =
4530               caseVal->opval.val;
4531           else
4532             pval->next = caseVal->opval.val;
4533         }
4534
4535     }
4536
4537   /* create the case label   */
4538   SNPRINTF(caseLbl, sizeof(caseLbl), 
4539            "_case_%d_%d",
4540            swStat->values.switchVals.swNum,
4541            (int) floatFromVal (caseVal->opval.val));
4542
4543   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4544   rexpr->lineno = 0;
4545   return rexpr;
4546 }
4547
4548 /*-----------------------------------------------------------------*/
4549 /* createDefault - creates the parse tree for the default statement */
4550 /*-----------------------------------------------------------------*/
4551 ast *
4552 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4553 {
4554   char defLbl[SDCC_NAME_MAX + 1];
4555
4556   /* if the switch statement does not exist */
4557   /* then case is out of context            */
4558   if (!swStat)
4559     {
4560       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4561       return NULL;
4562     }
4563
4564   if (swStat->values.switchVals.swDefault)
4565     {
4566       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4567                 "default");
4568       return NULL;
4569     }
4570
4571   /* turn on the default flag   */
4572   swStat->values.switchVals.swDefault = 1;
4573
4574   /* create the label  */
4575   SNPRINTF (defLbl, sizeof(defLbl),
4576             "_default_%d", swStat->values.switchVals.swNum);
4577   return createLabel (newSymbol (defLbl, 0), stmnt);
4578 }
4579
4580 /*-----------------------------------------------------------------*/
4581 /* createIf - creates the parsetree for the if statement           */
4582 /*-----------------------------------------------------------------*/
4583 ast *
4584 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4585 {
4586   static int Lblnum = 0;
4587   ast *ifTree;
4588   symbol *ifTrue, *ifFalse, *ifEnd;
4589
4590   /* if neither exists */
4591   if (!elseBody && !ifBody) {
4592     // if there are no side effects (i++, j() etc)
4593     if (!hasSEFcalls(condAst)) {
4594       return condAst;
4595     }
4596   }
4597
4598   /* create the labels */
4599   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4600   ifFalse = newSymbol (buffer, NestLevel);
4601   /* if no else body then end == false */
4602   if (!elseBody)
4603     ifEnd = ifFalse;
4604   else
4605     {
4606       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4607       ifEnd = newSymbol (buffer, NestLevel);
4608     }
4609
4610   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4611   ifTrue = newSymbol (buffer, NestLevel);
4612
4613   Lblnum++;
4614
4615   /* attach the ifTrue label to the top of it body */
4616   ifBody = createLabel (ifTrue, ifBody);
4617   /* attach a goto end to the ifBody if else is present */
4618   if (elseBody)
4619     {
4620       ifBody = newNode (NULLOP, ifBody,
4621                         newNode (GOTO,
4622                                  newAst_VALUE (symbolVal (ifEnd)),
4623                                  NULL));
4624       /* put the elseLabel on the else body */
4625       elseBody = createLabel (ifFalse, elseBody);
4626       /* out the end at the end of the body */
4627       elseBody = newNode (NULLOP,
4628                           elseBody,
4629                           createLabel (ifEnd, NULL));
4630     }
4631   else
4632     {
4633       ifBody = newNode (NULLOP, ifBody,
4634                         createLabel (ifFalse, NULL));
4635     }
4636   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4637   if (IS_IFX (condAst))
4638     ifTree = condAst;
4639   else
4640     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4641
4642   return newNode (NULLOP, ifTree,
4643                   newNode (NULLOP, ifBody, elseBody));
4644
4645 }
4646
4647 /*-----------------------------------------------------------------*/
4648 /* createDo - creates parse tree for do                            */
4649 /*        _dobody_n:                                               */
4650 /*            statements                                           */
4651 /*        _docontinue_n:                                           */
4652 /*            condition_expression +-> trueLabel -> _dobody_n      */
4653 /*                                 |                               */
4654 /*                                 +-> falseLabel-> _dobreak_n     */
4655 /*        _dobreak_n:                                              */
4656 /*-----------------------------------------------------------------*/
4657 ast *
4658 createDo (symbol * trueLabel, symbol * continueLabel,
4659           symbol * falseLabel, ast * condAst, ast * doBody)
4660 {
4661   ast *doTree;
4662
4663
4664   /* if the body does not exist then it is simple */
4665   if (!doBody)
4666     {
4667       condAst = backPatchLabels (condAst, continueLabel, NULL);
4668       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4669                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4670       doTree->trueLabel = continueLabel;
4671       doTree->falseLabel = NULL;
4672       return doTree;
4673     }
4674
4675   /* otherwise we have a body */
4676   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4677
4678   /* attach the body label to the top */
4679   doBody = createLabel (trueLabel, doBody);
4680   /* attach the continue label to end of body */
4681   doBody = newNode (NULLOP, doBody,
4682                     createLabel (continueLabel, NULL));
4683
4684   /* now put the break label at the end */
4685   if (IS_IFX (condAst))
4686     doTree = condAst;
4687   else
4688     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4689
4690   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4691
4692   /* putting it together */
4693   return newNode (NULLOP, doBody, doTree);
4694 }
4695
4696 /*-----------------------------------------------------------------*/
4697 /* createFor - creates parse tree for 'for' statement              */
4698 /*        initExpr                                                 */
4699 /*   _forcond_n:                                                   */
4700 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4701 /*                  |                                              */
4702 /*                  +-> falseLabel-> _forbreak_n                   */
4703 /*   _forbody_n:                                                   */
4704 /*        statements                                               */
4705 /*   _forcontinue_n:                                               */
4706 /*        loopExpr                                                 */
4707 /*        goto _forcond_n ;                                        */
4708 /*   _forbreak_n:                                                  */
4709 /*-----------------------------------------------------------------*/
4710 ast *
4711 createFor (symbol * trueLabel, symbol * continueLabel,
4712            symbol * falseLabel, symbol * condLabel,
4713            ast * initExpr, ast * condExpr, ast * loopExpr,
4714            ast * forBody)
4715 {
4716   ast *forTree;
4717
4718   /* if loopexpression not present then we can generate it */
4719   /* the same way as a while */
4720   if (!loopExpr)
4721     return newNode (NULLOP, initExpr,
4722                     createWhile (trueLabel, continueLabel,
4723                                  falseLabel, condExpr, forBody));
4724   /* vanilla for statement */
4725   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4726
4727   if (condExpr && !IS_IFX (condExpr))
4728     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4729
4730
4731   /* attach condition label to condition */
4732   condExpr = createLabel (condLabel, condExpr);
4733
4734   /* attach body label to body */
4735   forBody = createLabel (trueLabel, forBody);
4736
4737   /* attach continue to forLoop expression & attach */
4738   /* goto the forcond @ and of loopExpression       */
4739   loopExpr = createLabel (continueLabel,
4740                           newNode (NULLOP,
4741                                    loopExpr,
4742                                    newNode (GOTO,
4743                                        newAst_VALUE (symbolVal (condLabel)),
4744                                             NULL)));
4745   /* now start putting them together */
4746   forTree = newNode (NULLOP, initExpr, condExpr);
4747   forTree = newNode (NULLOP, forTree, forBody);
4748   forTree = newNode (NULLOP, forTree, loopExpr);
4749   /* finally add the break label */
4750   forTree = newNode (NULLOP, forTree,
4751                      createLabel (falseLabel, NULL));
4752   return forTree;
4753 }
4754
4755 /*-----------------------------------------------------------------*/
4756 /* createWhile - creates parse tree for while statement            */
4757 /*               the while statement will be created as follows    */
4758 /*                                                                 */
4759 /*      _while_continue_n:                                         */
4760 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4761 /*                                 |                               */
4762 /*                                 +-> falseLabel -> _while_break_n */
4763 /*      _while_body_n:                                             */
4764 /*            statements                                           */
4765 /*            goto _while_continue_n                               */
4766 /*      _while_break_n:                                            */
4767 /*-----------------------------------------------------------------*/
4768 ast *
4769 createWhile (symbol * trueLabel, symbol * continueLabel,
4770              symbol * falseLabel, ast * condExpr, ast * whileBody)
4771 {
4772   ast *whileTree;
4773
4774   /* put the continue label */
4775   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4776   condExpr = createLabel (continueLabel, condExpr);
4777   condExpr->lineno = 0;
4778
4779   /* put the body label in front of the body */
4780   whileBody = createLabel (trueLabel, whileBody);
4781   whileBody->lineno = 0;
4782   /* put a jump to continue at the end of the body */
4783   /* and put break label at the end of the body */
4784   whileBody = newNode (NULLOP,
4785                        whileBody,
4786                        newNode (GOTO,
4787                                 newAst_VALUE (symbolVal (continueLabel)),
4788                                 createLabel (falseLabel, NULL)));
4789
4790   /* put it all together */
4791   if (IS_IFX (condExpr))
4792     whileTree = condExpr;
4793   else
4794     {
4795       whileTree = newNode (IFX, condExpr, NULL);
4796       /* put the true & false labels in place */
4797       whileTree->trueLabel = trueLabel;
4798       whileTree->falseLabel = falseLabel;
4799     }
4800
4801   return newNode (NULLOP, whileTree, whileBody);
4802 }
4803
4804 /*-----------------------------------------------------------------*/
4805 /* optimizeGetHbit - get highest order bit of the expression       */
4806 /*-----------------------------------------------------------------*/
4807 ast *
4808 optimizeGetHbit (ast * tree)
4809 {
4810   int i, j;
4811   /* if this is not a bit and */
4812   if (!IS_BITAND (tree))
4813     return tree;
4814
4815   /* will look for tree of the form
4816      ( expr >> ((sizeof expr) -1) ) & 1 */
4817   if (!IS_AST_LIT_VALUE (tree->right))
4818     return tree;
4819
4820   if (AST_LIT_VALUE (tree->right) != 1)
4821     return tree;
4822
4823   if (!IS_RIGHT_OP (tree->left))
4824     return tree;
4825
4826   if (!IS_AST_LIT_VALUE (tree->left->right))
4827     return tree;
4828
4829   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4830       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4831     return tree;
4832       
4833   /* make sure the port supports GETHBIT */
4834   if (port->hasExtBitOp
4835       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4836     return tree;
4837
4838   return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
4839
4840 }
4841
4842 /*-----------------------------------------------------------------*/
4843 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4844 /*-----------------------------------------------------------------*/
4845 ast *
4846 optimizeRRCRLC (ast * root)
4847 {
4848   /* will look for trees of the form
4849      (?expr << 1) | (?expr >> 7) or
4850      (?expr >> 7) | (?expr << 1) will make that
4851      into a RLC : operation ..
4852      Will also look for
4853      (?expr >> 1) | (?expr << 7) or
4854      (?expr << 7) | (?expr >> 1) will make that
4855      into a RRC operation
4856      note : by 7 I mean (number of bits required to hold the
4857      variable -1 ) */
4858   /* if the root operations is not a | operation the not */
4859   if (!IS_BITOR (root))
4860     return root;
4861
4862   /* I have to think of a better way to match patterns this sucks */
4863   /* that aside let start looking for the first case : I use a the
4864      negative check a lot to improve the efficiency */
4865   /* (?expr << 1) | (?expr >> 7) */
4866   if (IS_LEFT_OP (root->left) &&
4867       IS_RIGHT_OP (root->right))
4868     {
4869
4870       if (!SPEC_USIGN (TETYPE (root->left->left)))
4871         return root;
4872
4873       if (!IS_AST_LIT_VALUE (root->left->right) ||
4874           !IS_AST_LIT_VALUE (root->right->right))
4875         goto tryNext0;
4876
4877       /* make sure it is the same expression */
4878       if (!isAstEqual (root->left->left,
4879                        root->right->left))
4880         goto tryNext0;
4881
4882       if (AST_LIT_VALUE (root->left->right) != 1)
4883         goto tryNext0;
4884
4885       if (AST_LIT_VALUE (root->right->right) !=
4886           (getSize (TTYPE (root->left->left)) * 8 - 1))
4887         goto tryNext0;
4888
4889       /* make sure the port supports RLC */
4890       if (port->hasExtBitOp
4891           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4892         return root;
4893
4894       /* whew got the first case : create the AST */
4895       return newNode (RLC, root->left->left, NULL);
4896     }
4897
4898 tryNext0:
4899   /* check for second case */
4900   /* (?expr >> 7) | (?expr << 1) */
4901   if (IS_LEFT_OP (root->right) &&
4902       IS_RIGHT_OP (root->left))
4903     {
4904
4905       if (!SPEC_USIGN (TETYPE (root->left->left)))
4906         return root;
4907
4908       if (!IS_AST_LIT_VALUE (root->left->right) ||
4909           !IS_AST_LIT_VALUE (root->right->right))
4910         goto tryNext1;
4911
4912       /* make sure it is the same symbol */
4913       if (!isAstEqual (root->left->left,
4914                        root->right->left))
4915         goto tryNext1;
4916
4917       if (AST_LIT_VALUE (root->right->right) != 1)
4918         goto tryNext1;
4919
4920       if (AST_LIT_VALUE (root->left->right) !=
4921           (getSize (TTYPE (root->left->left)) * 8 - 1))
4922         goto tryNext1;
4923
4924       /* make sure the port supports RLC */
4925       if (port->hasExtBitOp
4926           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4927         return root;
4928
4929       /* whew got the first case : create the AST */
4930       return newNode (RLC, root->left->left, NULL);
4931
4932     }
4933
4934 tryNext1:
4935   /* third case for RRC */
4936   /*  (?symbol >> 1) | (?symbol << 7) */
4937   if (IS_LEFT_OP (root->right) &&
4938       IS_RIGHT_OP (root->left))
4939     {
4940
4941       if (!SPEC_USIGN (TETYPE (root->left->left)))
4942         return root;
4943
4944       if (!IS_AST_LIT_VALUE (root->left->right) ||
4945           !IS_AST_LIT_VALUE (root->right->right))
4946         goto tryNext2;
4947
4948       /* make sure it is the same symbol */
4949       if (!isAstEqual (root->left->left,
4950                        root->right->left))
4951         goto tryNext2;
4952
4953       if (AST_LIT_VALUE (root->left->right) != 1)
4954         goto tryNext2;
4955
4956       if (AST_LIT_VALUE (root->right->right) !=
4957           (getSize (TTYPE (root->left->left)) * 8 - 1))
4958         goto tryNext2;
4959
4960       /* make sure the port supports RRC */
4961       if (port->hasExtBitOp
4962           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4963         return root;
4964
4965       /* whew got the first case : create the AST */
4966       return newNode (RRC, root->left->left, NULL);
4967
4968     }
4969 tryNext2:
4970   /* fourth and last case for now */
4971   /* (?symbol << 7) | (?symbol >> 1) */
4972   if (IS_RIGHT_OP (root->right) &&
4973       IS_LEFT_OP (root->left))
4974     {
4975
4976       if (!SPEC_USIGN (TETYPE (root->left->left)))
4977         return root;
4978
4979       if (!IS_AST_LIT_VALUE (root->left->right) ||
4980           !IS_AST_LIT_VALUE (root->right->right))
4981         return root;
4982
4983       /* make sure it is the same symbol */
4984       if (!isAstEqual (root->left->left,
4985                        root->right->left))
4986         return root;
4987
4988       if (AST_LIT_VALUE (root->right->right) != 1)
4989         return root;
4990
4991       if (AST_LIT_VALUE (root->left->right) !=
4992           (getSize (TTYPE (root->left->left)) * 8 - 1))
4993         return root;
4994
4995       /* make sure the port supports RRC */
4996       if (port->hasExtBitOp
4997           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4998         return root;
4999
5000       /* whew got the first case : create the AST */
5001       return newNode (RRC, root->left->left, NULL);
5002
5003     }
5004
5005   /* not found return root */
5006   return root;
5007 }
5008
5009 /*-----------------------------------------------------------------*/
5010 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5011 /*-----------------------------------------------------------------*/
5012 ast *
5013 optimizeSWAP (ast * root)
5014 {
5015   /* will look for trees of the form
5016      (?expr << 4) | (?expr >> 4) or
5017      (?expr >> 4) | (?expr << 4) will make that
5018      into a SWAP : operation ..
5019      note : by 4 I mean (number of bits required to hold the
5020      variable /2 ) */
5021   /* if the root operations is not a | operation the not */
5022   if (!IS_BITOR (root))
5023     return root;
5024
5025   /* (?expr << 4) | (?expr >> 4) */
5026   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5027       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5028     {
5029
5030       if (!SPEC_USIGN (TETYPE (root->left->left)))
5031         return root;
5032
5033       if (!IS_AST_LIT_VALUE (root->left->right) ||
5034           !IS_AST_LIT_VALUE (root->right->right))
5035         return root;
5036
5037       /* make sure it is the same expression */
5038       if (!isAstEqual (root->left->left,
5039                        root->right->left))
5040         return root;
5041
5042       if (AST_LIT_VALUE (root->left->right) !=
5043           (getSize (TTYPE (root->left->left)) * 4))
5044         return root;
5045
5046       if (AST_LIT_VALUE (root->right->right) !=
5047           (getSize (TTYPE (root->left->left)) * 4))
5048         return root;
5049
5050       /* make sure the port supports SWAP */
5051       if (port->hasExtBitOp
5052           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5053         return root;
5054
5055       /* found it : create the AST */
5056       return newNode (SWAP, root->left->left, NULL);
5057     }
5058
5059
5060   /* not found return root */
5061   return root;
5062 }
5063
5064 /*-----------------------------------------------------------------*/
5065 /* optimizeCompare - otimizes compares for bit variables     */
5066 /*-----------------------------------------------------------------*/
5067 static ast *
5068 optimizeCompare (ast * root)
5069 {
5070   ast *optExpr = NULL;
5071   value *vleft;
5072   value *vright;
5073   unsigned int litValue;
5074
5075   /* if nothing then return nothing */
5076   if (!root)
5077     return NULL;
5078
5079   /* if not a compare op then do leaves */
5080   if (!IS_COMPARE_OP (root))
5081     {
5082       root->left = optimizeCompare (root->left);
5083       root->right = optimizeCompare (root->right);
5084       return root;
5085     }
5086
5087   /* if left & right are the same then depending
5088      of the operation do */
5089   if (isAstEqual (root->left, root->right))
5090     {
5091       switch (root->opval.op)
5092         {
5093         case '>':
5094         case '<':
5095         case NE_OP:
5096           optExpr = newAst_VALUE (constVal ("0"));
5097           break;
5098         case GE_OP:
5099         case LE_OP:
5100         case EQ_OP:
5101           optExpr = newAst_VALUE (constVal ("1"));
5102           break;
5103         }
5104
5105       return decorateType (optExpr, RESULT_CHECK);
5106     }
5107
5108   vleft = (root->left->type == EX_VALUE ?
5109            root->left->opval.val : NULL);
5110
5111   vright = (root->right->type == EX_VALUE ?
5112             root->right->opval.val : NULL);
5113
5114   /* if left is a BITVAR in BITSPACE */
5115   /* and right is a LITERAL then opt- */
5116   /* imize else do nothing       */
5117   if (vleft && vright &&
5118       IS_BITVAR (vleft->etype) &&
5119       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5120       IS_LITERAL (vright->etype))
5121     {
5122
5123       /* if right side > 1 then comparison may never succeed */
5124       if ((litValue = (int) floatFromVal (vright)) > 1)
5125         {
5126           werror (W_BAD_COMPARE);
5127           goto noOptimize;
5128         }
5129
5130       if (litValue)
5131         {
5132           switch (root->opval.op)
5133             {
5134             case '>':           /* bit value greater than 1 cannot be */
5135               werror (W_BAD_COMPARE);
5136               goto noOptimize;
5137               break;
5138
5139             case '<':           /* bit value < 1 means 0 */
5140             case NE_OP:
5141               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5142               break;
5143
5144             case LE_OP: /* bit value <= 1 means no check */
5145               optExpr = newAst_VALUE (vright);
5146               break;
5147
5148             case GE_OP: /* bit value >= 1 means only check for = */
5149             case EQ_OP:
5150               optExpr = newAst_VALUE (vleft);
5151               break;
5152             }
5153         }
5154       else
5155         {                       /* literal is zero */
5156           switch (root->opval.op)
5157             {
5158             case '<':           /* bit value < 0 cannot be */
5159               werror (W_BAD_COMPARE);
5160               goto noOptimize;
5161               break;
5162
5163             case '>':           /* bit value > 0 means 1 */
5164             case NE_OP:
5165               optExpr = newAst_VALUE (vleft);
5166               break;
5167
5168             case LE_OP: /* bit value <= 0 means no check */
5169             case GE_OP: /* bit value >= 0 means no check */
5170               werror (W_BAD_COMPARE);
5171               goto noOptimize;
5172               break;
5173
5174             case EQ_OP: /* bit == 0 means ! of bit */
5175               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5176               break;
5177             }
5178         }
5179       return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
5180     }                           /* end-of-if of BITVAR */
5181
5182 noOptimize:
5183   return root;
5184 }
5185 /*-----------------------------------------------------------------*/
5186 /* addSymToBlock : adds the symbol to the first block we find      */
5187 /*-----------------------------------------------------------------*/
5188 void 
5189 addSymToBlock (symbol * sym, ast * tree)
5190 {
5191   /* reached end of tree or a leaf */
5192   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5193     return;
5194
5195   /* found a block */
5196   if (IS_AST_OP (tree) &&
5197       tree->opval.op == BLOCK)
5198     {
5199
5200       symbol *lsym = copySymbol (sym);
5201
5202       lsym->next = AST_VALUES (tree, sym);
5203       AST_VALUES (tree, sym) = lsym;
5204       return;
5205     }
5206
5207   addSymToBlock (sym, tree->left);
5208   addSymToBlock (sym, tree->right);
5209 }
5210
5211 /*-----------------------------------------------------------------*/
5212 /* processRegParms - do processing for register parameters         */
5213 /*-----------------------------------------------------------------*/
5214 static void 
5215 processRegParms (value * args, ast * body)
5216 {
5217   while (args)
5218     {
5219       if (IS_REGPARM (args->etype))
5220         addSymToBlock (args->sym, body);
5221       args = args->next;
5222     }
5223 }
5224
5225 /*-----------------------------------------------------------------*/
5226 /* resetParmKey - resets the operandkeys for the symbols           */
5227 /*-----------------------------------------------------------------*/
5228 DEFSETFUNC (resetParmKey)
5229 {
5230   symbol *sym = item;
5231
5232   sym->key = 0;
5233   sym->defs = NULL;
5234   sym->uses = NULL;
5235   sym->remat = 0;
5236   return 1;
5237 }
5238
5239 /*-----------------------------------------------------------------*/
5240 /* createFunction - This is the key node that calls the iCode for  */
5241 /*                  generating the code for a function. Note code  */
5242 /*                  is generated function by function, later when  */
5243 /*                  add inter-procedural analysis this will change */
5244 /*-----------------------------------------------------------------*/
5245 ast *
5246 createFunction (symbol * name, ast * body)
5247 {
5248   ast *ex;
5249   symbol *csym;
5250   int stack = 0;
5251   sym_link *fetype;
5252   iCode *piCode = NULL;
5253
5254   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
5255     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
5256
5257   /* if check function return 0 then some problem */
5258   if (checkFunction (name, NULL) == 0)
5259     return NULL;
5260
5261   /* create a dummy block if none exists */
5262   if (!body)
5263     body = newNode (BLOCK, NULL, NULL);
5264
5265   noLineno++;
5266
5267   /* check if the function name already in the symbol table */
5268   if ((csym = findSym (SymbolTab, NULL, name->name)))
5269     {
5270       name = csym;
5271       /* special case for compiler defined functions
5272          we need to add the name to the publics list : this
5273          actually means we are now compiling the compiler
5274          support routine */
5275       if (name->cdef)
5276         {
5277           addSet (&publics, name);
5278         }
5279     }
5280   else
5281     {
5282       addSymChain (name);
5283       allocVariables (name);
5284     }
5285   name->lastLine = mylineno;
5286   currFunc = name;
5287
5288   /* set the stack pointer */
5289   /* PENDING: check this for the mcs51 */
5290   stackPtr = -port->stack.direction * port->stack.call_overhead;
5291   if (IFFUNC_ISISR (name->type))
5292     stackPtr -= port->stack.direction * port->stack.isr_overhead;
5293   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
5294     stackPtr -= port->stack.direction * port->stack.reent_overhead;
5295
5296   xstackPtr = -port->stack.direction * port->stack.call_overhead;
5297
5298   fetype = getSpec (name->type);        /* get the specifier for the function */
5299   /* if this is a reentrant function then */
5300   if (IFFUNC_ISREENT (name->type))
5301     reentrant++;
5302
5303   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
5304
5305   /* do processing for parameters that are passed in registers */
5306   processRegParms (FUNC_ARGS(name->type), body);
5307
5308   /* set the stack pointer */
5309   stackPtr = 0;
5310   xstackPtr = -1;
5311
5312   /* allocate & autoinit the block variables */
5313   processBlockVars (body, &stack, ALLOCATE);
5314
5315   /* save the stack information */
5316   if (options.useXstack)
5317     name->xstack = SPEC_STAK (fetype) = stack;
5318   else
5319     name->stack = SPEC_STAK (fetype) = stack;
5320
5321   /* name needs to be mangled */
5322   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
5323
5324   body = resolveSymbols (body); /* resolve the symbols */
5325   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
5326                                         
5327
5328   ex = newAst_VALUE (symbolVal (name)); /* create name */
5329   ex = newNode (FUNCTION, ex, body);
5330   ex->values.args = FUNC_ARGS(name->type);
5331   ex->decorated=1;
5332   if (options.dump_tree) PA(ex);
5333   if (fatalError)
5334     {
5335       werror (E_FUNC_NO_CODE, name->name);
5336       goto skipall;
5337     }
5338
5339   /* create the node & generate intermediate code */
5340   GcurMemmap = code;
5341   codeOutFile = code->oFile;
5342   piCode = iCodeFromAst (ex);
5343
5344   if (fatalError)
5345     {
5346       werror (E_FUNC_NO_CODE, name->name);
5347       goto skipall;
5348     }
5349
5350   eBBlockFromiCode (piCode);
5351
5352   /* if there are any statics then do them */
5353   if (staticAutos)
5354     {
5355       GcurMemmap = statsg;
5356       codeOutFile = statsg->oFile;
5357       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
5358       staticAutos = NULL;
5359     }
5360
5361 skipall:
5362
5363   /* dealloc the block variables */
5364   processBlockVars (body, &stack, DEALLOCATE);
5365   outputDebugStackSymbols();
5366   /* deallocate paramaters */
5367   deallocParms (FUNC_ARGS(name->type));
5368
5369   if (IFFUNC_ISREENT (name->type))
5370     reentrant--;
5371
5372   /* we are done freeup memory & cleanup */
5373   noLineno--;
5374   if (port->reset_labelKey) labelKey = 1;
5375   name->key = 0;
5376   FUNC_HASBODY(name->type) = 1;
5377   addSet (&operKeyReset, name);
5378   applyToSet (operKeyReset, resetParmKey);
5379
5380   if (options.debug)
5381     cdbStructBlock(1);
5382
5383   cleanUpLevel (LabelTab, 0);
5384   cleanUpBlock (StructTab, 1);
5385   cleanUpBlock (TypedefTab, 1);
5386
5387   xstack->syms = NULL;
5388   istack->syms = NULL;
5389   return NULL;
5390 }
5391
5392
5393 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5394 /*-----------------------------------------------------------------*/
5395 /* ast_print : prints the ast (for debugging purposes)             */
5396 /*-----------------------------------------------------------------*/
5397
5398 void ast_print (ast * tree, FILE *outfile, int indent)
5399 {
5400
5401         if (!tree) return ;
5402
5403         /* can print only decorated trees */
5404         if (!tree->decorated) return;
5405
5406         /* if any child is an error | this one is an error do nothing */
5407         if (tree->isError ||
5408             (tree->left && tree->left->isError) ||
5409             (tree->right && tree->right->isError)) {
5410                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5411         }
5412
5413
5414         /* print the line          */
5415         /* if not block & function */
5416         if (tree->type == EX_OP &&
5417             (tree->opval.op != FUNCTION &&
5418              tree->opval.op != BLOCK &&
5419              tree->opval.op != NULLOP)) {
5420         }
5421
5422         if (tree->opval.op == FUNCTION) {
5423                 int arg=0;
5424                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5425                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5426                         tree->left->opval.val->name, tree);
5427                 printTypeChain (tree->left->opval.val->type->next,outfile);
5428                 fprintf(outfile,") args (");
5429                 do {
5430                   if (arg) {
5431                     fprintf (outfile, ", ");
5432                   }
5433                   printTypeChain (args ? args->type : NULL, outfile);
5434                   arg++;
5435                   args= args ? args->next : NULL;
5436                 } while (args);
5437                 fprintf(outfile,")\n");
5438                 ast_print(tree->left,outfile,indent);
5439                 ast_print(tree->right,outfile,indent);
5440                 return ;
5441         }
5442         if (tree->opval.op == BLOCK) {
5443                 symbol *decls = tree->values.sym;
5444                 INDENT(indent,outfile);
5445                 fprintf(outfile,"{\n");
5446                 while (decls) {
5447                         INDENT(indent+2,outfile);
5448                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5449                                 decls->name, decls);
5450                         printTypeChain(decls->type,outfile);
5451                         fprintf(outfile,")\n");
5452
5453                         decls = decls->next;
5454                 }
5455                 ast_print(tree->right,outfile,indent+2);
5456                 INDENT(indent,outfile);
5457                 fprintf(outfile,"}\n");
5458                 return;
5459         }
5460         if (tree->opval.op == NULLOP) {
5461                 ast_print(tree->left,outfile,indent);
5462                 ast_print(tree->right,outfile,indent);
5463                 return ;
5464         }
5465         INDENT(indent,outfile);
5466
5467         /*------------------------------------------------------------------*/
5468         /*----------------------------*/
5469         /*   leaf has been reached    */
5470         /*----------------------------*/
5471         /* if this is of type value */
5472         /* just get the type        */
5473         if (tree->type == EX_VALUE) {
5474
5475                 if (IS_LITERAL (tree->opval.val->etype)) {
5476                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5477                         if (SPEC_USIGN (tree->opval.val->etype))
5478                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5479                         else
5480                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5481                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5482                                                       floatFromVal(tree->opval.val));
5483                 } else if (tree->opval.val->sym) {
5484                         /* if the undefined flag is set then give error message */
5485                         if (tree->opval.val->sym->undefined) {
5486                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5487                         } else {
5488                                 fprintf(outfile,"SYMBOL ");
5489                         }
5490                         fprintf(outfile,"(%s=%p)",
5491                                 tree->opval.val->sym->name,tree);
5492                 }
5493                 if (tree->ftype) {
5494                         fprintf(outfile," type (");
5495                         printTypeChain(tree->ftype,outfile);
5496                         fprintf(outfile,")\n");
5497                 } else {
5498                         fprintf(outfile,"\n");
5499                 }
5500                 return ;
5501         }
5502
5503         /* if type link for the case of cast */
5504         if (tree->type == EX_LINK) {
5505                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5506                 printTypeChain(tree->opval.lnk,outfile);
5507                 fprintf(outfile,")\n");
5508                 return ;
5509         }
5510
5511
5512         /* depending on type of operator do */
5513
5514         switch (tree->opval.op) {
5515                 /*------------------------------------------------------------------*/
5516                 /*----------------------------*/
5517                 /*        array node          */
5518                 /*----------------------------*/
5519         case '[':
5520                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5521                 printTypeChain(tree->ftype,outfile);
5522                 fprintf(outfile,")\n");
5523                 ast_print(tree->left,outfile,indent+2);
5524                 ast_print(tree->right,outfile,indent+2);
5525                 return;
5526
5527                 /*------------------------------------------------------------------*/
5528                 /*----------------------------*/
5529                 /*      struct/union          */
5530                 /*----------------------------*/
5531         case '.':
5532                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5533                 printTypeChain(tree->ftype,outfile);
5534                 fprintf(outfile,")\n");
5535                 ast_print(tree->left,outfile,indent+2);
5536                 ast_print(tree->right,outfile,indent+2);
5537                 return ;
5538
5539                 /*------------------------------------------------------------------*/
5540                 /*----------------------------*/
5541                 /*    struct/union pointer    */
5542                 /*----------------------------*/
5543         case PTR_OP:
5544                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5545                 printTypeChain(tree->ftype,outfile);
5546                 fprintf(outfile,")\n");
5547                 ast_print(tree->left,outfile,indent+2);
5548                 ast_print(tree->right,outfile,indent+2);
5549                 return ;
5550
5551                 /*------------------------------------------------------------------*/
5552                 /*----------------------------*/
5553                 /*  ++/-- operation           */
5554                 /*----------------------------*/
5555         case INC_OP:
5556                 if (tree->left)
5557                   fprintf(outfile,"post-");
5558                 else
5559                   fprintf(outfile,"pre-");
5560                 fprintf(outfile,"INC_OP (%p) type (",tree);
5561                 printTypeChain(tree->ftype,outfile);
5562                 fprintf(outfile,")\n");
5563                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5564                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5565                 return ;
5566
5567         case DEC_OP:
5568                 if (tree->left)
5569                   fprintf(outfile,"post-");
5570                 else
5571                   fprintf(outfile,"pre-");
5572                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5573                 printTypeChain(tree->ftype,outfile);
5574                 fprintf(outfile,")\n");
5575                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5576                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5577                 return ;
5578
5579                 /*------------------------------------------------------------------*/
5580                 /*----------------------------*/
5581                 /*  bitwise and               */
5582                 /*----------------------------*/
5583         case '&':
5584                 if (tree->right) {
5585                         fprintf(outfile,"& (%p) type (",tree);
5586                         printTypeChain(tree->ftype,outfile);
5587                         fprintf(outfile,")\n");
5588                         ast_print(tree->left,outfile,indent+2);
5589                         ast_print(tree->right,outfile,indent+2);
5590                 } else {
5591                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5592                         printTypeChain(tree->ftype,outfile);
5593                         fprintf(outfile,")\n");
5594                         ast_print(tree->left,outfile,indent+2);
5595                         ast_print(tree->right,outfile,indent+2);
5596                 }
5597                 return ;
5598                 /*----------------------------*/
5599                 /*  bitwise or                */
5600                 /*----------------------------*/
5601         case '|':
5602                 fprintf(outfile,"OR (%p) type (",tree);
5603                 printTypeChain(tree->ftype,outfile);
5604                 fprintf(outfile,")\n");
5605                 ast_print(tree->left,outfile,indent+2);
5606                 ast_print(tree->right,outfile,indent+2);
5607                 return ;
5608                 /*------------------------------------------------------------------*/
5609                 /*----------------------------*/
5610                 /*  bitwise xor               */
5611                 /*----------------------------*/
5612         case '^':
5613                 fprintf(outfile,"XOR (%p) type (",tree);
5614                 printTypeChain(tree->ftype,outfile);
5615                 fprintf(outfile,")\n");
5616                 ast_print(tree->left,outfile,indent+2);
5617                 ast_print(tree->right,outfile,indent+2);
5618                 return ;
5619
5620                 /*------------------------------------------------------------------*/
5621                 /*----------------------------*/
5622                 /*  division                  */
5623                 /*----------------------------*/
5624         case '/':
5625                 fprintf(outfile,"DIV (%p) type (",tree);
5626                 printTypeChain(tree->ftype,outfile);
5627                 fprintf(outfile,")\n");
5628                 ast_print(tree->left,outfile,indent+2);
5629                 ast_print(tree->right,outfile,indent+2);
5630                 return ;
5631                 /*------------------------------------------------------------------*/
5632                 /*----------------------------*/
5633                 /*            modulus         */
5634                 /*----------------------------*/
5635         case '%':
5636                 fprintf(outfile,"MOD (%p) type (",tree);
5637                 printTypeChain(tree->ftype,outfile);
5638                 fprintf(outfile,")\n");
5639                 ast_print(tree->left,outfile,indent+2);
5640                 ast_print(tree->right,outfile,indent+2);
5641                 return ;
5642
5643                 /*------------------------------------------------------------------*/
5644                 /*----------------------------*/
5645                 /*  address dereference       */
5646                 /*----------------------------*/
5647         case '*':                       /* can be unary  : if right is null then unary operation */
5648                 if (!tree->right) {
5649                         fprintf(outfile,"DEREF (%p) type (",tree);
5650                         printTypeChain(tree->ftype,outfile);
5651                         fprintf(outfile,")\n");
5652                         ast_print(tree->left,outfile,indent+2);
5653                         return ;
5654                 }                       
5655                 /*------------------------------------------------------------------*/
5656                 /*----------------------------*/
5657                 /*      multiplication        */
5658                 /*----------------------------*/                
5659                 fprintf(outfile,"MULT (%p) type (",tree);
5660                 printTypeChain(tree->ftype,outfile);
5661                 fprintf(outfile,")\n");
5662                 ast_print(tree->left,outfile,indent+2);
5663                 ast_print(tree->right,outfile,indent+2);
5664                 return ;
5665
5666
5667                 /*------------------------------------------------------------------*/
5668                 /*----------------------------*/
5669                 /*    unary '+' operator      */
5670                 /*----------------------------*/
5671         case '+':
5672                 /* if unary plus */
5673                 if (!tree->right) {
5674                         fprintf(outfile,"UPLUS (%p) type (",tree);
5675                         printTypeChain(tree->ftype,outfile);
5676                         fprintf(outfile,")\n");
5677                         ast_print(tree->left,outfile,indent+2);
5678                 } else {
5679                         /*------------------------------------------------------------------*/
5680                         /*----------------------------*/
5681                         /*      addition              */
5682                         /*----------------------------*/
5683                         fprintf(outfile,"ADD (%p) type (",tree);
5684                         printTypeChain(tree->ftype,outfile);
5685                         fprintf(outfile,")\n");
5686                         ast_print(tree->left,outfile,indent+2);
5687                         ast_print(tree->right,outfile,indent+2);
5688                 }
5689                 return;
5690                 /*------------------------------------------------------------------*/
5691                 /*----------------------------*/
5692                 /*      unary '-'             */
5693                 /*----------------------------*/
5694         case '-':                       /* can be unary   */
5695                 if (!tree->right) {
5696                         fprintf(outfile,"UMINUS (%p) type (",tree);
5697                         printTypeChain(tree->ftype,outfile);
5698                         fprintf(outfile,")\n");
5699                         ast_print(tree->left,outfile,indent+2);
5700                 } else {
5701                         /*------------------------------------------------------------------*/
5702                         /*----------------------------*/
5703                         /*      subtraction           */
5704                         /*----------------------------*/
5705                         fprintf(outfile,"SUB (%p) type (",tree);
5706                         printTypeChain(tree->ftype,outfile);
5707                         fprintf(outfile,")\n");
5708                         ast_print(tree->left,outfile,indent+2);
5709                         ast_print(tree->right,outfile,indent+2);
5710                 }
5711                 return;
5712                 /*------------------------------------------------------------------*/
5713                 /*----------------------------*/
5714                 /*    compliment              */
5715                 /*----------------------------*/
5716         case '~':
5717                 fprintf(outfile,"COMPL (%p) type (",tree);
5718                 printTypeChain(tree->ftype,outfile);
5719                 fprintf(outfile,")\n");
5720                 ast_print(tree->left,outfile,indent+2);
5721                 return ;
5722                 /*------------------------------------------------------------------*/
5723                 /*----------------------------*/
5724                 /*           not              */
5725                 /*----------------------------*/
5726         case '!':
5727                 fprintf(outfile,"NOT (%p) type (",tree);
5728                 printTypeChain(tree->ftype,outfile);
5729                 fprintf(outfile,")\n");
5730                 ast_print(tree->left,outfile,indent+2);
5731                 return ;
5732                 /*------------------------------------------------------------------*/
5733                 /*----------------------------*/
5734                 /*           shift            */
5735                 /*----------------------------*/
5736         case RRC:
5737                 fprintf(outfile,"RRC (%p) type (",tree);
5738                 printTypeChain(tree->ftype,outfile);
5739                 fprintf(outfile,")\n");
5740                 ast_print(tree->left,outfile,indent+2);
5741                 return ;
5742
5743         case RLC:
5744                 fprintf(outfile,"RLC (%p) type (",tree);
5745                 printTypeChain(tree->ftype,outfile);
5746                 fprintf(outfile,")\n");
5747                 ast_print(tree->left,outfile,indent+2);
5748                 return ;
5749         case SWAP:
5750                 fprintf(outfile,"SWAP (%p) type (",tree);
5751                 printTypeChain(tree->ftype,outfile);
5752                 fprintf(outfile,")\n");
5753                 ast_print(tree->left,outfile,indent+2);
5754                 return ;
5755         case GETHBIT:
5756                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5757                 printTypeChain(tree->ftype,outfile);
5758                 fprintf(outfile,")\n");
5759                 ast_print(tree->left,outfile,indent+2);
5760                 return ;
5761         case LEFT_OP:
5762                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5763                 printTypeChain(tree->ftype,outfile);
5764                 fprintf(outfile,")\n");
5765                 ast_print(tree->left,outfile,indent+2);
5766                 ast_print(tree->right,outfile,indent+2);
5767                 return ;
5768         case RIGHT_OP:
5769                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5770                 printTypeChain(tree->ftype,outfile);
5771                 fprintf(outfile,")\n");
5772                 ast_print(tree->left,outfile,indent+2);
5773                 ast_print(tree->right,outfile,indent+2);
5774                 return ;
5775                 /*------------------------------------------------------------------*/
5776                 /*----------------------------*/
5777                 /*         casting            */
5778                 /*----------------------------*/
5779         case CAST:                      /* change the type   */
5780                 fprintf(outfile,"CAST (%p) from type (",tree);
5781                 printTypeChain(tree->right->ftype,outfile);
5782                 fprintf(outfile,") to type (");
5783                 printTypeChain(tree->ftype,outfile);
5784                 fprintf(outfile,")\n");
5785                 ast_print(tree->right,outfile,indent+2);
5786                 return ;
5787                 
5788         case AND_OP:
5789                 fprintf(outfile,"ANDAND (%p) type (",tree);
5790                 printTypeChain(tree->ftype,outfile);
5791                 fprintf(outfile,")\n");
5792                 ast_print(tree->left,outfile,indent+2);
5793                 ast_print(tree->right,outfile,indent+2);
5794                 return ;
5795         case OR_OP:
5796                 fprintf(outfile,"OROR (%p) type (",tree);
5797                 printTypeChain(tree->ftype,outfile);
5798                 fprintf(outfile,")\n");
5799                 ast_print(tree->left,outfile,indent+2);
5800                 ast_print(tree->right,outfile,indent+2);
5801                 return ;
5802                 
5803                 /*------------------------------------------------------------------*/
5804                 /*----------------------------*/
5805                 /*     comparison operators   */
5806                 /*----------------------------*/
5807         case '>':
5808                 fprintf(outfile,"GT(>) (%p) type (",tree);
5809                 printTypeChain(tree->ftype,outfile);
5810                 fprintf(outfile,")\n");
5811                 ast_print(tree->left,outfile,indent+2);
5812                 ast_print(tree->right,outfile,indent+2);
5813                 return ;
5814         case '<':
5815                 fprintf(outfile,"LT(<) (%p) type (",tree);
5816                 printTypeChain(tree->ftype,outfile);
5817                 fprintf(outfile,")\n");
5818                 ast_print(tree->left,outfile,indent+2);
5819                 ast_print(tree->right,outfile,indent+2);
5820                 return ;
5821         case LE_OP:
5822                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5823                 printTypeChain(tree->ftype,outfile);
5824                 fprintf(outfile,")\n");
5825                 ast_print(tree->left,outfile,indent+2);
5826                 ast_print(tree->right,outfile,indent+2);
5827                 return ;
5828         case GE_OP:
5829                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5830                 printTypeChain(tree->ftype,outfile);
5831                 fprintf(outfile,")\n");
5832                 ast_print(tree->left,outfile,indent+2);
5833                 ast_print(tree->right,outfile,indent+2);
5834                 return ;
5835         case EQ_OP:
5836                 fprintf(outfile,"EQ(==) (%p) type (",tree);
5837                 printTypeChain(tree->ftype,outfile);
5838                 fprintf(outfile,")\n");
5839                 ast_print(tree->left,outfile,indent+2);
5840                 ast_print(tree->right,outfile,indent+2);
5841                 return ;
5842         case NE_OP:
5843                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5844                 printTypeChain(tree->ftype,outfile);
5845                 fprintf(outfile,")\n");
5846                 ast_print(tree->left,outfile,indent+2);
5847                 ast_print(tree->right,outfile,indent+2);
5848                 /*------------------------------------------------------------------*/
5849                 /*----------------------------*/
5850                 /*             sizeof         */
5851                 /*----------------------------*/
5852         case SIZEOF:            /* evaluate wihout code generation */
5853                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5854                 return ;
5855
5856                 /*------------------------------------------------------------------*/
5857                 /*----------------------------*/
5858                 /* conditional operator  '?'  */
5859                 /*----------------------------*/
5860         case '?':
5861                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5862                 printTypeChain(tree->ftype,outfile);
5863                 fprintf(outfile,")\n");
5864                 ast_print(tree->left,outfile,indent+2);
5865                 ast_print(tree->right,outfile,indent+2);
5866                 return;
5867
5868         case ':':
5869                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5870                 printTypeChain(tree->ftype,outfile);
5871                 fprintf(outfile,")\n");
5872                 ast_print(tree->left,outfile,indent+2);
5873                 ast_print(tree->right,outfile,indent+2);
5874                 return ;
5875
5876                 /*------------------------------------------------------------------*/
5877                 /*----------------------------*/
5878                 /*    assignment operators    */
5879                 /*----------------------------*/
5880         case MUL_ASSIGN:
5881                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5882                 printTypeChain(tree->ftype,outfile);
5883                 fprintf(outfile,")\n");
5884                 ast_print(tree->left,outfile,indent+2);
5885                 ast_print(tree->right,outfile,indent+2);
5886                 return;
5887         case DIV_ASSIGN:
5888                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5889                 printTypeChain(tree->ftype,outfile);
5890                 fprintf(outfile,")\n");
5891                 ast_print(tree->left,outfile,indent+2);
5892                 ast_print(tree->right,outfile,indent+2);
5893                 return;
5894         case AND_ASSIGN:
5895                 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
5896                 printTypeChain(tree->ftype,outfile);
5897                 fprintf(outfile,")\n");
5898                 ast_print(tree->left,outfile,indent+2);
5899                 ast_print(tree->right,outfile,indent+2);
5900                 return;
5901         case OR_ASSIGN:
5902                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5903                 printTypeChain(tree->ftype,outfile);
5904                 fprintf(outfile,")\n");
5905                 ast_print(tree->left,outfile,indent+2);
5906                 ast_print(tree->right,outfile,indent+2);
5907                 return;
5908         case XOR_ASSIGN:
5909                 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
5910                 printTypeChain(tree->ftype,outfile);
5911                 fprintf(outfile,")\n");
5912                 ast_print(tree->left,outfile,indent+2);
5913                 ast_print(tree->right,outfile,indent+2);
5914                 return;
5915         case RIGHT_ASSIGN:
5916                 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
5917                 printTypeChain(tree->ftype,outfile);
5918                 fprintf(outfile,")\n");
5919                 ast_print(tree->left,outfile,indent+2);
5920                 ast_print(tree->right,outfile,indent+2);
5921                 return;
5922         case LEFT_ASSIGN:
5923                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5924                 printTypeChain(tree->ftype,outfile);
5925                 fprintf(outfile,")\n");
5926                 ast_print(tree->left,outfile,indent+2);
5927                 ast_print(tree->right,outfile,indent+2);
5928                 return;
5929                 /*------------------------------------------------------------------*/
5930                 /*----------------------------*/
5931                 /*    -= operator             */
5932                 /*----------------------------*/
5933         case SUB_ASSIGN:
5934                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5935                 printTypeChain(tree->ftype,outfile);
5936                 fprintf(outfile,")\n");
5937                 ast_print(tree->left,outfile,indent+2);
5938                 ast_print(tree->right,outfile,indent+2);
5939                 return;
5940                 /*------------------------------------------------------------------*/
5941                 /*----------------------------*/
5942                 /*          += operator       */
5943                 /*----------------------------*/
5944         case ADD_ASSIGN:
5945                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5946                 printTypeChain(tree->ftype,outfile);
5947                 fprintf(outfile,")\n");
5948                 ast_print(tree->left,outfile,indent+2);
5949                 ast_print(tree->right,outfile,indent+2);
5950                 return;
5951                 /*------------------------------------------------------------------*/
5952                 /*----------------------------*/
5953                 /*      straight assignemnt   */
5954                 /*----------------------------*/
5955         case '=':
5956                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5957                 printTypeChain(tree->ftype,outfile);
5958                 fprintf(outfile,")\n");
5959                 ast_print(tree->left,outfile,indent+2);
5960                 ast_print(tree->right,outfile,indent+2);
5961                 return;     
5962                 /*------------------------------------------------------------------*/
5963                 /*----------------------------*/
5964                 /*      comma operator        */
5965                 /*----------------------------*/
5966         case ',':
5967                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
5968                 printTypeChain(tree->ftype,outfile);
5969                 fprintf(outfile,")\n");
5970                 ast_print(tree->left,outfile,indent+2);
5971                 ast_print(tree->right,outfile,indent+2);
5972                 return;
5973                 /*------------------------------------------------------------------*/
5974                 /*----------------------------*/
5975                 /*       function call        */
5976                 /*----------------------------*/
5977         case CALL:
5978         case PCALL:
5979                 fprintf(outfile,"CALL (%p) type (",tree);
5980                 printTypeChain(tree->ftype,outfile);
5981                 fprintf(outfile,")\n");
5982                 ast_print(tree->left,outfile,indent+2);
5983                 ast_print(tree->right,outfile,indent+2);
5984                 return;
5985         case PARAM:
5986                 fprintf(outfile,"PARMS\n");
5987                 ast_print(tree->left,outfile,indent+2);
5988                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
5989                         ast_print(tree->right,outfile,indent+2);
5990                 }
5991                 return ;
5992                 /*------------------------------------------------------------------*/
5993                 /*----------------------------*/
5994                 /*     return statement       */
5995                 /*----------------------------*/
5996         case RETURN:
5997                 fprintf(outfile,"RETURN (%p) type (",tree);
5998                 if (tree->right) {
5999                     printTypeChain(tree->right->ftype,outfile);
6000                 }
6001                 fprintf(outfile,")\n");
6002                 ast_print(tree->right,outfile,indent+2);
6003                 return ;
6004                 /*------------------------------------------------------------------*/
6005                 /*----------------------------*/
6006                 /*     label statement        */
6007                 /*----------------------------*/
6008         case LABEL :
6009                 fprintf(outfile,"LABEL (%p)\n",tree);
6010                 ast_print(tree->left,outfile,indent+2);
6011                 ast_print(tree->right,outfile,indent);
6012                 return;
6013                 /*------------------------------------------------------------------*/
6014                 /*----------------------------*/
6015                 /*     switch statement       */
6016                 /*----------------------------*/
6017         case SWITCH:
6018                 {
6019                         value *val;
6020                         fprintf(outfile,"SWITCH (%p) ",tree);
6021                         ast_print(tree->left,outfile,0);
6022                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
6023                                 INDENT(indent+2,outfile);
6024                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
6025                                         (int) floatFromVal(val),
6026                                         tree->values.switchVals.swNum,
6027                                         (int) floatFromVal(val));
6028                         }
6029                         ast_print(tree->right,outfile,indent);
6030                 }
6031                 return ;
6032                 /*------------------------------------------------------------------*/
6033                 /*----------------------------*/
6034                 /* ifx Statement              */
6035                 /*----------------------------*/
6036         case IFX:
6037                 fprintf(outfile,"IF (%p) \n",tree);
6038                 ast_print(tree->left,outfile,indent+2);
6039                 if (tree->trueLabel) {
6040                         INDENT(indent+2,outfile);
6041                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
6042                 }
6043                 if (tree->falseLabel) {
6044                         INDENT(indent+2,outfile);
6045                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
6046                 }
6047                 ast_print(tree->right,outfile,indent+2);
6048                 return ;
6049                 /*----------------------------*/
6050                 /* goto Statement              */
6051                 /*----------------------------*/
6052         case GOTO:
6053                 fprintf(outfile,"GOTO (%p) \n",tree);
6054                 ast_print(tree->left,outfile,indent+2);
6055                 fprintf(outfile,"\n");
6056                 return ;
6057                 /*------------------------------------------------------------------*/
6058                 /*----------------------------*/
6059                 /* for Statement              */
6060                 /*----------------------------*/
6061         case FOR:
6062                 fprintf(outfile,"FOR (%p) \n",tree);
6063                 if (AST_FOR( tree, initExpr)) {
6064                         INDENT(indent+2,outfile);
6065                         fprintf(outfile,"INIT EXPR ");
6066                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
6067                 }
6068                 if (AST_FOR( tree, condExpr)) {
6069                         INDENT(indent+2,outfile);
6070                         fprintf(outfile,"COND EXPR ");
6071                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
6072                 }
6073                 if (AST_FOR( tree, loopExpr)) {
6074                         INDENT(indent+2,outfile);
6075                         fprintf(outfile,"LOOP EXPR ");
6076                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
6077                 }
6078                 fprintf(outfile,"FOR LOOP BODY \n");
6079                 ast_print(tree->left,outfile,indent+2);
6080                 return ;
6081         case CRITICAL:
6082                 fprintf(outfile,"CRITICAL (%p) \n",tree);
6083                 ast_print(tree->left,outfile,indent+2);
6084         default:
6085             return ;
6086         }
6087 }
6088
6089 void PA(ast *t)
6090 {
6091         ast_print(t,stdout,0);
6092 }
6093
6094
6095
6096 /*-----------------------------------------------------------------*/
6097 /* astErrors : returns non-zero if errors present in tree          */
6098 /*-----------------------------------------------------------------*/
6099 int astErrors(ast *t)
6100 {
6101   int errors=0;
6102   
6103   if (t)
6104     {
6105       if (t->isError)
6106         errors++;
6107   
6108       if (t->type == EX_VALUE
6109           && t->opval.val->sym
6110           && t->opval.val->sym->undefined)
6111         errors++;
6112
6113       errors += astErrors(t->left);
6114       errors += astErrors(t->right);
6115     }
6116     
6117   return errors;
6118 }