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