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