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