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