Implemented generic part of RFE #1880202
[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
231   if (src->ftype)
232     dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
233
234   /* if this is a leaf */
235   /* if value */
236   if (src->type == EX_VALUE)
237     {
238       dest->opval.val = copyValue (src->opval.val);
239       goto exit;
240     }
241
242   /* if link */
243   if (src->type == EX_LINK)
244     {
245       dest->opval.lnk = copyLinkChain (src->opval.lnk);
246       goto exit;
247     }
248
249   dest->opval.op = src->opval.op;
250
251   /* if this is a node that has special values */
252   copyAstValues (dest, src);
253
254   dest->trueLabel = copySymbol (src->trueLabel);
255   dest->falseLabel = copySymbol (src->falseLabel);
256   dest->left = copyAst (src->left);
257   dest->right = copyAst (src->right);
258 exit:
259   return dest;
260
261 }
262 #if 0
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's          */
265 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
268
269   // traverse the tree and remove inc/dec ops
270
271   if (!tree)
272     return NULL;
273
274   if (tree->type == EX_OP &&
275       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
276     if (tree->left)
277       tree=tree->left;
278     else
279       tree=tree->right;
280   }
281
282   tree->left=removeIncDecOps(tree->left);
283   tree->right=removeIncDecOps(tree->right);
284
285  return tree;
286 }
287
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's       */
290 /*                  "*++s += 3" -> "*++s = *++s + 3"               */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
293
294   // traverse the tree and remove pre-inc/dec ops
295
296   if (!tree)
297     return NULL;
298
299   if (tree->type == EX_OP &&
300       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
301     if (tree->right)
302       tree=tree->right;
303   }
304
305   tree->left=removePreIncDecOps(tree->left);
306   tree->right=removePreIncDecOps(tree->right);
307
308  return tree;
309 }
310
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's      */
313 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
316
317   // traverse the tree and remove pre-inc/dec ops
318
319   if (!tree)
320     return NULL;
321
322   if (tree->type == EX_OP &&
323       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
324     if (tree->left)
325       tree=tree->left;
326   }
327
328   tree->left=removePostIncDecOps(tree->left);
329   tree->right=removePostIncDecOps(tree->right);
330
331  return tree;
332 }
333 #endif
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg  */
336 /*            with a reference to a new temporary variable. Returns*/
337 /*            an AST which assigns the original value to the       */
338 /*            temporary.                                           */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
341 {
342   symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
343   ast *tempvar;
344
345   /* Tell gatherImplicitVariables() to automatically give the
346      symbol the correct type */
347   sym->infertype = 1;
348   sym->type = NULL;
349   sym->etype = NULL;
350
351   tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352   *treeptr = newAst_VALUE(symbolVal(sym));
353
354   addSymChain(&sym);
355
356   return tempvar;
357 }
358
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a       */
361 /*            temporary variable if necessary to avoid duplicating */
362 /*            any side effects, for use in e.g.                    */
363 /*               foo()->count += 5;      becomes                   */
364 /*               tmp = foo(); tmp->count = tmp->count + 5;         */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
367 {
368   ast *readval, *writeval;
369   ast *tempvar1 = NULL;
370   ast *tempvar2 = NULL;
371   ast *result;
372
373   if (!target || !operand) {
374     return NULL;
375   }
376
377   /* we need to create two copies of target: one to read from and
378      one to write to. but we need to do this without duplicating
379      any side effects that may be contained in the tree. */
380
381   if (IS_AST_OP(target)) {
382     /* if this is a dereference, put the referenced item in the temporary */
383     if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384       /* create a new temporary containing the item being dereferenced */
385       if (hasSEFcalls(target->left))
386         tempvar1 = replaceAstWithTemporary(&(target->left));
387     } else if (target->opval.op == '[') {
388       /* Array access is similar, but we have to avoid side effects in
389          both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390       if (hasSEFcalls(target->left))
391         tempvar1 = replaceAstWithTemporary(&(target->left));
392       if (hasSEFcalls(target->right))
393         tempvar2 = replaceAstWithTemporary(&(target->right));
394     } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395       /* illegal pre/post-increment/decrement */
396       werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
397     } else {
398       /* we would have to handle '.', but it is not generated any more */
399       wassertl(target->opval.op != '.', "obsolete opcode in tree");
400
401       /* no other kinds of ASTs are lvalues and can contain side effects */
402     }
403   }
404
405   readval = target;
406   writeval = copyAst(target);
407
408   result = newNode('=', writeval, newNode(op, readval, operand));
409   if (tempvar2)
410     result = newNode(',', tempvar2, result);
411   if (tempvar1)
412     result = newNode(',', tempvar1, result);
413
414   return result;
415
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call,         */
420 /*               inc/decrement, or other side effect               */
421 /*-----------------------------------------------------------------*/
422 bool
423 hasSEFcalls (ast * tree)
424 {
425   if (!tree)
426     return FALSE;
427
428   if (tree->type == EX_OP &&
429       (tree->opval.op == CALL ||
430        tree->opval.op == PCALL ||
431        tree->opval.op == '=' ||
432        tree->opval.op == INC_OP ||
433        tree->opval.op == DEC_OP))
434     return TRUE;
435
436   return (hasSEFcalls (tree->left) |
437           hasSEFcalls (tree->right));
438 }
439
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal    */
442 /*-----------------------------------------------------------------*/
443 static int
444 isAstEqual (ast * t1, ast * t2)
445 {
446   if (!t1 && !t2)
447     return 1;
448
449   if (!t1 || !t2)
450     return 0;
451
452   /* match type */
453   if (t1->type != t2->type)
454     return 0;
455
456   switch (t1->type)
457     {
458     case EX_OP:
459       if (t1->opval.op != t2->opval.op)
460         return 0;
461       return (isAstEqual (t1->left, t2->left) &&
462               isAstEqual (t1->right, t2->right));
463       break;
464
465     case EX_VALUE:
466       if (t1->opval.val->sym)
467         {
468           if (!t2->opval.val->sym)
469             return 0;
470           else
471             return isSymbolEqual (t1->opval.val->sym,
472                                   t2->opval.val->sym);
473         }
474       else
475         {
476           if (t2->opval.val->sym)
477             return 0;
478           else
479             return (floatFromVal (t1->opval.val) ==
480                     floatFromVal (t2->opval.val));
481         }
482       break;
483
484       /* only compare these two types */
485     default:
486       return 0;
487     }
488
489   return 0;
490 }
491
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table          */
494 /*-----------------------------------------------------------------*/
495 ast *
496 resolveSymbols (ast * tree)
497 {
498   /* walk the entire tree and check for values */
499   /* with symbols if we find one then replace  */
500   /* symbol with that from the symbol table    */
501
502   if (tree == NULL)
503     return tree;
504
505 #if 0
506   /* print the line          */
507   /* if not block & function */
508   if (tree->type == EX_OP &&
509       (tree->opval.op != FUNCTION &&
510        tree->opval.op != BLOCK &&
511        tree->opval.op != NULLOP))
512     {
513       filename = tree->filename;
514       lineno = tree->lineno;
515     }
516 #endif
517
518   /* make sure we resolve the true & false labels for ifx */
519   if (tree->type == EX_OP && tree->opval.op == IFX)
520     {
521       symbol *csym;
522
523       if (tree->trueLabel)
524         {
525           if ((csym = findSym (LabelTab, tree->trueLabel,
526                                tree->trueLabel->name)))
527             tree->trueLabel = csym;
528           else
529             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530                       tree->trueLabel->name);
531         }
532
533       if (tree->falseLabel)
534         {
535           if ((csym = findSym (LabelTab,
536                                tree->falseLabel,
537                                tree->falseLabel->name)))
538             tree->falseLabel = csym;
539           else
540             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541                       tree->falseLabel->name);
542         }
543
544     }
545
546   /* if this is a label resolve it from the labelTab */
547   if (IS_AST_VALUE (tree) &&
548       tree->opval.val->sym &&
549       tree->opval.val->sym->islbl)
550     {
551
552       symbol *csym = findSym (LabelTab, tree->opval.val->sym,
553                               tree->opval.val->sym->name);
554
555       if (!csym)
556         werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
557                   tree->opval.val->sym->name);
558       else
559         tree->opval.val->sym = csym;
560
561       goto resolveChildren;
562     }
563
564   /* do only for leafs */
565   if (IS_AST_VALUE (tree) &&
566       tree->opval.val->sym &&
567       !tree->opval.val->sym->implicit)
568     {
569
570       symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
571
572       /* if found in the symbol table & they are not the same */
573       if (csym && tree->opval.val->sym != csym)
574         {
575           tree->opval.val->sym = csym;
576           tree->opval.val->type = csym->type;
577           tree->opval.val->etype = csym->etype;
578         }
579
580       /* if not found in the symbol table */
581       /* mark it as undefined & assume it */
582       /* is an integer in data space      */
583       if (!csym && !tree->opval.val->sym->implicit)
584         {
585
586           /* if this is a function name then */
587           /* mark it as returning an int     */
588           if (tree->funcName)
589             {
590               tree->opval.val->sym->type = newLink (DECLARATOR);
591               DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
592               tree->opval.val->sym->type->next =
593                 tree->opval.val->sym->etype = newIntLink ();
594               tree->opval.val->etype = tree->opval.val->etype;
595               tree->opval.val->type = tree->opval.val->sym->type;
596               werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
597                         tree->opval.val->sym->name);
598               //tree->opval.val->sym->undefined = 1;
599               allocVariables (tree->opval.val->sym);
600             }
601           else
602             {
603               tree->opval.val->sym->undefined = 1;
604               tree->opval.val->type =
605                 tree->opval.val->etype = newIntLink ();
606               tree->opval.val->sym->type =
607                 tree->opval.val->sym->etype = newIntLink ();
608             }
609         }
610     }
611
612 resolveChildren:
613   resolveSymbols (tree->left);
614   resolveSymbols (tree->right);
615
616   return tree;
617 }
618
619 /*------------------------------------------------------------------------*/
620 /* setAstFileLine - walks a ast tree & sets the file name and line number */
621 /*------------------------------------------------------------------------*/
622 int setAstFileLine (ast * tree, char *filename, int lineno)
623 {
624   if (!tree)
625     return 0;
626
627   tree->filename = filename;
628   tree->lineno = lineno;
629   setAstFileLine (tree->left, filename, lineno);
630   setAstFileLine (tree->right, filename, lineno);
631   return 0;
632 }
633
634 /*-----------------------------------------------------------------*/
635 /* funcOfType :- function of type with name                        */
636 /*-----------------------------------------------------------------*/
637 symbol *
638 funcOfType (char *name, sym_link * type, sym_link * argType,
639             int nArgs, int rent)
640 {
641   symbol *sym;
642   /* create the symbol */
643   sym = newSymbol (name, 0);
644
645   /* setup return value */
646   sym->type = newLink (DECLARATOR);
647   DCL_TYPE (sym->type) = FUNCTION;
648   sym->type->next = copyLinkChain (type);
649   sym->etype = getSpec (sym->type);
650   FUNC_ISREENT(sym->type) = rent ? 1 : 0;
651
652   /* if arguments required */
653   if (nArgs)
654     {
655       value *args;
656       args = FUNC_ARGS(sym->type) = newValue ();
657
658       while (nArgs--)
659         {
660           args->type = copyLinkChain (argType);
661           args->etype = getSpec (args->type);
662           SPEC_EXTR(args->etype)=1;
663           if (!nArgs)
664             break;
665           args = args->next = newValue ();
666         }
667     }
668
669   /* save it */
670   addSymChain (&sym);
671   sym->cdef = 1;
672   allocVariables (sym);
673   return sym;
674
675 }
676
677 /*-----------------------------------------------------------------*/
678 /* funcOfTypeVarg :- function of type with name and argtype        */
679 /*-----------------------------------------------------------------*/
680 symbol *
681 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
682 {
683
684     symbol *sym;
685     int i ;
686     /* create the symbol */
687     sym = newSymbol (name, 0);
688
689     /* setup return value */
690     sym->type = newLink (DECLARATOR);
691     DCL_TYPE (sym->type) = FUNCTION;
692     sym->type->next = typeFromStr(rtype);
693     sym->etype = getSpec (sym->type);
694
695     /* if arguments required */
696     if (nArgs) {
697         value *args;
698         args = FUNC_ARGS(sym->type) = newValue ();
699
700         for ( i = 0 ; i < nArgs ; i++ ) {
701             args->type = typeFromStr(atypes[i]);
702             args->etype = getSpec (args->type);
703             SPEC_EXTR(args->etype)=1;
704             if ((i + 1) == nArgs) break;
705             args = args->next = newValue ();
706         }
707     }
708
709     /* save it */
710     addSymChain (&sym);
711     sym->cdef = 1;
712     allocVariables (sym);
713     return sym;
714
715 }
716
717 /*-----------------------------------------------------------------*/
718 /* reverseParms - will reverse a parameter tree                    */
719 /*-----------------------------------------------------------------*/
720 static void
721 reverseParms (ast * ptree)
722 {
723   ast *ttree;
724   if (!ptree)
725     return;
726
727   /* top down if we find a nonParm tree then quit */
728   if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
729     {
730       /* The various functions expect the parameter tree to be right heavy. */
731       /* Rotate the tree to be left heavy so that after reversal it is */
732       /* right heavy again. */
733       while ((ttree = ptree->right) && ttree->type == EX_OP &&
734              ttree->opval.op == PARAM)
735         {
736           ptree->right = ttree->right;
737           ttree->right = ttree->left;
738           ttree->left = ptree->left;
739           ptree->left = ttree;
740         }
741
742       /* Now reverse */
743       ttree = ptree->left;
744       ptree->left = ptree->right;
745       ptree->right = ttree;
746       ptree->reversed = 1;
747       reverseParms (ptree->left);
748       reverseParms (ptree->right);
749     }
750
751   return;
752 }
753
754 /*-----------------------------------------------------------------*/
755 /* processParms  - makes sure the parameters are okay and do some  */
756 /*                 processing with them                            */
757 /*-----------------------------------------------------------------*/
758 static int
759 processParms (ast *func,
760               value *defParm,
761               ast **actParm,
762               int *parmNumber, /* unused, although updated */
763               bool rightmost)
764 {
765   RESULT_TYPE resultType;
766   sym_link *functype;
767
768   /* if none of them exist */
769   if (!defParm && !*actParm)
770     return 0;
771
772   if (defParm)
773     {
774       if (getenv("DEBUG_SANITY"))
775         {
776           fprintf (stderr, "processParms: %s ", defParm->name);
777         }
778       /* make sure the type is complete and sane */
779       checkTypeSanity(defParm->etype, defParm->name);
780     }
781
782   if (IS_CODEPTR (func->ftype))
783     functype = func->ftype->next;
784   else
785     functype = func->ftype;
786
787   /* if the function is being called via a pointer &  */
788   /* it has not been defined reentrant then we cannot */
789   /* have parameters                                  */
790   /* PIC16 port can... */
791   if (!TARGET_IS_PIC16)
792     {
793       if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
794         {
795           werror (E_NONRENT_ARGS);
796           fatalError++;
797           return 1;
798         }
799     }
800
801   /* if defined parameters ended but actual parameters */
802   /* exist and this is not defined as a variable arg   */
803   if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
804     {
805       werror (E_TOO_MANY_PARMS);
806       return 1;
807     }
808
809   /* if defined parameters present but no actual parameters */
810   if (defParm && !*actParm)
811     {
812       werror (E_TOO_FEW_PARMS);
813       return 1;
814     }
815
816   /* if this is a PARAM node then match left & right */
817   if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
818     {
819       (*actParm)->decorated = 1;
820       return (processParms (func, defParm,
821                             &(*actParm)->left,  parmNumber, FALSE) ||
822               processParms (func, defParm ? defParm->next : NULL,
823                             &(*actParm)->right, parmNumber, rightmost));
824     }
825   else if (defParm) /* not vararg */
826     {
827       /* If we have found a value node by following only right-hand links,
828        * then we know that there are no more values after us.
829        *
830        * Therefore, if there are more defined parameters, the caller didn't
831        * supply enough.
832        */
833       if (rightmost && defParm->next)
834         {
835           werror (E_TOO_FEW_PARMS);
836           return 1;
837         }
838     }
839
840   /* decorate parameter */
841   resultType = defParm ? getResultTypeFromType (defParm->type) :
842                          RESULT_TYPE_NONE;
843   *actParm = decorateType (*actParm, resultType);
844
845   if (IS_VOID((*actParm)->ftype))
846     {
847       werror (E_VOID_VALUE_USED);
848       return 1;
849     }
850
851   /* If this is a varargs function... */
852   if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
853     {
854       ast *newType = NULL;
855       sym_link *ftype;
856
857       /* don't perform integer promotion of explicitly typecasted variable arguments
858        * if sdcc extensions are enabled */
859       if (options.std_sdcc && 
860         (IS_CAST_OP (*actParm) ||
861         (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
862         (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
863         {
864           /* Parameter was explicitly typecast; don't touch it. */
865           return 0;
866         }
867
868       ftype = (*actParm)->ftype;
869
870       /* If it's a char, upcast to int. */
871       if (IS_INTEGRAL (ftype)
872           && (getSize (ftype) < (unsigned) INTSIZE))
873         {
874           newType = newAst_LINK(INTTYPE);
875         }
876
877       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
878         {
879           newType = newAst_LINK (copyLinkChain(ftype));
880           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
881         }
882
883       if (IS_AGGREGATE (ftype))
884         {
885           newType = newAst_LINK (copyLinkChain (ftype));
886           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
887         }
888
889       if (newType)
890         {
891           /* cast required; change this op to a cast. */
892           (*actParm)->decorated = 0;
893            *actParm = newNode (CAST, newType, *actParm);
894           (*actParm)->filename = (*actParm)->right->filename;
895           (*actParm)->lineno = (*actParm)->right->lineno;
896
897           decorateType (*actParm, RESULT_TYPE_NONE);
898         }
899       return 0;
900     } /* vararg */
901
902   /* if defined parameters ended but actual has not & */
903   /* reentrant */
904   if (!defParm && *actParm &&
905       (options.stackAuto || IFFUNC_ISREENT (functype)))
906     return 0;
907
908   resolveSymbols (*actParm);
909
910   /* the parameter type must be at least castable */
911   if (compareType (defParm->type, (*actParm)->ftype) == 0)
912     {
913       werror (E_INCOMPAT_TYPES);
914       printFromToType ((*actParm)->ftype, defParm->type);
915       return 1;
916     }
917
918   /* if the parameter is castable then add the cast */
919   if (compareType (defParm->type, (*actParm)->ftype) < 0)
920     {
921       ast *pTree;
922
923       resultType = getResultTypeFromType (defParm->etype);
924       pTree = resolveSymbols (copyAst (*actParm));
925
926       /* now change the current one to a cast */
927       (*actParm)->type = EX_OP;
928       (*actParm)->opval.op = CAST;
929       (*actParm)->left = newAst_LINK (defParm->type);
930       (*actParm)->right = pTree;
931       (*actParm)->decorated = 0; /* force typechecking */
932       decorateType (*actParm, resultType);
933     }
934
935   /* make a copy and change the regparm type to the defined parm */
936   (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
937   SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
938   SPEC_ARGREG  ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
939
940   /* if the function is being called via a pointer &  */
941   /* this parameter is not passed in registers        */
942   /* then the function must be defined reentrant      */
943   if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
944       !IFFUNC_ISREENT (functype) && !options.stackAuto)
945     {
946       werror (E_NONRENT_ARGS);
947       fatalError++;
948       return 1;
949     }
950
951   (*parmNumber)++;
952   return 0;
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* createIvalType - generates ival for basic types                 */
957 /*-----------------------------------------------------------------*/
958 static ast *
959 createIvalType (ast * sym, sym_link * type, initList * ilist)
960 {
961   ast *iExpr;
962
963   /* if initList is deep */
964   if (ilist->type == INIT_DEEP)
965     ilist = ilist->init.deep;
966
967   iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
968   return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
969 }
970
971 /*-----------------------------------------------------------------*/
972 /* createIvalStruct - generates initial value for structures       */
973 /*-----------------------------------------------------------------*/
974 static ast *
975 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
976 {
977   ast *rast = NULL;
978   ast *lAst;
979   symbol *sflds;
980   initList *iloop;
981
982   sflds = SPEC_STRUCT (type)->fields;
983   if (ilist->type != INIT_DEEP)
984     {
985       werror (E_INIT_STRUCT, "");
986       return NULL;
987     }
988
989   iloop = ilist->init.deep;
990
991   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
992     {
993       /* if we have come to end */
994       if (!iloop)
995         break;
996       sflds->implicit = 1;
997       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
998       lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
999       rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
1000                                                        iloop, rast, rootValue)),
1001                            RESULT_TYPE_NONE);
1002
1003     }
1004
1005   if (iloop)
1006     {
1007       if (IS_AST_VALUE (sym))
1008         werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1009                   W_EXCESS_INITIALIZERS, "struct",
1010                   sym->opval.val->sym->name);
1011       else
1012         werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1013   }
1014
1015   return rast;
1016 }
1017
1018
1019 /*-----------------------------------------------------------------*/
1020 /* createIvalArray - generates code for array initialization       */
1021 /*-----------------------------------------------------------------*/
1022 static ast *
1023 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1024 {
1025   ast *rast = NULL;
1026   initList *iloop;
1027   int lcnt = 0, size = 0;
1028   literalList *literalL;
1029
1030   /* take care of the special   case  */
1031   /* array of characters can be init  */
1032   /* by a string                      */
1033   if (IS_CHAR (type->next))
1034     if ((rast = createIvalCharPtr (sym,
1035                                    type,
1036                         decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1037                                    rootValue)))
1038
1039       return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1040
1041   /* not the special case             */
1042   if (ilist->type != INIT_DEEP)
1043   {
1044       werror (E_INIT_STRUCT, "");
1045       return NULL;
1046   }
1047
1048   iloop = ilist->init.deep;
1049   lcnt = DCL_ELEM (type);
1050
1051   if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1052   {
1053       ast *aSym;
1054
1055       aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1056
1057       rast = newNode(ARRAYINIT, aSym, NULL);
1058       rast->values.constlist = literalL;
1059
1060       // Make sure size is set to length of initializer list.
1061       while (iloop)
1062       {
1063           size++;
1064           iloop = iloop->next;
1065       }
1066
1067       if (lcnt && size > lcnt)
1068       {
1069           // Array size was specified, and we have more initializers than needed.
1070           werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1071             W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1072       }
1073   }
1074   else
1075   {
1076       for (;;)
1077       {
1078           ast *aSym;
1079
1080           aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1081           aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1082           rast = createIval (aSym, type->next, iloop, rast, rootValue);
1083           iloop = (iloop ? iloop->next : NULL);
1084           if (!iloop)
1085           {
1086               break;
1087           }
1088
1089           /* no of elements given and we    */
1090           /* have generated for all of them */
1091           if (!--lcnt)
1092           {
1093               // is this a better way? at least it won't crash
1094               char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1095               werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1096
1097               break;
1098           }
1099       }
1100   }
1101
1102   /* if we have not been given a size  */
1103   if (!DCL_ELEM (type))
1104     {
1105       /* check, if it's a flexible array */
1106       if (IS_STRUCT (AST_VALUE (rootValue)->type))
1107         AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1108       else
1109         DCL_ELEM (type) = size;
1110     }
1111
1112   return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1113 }
1114
1115
1116 /*-----------------------------------------------------------------*/
1117 /* createIvalCharPtr - generates initial values for char pointers  */
1118 /*-----------------------------------------------------------------*/
1119 static ast *
1120 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1121 {
1122   ast *rast = NULL;
1123   unsigned size = 0;
1124
1125   /* if this is a pointer & right is a literal array then */
1126   /* just assignment will do                              */
1127   if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1128                          SPEC_SCLS (iexpr->etype) == S_CODE)
1129                         && IS_ARRAY (iexpr->ftype)))
1130     return newNode ('=', sym, iexpr);
1131
1132   /* left side is an array so we have to assign each element */
1133   if ((IS_LITERAL (iexpr->etype) ||
1134        SPEC_SCLS (iexpr->etype) == S_CODE)
1135       && IS_ARRAY (iexpr->ftype))
1136     {
1137       /* for each character generate an assignment */
1138       /* to the array element */
1139       char *s = SPEC_CVAL (iexpr->etype).v_char;
1140       unsigned int i = 0;
1141       unsigned int symsize = getSize (type);
1142
1143       size = getSize (iexpr->ftype);
1144       if (symsize && size>symsize)
1145         {
1146           if (size>(symsize+1))
1147             {
1148               char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1149
1150               werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1151                         "string", name);
1152             }
1153           size = symsize;
1154         }
1155
1156       for (i=0;i<size;i++)
1157         {
1158           rast = newNode (NULLOP,
1159                           rast,
1160                           newNode ('=',
1161                                    newNode ('[', sym,
1162                                    newAst_VALUE (valueFromLit ((float) i))),
1163                                    newAst_VALUE (valueFromLit (*s))));
1164           s++;
1165         }
1166
1167       // now WE don't need iexpr's symbol anymore
1168       freeStringSymbol(AST_SYMBOL(iexpr));
1169
1170       /* if we have not been given a size  */
1171       if (!DCL_ELEM (type))
1172         {
1173           /* check, if it's a flexible array */
1174           if (IS_STRUCT (AST_VALUE (rootVal)->type))
1175             AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1176           else
1177             DCL_ELEM (type) = size;
1178         }
1179
1180       return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1181     }
1182
1183   return NULL;
1184 }
1185
1186 /*-----------------------------------------------------------------*/
1187 /* createIvalPtr - generates initial value for pointers            */
1188 /*-----------------------------------------------------------------*/
1189 static ast *
1190 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1191 {
1192   ast *rast;
1193   ast *iexpr;
1194
1195   /* if deep then   */
1196   if (ilist->type == INIT_DEEP)
1197     ilist = ilist->init.deep;
1198
1199   iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1200
1201   /* if character pointer */
1202   if (IS_CHAR (type->next))
1203     if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1204       return rast;
1205
1206   return newNode ('=', sym, iexpr);
1207 }
1208
1209 /*-----------------------------------------------------------------*/
1210 /* createIval - generates code for initial value                   */
1211 /*-----------------------------------------------------------------*/
1212 static ast *
1213 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1214 {
1215   ast *rast = NULL;
1216
1217   if (!ilist)
1218     return NULL;
1219
1220   /* if structure then    */
1221   if (IS_STRUCT (type))
1222     rast = createIvalStruct (sym, type, ilist, rootValue);
1223   else
1224     /* if this is a pointer */
1225   if (IS_PTR (type))
1226     rast = createIvalPtr (sym, type, ilist, rootValue);
1227   else
1228     /* if this is an array   */
1229   if (IS_ARRAY (type))
1230     rast = createIvalArray (sym, type, ilist, rootValue);
1231   else
1232     /* if type is SPECIFIER */
1233   if (IS_SPEC (type))
1234     rast = createIvalType (sym, type, ilist);
1235
1236   if (wid)
1237     return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1238   else
1239     return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* initAggregates - initialises aggregate variables with initv     */
1244 /*-----------------------------------------------------------------*/
1245 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1246   ast *newAst = newAst_VALUE (symbolVal (sym));
1247   return createIval (newAst, sym->type, ival, wid, newAst);
1248 }
1249
1250 /*-----------------------------------------------------------------*/
1251 /* gatherAutoInit - creates assignment expressions for initial     */
1252 /*                  values                                         */
1253 /*-----------------------------------------------------------------*/
1254 static ast *
1255 gatherAutoInit (symbol * autoChain)
1256 {
1257   ast *init = NULL;
1258   ast *work;
1259   symbol *sym;
1260
1261   inInitMode = 1;
1262   for (sym = autoChain; sym; sym = sym->next)
1263     {
1264
1265       /* resolve the symbols in the ival */
1266       if (sym->ival)
1267         resolveIvalSym (sym->ival, sym->type);
1268
1269 #if 1
1270       /* if we are PIC16 port,
1271        * and this is a static,
1272        * and have initial value,
1273        * and not S_CODE, don't emit in gs segment,
1274        * but allow glue.c:pic16emitRegularMap to put symbol
1275        * in idata section */
1276       if(TARGET_IS_PIC16 &&
1277         IS_STATIC (sym->etype) && sym->ival
1278         && SPEC_SCLS(sym->etype) != S_CODE) {
1279         SPEC_SCLS (sym->etype) = S_DATA;
1280         continue;
1281       }
1282 #endif
1283
1284       /* if this is a static variable & has an */
1285       /* initial value the code needs to be lifted */
1286       /* here to the main portion since they can be */
1287       /* initialised only once at the start    */
1288       if (IS_STATIC (sym->etype) && sym->ival &&
1289           SPEC_SCLS (sym->etype) != S_CODE)
1290         {
1291           symbol *newSym;
1292
1293           /* insert the symbol into the symbol table */
1294           /* with level = 0 & name = rname       */
1295           newSym = copySymbol (sym);
1296           addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1297
1298           /* now lift the code to main */
1299           if (IS_AGGREGATE (sym->type)) {
1300             work = initAggregates (sym, sym->ival, NULL);
1301           } else {
1302             if (getNelements(sym->type, sym->ival)>1) {
1303               werrorfl (sym->fileDef, sym->lineDef,
1304                         W_EXCESS_INITIALIZERS, "scalar",
1305                         sym->name);
1306             }
1307             work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1308                             list2expr (sym->ival));
1309           }
1310
1311           setAstFileLine (work, sym->fileDef, sym->lineDef);
1312
1313           sym->ival = NULL;
1314           if (staticAutos)
1315             staticAutos = newNode (NULLOP, staticAutos, work);
1316           else
1317             staticAutos = work;
1318
1319           continue;
1320         }
1321
1322       /* if there is an initial value */
1323       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1324         {
1325           initList *ilist=sym->ival;
1326
1327           while (ilist->type == INIT_DEEP) {
1328             ilist = ilist->init.deep;
1329           }
1330
1331           /* update lineno for error msg */
1332           filename = sym->fileDef;
1333           lineno = sym->lineDef;
1334           setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1335
1336           if (IS_AGGREGATE (sym->type)) {
1337             work = initAggregates (sym, sym->ival, NULL);
1338           } else {
1339             if (getNelements(sym->type, sym->ival)>1) {
1340               werrorfl (sym->fileDef, sym->lineDef,
1341                         W_EXCESS_INITIALIZERS, "scalar",
1342                         sym->name);
1343             }
1344             work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1345                             list2expr (sym->ival));
1346           }
1347
1348           // just to be sure
1349           setAstFileLine (work, sym->fileDef, sym->lineDef);
1350
1351           sym->ival = NULL;
1352           if (init)
1353             init = newNode (NULLOP, init, work);
1354           else
1355             init = work;
1356         }
1357     }
1358   inInitMode = 0;
1359   return init;
1360 }
1361
1362 /*-----------------------------------------------------------------*/
1363 /* freeStringSymbol - delete a literal string if no more usage     */
1364 /*-----------------------------------------------------------------*/
1365 void freeStringSymbol(symbol *sym) {
1366   /* make sure this is a literal string */
1367   assert (sym->isstrlit);
1368   if (--sym->isstrlit == 0) { // lower the usage count
1369     memmap *segment=SPEC_OCLS(sym->etype);
1370     if (segment) {
1371       deleteSetItem(&segment->syms, sym);
1372     }
1373   }
1374 }
1375
1376 /*-----------------------------------------------------------------*/
1377 /* stringToSymbol - creates a symbol from a literal string         */
1378 /*-----------------------------------------------------------------*/
1379 static value *
1380 stringToSymbol (value * val)
1381 {
1382   char name[SDCC_NAME_MAX + 1];
1383   static int charLbl = 0;
1384   symbol *sym;
1385   set *sp;
1386   unsigned int size;
1387
1388   // have we heard this before?
1389   for (sp = statsg->syms; sp; sp = sp->next)
1390     {
1391       sym = sp->item;
1392       size = getSize (sym->type);
1393       if (sym->isstrlit && size == getSize (val->type) &&
1394           !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1395         {
1396           // yes, this is old news. Don't publish it again.
1397           sym->isstrlit++; // but raise the usage count
1398           return symbolVal (sym);
1399         }
1400     }
1401
1402   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1403   sym = newSymbol (name, 0);    /* make it @ level 0 */
1404   strncpyz (sym->rname, name, SDCC_NAME_MAX);
1405
1406   /* copy the type from the value passed */
1407   sym->type = copyLinkChain (val->type);
1408   sym->etype = getSpec (sym->type);
1409   /* change to storage class & output class */
1410   SPEC_SCLS (sym->etype) = S_CODE;
1411   SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1412   SPEC_STAT (sym->etype) = 1;
1413   /* make the level & block = 0 */
1414   sym->block = sym->level = 0;
1415   sym->isstrlit = 1;
1416   /* create an ival */
1417   sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1418   if (noAlloc == 0)
1419     {
1420       /* allocate it */
1421       addSymChain (&sym);
1422       allocVariables (sym);
1423     }
1424   sym->ival = NULL;
1425   return symbolVal (sym);
1426
1427 }
1428
1429 /*-----------------------------------------------------------------*/
1430 /* processBlockVars - will go thru the ast looking for block if    */
1431 /*                    a block is found then will allocate the syms */
1432 /*                    will also gather the auto inits present      */
1433 /*-----------------------------------------------------------------*/
1434 ast *
1435 processBlockVars (ast * tree, int *stack, int action)
1436 {
1437   if (!tree)
1438     return NULL;
1439
1440   /* if this is a block */
1441   if (tree->type == EX_OP && tree->opval.op == BLOCK)
1442     {
1443       ast *autoInit;
1444
1445       if (action == ALLOCATE)
1446         {
1447           *stack += allocVariables (tree->values.sym);
1448           autoInit = gatherAutoInit (tree->values.sym);
1449
1450           /* if there are auto inits then do them */
1451           if (autoInit)
1452             tree->left = newNode (NULLOP, autoInit, tree->left);
1453         }
1454       else                      /* action is deallocate */
1455         deallocLocal (tree->values.sym);
1456     }
1457
1458   processBlockVars (tree->left, stack, action);
1459   processBlockVars (tree->right, stack, action);
1460   return tree;
1461 }
1462
1463
1464 /*-------------------------------------------------------------*/
1465 /* constExprTree - returns TRUE if this tree is a constant     */
1466 /*                 expression                                  */
1467 /*-------------------------------------------------------------*/
1468 bool constExprTree (ast *cexpr) {
1469
1470   if (!cexpr) {
1471     return TRUE;
1472   }
1473
1474   cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1475
1476   switch (cexpr->type)
1477     {
1478     case EX_VALUE:
1479       if (IS_AST_LIT_VALUE(cexpr)) {
1480         // this is a literal
1481         return TRUE;
1482       }
1483       if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1484         // a function's address will never change
1485         return TRUE;
1486       }
1487       if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1488         // an array's address will never change
1489         return TRUE;
1490       }
1491       if (IS_AST_SYM_VALUE(cexpr) &&
1492           IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1493         // a symbol in code space will never change
1494         // This is only for the 'char *s="hallo"' case and will have to leave
1495         //printf(" code space symbol");
1496         return TRUE;
1497       }
1498       return FALSE;
1499     case EX_LINK:
1500       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501               "unexpected link in expression tree\n");
1502       return FALSE;
1503     case EX_OP:
1504       if (cexpr->opval.op==ARRAYINIT) {
1505         // this is a list of literals
1506         return TRUE;
1507       }
1508       if (cexpr->opval.op=='=') {
1509         return constExprTree(cexpr->right);
1510       }
1511       if (cexpr->opval.op==CAST) {
1512         // cast ignored, maybe we should throw a warning here?
1513         return constExprTree(cexpr->right);
1514       }
1515       if (cexpr->opval.op=='&') {
1516         return TRUE;
1517       }
1518       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1519         return FALSE;
1520       }
1521       if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1522         return TRUE;
1523       }
1524       return FALSE;
1525     case EX_OPERAND:
1526       return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1527     }
1528   return FALSE;
1529 }
1530
1531 /*-----------------------------------------------------------------*/
1532 /* constExprValue - returns the value of a constant expression     */
1533 /*                  or NULL if it is not a constant expression     */
1534 /*-----------------------------------------------------------------*/
1535 value *
1536 constExprValue (ast * cexpr, int check)
1537 {
1538   cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1539
1540   /* if this is not a constant then */
1541   if (!IS_LITERAL (cexpr->ftype))
1542     {
1543       /* then check if this is a literal array
1544          in code segment */
1545       if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1546           SPEC_CVAL (cexpr->etype).v_char &&
1547           IS_ARRAY (cexpr->ftype))
1548         {
1549           value *val = valFromType (cexpr->ftype);
1550           SPEC_SCLS (val->etype) = S_LITERAL;
1551           val->sym = cexpr->opval.val->sym;
1552           val->sym->type = copyLinkChain (cexpr->ftype);
1553           val->sym->etype = getSpec (val->sym->type);
1554           strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1555           return val;
1556         }
1557
1558       /* if we are casting a literal value then */
1559       if (IS_AST_OP (cexpr) &&
1560           cexpr->opval.op == CAST &&
1561           IS_LITERAL (cexpr->right->ftype))
1562         {
1563           return valCastLiteral (cexpr->ftype,
1564                                  floatFromVal (cexpr->right->opval.val));
1565         }
1566
1567       if (IS_AST_VALUE (cexpr))
1568         {
1569           return cexpr->opval.val;
1570         }
1571
1572       if (check)
1573         werror (E_CONST_EXPECTED, "found expression");
1574
1575       return NULL;
1576     }
1577
1578   /* return the value */
1579   if (IS_AST_VALUE (cexpr))
1580     {
1581       return cexpr->opval.val;
1582     }
1583   return NULL;
1584 }
1585
1586 /*-----------------------------------------------------------------*/
1587 /* isLabelInAst - will return true if a given label is found       */
1588 /*-----------------------------------------------------------------*/
1589 bool
1590 isLabelInAst (symbol * label, ast * tree)
1591 {
1592   if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1593     return FALSE;
1594
1595   if (IS_AST_OP (tree) &&
1596       tree->opval.op == LABEL &&
1597       isSymbolEqual (AST_SYMBOL (tree->left), label))
1598     return TRUE;
1599
1600   return isLabelInAst (label, tree->right) &&
1601     isLabelInAst (label, tree->left);
1602 }
1603
1604 /*-----------------------------------------------------------------*/
1605 /* isLoopCountable - return true if the loop count can be determi- */
1606 /* -ned at compile time .                                          */
1607 /*-----------------------------------------------------------------*/
1608 static bool
1609 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1610                  symbol ** sym, ast ** init, ast ** end)
1611 {
1612
1613   /* the loop is considered countable if the following
1614      conditions are true :-
1615
1616      a) initExpr :- <sym> = <const>
1617      b) condExpr :- <sym> < <const1>
1618      c) loopExpr :- <sym> ++
1619    */
1620
1621   /* first check the initExpr */
1622   if (IS_AST_OP (initExpr) &&
1623       initExpr->opval.op == '=' &&      /* is assignment */
1624       IS_AST_SYM_VALUE (initExpr->left))
1625     {                           /* left is a symbol */
1626
1627       *sym = AST_SYMBOL (initExpr->left);
1628       *init = initExpr->right;
1629     }
1630   else
1631     return FALSE;
1632
1633   /* don't reverse loop with volatile counter */
1634   if (IS_VOLATILE ((*sym)->type))
1635     return FALSE;
1636
1637   /* for now the symbol has to be of
1638      integral type */
1639   if (!IS_INTEGRAL ((*sym)->type))
1640     return FALSE;
1641
1642   /* now check condExpr */
1643   if (IS_AST_OP (condExpr))
1644     {
1645
1646       switch (condExpr->opval.op)
1647         {
1648         case '<':
1649           if (IS_AST_SYM_VALUE (condExpr->left) &&
1650               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1651               IS_AST_LIT_VALUE (condExpr->right))
1652             {
1653               *end = condExpr->right;
1654               break;
1655             }
1656           return FALSE;
1657
1658         case '!':
1659           if (IS_AST_OP (condExpr->left) &&
1660               condExpr->left->opval.op == '>' &&
1661               IS_AST_LIT_VALUE (condExpr->left->right) &&
1662               IS_AST_SYM_VALUE (condExpr->left->left) &&
1663               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1664             {
1665
1666               *end = newNode ('+', condExpr->left->right,
1667                               newAst_VALUE (constCharVal (1)));
1668               break;
1669             }
1670           return FALSE;
1671
1672         default:
1673           return FALSE;
1674         }
1675
1676     }
1677   else
1678     return FALSE;
1679
1680   /* check loop expression is of the form <sym>++ */
1681   if (!IS_AST_OP (loopExpr))
1682     return FALSE;
1683
1684   /* check if <sym> ++ */
1685   if (loopExpr->opval.op == INC_OP)
1686     {
1687
1688       if (loopExpr->left)
1689         {
1690           /* pre */
1691           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1692               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1693             return TRUE;
1694
1695         }
1696       else
1697         {
1698           /* post */
1699           if (IS_AST_SYM_VALUE (loopExpr->right) &&
1700               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1701             return TRUE;
1702         }
1703
1704     }
1705   else
1706     {
1707       /* check for += */
1708       if (loopExpr->opval.op == ADD_ASSIGN)
1709         {
1710
1711           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1712               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1713               IS_AST_LIT_VALUE (loopExpr->right) &&
1714               AST_ULONG_VALUE (loopExpr->right) != 1)
1715             return TRUE;
1716         }
1717     }
1718
1719   return FALSE;
1720 }
1721
1722 /*-----------------------------------------------------------------*/
1723 /* astHasVolatile - returns true if ast contains any volatile      */
1724 /*-----------------------------------------------------------------*/
1725 bool
1726 astHasVolatile (ast * tree)
1727 {
1728   if (!tree)
1729     return FALSE;
1730
1731   if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1732     return TRUE;
1733
1734   if (IS_AST_OP (tree))
1735     return astHasVolatile (tree->left) ||
1736       astHasVolatile (tree->right);
1737   else
1738     return FALSE;
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* astHasPointer - return true if the ast contains any ptr variable */
1743 /*-----------------------------------------------------------------*/
1744 bool
1745 astHasPointer (ast * tree)
1746 {
1747   if (!tree)
1748     return FALSE;
1749
1750   if (IS_AST_LINK (tree))
1751     return TRUE;
1752
1753   /* if we hit an array expression then check
1754      only the left side */
1755   if (IS_AST_OP (tree) && tree->opval.op == '[')
1756     return astHasPointer (tree->left);
1757
1758   if (IS_AST_VALUE (tree))
1759     return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1760
1761   return astHasPointer (tree->left) ||
1762     astHasPointer (tree->right);
1763
1764 }
1765
1766 /*-----------------------------------------------------------------*/
1767 /* astHasSymbol - return true if the ast has the given symbol      */
1768 /*-----------------------------------------------------------------*/
1769 bool
1770 astHasSymbol (ast * tree, symbol * sym)
1771 {
1772   if (!tree || IS_AST_LINK (tree))
1773     return FALSE;
1774
1775   if (IS_AST_VALUE (tree))
1776     {
1777       if (IS_AST_SYM_VALUE (tree))
1778         return isSymbolEqual (AST_SYMBOL (tree), sym);
1779       else
1780         return FALSE;
1781     }
1782
1783   return astHasSymbol (tree->left, sym) ||
1784     astHasSymbol (tree->right, sym);
1785 }
1786
1787 /*-----------------------------------------------------------------*/
1788 /* astHasDeref - return true if the ast has an indirect access     */
1789 /*-----------------------------------------------------------------*/
1790 static bool
1791 astHasDeref (ast * tree)
1792 {
1793   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1794     return FALSE;
1795
1796   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1797
1798   return astHasDeref (tree->left) || astHasDeref (tree->right);
1799 }
1800
1801 /*-----------------------------------------------------------------*/
1802 /* isConformingBody - the loop body has to conform to a set of     */
1803 /* rules for the loop to be considered reversible read on for rules*/
1804 /*-----------------------------------------------------------------*/
1805 bool
1806 isConformingBody (ast * pbody, symbol * sym, ast * body)
1807 {
1808
1809   /* we are going to do a pre-order traversal of the
1810      tree && check for the following conditions. (essentially
1811      a set of very shallow tests )
1812      a) the sym passed does not participate in any arithmetic operation
1813      b) There are no function calls
1814      c) all jumps are within the body
1815      d) address of loop control variable not taken
1816      e) if an assignment has a pointer on the left hand side make sure
1817         right does not have loop control variable
1818   */
1819
1820   /* if we reach the end or a leaf then true */
1821   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1822     return TRUE;
1823
1824   /* if anything else is "volatile" */
1825   if (IS_VOLATILE (TETYPE (pbody)))
1826     return FALSE;
1827
1828   /* we will walk the body in a pre-order traversal for
1829      efficiency sake */
1830   switch (pbody->opval.op)
1831     {
1832 /*------------------------------------------------------------------*/
1833     case '[':
1834       // if the loopvar is used as an index
1835       /* array op is commutative -- must check both left & right */
1836       if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1837         return FALSE;
1838       }
1839       return isConformingBody (pbody->right, sym, body)
1840               && isConformingBody (pbody->left, sym, body);
1841
1842 /*------------------------------------------------------------------*/
1843     case PTR_OP:
1844     case '.':
1845       return TRUE;
1846
1847 /*------------------------------------------------------------------*/
1848     case INC_OP:
1849     case DEC_OP:
1850
1851       /* sure we are not sym is not modified */
1852       if (pbody->left &&
1853           IS_AST_SYM_VALUE (pbody->left) &&
1854           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1855         return FALSE;
1856
1857       if (pbody->right &&
1858           IS_AST_SYM_VALUE (pbody->right) &&
1859           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1860         return FALSE;
1861
1862       return TRUE;
1863
1864 /*------------------------------------------------------------------*/
1865
1866     case '*':                   /* can be unary  : if right is null then unary operation */
1867     case '+':
1868     case '-':
1869     case '&':
1870
1871       /* if right is NULL then unary operation  */
1872 /*------------------------------------------------------------------*/
1873       /*----------------------------*/
1874       /*  address of                */
1875       /*----------------------------*/
1876       if (!pbody->right)
1877         {
1878           if (IS_AST_SYM_VALUE (pbody->left) &&
1879               isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1880             return FALSE;
1881           else
1882             return isConformingBody (pbody->left, sym, body);
1883         }
1884       else
1885         {
1886           if (astHasSymbol (pbody->left, sym) ||
1887               astHasSymbol (pbody->right, sym))
1888             return FALSE;
1889         }
1890
1891
1892 /*------------------------------------------------------------------*/
1893     case '|':
1894     case '^':
1895     case '/':
1896     case '%':
1897     case LEFT_OP:
1898     case RIGHT_OP:
1899     case GETABIT:
1900     case GETBYTE:
1901     case GETWORD:
1902
1903       if (IS_AST_SYM_VALUE (pbody->left) &&
1904           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1905         return FALSE;
1906
1907       if (IS_AST_SYM_VALUE (pbody->right) &&
1908           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1909         return FALSE;
1910
1911       return isConformingBody (pbody->left, sym, body) &&
1912         isConformingBody (pbody->right, sym, body);
1913
1914     case '~':
1915     case '!':
1916     case RRC:
1917     case RLC:
1918     case GETHBIT:
1919     case SWAP:
1920       if (IS_AST_SYM_VALUE (pbody->left) &&
1921           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1922         return FALSE;
1923       return isConformingBody (pbody->left, sym, body);
1924
1925 /*------------------------------------------------------------------*/
1926
1927     case AND_OP:
1928     case OR_OP:
1929     case '>':
1930     case '<':
1931     case LE_OP:
1932     case GE_OP:
1933     case EQ_OP:
1934     case NE_OP:
1935     case '?':
1936     case ':':
1937     case SIZEOF:                /* evaluate wihout code generation */
1938
1939       if (IS_AST_SYM_VALUE (pbody->left) &&
1940           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1941         return FALSE;
1942
1943       if (IS_AST_SYM_VALUE (pbody->right) &&
1944           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1945         return FALSE;
1946
1947       return isConformingBody (pbody->left, sym, body) &&
1948         isConformingBody (pbody->right, sym, body);
1949
1950 /*------------------------------------------------------------------*/
1951     case '=':
1952
1953       /* if left has a pointer & right has loop
1954          control variable then we cannot */
1955       if (astHasPointer (pbody->left) &&
1956           astHasSymbol (pbody->right, sym))
1957         return FALSE;
1958       if (astHasVolatile (pbody->left))
1959         return FALSE;
1960
1961       if (IS_AST_SYM_VALUE (pbody->left)) {
1962         // if the loopvar has an assignment
1963         if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1964           return FALSE;
1965         // if the loopvar is used in another (maybe conditional) block
1966         if (astHasSymbol (pbody->right, sym) &&
1967             (pbody->level >= body->level)) {
1968           return FALSE;
1969         }
1970       }
1971
1972       if (astHasVolatile (pbody->left))
1973         return FALSE;
1974
1975       if (astHasDeref(pbody->right))
1976         return FALSE;
1977
1978       return isConformingBody (pbody->left, sym, body) &&
1979         isConformingBody (pbody->right, sym, body);
1980
1981     case MUL_ASSIGN:
1982     case DIV_ASSIGN:
1983     case AND_ASSIGN:
1984     case OR_ASSIGN:
1985     case XOR_ASSIGN:
1986     case RIGHT_ASSIGN:
1987     case LEFT_ASSIGN:
1988     case SUB_ASSIGN:
1989     case ADD_ASSIGN:
1990       assert ("Parser should not have generated this\n");
1991
1992 /*------------------------------------------------------------------*/
1993       /*----------------------------*/
1994       /*      comma operator        */
1995       /*----------------------------*/
1996     case ',':
1997       return isConformingBody (pbody->left, sym, body) &&
1998         isConformingBody (pbody->right, sym, body);
1999
2000 /*------------------------------------------------------------------*/
2001       /*----------------------------*/
2002       /*       function call        */
2003       /*----------------------------*/
2004     case CALL:
2005         /* if local & not passed as parameter &
2006            not used to find the function then ok */
2007         if (sym->level && !astHasSymbol (pbody->right, sym) &&
2008             !astHasSymbol (pbody->left, sym))
2009           {
2010             return TRUE;
2011           }
2012       return FALSE;
2013
2014 /*------------------------------------------------------------------*/
2015       /*----------------------------*/
2016       /*     return statement       */
2017       /*----------------------------*/
2018     case RETURN:
2019       return FALSE;
2020
2021     case GOTO:
2022       if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2023         return TRUE;
2024       else
2025         return FALSE;
2026     case SWITCH:
2027       if (astHasSymbol (pbody->left, sym))
2028         return FALSE;
2029
2030     default:
2031       break;
2032     }
2033
2034   return isConformingBody (pbody->left, sym, body) &&
2035     isConformingBody (pbody->right, sym, body);
2036 }
2037
2038 /*-----------------------------------------------------------------*/
2039 /* isLoopReversible - takes a for loop as input && returns true    */
2040 /* if the for loop is reversible. If yes will set the value of     */
2041 /* the loop control var & init value & termination value           */
2042 /*-----------------------------------------------------------------*/
2043 static bool
2044 isLoopReversible (ast * loop, symbol ** loopCntrl,
2045                   ast ** init, ast ** end)
2046 {
2047   /* if option says don't do it then don't */
2048   if (optimize.noLoopReverse)
2049     return 0;
2050   /* there are several tests to determine this */
2051
2052   /* for loop has to be of the form
2053      for ( <sym> = <const1> ;
2054      [<sym> < <const2>]  ;
2055      [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2056      forBody */
2057   if (!isLoopCountable (AST_FOR (loop, initExpr),
2058                         AST_FOR (loop, condExpr),
2059                         AST_FOR (loop, loopExpr),
2060                         loopCntrl, init, end))
2061     return 0;
2062
2063   /* now do some serious checking on the body of the loop
2064    */
2065
2066   return isConformingBody (loop->left, *loopCntrl, loop->left);
2067
2068 }
2069
2070 /*-----------------------------------------------------------------*/
2071 /* replLoopSym - replace the loop sym by loop sym -1               */
2072 /*-----------------------------------------------------------------*/
2073 static void
2074 replLoopSym (ast * body, symbol * sym)
2075 {
2076   /* reached end */
2077   if (!body || IS_AST_LINK (body))
2078     return;
2079
2080   if (IS_AST_SYM_VALUE (body))
2081     {
2082
2083       if (isSymbolEqual (AST_SYMBOL (body), sym))
2084         {
2085
2086           body->type = EX_OP;
2087           body->opval.op = '-';
2088           body->left = newAst_VALUE (symbolVal (sym));
2089           body->right = newAst_VALUE (constCharVal (1));
2090
2091         }
2092
2093       return;
2094
2095     }
2096
2097   replLoopSym (body->left, sym);
2098   replLoopSym (body->right, sym);
2099
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* reverseLoop - do the actual loop reversal                       */
2104 /*-----------------------------------------------------------------*/
2105 ast *
2106 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2107 {
2108   ast *rloop;
2109
2110   /* create the following tree
2111      <sym> = loopCount ;
2112      for_continue:
2113      forbody
2114      <sym> -= 1;
2115      if (sym) goto for_continue ;
2116      <sym> = end */
2117
2118   /* put it together piece by piece */
2119   rloop = newNode (NULLOP,
2120                    createIf (newAst_VALUE (symbolVal (sym)),
2121                              newNode (GOTO,
2122                                       newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2123                                       NULL), NULL),
2124                    newNode ('=',
2125                             newAst_VALUE (symbolVal (sym)),
2126                             end));
2127
2128   replLoopSym (loop->left, sym);
2129   setAstFileLine (rloop, init->filename, init->lineno);
2130
2131   rloop = newNode (NULLOP,
2132                    newNode ('=',
2133                             newAst_VALUE (symbolVal (sym)),
2134                             newNode ('-', end, init)),
2135                    createLabel (AST_FOR (loop, continueLabel),
2136                                 newNode (NULLOP,
2137                                          loop->left,
2138                                          newNode (NULLOP,
2139                                                   newNode (SUB_ASSIGN,
2140                                                            newAst_VALUE (symbolVal (sym)),
2141                                                            newAst_VALUE (constCharVal (1))),
2142                                                   rloop))));
2143
2144   rloop->lineno=init->lineno;
2145   return decorateType (rloop, RESULT_TYPE_NONE);
2146
2147 }
2148
2149 /*-----------------------------------------------------------------*/
2150 /* searchLitOp - search tree (*ops only) for an ast with literal */
2151 /*-----------------------------------------------------------------*/
2152 static ast *
2153 searchLitOp (ast *tree, ast **parent, const char *ops)
2154 {
2155   ast *ret;
2156
2157   if (tree && optimize.global_cse)
2158     {
2159       /* is there a literal operand? */
2160       if (tree->right &&
2161           IS_AST_OP(tree->right) &&
2162           tree->right->right &&
2163           (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2164         {
2165           if (IS_LITERAL (RTYPE (tree->right)) !=
2166               IS_LITERAL (LTYPE (tree->right)))
2167             {
2168               tree->right->decorated = 0;
2169               tree->decorated = 0;
2170               *parent = tree;
2171               return tree->right;
2172             }
2173           ret = searchLitOp (tree->right, parent, ops);
2174           if (ret)
2175             return ret;
2176         }
2177       if (tree->left &&
2178           IS_AST_OP(tree->left) &&
2179           tree->left->right &&
2180           (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2181         {
2182           if (IS_LITERAL (RTYPE (tree->left)) !=
2183               IS_LITERAL (LTYPE (tree->left)))
2184             {
2185               tree->left->decorated = 0;
2186               tree->decorated = 0;
2187               *parent = tree;
2188               return tree->left;
2189             }
2190           ret = searchLitOp (tree->left, parent, ops);
2191           if (ret)
2192             return ret;
2193         }
2194     }
2195   return NULL;
2196 }
2197
2198 /*-----------------------------------------------------------------*/
2199 /* getResultFromType                                               */
2200 /*-----------------------------------------------------------------*/
2201 RESULT_TYPE
2202 getResultTypeFromType (sym_link *type)
2203 {
2204   /* type = getSpec (type); */
2205   if (IS_BIT (type))
2206     return RESULT_TYPE_BIT;
2207   if (IS_BITFIELD (type))
2208     {
2209       int blen = SPEC_BLEN (type);
2210
2211       if (blen <= 1)
2212         return RESULT_TYPE_BIT;
2213       if (blen <= 8)
2214         return RESULT_TYPE_CHAR;
2215       return RESULT_TYPE_INT;
2216     }
2217   if (IS_CHAR (type))
2218     return RESULT_TYPE_CHAR;
2219   if (IS_INT (type) && !IS_LONG (type))
2220     return RESULT_TYPE_INT;
2221   return RESULT_TYPE_OTHER;
2222 }
2223
2224 /*-----------------------------------------------------------------*/
2225 /* addCast - adds casts to a type specified by RESULT_TYPE         */
2226 /*-----------------------------------------------------------------*/
2227 static ast *
2228 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2229 {
2230   sym_link *newLink;
2231   bool upCasted = FALSE;
2232
2233   switch (resultType)
2234     {
2235       case RESULT_TYPE_NONE:
2236         /* if thing smaller than int must be promoted to int */
2237         if (!promote ||
2238             getSize (tree->etype) >= INTSIZE)
2239           /* promotion not necessary or already an int */
2240           return tree;
2241         /* char and bits: promote to int */
2242         newLink = newIntLink();
2243         upCasted = TRUE;
2244         break;
2245       case RESULT_TYPE_BIT:
2246         if (!promote ||
2247             /* already an int */
2248             bitsForType (tree->etype) >= 16 ||
2249             /* bit to bit operation: don't promote, the code generators
2250                hopefully know everything about promotion rules */
2251             bitsForType (tree->etype) == 1)
2252           return tree;
2253         newLink = newIntLink();
2254         upCasted = TRUE;
2255         break;
2256       case RESULT_TYPE_CHAR:
2257         if (IS_CHAR (tree->etype) ||
2258             IS_FLOAT(tree->etype) ||
2259             IS_FIXED(tree->etype))
2260           return tree;
2261         newLink = newCharLink();
2262         break;
2263       case RESULT_TYPE_INT:
2264 #if 0
2265         if (getSize (tree->etype) > INTSIZE)
2266           {
2267             /* warn ("Loosing significant digits"); */
2268             return;
2269           }
2270 #endif
2271         /* char: promote to int */
2272         if (!promote ||
2273             getSize (tree->etype) >= INTSIZE)
2274           return tree;
2275         newLink = newIntLink();
2276         upCasted = TRUE;
2277         break;
2278       case RESULT_TYPE_IFX:
2279       case RESULT_TYPE_OTHER:
2280         if (!promote ||
2281             /* return type is ifx, long, float: promote char to int */
2282             getSize (tree->etype) >= INTSIZE)
2283           return tree;
2284         newLink = newIntLink();
2285         upCasted = TRUE;
2286         break;
2287       default:
2288         return tree;
2289     }
2290   tree->decorated = 0;
2291   tree = newNode (CAST, newAst_LINK (newLink), tree);
2292   tree->filename = tree->right->filename;
2293   tree->lineno = tree->right->lineno;
2294   /* keep unsigned type during cast to smaller type,
2295      but not when promoting from char to int */
2296   if (!upCasted)
2297     SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2298   return decorateType (tree, resultType);
2299 }
2300
2301 /*-----------------------------------------------------------------*/
2302 /* resultTypePropagate - decides if resultType can be propagated   */
2303 /*-----------------------------------------------------------------*/
2304 static RESULT_TYPE
2305 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2306 {
2307   switch (tree->opval.op)
2308     {
2309       case AND_OP:
2310       case OR_OP:
2311       case '!':
2312       case '=':
2313       case '?':
2314       case ':':
2315       case '|':
2316       case '^':
2317       case '~':
2318       case LEFT_OP:
2319       case LABEL:
2320         return resultType;
2321       case '*':
2322       case '+':
2323       case '-':
2324         if ((IS_AST_VALUE (tree->left)  && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2325             (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2326           return RESULT_TYPE_NONE;
2327         return resultType;
2328       case '&':
2329         if (!tree->right)
2330           /* can be unary */
2331           return RESULT_TYPE_NONE;
2332         else
2333           return resultType;
2334       case IFX:
2335         return RESULT_TYPE_IFX;
2336       default:
2337         return RESULT_TYPE_NONE;
2338     }
2339 }
2340
2341 /*-----------------------------------------------------------------*/
2342 /* getLeftResultType - gets type from left branch for propagation  */
2343 /*-----------------------------------------------------------------*/
2344 static RESULT_TYPE
2345 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2346 {
2347   switch (tree->opval.op)
2348     {
2349       case '=':
2350       case CAST:
2351         if (IS_PTR (LTYPE (tree)))
2352           return RESULT_TYPE_NONE;
2353         else
2354           return getResultTypeFromType (LETYPE (tree));
2355       case RETURN:
2356         if (IS_PTR (currFunc->type->next))
2357           return RESULT_TYPE_NONE;
2358         else
2359           return getResultTypeFromType (currFunc->type->next);
2360       case '[':
2361         if (!IS_ARRAY (LTYPE (tree)))
2362           return resultType;
2363         if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2364           return RESULT_TYPE_CHAR;
2365         return resultType;
2366       default:
2367         return resultType;
2368     }
2369 }
2370
2371 /*------------------------------------------------------------------*/
2372 /* gatherImplicitVariables: assigns correct type information to     */
2373 /*            symbols and values created by replaceAstWithTemporary */
2374 /*            and adds the symbols to the declarations list of the  */
2375 /*            innermost block that contains them                    */
2376 /*------------------------------------------------------------------*/
2377 void
2378 gatherImplicitVariables (ast * tree, ast * block)
2379 {
2380   if (!tree)
2381     return;
2382
2383   if (tree->type == EX_OP && tree->opval.op == BLOCK)
2384     {
2385       /* keep track of containing scope */
2386       block = tree;
2387     }
2388   if (tree->type == EX_OP && tree->opval.op == '=' &&
2389       tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2390     {
2391       symbol *assignee = tree->left->opval.val->sym;
2392
2393       /* special case for assignment to compiler-generated temporary variable:
2394          compute type of RHS, and set the symbol's type to match */
2395       if (assignee->type == NULL && assignee->infertype) {
2396         ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2397
2398         if (dtr != tree->right)
2399           tree->right = dtr;
2400
2401         assignee->type = copyLinkChain(TTYPE(dtr));
2402         assignee->etype = getSpec(assignee->type);
2403         SPEC_SCLS (assignee->etype) = S_AUTO;
2404         SPEC_OCLS (assignee->etype) = NULL;
2405         SPEC_EXTR (assignee->etype) = 0;
2406         SPEC_STAT (assignee->etype) = 0;
2407         SPEC_VOLATILE (assignee->etype) = 0;
2408         SPEC_ABSA (assignee->etype) = 0;
2409
2410         wassertl(block != NULL, "implicit variable not contained in block");
2411         wassert(assignee->next == NULL);
2412         if (block != NULL) {
2413           symbol **decl = &(block->values.sym);
2414
2415           while (*decl) {
2416             wassert(*decl != assignee);  /* should not already be in list */
2417             decl = &( (*decl)->next );
2418           }
2419
2420           *decl = assignee;
2421         }
2422       }
2423     }
2424   if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2425       tree->opval.val->type == NULL &&
2426       tree->opval.val->sym &&
2427       tree->opval.val->sym->infertype)
2428     {
2429       /* fixup type of value for compiler-inferred temporary var */
2430       tree->opval.val->type = tree->opval.val->sym->type;
2431       tree->opval.val->etype = tree->opval.val->sym->etype;
2432     }
2433
2434   gatherImplicitVariables(tree->left, block);
2435   gatherImplicitVariables(tree->right, block);
2436 }
2437
2438 /*--------------------------------------------------------------------*/
2439 /* decorateType - compute type for this tree, also does type checking.*/
2440 /* This is done bottom up, since type has to flow upwards.            */
2441 /* resultType flows top-down and forces e.g. char-arithmetic, if the  */
2442 /* result is a char and the operand(s) are int's.                     */
2443 /* It also does constant folding, and parameter checking.             */
2444 /*--------------------------------------------------------------------*/
2445 ast *
2446 decorateType (ast * tree, RESULT_TYPE resultType)
2447 {
2448   int parmNumber;
2449   sym_link *p;
2450   RESULT_TYPE resultTypeProp;
2451
2452   if (!tree)
2453     return tree;
2454
2455   /* if already has type then do nothing */
2456   if (tree->decorated)
2457     return tree;
2458
2459   tree->decorated = 1;
2460
2461 #if 0
2462   /* print the line          */
2463   /* if not block & function */
2464   if (tree->type == EX_OP &&
2465       (tree->opval.op != FUNCTION &&
2466        tree->opval.op != BLOCK &&
2467        tree->opval.op != NULLOP))
2468     {
2469       filename = tree->filename;
2470       lineno = tree->lineno;
2471     }
2472 #endif
2473
2474   /* if any child is an error | this one is an error do nothing */
2475   if (tree->isError ||
2476       (tree->left && tree->left->isError) ||
2477       (tree->right && tree->right->isError))
2478     return tree;
2479
2480 /*------------------------------------------------------------------*/
2481 /*----------------------------*/
2482 /*   leaf has been reached    */
2483 /*----------------------------*/
2484   filename = tree->filename;
2485   lineno = tree->lineno;
2486   /* if this is of type value */
2487   /* just get the type        */
2488   if (tree->type == EX_VALUE)
2489     {
2490
2491       if (IS_LITERAL (tree->opval.val->etype))
2492         {
2493
2494           /* if this is a character array then declare it */
2495           if (IS_ARRAY (tree->opval.val->type))
2496             tree->opval.val = stringToSymbol (tree->opval.val);
2497
2498           /* otherwise just copy the type information */
2499           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2500           return tree;
2501         }
2502
2503       if (tree->opval.val->sym)
2504         {
2505           /* if the undefined flag is set then give error message */
2506           if (tree->opval.val->sym->undefined)
2507             {
2508               werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2509               /* assume int */
2510               TTYPE (tree) = TETYPE (tree) =
2511                 tree->opval.val->type = tree->opval.val->sym->type =
2512                 tree->opval.val->etype = tree->opval.val->sym->etype =
2513                 copyLinkChain (INTTYPE);
2514             }
2515           else if (tree->opval.val->sym->implicit)
2516             {
2517               /* if implicit i.e. struct/union member then no type */
2518               TTYPE (tree) = TETYPE (tree) = NULL;
2519             }
2520           else
2521             {
2522               /* copy the type from the value into the ast */
2523               COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2524
2525               /* and mark the symbol as referenced */
2526               tree->opval.val->sym->isref = 1;
2527             }
2528         }
2529       else
2530         wassert(0); /* unreached: all values are literals or symbols */
2531
2532       return tree;
2533     }
2534
2535   /* if type link for the case of cast */
2536   if (tree->type == EX_LINK)
2537     {
2538       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2539       return tree;
2540     }
2541
2542   {
2543     ast *dtl, *dtr;
2544
2545     #if 0
2546     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2547       {
2548         if (tree->left && tree->left->type == EX_OPERAND
2549             && (tree->left->opval.op == INC_OP
2550                 || tree->left->opval.op == DEC_OP)
2551             && tree->left->left)
2552           {
2553             tree->left->right = tree->left->left;
2554             tree->left->left = NULL;
2555           }
2556         if (tree->right && tree->right->type == EX_OPERAND
2557             && (tree->right->opval.op == INC_OP
2558                 || tree->right->opval.op == DEC_OP)
2559             && tree->right->left)
2560           {
2561             tree->right->right = tree->right->left;
2562             tree->right->left = NULL;
2563           }
2564       }
2565     #endif
2566
2567     /* Before decorating the left branch we've to decide in dependence
2568        upon tree->opval.op, if resultType can be propagated */
2569     resultTypeProp = resultTypePropagate (tree, resultType);
2570
2571     if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2572       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2573     else
2574       dtl = decorateType (tree->left, resultTypeProp);
2575
2576     /* if an array node, we may need to swap branches */
2577     if (tree->opval.op == '[')
2578       {
2579         /* determine which is the array & which the index */
2580         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2581             IS_INTEGRAL (LTYPE (tree)))
2582           {
2583             ast *tempTree = tree->left;
2584             tree->left = tree->right;
2585             tree->right = tempTree;
2586           }
2587       }
2588
2589     /* After decorating the left branch there's type information available
2590        in tree->left->?type. If the op is e.g. '=' we extract the type
2591        information from there and propagate it to the right branch. */
2592     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2593
2594     switch (tree->opval.op)
2595       {
2596         case '?':
2597           /* delay right side for '?' operator since conditional macro
2598              expansions might rely on this */
2599           dtr = tree->right;
2600           break;
2601         case CALL:
2602           /* decorate right side for CALL (parameter list) in processParms();
2603              there is resultType available */
2604           dtr = tree->right;
2605           break;
2606         case SIZEOF:
2607           /* don't allocate string if it is a sizeof argument */
2608           ++noAlloc;
2609           dtr = decorateType (tree->right, resultTypeProp);
2610           --noAlloc;
2611           break;
2612         default:
2613           dtr = decorateType (tree->right, resultTypeProp);
2614           break;
2615       }
2616
2617     /* this is to take care of situations
2618        when the tree gets rewritten */
2619     if (dtl != tree->left)
2620       tree->left = dtl;
2621     if (dtr != tree->right)
2622       tree->right = dtr;
2623     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2624       return tree;
2625   }
2626
2627   /* depending on type of operator do */
2628
2629   switch (tree->opval.op)
2630     {
2631         /*------------------------------------------------------------------*/
2632         /*----------------------------*/
2633         /*        array node          */
2634         /*----------------------------*/
2635     case '[':
2636
2637       /* first check if this is a array or a pointer */
2638       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2639         {
2640           werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2641           goto errorTreeReturn;
2642         }
2643
2644       /* check if the type of the idx */
2645       if (!IS_INTEGRAL (RTYPE (tree)))
2646         {
2647           werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2648           goto errorTreeReturn;
2649         }
2650
2651       /* if the left is an rvalue then error */
2652       if (LRVAL (tree))
2653         {
2654           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2655           goto errorTreeReturn;
2656         }
2657
2658       if (IS_LITERAL (RTYPE (tree)))
2659         {
2660           int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2661           int arraySize = DCL_ELEM (LTYPE (tree));
2662           if (arraySize && arrayIndex >= arraySize)
2663             {
2664               werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2665             }
2666         }
2667
2668       RRVAL (tree) = 1;
2669       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2670       SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2671       return tree;
2672
2673       /*------------------------------------------------------------------*/
2674       /*----------------------------*/
2675       /*      struct/union          */
2676       /*----------------------------*/
2677     case '.':
2678       /* if this is not a structure */
2679       if (!IS_STRUCT (LTYPE (tree)))
2680         {
2681           werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2682           goto errorTreeReturn;
2683         }
2684       TTYPE (tree) = structElemType (LTYPE (tree),
2685                                      (tree->right->type == EX_VALUE ?
2686                                tree->right->opval.val : NULL));
2687       TETYPE (tree) = getSpec (TTYPE (tree));
2688       return tree;
2689
2690       /*------------------------------------------------------------------*/
2691       /*----------------------------*/
2692       /*    struct/union pointer    */
2693       /*----------------------------*/
2694     case PTR_OP:
2695       /* if not pointer to a structure */
2696       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2697         {
2698           werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2699           goto errorTreeReturn;
2700         }
2701
2702       if (!IS_STRUCT (LTYPE (tree)->next))
2703         {
2704           werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2705           goto errorTreeReturn;
2706         }
2707
2708       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2709                                      (tree->right->type == EX_VALUE ?
2710                                tree->right->opval.val : NULL));
2711       TETYPE (tree) = getSpec (TTYPE (tree));
2712
2713       /* adjust the storage class */
2714       switch (DCL_TYPE(tree->left->ftype)) {
2715       case POINTER:
2716         SPEC_SCLS(TETYPE(tree)) = S_DATA;
2717         break;
2718       case FPOINTER:
2719         SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2720         break;
2721       case CPOINTER:
2722         SPEC_SCLS(TETYPE(tree)) = S_CODE;
2723         break;
2724       case GPOINTER:
2725         SPEC_SCLS (TETYPE (tree)) = 0;
2726         break;
2727       case PPOINTER:
2728         SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2729         break;
2730       case IPOINTER:
2731         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2732         break;
2733       case EEPPOINTER:
2734         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2735         break;
2736       case UPOINTER:
2737         SPEC_SCLS (TETYPE (tree)) = 0;
2738         break;
2739       case ARRAY:
2740       case FUNCTION:
2741         break;
2742       }
2743
2744       /* This breaks with extern declarations, bitfields, and perhaps other */
2745       /* cases (gcse). Let's leave this optimization disabled for now and   */
2746       /* ponder if there's a safe way to do this. -- EEP                    */
2747       #if 0
2748       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2749           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2750         {
2751             /* If defined    struct type at addr var
2752                then rewrite  (&struct var)->member
2753                as            temp
2754                and define    membertype at (addr+offsetof(struct var,member)) temp
2755             */
2756             symbol *sym;
2757             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2758                                                 AST_SYMBOL(tree->right));
2759
2760             sym = newSymbol(genSymName (0), 0);
2761             sym->type = TTYPE (tree);
2762             sym->etype = getSpec(sym->type);
2763             sym->lineDef = tree->lineno;
2764             sym->cdef = 1;
2765             sym->isref = 1;
2766             SPEC_STAT (sym->etype) = 1;
2767             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2768                                      + element->offset;
2769             SPEC_ABSA(sym->etype) = 1;
2770             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2771             allocGlobal (sym);
2772
2773             AST_VALUE (tree) = symbolVal(sym);
2774             TLVAL (tree) = 1;
2775             TRVAL (tree) = 0;
2776             tree->type = EX_VALUE;
2777             tree->left = NULL;
2778             tree->right = NULL;
2779         }
2780       #endif
2781
2782       return tree;
2783
2784       /*------------------------------------------------------------------*/
2785       /*----------------------------*/
2786       /*  ++/-- operation           */
2787       /*----------------------------*/
2788     case INC_OP:
2789     case DEC_OP:
2790       {
2791         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2792         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2793         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2794           werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2795
2796         if (tree->right)
2797           RLVAL (tree) = 1;
2798         else
2799           LLVAL (tree) = 1;
2800         return tree;
2801       }
2802
2803       /*------------------------------------------------------------------*/
2804       /*----------------------------*/
2805       /*  bitwise and               */
2806       /*----------------------------*/
2807     case '&':                   /* can be unary   */
2808       /* if right is NULL then unary operation  */
2809       if (tree->right)          /* not an unary operation */
2810         {
2811
2812           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2813             {
2814               werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2815               werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2816               printTypeChain (LTYPE (tree), stderr);
2817               fprintf (stderr, ",");
2818               printTypeChain (RTYPE (tree), stderr);
2819               fprintf (stderr, "\n");
2820               goto errorTreeReturn;
2821             }
2822
2823           /* if they are both literal */
2824           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2825             {
2826               tree->type = EX_VALUE;
2827               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2828                                           valFromType (RETYPE (tree)), '&');
2829
2830               tree->right = tree->left = NULL;
2831               TETYPE (tree) = tree->opval.val->etype;
2832               TTYPE (tree) = tree->opval.val->type;
2833               return tree;
2834             }
2835
2836           /* see if this is a GETHBIT operation if yes
2837              then return that */
2838           {
2839             ast *otree = optimizeGetHbit (tree, resultType);
2840
2841             if (otree != tree)
2842               return decorateType (otree, RESULT_TYPE_NONE);
2843           }
2844
2845           /* see if this is a GETABIT operation if yes
2846              then return that */
2847           {
2848             ast *otree = optimizeGetAbit (tree, resultType);
2849
2850             if (otree != tree)
2851               return decorateType (otree, RESULT_TYPE_NONE);
2852           }
2853
2854           /* see if this is a GETBYTE operation if yes
2855              then return that */
2856           {
2857             ast *otree = optimizeGetByte (tree, resultType);
2858
2859             if (otree != tree)
2860               return decorateType (otree, RESULT_TYPE_NONE);
2861           }
2862
2863           /* see if this is a GETWORD operation if yes
2864              then return that */
2865           {
2866             ast *otree = optimizeGetWord (tree, resultType);
2867
2868             if (otree != tree)
2869               return decorateType (otree, RESULT_TYPE_NONE);
2870           }
2871
2872           /* if left is a literal exchange left & right */
2873           if (IS_LITERAL (LTYPE (tree)))
2874             {
2875               ast *tTree = tree->left;
2876               tree->left = tree->right;
2877               tree->right = tTree;
2878             }
2879
2880           /* if right is a literal and */
2881           /* we can find a 2nd literal in an and-tree then */
2882           /* rearrange the tree */
2883           if (IS_LITERAL (RTYPE (tree)))
2884             {
2885               ast *parent;
2886               ast *litTree = searchLitOp (tree, &parent, "&");
2887               if (litTree)
2888                 {
2889                   DEBUG_CF("&")
2890                   ast *tTree = litTree->left;
2891                   litTree->left = tree->right;
2892                   tree->right = tTree;
2893                   /* both operands in litTree are literal now */
2894                   decorateType (parent, resultType);
2895                 }
2896             }
2897
2898           LRVAL (tree) = RRVAL (tree) = 1;
2899
2900           TTYPE (tree) = computeType (LTYPE (tree),
2901                                       RTYPE (tree),
2902                                       resultType,
2903                                       tree->opval.op);
2904           TETYPE (tree) = getSpec (TTYPE (tree));
2905
2906           return tree;
2907         }
2908
2909       /*------------------------------------------------------------------*/
2910       /*----------------------------*/
2911       /*  address of                */
2912       /*----------------------------*/
2913       p = newLink (DECLARATOR);
2914       /* if bit field then error */
2915       if (IS_BITVAR (tree->left->etype))
2916         {
2917           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2918           goto errorTreeReturn;
2919         }
2920
2921       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2922         {
2923           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2924           goto errorTreeReturn;
2925         }
2926
2927       if (IS_FUNC (LTYPE (tree)))
2928         {
2929           // this ought to be ignored
2930           return (tree->left);
2931         }
2932
2933       if (IS_LITERAL(LTYPE(tree)))
2934         {
2935           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2936           goto errorTreeReturn;
2937         }
2938
2939      if (LRVAL (tree))
2940         {
2941           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2942           goto errorTreeReturn;
2943         }
2944       if (!LETYPE (tree))
2945         DCL_TYPE (p) = POINTER;
2946       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2947         DCL_TYPE (p) = CPOINTER;
2948       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2949         DCL_TYPE (p) = FPOINTER;
2950       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2951         DCL_TYPE (p) = PPOINTER;
2952       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2953         DCL_TYPE (p) = IPOINTER;
2954       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2955         DCL_TYPE (p) = EEPPOINTER;
2956       else if (SPEC_OCLS(tree->left->etype))
2957           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2958       else
2959           DCL_TYPE (p) = POINTER;
2960
2961       if (IS_AST_SYM_VALUE (tree->left))
2962         {
2963           AST_SYMBOL (tree->left)->addrtaken = 1;
2964           AST_SYMBOL (tree->left)->allocreq = 1;
2965         }
2966
2967       p->next = LTYPE (tree);
2968       TTYPE (tree) = p;
2969       TETYPE (tree) = getSpec (TTYPE (tree));
2970       LLVAL (tree) = 1;
2971       TLVAL (tree) = 1;
2972
2973       #if 0
2974       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2975           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2976         {
2977           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2978                                       AST_SYMBOL(tree->left->right));
2979           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2980                                     valueFromLit(element->offset));
2981           tree->left = NULL;
2982           tree->right = NULL;
2983           tree->type = EX_VALUE;
2984           tree->values.literalFromCast = 1;
2985         }
2986       #endif
2987
2988       return tree;
2989
2990       /*------------------------------------------------------------------*/
2991       /*----------------------------*/
2992       /*  bitwise or                */
2993       /*----------------------------*/
2994     case '|':
2995       /* if the rewrite succeeds then don't go any further */
2996       {
2997         ast *wtree = optimizeRRCRLC (tree);
2998         if (wtree != tree)
2999           return decorateType (wtree, RESULT_TYPE_NONE);
3000
3001         wtree = optimizeSWAP (tree);
3002         if (wtree != tree)
3003           return decorateType (wtree, RESULT_TYPE_NONE);
3004       }
3005
3006       /* if left is a literal exchange left & right */
3007       if (IS_LITERAL (LTYPE (tree)))
3008         {
3009           ast *tTree = tree->left;
3010           tree->left = tree->right;
3011           tree->right = tTree;
3012         }
3013
3014       /* if right is a literal and */
3015       /* we can find a 2nd literal in an or-tree then */
3016       /* rearrange the tree */
3017       if (IS_LITERAL (RTYPE (tree)))
3018         {
3019           ast *parent;
3020           ast *litTree = searchLitOp (tree, &parent, "|");
3021           if (litTree)
3022             {
3023               DEBUG_CF("|")
3024               ast *tTree = litTree->left;
3025               litTree->left = tree->right;
3026               tree->right = tTree;
3027               /* both operands in tTree are literal now */
3028               decorateType (parent, resultType);
3029             }
3030         }
3031       /* fall through */
3032
3033       /*------------------------------------------------------------------*/
3034       /*----------------------------*/
3035       /*  bitwise xor               */
3036       /*----------------------------*/
3037     case '^':
3038       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3039         {
3040           werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3041           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3042           printTypeChain (LTYPE (tree), stderr);
3043           fprintf (stderr, ",");
3044           printTypeChain (RTYPE (tree), stderr);
3045           fprintf (stderr, "\n");
3046           goto errorTreeReturn;
3047         }
3048
3049       /* if they are both literal then rewrite the tree */
3050       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3051         {
3052           tree->type = EX_VALUE;
3053           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3054                                         valFromType (RETYPE (tree)),
3055                                         tree->opval.op);
3056           tree->right = tree->left = NULL;
3057           TETYPE (tree) = tree->opval.val->etype;
3058           TTYPE (tree) = tree->opval.val->type;
3059           return tree;
3060         }
3061
3062       /* if left is a literal exchange left & right */
3063       if (IS_LITERAL (LTYPE (tree)))
3064         {
3065           ast *tTree = tree->left;
3066           tree->left = tree->right;
3067           tree->right = tTree;
3068         }
3069
3070       /* if right is a literal and */
3071       /* we can find a 2nd literal in a xor-tree then */
3072       /* rearrange the tree */
3073       if (IS_LITERAL (RTYPE (tree)) &&
3074           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3075         {
3076           ast *parent;
3077           ast *litTree = searchLitOp (tree, &parent, "^");
3078           if (litTree)
3079             {
3080               DEBUG_CF("^")
3081               ast *tTree = litTree->left;
3082               litTree->left = tree->right;
3083               tree->right = tTree;
3084               /* both operands in litTree are literal now */
3085               decorateType (parent, resultType);
3086             }
3087         }
3088
3089       LRVAL (tree) = RRVAL (tree) = 1;
3090
3091       TTYPE (tree) = computeType (LTYPE (tree),
3092                                   RTYPE (tree),
3093                                   resultType,
3094                                   tree->opval.op);
3095       TETYPE (tree) = getSpec (TTYPE (tree));
3096
3097       return tree;
3098
3099       /*------------------------------------------------------------------*/
3100       /*----------------------------*/
3101       /*  division                  */
3102       /*----------------------------*/
3103     case '/':
3104       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3105         {
3106           werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3107           goto errorTreeReturn;
3108         }
3109       /* if they are both literal then */
3110       /* rewrite the tree */
3111       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3112         {
3113           tree->type = EX_VALUE;
3114           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3115                                     valFromType (RETYPE (tree)));
3116           tree->right = tree->left = NULL;
3117           TETYPE (tree) = getSpec (TTYPE (tree) =
3118                                    tree->opval.val->type);
3119           return tree;
3120         }
3121
3122       LRVAL (tree) = RRVAL (tree) = 1;
3123
3124       TETYPE (tree) = getSpec (TTYPE (tree) =
3125                                computeType (LTYPE (tree),
3126                                             RTYPE (tree),
3127                                             resultType,
3128                                             tree->opval.op));
3129
3130       /* if right is a literal and */
3131       /* left is also a division by a literal then */
3132       /* rearrange the tree */
3133       if (IS_LITERAL (RTYPE (tree))
3134           /* avoid infinite loop */
3135           && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3136         {
3137           ast *parent;
3138           ast *litTree = searchLitOp (tree, &parent, "/");
3139           if (litTree)
3140             {
3141               if (IS_LITERAL (RTYPE (litTree)))
3142                 {
3143                   /* foo_div */
3144                   DEBUG_CF("div r")
3145                   litTree->right = newNode ('*',
3146                                             litTree->right,
3147                                             copyAst (tree->right));
3148                   litTree->right->filename = tree->filename;
3149                   litTree->right->lineno = tree->lineno;
3150
3151                   tree->right->opval.val = constCharVal (1);
3152                   decorateType (parent, resultType);
3153                 }
3154               else
3155                 {
3156                   /* litTree->left is literal: no gcse possible.
3157                      We can't call decorateType(parent, RESULT_TYPE_NONE), because
3158                      this would cause an infinit loop. */
3159                   parent->decorated = 1;
3160                   decorateType (litTree, resultType);
3161                 }
3162             }
3163         }
3164
3165       return tree;
3166
3167       /*------------------------------------------------------------------*/
3168       /*----------------------------*/
3169       /*            modulus         */
3170       /*----------------------------*/
3171     case '%':
3172       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3173         {
3174           werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3175           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3176           printTypeChain (LTYPE (tree), stderr);
3177           fprintf (stderr, ",");
3178           printTypeChain (RTYPE (tree), stderr);
3179           fprintf (stderr, "\n");
3180           goto errorTreeReturn;
3181         }
3182       /* if they are both literal then */
3183       /* rewrite the tree */
3184       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3185         {
3186           tree->type = EX_VALUE;
3187           tree->opval.val = valMod (valFromType (LETYPE (tree)),
3188                                     valFromType (RETYPE (tree)));
3189           tree->right = tree->left = NULL;
3190           TETYPE (tree) = getSpec (TTYPE (tree) =
3191                                    tree->opval.val->type);
3192           return tree;
3193         }
3194       LRVAL (tree) = RRVAL (tree) = 1;
3195       TETYPE (tree) = getSpec (TTYPE (tree) =
3196                                computeType (LTYPE (tree),
3197                                             RTYPE (tree),
3198                                             resultType,
3199                                             tree->opval.op));
3200       return tree;
3201
3202       /*------------------------------------------------------------------*/
3203       /*----------------------------*/
3204       /*  address dereference       */
3205       /*----------------------------*/
3206     case '*':                   /* can be unary  : if right is null then unary operation */
3207       if (!tree->right)
3208         {
3209           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3210             {
3211               werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3212               goto errorTreeReturn;
3213             }
3214
3215           if (LRVAL (tree))
3216             {
3217               werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3218               goto errorTreeReturn;
3219             }
3220           if (IS_ADDRESS_OF_OP(tree->left))
3221             {
3222               /* replace *&obj with obj */
3223               return tree->left->left;
3224             }
3225           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3226           TETYPE (tree) = getSpec (TTYPE (tree));
3227           /* adjust the storage class */
3228           switch (DCL_TYPE(tree->left->ftype)) {
3229             case POINTER:
3230               SPEC_SCLS(TETYPE(tree)) = S_DATA;
3231               break;
3232             case FPOINTER:
3233               SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3234               break;
3235             case CPOINTER:
3236               SPEC_SCLS(TETYPE(tree)) = S_CODE;
3237               break;
3238             case GPOINTER:
3239               SPEC_SCLS (TETYPE (tree)) = 0;
3240               break;
3241             case PPOINTER:
3242               SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3243               break;
3244             case IPOINTER:
3245               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3246               break;
3247             case EEPPOINTER:
3248               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3249               break;
3250             case UPOINTER:
3251               SPEC_SCLS (TETYPE (tree)) = 0;
3252               break;
3253             case ARRAY:
3254             case FUNCTION:
3255               break;
3256           }
3257           return tree;
3258         }
3259
3260       /*------------------------------------------------------------------*/
3261       /*----------------------------*/
3262       /*      multiplication        */
3263       /*----------------------------*/
3264       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3265         {
3266           werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3267           goto errorTreeReturn;
3268         }
3269
3270       /* if they are both literal then */
3271       /* rewrite the tree */
3272       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3273         {
3274           tree->type = EX_VALUE;
3275           tree->opval.val = valMult (valFromType (LETYPE (tree)),
3276                                      valFromType (RETYPE (tree)));
3277           tree->right = tree->left = NULL;
3278           TETYPE (tree) = getSpec (TTYPE (tree) =
3279                                    tree->opval.val->type);
3280           return tree;
3281         }
3282
3283       /* if left is a literal exchange left & right */
3284       if (IS_LITERAL (LTYPE (tree)))
3285         {
3286           ast *tTree = tree->left;
3287           tree->left = tree->right;
3288           tree->right = tTree;
3289         }
3290
3291       /* if right is a literal and */
3292       /* we can find a 2nd literal in a mul-tree then */
3293       /* rearrange the tree */
3294       if (IS_LITERAL (RTYPE (tree)))
3295         {
3296           ast *parent;
3297           ast *litTree = searchLitOp (tree, &parent, "*");
3298           if (litTree)
3299             {
3300               DEBUG_CF("mul")
3301               ast *tTree = litTree->left;
3302               litTree->left = tree->right;
3303               tree->right = tTree;
3304               /* both operands in litTree are literal now */
3305               decorateType (parent, resultType);
3306             }
3307         }
3308
3309       LRVAL (tree) = RRVAL (tree) = 1;
3310       tree->left  = addCast (tree->left,  resultTypeProp, FALSE);
3311       tree->right = addCast (tree->right, resultTypeProp, FALSE);
3312       TETYPE (tree) = getSpec (TTYPE (tree) =
3313                                    computeType (LTYPE (tree),
3314                                                 RTYPE (tree),
3315                                                 resultType,
3316                                                 tree->opval.op));
3317
3318       return tree;
3319
3320       /*------------------------------------------------------------------*/
3321       /*----------------------------*/
3322       /*    unary '+' operator      */
3323       /*----------------------------*/
3324     case '+':
3325       /* if unary plus */
3326       if (!tree->right)
3327         {
3328           if (!IS_ARITHMETIC (LTYPE (tree)))
3329             {
3330               werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3331               goto errorTreeReturn;
3332             }
3333
3334           /* if left is a literal then do it */
3335           if (IS_LITERAL (LTYPE (tree)))
3336             {
3337               tree->type = EX_VALUE;
3338               tree->opval.val = valFromType (LETYPE (tree));
3339               tree->left = NULL;
3340               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3341               return tree;
3342             }
3343           LRVAL (tree) = 1;
3344           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3345           return tree;
3346         }
3347
3348       /*------------------------------------------------------------------*/
3349       /*----------------------------*/
3350       /*      addition              */
3351       /*----------------------------*/
3352
3353       /* this is not a unary operation */
3354       /* if both pointers then problem */
3355       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3356           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3357         {
3358           werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3359           goto errorTreeReturn;
3360         }
3361
3362       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3363           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3364         {
3365           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3366           goto errorTreeReturn;
3367         }
3368
3369       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3370           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3371         {
3372           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3373           goto errorTreeReturn;
3374         }
3375       /* if they are both literal then */
3376       /* rewrite the tree */
3377       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3378         {
3379           tree->type = EX_VALUE;
3380           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3381           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3382           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3383                                      valFromType (RETYPE (tree)));
3384           tree->right = tree->left = NULL;
3385           TETYPE (tree) = getSpec (TTYPE (tree) =
3386                                    tree->opval.val->type);
3387           return tree;
3388         }
3389
3390       /* if the right is a pointer or left is a literal
3391          xchange left & right */
3392       if (IS_ARRAY (RTYPE (tree)) ||
3393           IS_PTR (RTYPE (tree)) ||
3394           IS_LITERAL (LTYPE (tree)))
3395         {
3396           ast *tTree = tree->left;
3397           tree->left = tree->right;
3398           tree->right = tTree;
3399         }
3400
3401       /* if right is a literal and */
3402       /* left is also an addition/subtraction with a literal then */
3403       /* rearrange the tree */
3404       if (IS_LITERAL (RTYPE (tree)))
3405         {
3406           ast *litTree, *parent;
3407           litTree = searchLitOp (tree, &parent, "+-");
3408           if (litTree)
3409             {
3410               if (litTree->opval.op == '+')
3411                 {
3412                   /* foo_aa */
3413                   DEBUG_CF("+ 1 AA")
3414                   ast *tTree = litTree->left;
3415                   litTree->left = tree->right;
3416                   tree->right = tree->left;
3417                   tree->left = tTree;
3418                 }
3419               else if (litTree->opval.op == '-')
3420                 {
3421                   if (IS_LITERAL (RTYPE (litTree)))
3422                     {
3423                       DEBUG_CF("+ 2 ASR")
3424                       /* foo_asr */
3425                       ast *tTree = litTree->left;
3426                       litTree->left = tree->right;
3427                       tree->right = tTree;
3428                     }
3429                   else
3430                     {
3431                       DEBUG_CF("+ 3 ASL")
3432                       /* foo_asl */
3433                       ast *tTree = litTree->right;
3434                       litTree->right = tree->right;
3435                       tree->right = tTree;
3436                       litTree->opval.op = '+';
3437                       tree->opval.op = '-';
3438                     }
3439                 }
3440               decorateType (parent, resultType);
3441             }
3442         }
3443
3444       LRVAL (tree) = RRVAL (tree) = 1;
3445       /* if the left is a pointer */
3446       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3447         TETYPE (tree) = getSpec (TTYPE (tree) =
3448                                  LTYPE (tree));
3449       else
3450         {
3451           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3452           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3453           TETYPE (tree) = getSpec (TTYPE (tree) =
3454                                      computeType (LTYPE (tree),
3455                                                   RTYPE (tree),
3456                                                   resultType,
3457                                                   tree->opval.op));
3458         }
3459
3460       return tree;
3461
3462       /*------------------------------------------------------------------*/
3463       /*----------------------------*/
3464       /*      unary '-'             */
3465       /*----------------------------*/
3466     case '-':                   /* can be unary   */
3467       /* if right is null then unary */
3468       if (!tree->right)
3469         {
3470
3471           if (!IS_ARITHMETIC (LTYPE (tree)))
3472             {
3473               werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3474               goto errorTreeReturn;
3475             }
3476
3477           /* if left is a literal then do it */
3478           if (IS_LITERAL (LTYPE (tree)))
3479             {
3480               tree->type = EX_VALUE;
3481               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3482               tree->left = NULL;
3483               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3484               return tree;
3485             }
3486           tree->left  = addCast (tree->left, resultTypeProp, TRUE);
3487           TETYPE (tree) = getSpec (TTYPE (tree) =
3488                                      computeType (LTYPE (tree),
3489                                                   NULL,
3490                                                   resultType,
3491                                                   tree->opval.op));
3492           LRVAL (tree) = 1;
3493           return tree;
3494         }
3495
3496       /*------------------------------------------------------------------*/
3497       /*----------------------------*/
3498       /*    subtraction             */
3499       /*----------------------------*/
3500
3501       if (!(IS_PTR (LTYPE (tree)) ||
3502             IS_ARRAY (LTYPE (tree)) ||
3503             IS_ARITHMETIC (LTYPE (tree))))
3504         {
3505           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3506           goto errorTreeReturn;
3507         }
3508
3509       if (!(IS_PTR (RTYPE (tree)) ||
3510             IS_ARRAY (RTYPE (tree)) ||
3511             IS_ARITHMETIC (RTYPE (tree))))
3512         {
3513           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3514           goto errorTreeReturn;
3515         }
3516
3517       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3518           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3519             IS_INTEGRAL (RTYPE (tree))))
3520         {
3521           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3522           goto errorTreeReturn;
3523         }
3524
3525       /* if they are both literal then */
3526       /* rewrite the tree */
3527       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3528         {
3529           tree->type = EX_VALUE;
3530           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3531           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3532           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3533                                       valFromType (RETYPE (tree)));
3534           tree->right = tree->left = NULL;
3535           TETYPE (tree) = getSpec (TTYPE (tree) =
3536                                    tree->opval.val->type);
3537           return tree;
3538         }
3539
3540       /* if the left & right are equal then zero */
3541       if (isAstEqual (tree->left, tree->right))
3542         {
3543           tree->type = EX_VALUE;
3544           tree->left = tree->right = NULL;
3545           tree->opval.val = constCharVal (0);
3546           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3547           return tree;
3548         }
3549
3550       /* if both of them are pointers or arrays then */
3551       /* the result is going to be an integer        */
3552       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3553           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3554         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3555       else
3556         /* if only the left is a pointer */
3557         /* then result is a pointer      */
3558       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3559         TETYPE (tree) = getSpec (TTYPE (tree) =
3560                                  LTYPE (tree));
3561       else
3562         {
3563           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3564           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3565
3566           TETYPE (tree) = getSpec (TTYPE (tree) =
3567                                      computeType (LTYPE (tree),
3568                                                   RTYPE (tree),
3569                                                   resultType,
3570                                                   tree->opval.op));
3571         }
3572
3573       LRVAL (tree) = RRVAL (tree) = 1;
3574
3575       /* if right is a literal and */
3576       /* left is also an addition/subtraction with a literal then */
3577       /* rearrange the tree */
3578       if (IS_LITERAL (RTYPE (tree))
3579           /* avoid infinite loop */
3580           && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3581         {
3582           ast *litTree, *litParent;
3583           litTree = searchLitOp (tree, &litParent, "+-");
3584           if (litTree)
3585             {
3586               if (litTree->opval.op == '+')
3587                 {
3588                   /* foo_sa */
3589                   DEBUG_CF("- 1 SA")
3590                   ast *tTree = litTree->left;
3591                   litTree->left = litTree->right;
3592                   litTree->right = tree->right;
3593                   tree->right = tTree;
3594                   tree->opval.op = '+';
3595                   litTree->opval.op = '-';
3596                 }
3597               else if (litTree->opval.op == '-')
3598                 {
3599                   if (IS_LITERAL (RTYPE (litTree)))
3600                     {
3601                       /* foo_ssr */
3602                       DEBUG_CF("- 2 SSR")
3603                       ast *tTree = litTree->left;
3604                       litTree->left = tree->right;
3605                       tree->right = litParent->left;
3606                       litParent->left = tTree;
3607                       litTree->opval.op = '+';
3608
3609                       tree->decorated = 0;
3610                       decorateType (tree, resultType);
3611                     }
3612                   else
3613                     {
3614                       /* foo_ssl */
3615                       DEBUG_CF("- 3 SSL")
3616                       ast *tTree = litTree->right;
3617                       litTree->right = tree->right;
3618                       tree->right = tTree;
3619                     }
3620                 }
3621               decorateType (litParent, resultType);
3622             }
3623         }
3624       return tree;
3625
3626       /*------------------------------------------------------------------*/
3627       /*----------------------------*/
3628       /*    complement              */
3629       /*----------------------------*/
3630     case '~':
3631       /* can be only integral type */
3632       if (!IS_INTEGRAL (LTYPE (tree)))
3633         {
3634           werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3635           goto errorTreeReturn;
3636         }
3637
3638       /* if left is a literal then do it */
3639       if (IS_LITERAL (LTYPE (tree)))
3640         {
3641           tree->type = EX_VALUE;
3642           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3643           tree->left = NULL;
3644           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3645           return addCast (tree, resultTypeProp, TRUE);
3646         }
3647
3648       if (resultType == RESULT_TYPE_BIT &&
3649           IS_UNSIGNED (tree->left->etype) &&
3650           getSize (tree->left->etype) < INTSIZE)
3651         {
3652           /* promotion rules are responsible for this strange result:
3653              bit -> int -> ~int -> bit
3654              uchar -> int -> ~int -> bit
3655           */
3656           werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3657
3658           /* optimize bit-result, even if we optimize a buggy source */
3659           tree->type = EX_VALUE;
3660           tree->opval.val = constCharVal (1);
3661         }
3662       else
3663         tree->left = addCast (tree->left, resultTypeProp, TRUE);
3664       LRVAL (tree) = 1;
3665       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3666       return tree;
3667
3668       /*------------------------------------------------------------------*/
3669       /*----------------------------*/
3670       /*           not              */
3671       /*----------------------------*/
3672     case '!':
3673       /* can be pointer */
3674       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3675           !IS_PTR (LTYPE (tree)) &&
3676           !IS_ARRAY (LTYPE (tree)))
3677         {
3678           werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3679           goto errorTreeReturn;
3680         }
3681
3682       /* if left is another '!' */
3683       if (IS_AST_NOT_OPER (tree->left))
3684         {
3685           if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3686             {
3687               /* replace double '!!X' by 'X' */
3688               return tree->left->left;
3689             }
3690           /* remove double '!!X' by 'X ? 1 : 0' */
3691           tree->opval.op = '?';
3692           tree->left  = tree->left->left;
3693           tree->right = newNode (':',
3694                                   newAst_VALUE (constCharVal (1)),
3695                                   newAst_VALUE (constCharVal (0)));
3696           tree->right->filename = tree->filename;
3697           tree->right->lineno = tree->lineno;
3698           tree->decorated = 0;
3699           return decorateType (tree, resultType);
3700         }
3701
3702       /* if left is a literal then do it */
3703       if (IS_LITERAL (LTYPE (tree)))
3704         {
3705           tree->type = EX_VALUE;
3706           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3707           tree->left = NULL;
3708           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3709           return tree;
3710         }
3711       LRVAL (tree) = 1;
3712       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3713       return tree;
3714
3715       /*------------------------------------------------------------------*/
3716       /*----------------------------*/
3717       /*           shift            */
3718       /*----------------------------*/
3719     case RRC:
3720     case RLC:
3721     case SWAP:
3722       TTYPE (tree) = LTYPE (tree);
3723       TETYPE (tree) = LETYPE (tree);
3724       return tree;
3725
3726     case GETHBIT:
3727     case GETABIT:
3728       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3729       return tree;
3730
3731     case GETBYTE:
3732       TTYPE (tree) = TETYPE (tree) = newCharLink();
3733       return tree;
3734
3735     case GETWORD:
3736       TTYPE (tree) = TETYPE (tree) = newIntLink();
3737       return tree;
3738
3739     case LEFT_OP:
3740     case RIGHT_OP:
3741       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3742         {
3743           werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3744           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3745           printTypeChain (LTYPE (tree), stderr);
3746           fprintf (stderr, ",");
3747           printTypeChain (RTYPE (tree), stderr);
3748           fprintf (stderr, "\n");
3749           goto errorTreeReturn;
3750         }
3751
3752       /* make smaller type only if it's a LEFT_OP */
3753       if (tree->opval.op == LEFT_OP)
3754         tree->left = addCast (tree->left, resultTypeProp, TRUE);
3755
3756       /* if they are both literal then */
3757       /* rewrite the tree */
3758       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3759         {
3760           tree->type = EX_VALUE;
3761           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3762                                       valFromType (RETYPE (tree)),
3763                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3764           tree->right = tree->left = NULL;
3765           TETYPE (tree) = getSpec (TTYPE (tree) =
3766                                    tree->opval.val->type);
3767           return tree;
3768         }
3769
3770       /* see if this is a GETBYTE operation if yes
3771          then return that */
3772       {
3773         ast *otree = optimizeGetByte (tree, resultType);
3774
3775         if (otree != tree)
3776           return decorateType (otree, RESULT_TYPE_NONE);
3777       }
3778
3779       /* see if this is a GETWORD operation if yes
3780          then return that */
3781       {
3782         ast *otree = optimizeGetWord (tree, resultType);
3783
3784         if (otree != tree)
3785           return decorateType (otree, RESULT_TYPE_NONE);
3786       }
3787
3788       LRVAL (tree) = RRVAL (tree) = 1;
3789       if (tree->opval.op == LEFT_OP)
3790         {
3791           TETYPE (tree) = getSpec (TTYPE (tree) =
3792                                        computeType (LTYPE (tree),
3793                                                     NULL,
3794                                                     resultType,
3795                                                     tree->opval.op));
3796         }
3797       else /* RIGHT_OP */
3798         {
3799           /* no promotion necessary */
3800           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3801           if (IS_LITERAL (TTYPE (tree)))
3802             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3803         }
3804
3805       /* if only the right side is a literal & we are
3806          shifting more than size of the left operand then zero */
3807       if (IS_LITERAL (RTYPE (tree)) &&
3808           ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3809           (getSize (TETYPE (tree)) * 8))
3810         {
3811           if (tree->opval.op==LEFT_OP ||
3812               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3813             {
3814               werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3815                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3816               tree->type = EX_VALUE;
3817               tree->left = tree->right = NULL;
3818               tree->opval.val = constCharVal (0);
3819               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3820               return tree;
3821             }
3822         }
3823
3824       return tree;
3825
3826       /*------------------------------------------------------------------*/
3827       /*----------------------------*/
3828       /*         casting            */
3829       /*----------------------------*/
3830     case CAST:                  /* change the type   */
3831       /* cannot cast to an aggregate type */
3832       if (IS_AGGREGATE (LTYPE (tree)))
3833         {
3834           werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3835           goto errorTreeReturn;
3836         }
3837
3838       /* make sure the type is complete and sane */
3839       changePointer(LTYPE(tree));
3840       checkTypeSanity(LETYPE(tree), "(cast)");
3841
3842
3843       /* if 'from' and 'to' are the same remove the superfluous cast,
3844        * this helps other optimizations */
3845       if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3846         {
3847           /* mark that the explicit cast has been removed,
3848            * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3849           tree->right->values.removedCast = 1;
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 }