4b16e347aa386ead902d6e019fbe67b9b7608f09
[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       if (IS_LITERAL (tree->opval.val->etype))
2491         {
2492           /* if this is a character array then declare it */
2493           if (IS_ARRAY (tree->opval.val->type))
2494             tree->opval.val = stringToSymbol (tree->opval.val);
2495
2496           /* otherwise just copy the type information */
2497           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2498           return tree;
2499         }
2500
2501       if (tree->opval.val->sym)
2502         {
2503           /* if the undefined flag is set then give error message */
2504           if (tree->opval.val->sym->undefined)
2505             {
2506               werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2507               /* assume int */
2508               TTYPE (tree) = TETYPE (tree) =
2509                 tree->opval.val->type = tree->opval.val->sym->type =
2510                 tree->opval.val->etype = tree->opval.val->sym->etype =
2511                 copyLinkChain (INTTYPE);
2512             }
2513           else if (tree->opval.val->sym->implicit)
2514             {
2515               /* if implicit i.e. struct/union member then no type */
2516               TTYPE (tree) = TETYPE (tree) = NULL;
2517             }
2518           else
2519             {
2520               /* copy the type from the value into the ast */
2521               COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2522
2523               /* and mark the symbol as referenced */
2524               tree->opval.val->sym->isref = 1;
2525             }
2526         }
2527       else
2528         wassert(0); /* unreached: all values are literals or symbols */
2529
2530       return tree;
2531     }
2532
2533   /* if type link for the case of cast */
2534   if (tree->type == EX_LINK)
2535     {
2536       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2537       return tree;
2538     }
2539
2540   {
2541     ast *dtl, *dtr;
2542
2543     #if 0
2544     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2545       {
2546         if (tree->left && tree->left->type == EX_OPERAND
2547             && (tree->left->opval.op == INC_OP
2548                 || tree->left->opval.op == DEC_OP)
2549             && tree->left->left)
2550           {
2551             tree->left->right = tree->left->left;
2552             tree->left->left = NULL;
2553           }
2554         if (tree->right && tree->right->type == EX_OPERAND
2555             && (tree->right->opval.op == INC_OP
2556                 || tree->right->opval.op == DEC_OP)
2557             && tree->right->left)
2558           {
2559             tree->right->right = tree->right->left;
2560             tree->right->left = NULL;
2561           }
2562       }
2563     #endif
2564
2565     /* Before decorating the left branch we've to decide in dependence
2566        upon tree->opval.op, if resultType can be propagated */
2567     resultTypeProp = resultTypePropagate (tree, resultType);
2568
2569     if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2570       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2571     else
2572       dtl = decorateType (tree->left, resultTypeProp);
2573
2574     /* if an array node, we may need to swap branches */
2575     if (tree->opval.op == '[')
2576       {
2577         /* determine which is the array & which the index */
2578         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2579             IS_INTEGRAL (LTYPE (tree)))
2580           {
2581             ast *tempTree = tree->left;
2582             tree->left = tree->right;
2583             tree->right = tempTree;
2584           }
2585       }
2586
2587     /* After decorating the left branch there's type information available
2588        in tree->left->?type. If the op is e.g. '=' we extract the type
2589        information from there and propagate it to the right branch. */
2590     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2591
2592     switch (tree->opval.op)
2593       {
2594         case '?':
2595           /* delay right side for '?' operator since conditional macro
2596              expansions might rely on this */
2597           dtr = tree->right;
2598           break;
2599         case CALL:
2600           /* decorate right side for CALL (parameter list) in processParms();
2601              there is resultType available */
2602           dtr = tree->right;
2603           break;
2604         case SIZEOF:
2605           /* don't allocate string if it is a sizeof argument */
2606           ++noAlloc;
2607           dtr = decorateType (tree->right, resultTypeProp);
2608           --noAlloc;
2609           break;
2610         default:
2611           dtr = decorateType (tree->right, resultTypeProp);
2612           break;
2613       }
2614
2615     /* this is to take care of situations
2616        when the tree gets rewritten */
2617     if (dtl != tree->left)
2618       tree->left = dtl;
2619     if (dtr != tree->right)
2620       tree->right = dtr;
2621     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2622       return tree;
2623   }
2624
2625   /* depending on type of operator do */
2626
2627   switch (tree->opval.op)
2628     {
2629         /*------------------------------------------------------------------*/
2630         /*----------------------------*/
2631         /*        array node          */
2632         /*----------------------------*/
2633     case '[':
2634
2635       /* first check if this is a array or a pointer */
2636       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2637         {
2638           werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2639           goto errorTreeReturn;
2640         }
2641
2642       /* check if the type of the idx */
2643       if (!IS_INTEGRAL (RTYPE (tree)))
2644         {
2645           werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2646           goto errorTreeReturn;
2647         }
2648
2649       /* if the left is an rvalue then error */
2650       if (LRVAL (tree))
2651         {
2652           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2653           goto errorTreeReturn;
2654         }
2655
2656       if (IS_LITERAL (RTYPE (tree)))
2657         {
2658           int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2659           int arraySize = DCL_ELEM (LTYPE (tree));
2660           if (arraySize && arrayIndex >= arraySize)
2661             {
2662               werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2663             }
2664         }
2665
2666       RRVAL (tree) = 1;
2667       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2668       SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2669       return tree;
2670
2671       /*------------------------------------------------------------------*/
2672       /*----------------------------*/
2673       /*      struct/union          */
2674       /*----------------------------*/
2675     case '.':
2676       /* if this is not a structure */
2677       if (!IS_STRUCT (LTYPE (tree)))
2678         {
2679           werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2680           goto errorTreeReturn;
2681         }
2682       TTYPE (tree) = structElemType (LTYPE (tree),
2683                                      (tree->right->type == EX_VALUE ?
2684                                tree->right->opval.val : NULL));
2685       TETYPE (tree) = getSpec (TTYPE (tree));
2686       return tree;
2687
2688       /*------------------------------------------------------------------*/
2689       /*----------------------------*/
2690       /*    struct/union pointer    */
2691       /*----------------------------*/
2692     case PTR_OP:
2693       /* if not pointer to a structure */
2694       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2695         {
2696           werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2697           goto errorTreeReturn;
2698         }
2699
2700       if (!IS_STRUCT (LTYPE (tree)->next))
2701         {
2702           werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2703           goto errorTreeReturn;
2704         }
2705
2706       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2707                                      (tree->right->type == EX_VALUE ?
2708                                tree->right->opval.val : NULL));
2709       TETYPE (tree) = getSpec (TTYPE (tree));
2710
2711       /* adjust the storage class */
2712       switch (DCL_TYPE(tree->left->ftype)) {
2713       case POINTER:
2714         SPEC_SCLS(TETYPE(tree)) = S_DATA;
2715         break;
2716       case FPOINTER:
2717         SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2718         break;
2719       case CPOINTER:
2720         SPEC_SCLS(TETYPE(tree)) = S_CODE;
2721         break;
2722       case GPOINTER:
2723         SPEC_SCLS (TETYPE (tree)) = 0;
2724         break;
2725       case PPOINTER:
2726         SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2727         break;
2728       case IPOINTER:
2729         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2730         break;
2731       case EEPPOINTER:
2732         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2733         break;
2734       case UPOINTER:
2735         SPEC_SCLS (TETYPE (tree)) = 0;
2736         break;
2737       case ARRAY:
2738       case FUNCTION:
2739         break;
2740       }
2741
2742       /* This breaks with extern declarations, bitfields, and perhaps other */
2743       /* cases (gcse). Let's leave this optimization disabled for now and   */
2744       /* ponder if there's a safe way to do this. -- EEP                    */
2745       #if 0
2746       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2747           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2748         {
2749             /* If defined    struct type at addr var
2750                then rewrite  (&struct var)->member
2751                as            temp
2752                and define    membertype at (addr+offsetof(struct var,member)) temp
2753             */
2754             symbol *sym;
2755             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2756                                                 AST_SYMBOL(tree->right));
2757
2758             sym = newSymbol(genSymName (0), 0);
2759             sym->type = TTYPE (tree);
2760             sym->etype = getSpec(sym->type);
2761             sym->lineDef = tree->lineno;
2762             sym->cdef = 1;
2763             sym->isref = 1;
2764             SPEC_STAT (sym->etype) = 1;
2765             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2766                                      + element->offset;
2767             SPEC_ABSA(sym->etype) = 1;
2768             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2769             allocGlobal (sym);
2770
2771             AST_VALUE (tree) = symbolVal(sym);
2772             TLVAL (tree) = 1;
2773             TRVAL (tree) = 0;
2774             tree->type = EX_VALUE;
2775             tree->left = NULL;
2776             tree->right = NULL;
2777         }
2778       #endif
2779
2780       return tree;
2781
2782       /*------------------------------------------------------------------*/
2783       /*----------------------------*/
2784       /*  ++/-- operation           */
2785       /*----------------------------*/
2786     case INC_OP:
2787     case DEC_OP:
2788       {
2789         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2790         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2791         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2792           werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2793
2794         if (tree->right)
2795           RLVAL (tree) = 1;
2796         else
2797           LLVAL (tree) = 1;
2798         return tree;
2799       }
2800
2801       /*------------------------------------------------------------------*/
2802       /*----------------------------*/
2803       /*  bitwise and               */
2804       /*----------------------------*/
2805     case '&':                   /* can be unary   */
2806       /* if right is NULL then unary operation  */
2807       if (tree->right)          /* not an unary operation */
2808         {
2809
2810           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2811             {
2812               werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2813               werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2814               printTypeChain (LTYPE (tree), stderr);
2815               fprintf (stderr, ",");
2816               printTypeChain (RTYPE (tree), stderr);
2817               fprintf (stderr, "\n");
2818               goto errorTreeReturn;
2819             }
2820
2821           /* if they are both literal */
2822           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2823             {
2824               tree->type = EX_VALUE;
2825               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2826                                           valFromType (RETYPE (tree)), '&');
2827
2828               tree->right = tree->left = NULL;
2829               TETYPE (tree) = tree->opval.val->etype;
2830               TTYPE (tree) = tree->opval.val->type;
2831               return tree;
2832             }
2833
2834           /* see if this is a GETHBIT operation if yes
2835              then return that */
2836           {
2837             ast *otree = optimizeGetHbit (tree, resultType);
2838
2839             if (otree != tree)
2840               return decorateType (otree, RESULT_TYPE_NONE);
2841           }
2842
2843           /* see if this is a GETABIT operation if yes
2844              then return that */
2845           {
2846             ast *otree = optimizeGetAbit (tree, resultType);
2847
2848             if (otree != tree)
2849               return decorateType (otree, RESULT_TYPE_NONE);
2850           }
2851
2852           /* see if this is a GETBYTE operation if yes
2853              then return that */
2854           {
2855             ast *otree = optimizeGetByte (tree, resultType);
2856
2857             if (otree != tree)
2858               return decorateType (otree, RESULT_TYPE_NONE);
2859           }
2860
2861           /* see if this is a GETWORD operation if yes
2862              then return that */
2863           {
2864             ast *otree = optimizeGetWord (tree, resultType);
2865
2866             if (otree != tree)
2867               return decorateType (otree, RESULT_TYPE_NONE);
2868           }
2869
2870           /* if left is a literal exchange left & right */
2871           if (IS_LITERAL (LTYPE (tree)))
2872             {
2873               ast *tTree = tree->left;
2874               tree->left = tree->right;
2875               tree->right = tTree;
2876             }
2877
2878           /* if right is a literal and */
2879           /* we can find a 2nd literal in an and-tree then */
2880           /* rearrange the tree */
2881           if (IS_LITERAL (RTYPE (tree)))
2882             {
2883               ast *parent;
2884               ast *litTree = searchLitOp (tree, &parent, "&");
2885               if (litTree)
2886                 {
2887                   DEBUG_CF("&")
2888                   ast *tTree = litTree->left;
2889                   litTree->left = tree->right;
2890                   tree->right = tTree;
2891                   /* both operands in litTree are literal now */
2892                   decorateType (parent, resultType);
2893                 }
2894             }
2895
2896           LRVAL (tree) = RRVAL (tree) = 1;
2897
2898           TTYPE (tree) = computeType (LTYPE (tree),
2899                                       RTYPE (tree),
2900                                       resultType,
2901                                       tree->opval.op);
2902           TETYPE (tree) = getSpec (TTYPE (tree));
2903
2904           return tree;
2905         }
2906
2907       /*------------------------------------------------------------------*/
2908       /*----------------------------*/
2909       /*  address of                */
2910       /*----------------------------*/
2911       p = newLink (DECLARATOR);
2912       /* if bit field then error */
2913       if (IS_BITVAR (tree->left->etype))
2914         {
2915           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2916           goto errorTreeReturn;
2917         }
2918
2919       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2920         {
2921           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2922           goto errorTreeReturn;
2923         }
2924
2925       if (IS_FUNC (LTYPE (tree)))
2926         {
2927           // this ought to be ignored
2928           return (tree->left);
2929         }
2930
2931       if (IS_LITERAL(LTYPE(tree)))
2932         {
2933           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2934           goto errorTreeReturn;
2935         }
2936
2937      if (LRVAL (tree))
2938         {
2939           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2940           goto errorTreeReturn;
2941         }
2942       if (!LETYPE (tree))
2943         DCL_TYPE (p) = POINTER;
2944       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2945         DCL_TYPE (p) = CPOINTER;
2946       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2947         DCL_TYPE (p) = FPOINTER;
2948       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2949         DCL_TYPE (p) = PPOINTER;
2950       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2951         DCL_TYPE (p) = IPOINTER;
2952       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2953         DCL_TYPE (p) = EEPPOINTER;
2954       else if (SPEC_OCLS(tree->left->etype))
2955           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2956       else
2957           DCL_TYPE (p) = POINTER;
2958
2959       if (IS_AST_SYM_VALUE (tree->left))
2960         {
2961           AST_SYMBOL (tree->left)->addrtaken = 1;
2962           AST_SYMBOL (tree->left)->allocreq = 1;
2963         }
2964
2965       p->next = LTYPE (tree);
2966       TTYPE (tree) = p;
2967       TETYPE (tree) = getSpec (TTYPE (tree));
2968       LLVAL (tree) = 1;
2969       TLVAL (tree) = 1;
2970
2971       #if 0
2972       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2973           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2974         {
2975           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2976                                       AST_SYMBOL(tree->left->right));
2977           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2978                                     valueFromLit(element->offset));
2979           tree->left = NULL;
2980           tree->right = NULL;
2981           tree->type = EX_VALUE;
2982           tree->values.literalFromCast = 1;
2983         }
2984       #endif
2985
2986       return tree;
2987
2988       /*------------------------------------------------------------------*/
2989       /*----------------------------*/
2990       /*  bitwise or                */
2991       /*----------------------------*/
2992     case '|':
2993       /* if the rewrite succeeds then don't go any further */
2994       {
2995         ast *wtree = optimizeRRCRLC (tree);
2996         if (wtree != tree)
2997           return decorateType (wtree, RESULT_TYPE_NONE);
2998
2999         wtree = optimizeSWAP (tree);
3000         if (wtree != tree)
3001           return decorateType (wtree, RESULT_TYPE_NONE);
3002       }
3003
3004       /* if left is a literal exchange left & right */
3005       if (IS_LITERAL (LTYPE (tree)))
3006         {
3007           ast *tTree = tree->left;
3008           tree->left = tree->right;
3009           tree->right = tTree;
3010         }
3011
3012       /* if right is a literal and */
3013       /* we can find a 2nd literal in an or-tree then */
3014       /* rearrange the tree */
3015       if (IS_LITERAL (RTYPE (tree)))
3016         {
3017           ast *parent;
3018           ast *litTree = searchLitOp (tree, &parent, "|");
3019           if (litTree)
3020             {
3021               DEBUG_CF("|")
3022               ast *tTree = litTree->left;
3023               litTree->left = tree->right;
3024               tree->right = tTree;
3025               /* both operands in tTree are literal now */
3026               decorateType (parent, resultType);
3027             }
3028         }
3029       /* fall through */
3030
3031       /*------------------------------------------------------------------*/
3032       /*----------------------------*/
3033       /*  bitwise xor               */
3034       /*----------------------------*/
3035     case '^':
3036       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3037         {
3038           werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3039           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3040           printTypeChain (LTYPE (tree), stderr);
3041           fprintf (stderr, ",");
3042           printTypeChain (RTYPE (tree), stderr);
3043           fprintf (stderr, "\n");
3044           goto errorTreeReturn;
3045         }
3046
3047       /* if they are both literal then rewrite the tree */
3048       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3049         {
3050           tree->type = EX_VALUE;
3051           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3052                                         valFromType (RETYPE (tree)),
3053                                         tree->opval.op);
3054           tree->right = tree->left = NULL;
3055           TETYPE (tree) = tree->opval.val->etype;
3056           TTYPE (tree) = tree->opval.val->type;
3057           return tree;
3058         }
3059
3060       /* if left is a literal exchange left & right */
3061       if (IS_LITERAL (LTYPE (tree)))
3062         {
3063           ast *tTree = tree->left;
3064           tree->left = tree->right;
3065           tree->right = tTree;
3066         }
3067
3068       /* if right is a literal and */
3069       /* we can find a 2nd literal in a xor-tree then */
3070       /* rearrange the tree */
3071       if (IS_LITERAL (RTYPE (tree)) &&
3072           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3073         {
3074           ast *parent;
3075           ast *litTree = searchLitOp (tree, &parent, "^");
3076           if (litTree)
3077             {
3078               DEBUG_CF("^")
3079               ast *tTree = litTree->left;
3080               litTree->left = tree->right;
3081               tree->right = tTree;
3082               /* both operands in litTree are literal now */
3083               decorateType (parent, resultType);
3084             }
3085         }
3086
3087       LRVAL (tree) = RRVAL (tree) = 1;
3088
3089       TTYPE (tree) = computeType (LTYPE (tree),
3090                                   RTYPE (tree),
3091                                   resultType,
3092                                   tree->opval.op);
3093       TETYPE (tree) = getSpec (TTYPE (tree));
3094
3095       return tree;
3096
3097       /*------------------------------------------------------------------*/
3098       /*----------------------------*/
3099       /*  division                  */
3100       /*----------------------------*/
3101     case '/':
3102       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3103         {
3104           werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3105           goto errorTreeReturn;
3106         }
3107       /* if they are both literal then */
3108       /* rewrite the tree */
3109       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3110         {
3111           tree->type = EX_VALUE;
3112           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3113                                     valFromType (RETYPE (tree)));
3114           tree->right = tree->left = NULL;
3115           TETYPE (tree) = getSpec (TTYPE (tree) =
3116                                    tree->opval.val->type);
3117           return tree;
3118         }
3119
3120       LRVAL (tree) = RRVAL (tree) = 1;
3121
3122       TETYPE (tree) = getSpec (TTYPE (tree) =
3123                                computeType (LTYPE (tree),
3124                                             RTYPE (tree),
3125                                             resultType,
3126                                             tree->opval.op));
3127
3128       /* if right is a literal and */
3129       /* left is also a division by a literal then */
3130       /* rearrange the tree */
3131       if (IS_LITERAL (RTYPE (tree))
3132           /* avoid infinite loop */
3133           && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3134         {
3135           ast *parent;
3136           ast *litTree = searchLitOp (tree, &parent, "/");
3137           if (litTree)
3138             {
3139               if (IS_LITERAL (RTYPE (litTree)))
3140                 {
3141                   /* foo_div */
3142                   DEBUG_CF("div r")
3143                   litTree->right = newNode ('*',
3144                                             litTree->right,
3145                                             copyAst (tree->right));
3146                   litTree->right->filename = tree->filename;
3147                   litTree->right->lineno = tree->lineno;
3148
3149                   tree->right->opval.val = constCharVal (1);
3150                   decorateType (parent, resultType);
3151                 }
3152               else
3153                 {
3154                   /* litTree->left is literal: no gcse possible.
3155                      We can't call decorateType(parent, RESULT_TYPE_NONE), because
3156                      this would cause an infinit loop. */
3157                   parent->decorated = 1;
3158                   decorateType (litTree, resultType);
3159                 }
3160             }
3161         }
3162
3163       return tree;
3164
3165       /*------------------------------------------------------------------*/
3166       /*----------------------------*/
3167       /*            modulus         */
3168       /*----------------------------*/
3169     case '%':
3170       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3171         {
3172           werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3173           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3174           printTypeChain (LTYPE (tree), stderr);
3175           fprintf (stderr, ",");
3176           printTypeChain (RTYPE (tree), stderr);
3177           fprintf (stderr, "\n");
3178           goto errorTreeReturn;
3179         }
3180       /* if they are both literal then */
3181       /* rewrite the tree */
3182       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3183         {
3184           tree->type = EX_VALUE;
3185           tree->opval.val = valMod (valFromType (LETYPE (tree)),
3186                                     valFromType (RETYPE (tree)));
3187           tree->right = tree->left = NULL;
3188           TETYPE (tree) = getSpec (TTYPE (tree) =
3189                                    tree->opval.val->type);
3190           return tree;
3191         }
3192       LRVAL (tree) = RRVAL (tree) = 1;
3193       TETYPE (tree) = getSpec (TTYPE (tree) =
3194                                computeType (LTYPE (tree),
3195                                             RTYPE (tree),
3196                                             resultType,
3197                                             tree->opval.op));
3198       return tree;
3199
3200       /*------------------------------------------------------------------*/
3201       /*----------------------------*/
3202       /*  address dereference       */
3203       /*----------------------------*/
3204     case '*':                   /* can be unary  : if right is null then unary operation */
3205       if (!tree->right)
3206         {
3207           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3208             {
3209               werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3210               goto errorTreeReturn;
3211             }
3212
3213           if (LRVAL (tree))
3214             {
3215               werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3216               goto errorTreeReturn;
3217             }
3218           if (IS_ADDRESS_OF_OP(tree->left))
3219             {
3220               /* replace *&obj with obj */
3221               return tree->left->left;
3222             }
3223           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3224           TETYPE (tree) = getSpec (TTYPE (tree));
3225           /* adjust the storage class */
3226           switch (DCL_TYPE(tree->left->ftype)) {
3227             case POINTER:
3228               SPEC_SCLS(TETYPE(tree)) = S_DATA;
3229               break;
3230             case FPOINTER:
3231               SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3232               break;
3233             case CPOINTER:
3234               SPEC_SCLS(TETYPE(tree)) = S_CODE;
3235               break;
3236             case GPOINTER:
3237               SPEC_SCLS (TETYPE (tree)) = 0;
3238               break;
3239             case PPOINTER:
3240               SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3241               break;
3242             case IPOINTER:
3243               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3244               break;
3245             case EEPPOINTER:
3246               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3247               break;
3248             case UPOINTER:
3249               SPEC_SCLS (TETYPE (tree)) = 0;
3250               break;
3251             case ARRAY:
3252             case FUNCTION:
3253               break;
3254           }
3255           return tree;
3256         }
3257
3258       /*------------------------------------------------------------------*/
3259       /*----------------------------*/
3260       /*      multiplication        */
3261       /*----------------------------*/
3262       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3263         {
3264           werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3265           goto errorTreeReturn;
3266         }
3267
3268       /* if they are both literal then */
3269       /* rewrite the tree */
3270       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3271         {
3272           tree->type = EX_VALUE;
3273           tree->opval.val = valMult (valFromType (LETYPE (tree)),
3274                                      valFromType (RETYPE (tree)));
3275           tree->right = tree->left = NULL;
3276           TETYPE (tree) = getSpec (TTYPE (tree) =
3277                                    tree->opval.val->type);
3278           return tree;
3279         }
3280
3281       /* if left is a literal exchange left & right */
3282       if (IS_LITERAL (LTYPE (tree)))
3283         {
3284           ast *tTree = tree->left;
3285           tree->left = tree->right;
3286           tree->right = tTree;
3287         }
3288
3289       /* if right is a literal and */
3290       /* we can find a 2nd literal in a mul-tree then */
3291       /* rearrange the tree */
3292       if (IS_LITERAL (RTYPE (tree)))
3293         {
3294           ast *parent;
3295           ast *litTree = searchLitOp (tree, &parent, "*");
3296           if (litTree)
3297             {
3298               DEBUG_CF("mul")
3299               ast *tTree = litTree->left;
3300               litTree->left = tree->right;
3301               tree->right = tTree;
3302               /* both operands in litTree are literal now */
3303               decorateType (parent, resultType);
3304             }
3305         }
3306
3307       LRVAL (tree) = RRVAL (tree) = 1;
3308       tree->left  = addCast (tree->left,  resultTypeProp, FALSE);
3309       tree->right = addCast (tree->right, resultTypeProp, FALSE);
3310       TETYPE (tree) = getSpec (TTYPE (tree) =
3311                                    computeType (LTYPE (tree),
3312                                                 RTYPE (tree),
3313                                                 resultType,
3314                                                 tree->opval.op));
3315
3316       return tree;
3317
3318       /*------------------------------------------------------------------*/
3319       /*----------------------------*/
3320       /*    unary '+' operator      */
3321       /*----------------------------*/
3322     case '+':
3323       /* if unary plus */
3324       if (!tree->right)
3325         {
3326           if (!IS_ARITHMETIC (LTYPE (tree)))
3327             {
3328               werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3329               goto errorTreeReturn;
3330             }
3331
3332           /* if left is a literal then do it */
3333           if (IS_LITERAL (LTYPE (tree)))
3334             {
3335               tree->type = EX_VALUE;
3336               tree->opval.val = valFromType (LETYPE (tree));
3337               tree->left = NULL;
3338               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3339               return tree;
3340             }
3341           LRVAL (tree) = 1;
3342           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3343           return tree;
3344         }
3345
3346       /*------------------------------------------------------------------*/
3347       /*----------------------------*/
3348       /*      addition              */
3349       /*----------------------------*/
3350
3351       /* this is not a unary operation */
3352       /* if both pointers then problem */
3353       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3354           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3355         {
3356           werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3357           goto errorTreeReturn;
3358         }
3359
3360       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3361           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3362         {
3363           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3364           goto errorTreeReturn;
3365         }
3366
3367       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3368           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3369         {
3370           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3371           goto errorTreeReturn;
3372         }
3373       /* if they are both literal then */
3374       /* rewrite the tree */
3375       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3376         {
3377           tree->type = EX_VALUE;
3378           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3379           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3380           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3381                                      valFromType (RETYPE (tree)));
3382           tree->right = tree->left = NULL;
3383           TETYPE (tree) = getSpec (TTYPE (tree) =
3384                                    tree->opval.val->type);
3385           return tree;
3386         }
3387
3388       /* if the right is a pointer or left is a literal
3389          xchange left & right */
3390       if (IS_ARRAY (RTYPE (tree)) ||
3391           IS_PTR (RTYPE (tree)) ||
3392           IS_LITERAL (LTYPE (tree)))
3393         {
3394           ast *tTree = tree->left;
3395           tree->left = tree->right;
3396           tree->right = tTree;
3397         }
3398
3399       /* if right is a literal and */
3400       /* left is also an addition/subtraction with a literal then */
3401       /* rearrange the tree */
3402       if (IS_LITERAL (RTYPE (tree)))
3403         {
3404           ast *litTree, *parent;
3405           litTree = searchLitOp (tree, &parent, "+-");
3406           if (litTree)
3407             {
3408               if (litTree->opval.op == '+')
3409                 {
3410                   /* foo_aa */
3411                   DEBUG_CF("+ 1 AA")
3412                   ast *tTree = litTree->left;
3413                   litTree->left = tree->right;
3414                   tree->right = tree->left;
3415                   tree->left = tTree;
3416                 }
3417               else if (litTree->opval.op == '-')
3418                 {
3419                   if (IS_LITERAL (RTYPE (litTree)))
3420                     {
3421                       DEBUG_CF("+ 2 ASR")
3422                       /* foo_asr */
3423                       ast *tTree = litTree->left;
3424                       litTree->left = tree->right;
3425                       tree->right = tTree;
3426                     }
3427                   else
3428                     {
3429                       DEBUG_CF("+ 3 ASL")
3430                       /* foo_asl */
3431                       ast *tTree = litTree->right;
3432                       litTree->right = tree->right;
3433                       tree->right = tTree;
3434                       litTree->opval.op = '+';
3435                       tree->opval.op = '-';
3436                     }
3437                 }
3438               decorateType (parent, resultType);
3439             }
3440         }
3441
3442       LRVAL (tree) = RRVAL (tree) = 1;
3443       /* if the left is a pointer */
3444       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3445         TETYPE (tree) = getSpec (TTYPE (tree) =
3446                                  LTYPE (tree));
3447       else
3448         {
3449           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3450           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3451           TETYPE (tree) = getSpec (TTYPE (tree) =
3452                                      computeType (LTYPE (tree),
3453                                                   RTYPE (tree),
3454                                                   resultType,
3455                                                   tree->opval.op));
3456         }
3457
3458       return tree;
3459
3460       /*------------------------------------------------------------------*/
3461       /*----------------------------*/
3462       /*      unary '-'             */
3463       /*----------------------------*/
3464     case '-':                   /* can be unary   */
3465       /* if right is null then unary */
3466       if (!tree->right)
3467         {
3468
3469           if (!IS_ARITHMETIC (LTYPE (tree)))
3470             {
3471               werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3472               goto errorTreeReturn;
3473             }
3474
3475           /* if left is a literal then do it */
3476           if (IS_LITERAL (LTYPE (tree)))
3477             {
3478               tree->type = EX_VALUE;
3479               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3480               tree->left = NULL;
3481               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3482               return tree;
3483             }
3484           tree->left  = addCast (tree->left, resultTypeProp, TRUE);
3485           TETYPE (tree) = getSpec (TTYPE (tree) =
3486                                      computeType (LTYPE (tree),
3487                                                   NULL,
3488                                                   resultType,
3489                                                   tree->opval.op));
3490           LRVAL (tree) = 1;
3491           return tree;
3492         }
3493
3494       /*------------------------------------------------------------------*/
3495       /*----------------------------*/
3496       /*    subtraction             */
3497       /*----------------------------*/
3498
3499       if (!(IS_PTR (LTYPE (tree)) ||
3500             IS_ARRAY (LTYPE (tree)) ||
3501             IS_ARITHMETIC (LTYPE (tree))))
3502         {
3503           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3504           goto errorTreeReturn;
3505         }
3506
3507       if (!(IS_PTR (RTYPE (tree)) ||
3508             IS_ARRAY (RTYPE (tree)) ||
3509             IS_ARITHMETIC (RTYPE (tree))))
3510         {
3511           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3512           goto errorTreeReturn;
3513         }
3514
3515       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3516           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3517             IS_INTEGRAL (RTYPE (tree))))
3518         {
3519           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3520           goto errorTreeReturn;
3521         }
3522
3523       /* if they are both literal then */
3524       /* rewrite the tree */
3525       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3526         {
3527           tree->type = EX_VALUE;
3528           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3529           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3530           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3531                                       valFromType (RETYPE (tree)));
3532           tree->right = tree->left = NULL;
3533           TETYPE (tree) = getSpec (TTYPE (tree) =
3534                                    tree->opval.val->type);
3535           return tree;
3536         }
3537
3538       /* if the left & right are equal then zero */
3539       if (isAstEqual (tree->left, tree->right))
3540         {
3541           tree->type = EX_VALUE;
3542           tree->left = tree->right = NULL;
3543           tree->opval.val = constCharVal (0);
3544           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3545           return tree;
3546         }
3547
3548       /* if both of them are pointers or arrays then */
3549       /* the result is going to be an integer        */
3550       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3551           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3552         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3553       else
3554         /* if only the left is a pointer */
3555         /* then result is a pointer      */
3556       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3557         TETYPE (tree) = getSpec (TTYPE (tree) =
3558                                  LTYPE (tree));
3559       else
3560         {
3561           tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
3562           tree->right = addCast (tree->right, resultTypeProp, TRUE);
3563
3564           TETYPE (tree) = getSpec (TTYPE (tree) =
3565                                      computeType (LTYPE (tree),
3566                                                   RTYPE (tree),
3567                                                   resultType,
3568                                                   tree->opval.op));
3569         }
3570
3571       LRVAL (tree) = RRVAL (tree) = 1;
3572
3573       /* if right is a literal and */
3574       /* left is also an addition/subtraction with a literal then */
3575       /* rearrange the tree */
3576       if (IS_LITERAL (RTYPE (tree))
3577           /* avoid infinite loop */
3578           && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3579         {
3580           ast *litTree, *litParent;
3581           litTree = searchLitOp (tree, &litParent, "+-");
3582           if (litTree)
3583             {
3584               if (litTree->opval.op == '+')
3585                 {
3586                   /* foo_sa */
3587                   DEBUG_CF("- 1 SA")
3588                   ast *tTree = litTree->left;
3589                   litTree->left = litTree->right;
3590                   litTree->right = tree->right;
3591                   tree->right = tTree;
3592                   tree->opval.op = '+';
3593                   litTree->opval.op = '-';
3594                 }
3595               else if (litTree->opval.op == '-')
3596                 {
3597                   if (IS_LITERAL (RTYPE (litTree)))
3598                     {
3599                       /* foo_ssr */
3600                       DEBUG_CF("- 2 SSR")
3601                       ast *tTree = litTree->left;
3602                       litTree->left = tree->right;
3603                       tree->right = litParent->left;
3604                       litParent->left = tTree;
3605                       litTree->opval.op = '+';
3606
3607                       tree->decorated = 0;
3608                       decorateType (tree, resultType);
3609                     }
3610                   else
3611                     {
3612                       /* foo_ssl */
3613                       DEBUG_CF("- 3 SSL")
3614                       ast *tTree = litTree->right;
3615                       litTree->right = tree->right;
3616                       tree->right = tTree;
3617                     }
3618                 }
3619               decorateType (litParent, resultType);
3620             }
3621         }
3622       return tree;
3623
3624       /*------------------------------------------------------------------*/
3625       /*----------------------------*/
3626       /*    complement              */
3627       /*----------------------------*/
3628     case '~':
3629       /* can be only integral type */
3630       if (!IS_INTEGRAL (LTYPE (tree)))
3631         {
3632           werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3633           goto errorTreeReturn;
3634         }
3635
3636       /* if left is a literal then do it */
3637       if (IS_LITERAL (LTYPE (tree)))
3638         {
3639           tree->type = EX_VALUE;
3640           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3641           tree->left = NULL;
3642           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3643           return addCast (tree, resultTypeProp, TRUE);
3644         }
3645
3646       if (resultType == RESULT_TYPE_BIT &&
3647           IS_UNSIGNED (tree->left->etype) &&
3648           getSize (tree->left->etype) < INTSIZE)
3649         {
3650           /* promotion rules are responsible for this strange result:
3651              bit -> int -> ~int -> bit
3652              uchar -> int -> ~int -> bit
3653           */
3654           werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3655
3656           /* optimize bit-result, even if we optimize a buggy source */
3657           tree->type = EX_VALUE;
3658           tree->opval.val = constCharVal (1);
3659         }
3660       else
3661         tree->left = addCast (tree->left, resultTypeProp, TRUE);
3662       LRVAL (tree) = 1;
3663       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3664       return tree;
3665
3666       /*------------------------------------------------------------------*/
3667       /*----------------------------*/
3668       /*           not              */
3669       /*----------------------------*/
3670     case '!':
3671       /* can be pointer */
3672       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3673           !IS_PTR (LTYPE (tree)) &&
3674           !IS_ARRAY (LTYPE (tree)))
3675         {
3676           werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3677           goto errorTreeReturn;
3678         }
3679
3680       /* if left is another '!' */
3681       if (IS_AST_NOT_OPER (tree->left))
3682         {
3683           if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3684             {
3685               /* replace double '!!X' by 'X' */
3686               return tree->left->left;
3687             }
3688           /* remove double '!!X' by 'X ? 1 : 0' */
3689           tree->opval.op = '?';
3690           tree->left  = tree->left->left;
3691           tree->right = newNode (':',
3692                                   newAst_VALUE (constCharVal (1)),
3693                                   newAst_VALUE (constCharVal (0)));
3694           tree->right->filename = tree->filename;
3695           tree->right->lineno = tree->lineno;
3696           tree->decorated = 0;
3697           return decorateType (tree, resultType);
3698         }
3699
3700       /* if left is a literal then do it */
3701       if (IS_LITERAL (LTYPE (tree)))
3702         {
3703           tree->type = EX_VALUE;
3704           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3705           tree->left = NULL;
3706           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3707           return tree;
3708         }
3709       LRVAL (tree) = 1;
3710       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3711       return tree;
3712
3713       /*------------------------------------------------------------------*/
3714       /*----------------------------*/
3715       /*           shift            */
3716       /*----------------------------*/
3717     case RRC:
3718     case RLC:
3719     case SWAP:
3720       TTYPE (tree) = LTYPE (tree);
3721       TETYPE (tree) = LETYPE (tree);
3722       return tree;
3723
3724     case GETHBIT:
3725     case GETABIT:
3726       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3727       return tree;
3728
3729     case GETBYTE:
3730       TTYPE (tree) = TETYPE (tree) = newCharLink();
3731       return tree;
3732
3733     case GETWORD:
3734       TTYPE (tree) = TETYPE (tree) = newIntLink();
3735       return tree;
3736
3737     case LEFT_OP:
3738     case RIGHT_OP:
3739       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3740         {
3741           werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3742           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3743           printTypeChain (LTYPE (tree), stderr);
3744           fprintf (stderr, ",");
3745           printTypeChain (RTYPE (tree), stderr);
3746           fprintf (stderr, "\n");
3747           goto errorTreeReturn;
3748         }
3749
3750       /* make smaller type only if it's a LEFT_OP */
3751       if (tree->opval.op == LEFT_OP)
3752         tree->left = addCast (tree->left, resultTypeProp, TRUE);
3753
3754       /* if they are both literal then */
3755       /* rewrite the tree */
3756       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3757         {
3758           tree->type = EX_VALUE;
3759           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3760                                       valFromType (RETYPE (tree)),
3761                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3762           tree->right = tree->left = NULL;
3763           TETYPE (tree) = getSpec (TTYPE (tree) =
3764                                    tree->opval.val->type);
3765           return tree;
3766         }
3767
3768       /* see if this is a GETBYTE operation if yes
3769          then return that */
3770       {
3771         ast *otree = optimizeGetByte (tree, resultType);
3772
3773         if (otree != tree)
3774           return decorateType (otree, RESULT_TYPE_NONE);
3775       }
3776
3777       /* see if this is a GETWORD operation if yes
3778          then return that */
3779       {
3780         ast *otree = optimizeGetWord (tree, resultType);
3781
3782         if (otree != tree)
3783           return decorateType (otree, RESULT_TYPE_NONE);
3784       }
3785
3786       LRVAL (tree) = RRVAL (tree) = 1;
3787       if (tree->opval.op == LEFT_OP)
3788         {
3789           TETYPE (tree) = getSpec (TTYPE (tree) =
3790                                        computeType (LTYPE (tree),
3791                                                     NULL,
3792                                                     resultType,
3793                                                     tree->opval.op));
3794         }
3795       else /* RIGHT_OP */
3796         {
3797           /* no promotion necessary */
3798           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3799           if (IS_LITERAL (TTYPE (tree)))
3800             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3801         }
3802
3803       /* if only the right side is a literal & we are
3804          shifting more than size of the left operand then zero */
3805       if (IS_LITERAL (RTYPE (tree)) &&
3806           ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3807           (getSize (TETYPE (tree)) * 8))
3808         {
3809           if (tree->opval.op==LEFT_OP ||
3810               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3811             {
3812               werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3813                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3814               tree->type = EX_VALUE;
3815               tree->left = tree->right = NULL;
3816               tree->opval.val = constCharVal (0);
3817               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3818               return tree;
3819             }
3820         }
3821
3822       return tree;
3823
3824       /*------------------------------------------------------------------*/
3825       /*----------------------------*/
3826       /*         casting            */
3827       /*----------------------------*/
3828     case CAST:                  /* change the type   */
3829       /* cannot cast to an aggregate type */
3830       if (IS_AGGREGATE (LTYPE (tree)))
3831         {
3832           werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3833           goto errorTreeReturn;
3834         }
3835
3836       /* make sure the type is complete and sane */
3837       changePointer(LTYPE(tree));
3838       checkTypeSanity(LETYPE(tree), "(cast)");
3839
3840
3841       /* if 'from' and 'to' are the same remove the superfluous cast,
3842        * this helps other optimizations */
3843       if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3844         {
3845           /* mark that the explicit cast has been removed,
3846            * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3847           tree->right->values.removedCast = 1;
3848           return tree->right;
3849         }
3850
3851       /* If code memory is read only, then pointers to code memory */
3852       /* implicitly point to constants -- make this explicit       */
3853       {
3854         sym_link *t = LTYPE(tree);
3855         while (t && t->next)
3856           {
3857             if (IS_CODEPTR(t) && port->mem.code_ro)
3858               {
3859                 if (IS_SPEC(t->next))
3860                   SPEC_CONST (t->next) = 1;
3861                 else
3862                   DCL_PTR_CONST (t->next) = 1;
3863               }
3864             t = t->next;
3865           }
3866       }
3867
3868 #if 0
3869       /* if the right is a literal replace the tree */
3870       if (IS_LITERAL (RETYPE (tree))) {
3871               if (!IS_PTR (LTYPE (tree))) {
3872                       tree->type = EX_VALUE;
3873                       tree->opval.val =
3874                               valCastLiteral (LTYPE (tree),
3875                                               floatFromVal (valFromType (RETYPE (tree))));
3876                       tree->left = NULL;
3877                       tree->right = NULL;
3878                       TTYPE (tree) = tree->opval.val->type;
3879                       tree->values.literalFromCast = 1;
3880               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3881                          ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3882                       sym_link *rest = LTYPE(tree)->next;
3883                       werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3884                       TTYPE(tree) = newLink(DECLARATOR);
3885                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3886                       TTYPE(tree)->next = rest;
3887                       tree->left->opval.lnk = TTYPE(tree);
3888                       LRVAL (tree) = 1;
3889               } else {
3890                       TTYPE (tree) = LTYPE (tree);
3891                       LRVAL (tree) = 1;
3892               }
3893       } else {
3894               TTYPE (tree) = LTYPE (tree);
3895               LRVAL (tree) = 1;
3896       }
3897 #else
3898 #if 0 // this is already checked, now this could be explicit
3899       /* if pointer to struct then check names */
3900       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3901           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3902           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3903         {
3904           werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3905                  SPEC_STRUCT(LETYPE(tree))->tag);
3906         }
3907 #endif
3908       if (IS_ADDRESS_OF_OP(tree->right)
3909           && IS_AST_SYM_VALUE (tree->right->left)
3910           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3911
3912         symbol * sym = AST_SYMBOL (tree->right->left);
3913         unsigned int gptype = 0;
3914         unsigned int addr = SPEC_ADDR (sym->etype);
3915
3916         if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3917                                         || TARGET_IS_PIC16) )
3918           {
3919             switch (SPEC_SCLS (sym->etype))
3920               {
3921               case S_CODE:
3922                 gptype = GPTYPE_CODE;
3923                 break;
3924               case S_XDATA:
3925                 gptype = GPTYPE_FAR;
3926                 break;
3927               case S_DATA:
3928               case S_IDATA:
3929                 gptype = GPTYPE_NEAR;
3930                 break;
3931               case S_PDATA:
3932                 gptype = GPTYPE_XSTACK;
3933                 break;
3934               default:
3935                 gptype = 0;
3936
3937                 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3938                     gptype = GPTYPE_NEAR;
3939               }
3940             addr |= gptype << (8*(GPTRSIZE - 1));
3941           }
3942
3943         tree->type = EX_VALUE;
3944         tree->opval.val =
3945           valCastLiteral (LTYPE (tree), addr);
3946         TTYPE (tree) = tree->opval.val->type;
3947         TETYPE (tree) = getSpec (TTYPE (tree));
3948         tree->left = NULL;
3949         tree->right = NULL;
3950         tree->values.literalFromCast = 1;
3951         return tree;
3952       }
3953
3954       /* handle offsetof macro:            */
3955       /* #define offsetof(TYPE, MEMBER) \  */
3956       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3957       if (IS_ADDRESS_OF_OP(tree->right)
3958           && IS_AST_OP (tree->right->left)
3959           && tree->right->left->opval.op == PTR_OP
3960           && IS_AST_OP (tree->right->left->left)
3961           && tree->right->left->left->opval.op == CAST
3962           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3963
3964         symbol *element = getStructElement (
3965           SPEC_STRUCT (LETYPE(tree->right->left)),
3966           AST_SYMBOL(tree->right->left->right)
3967         );
3968
3969         if (element) {
3970           tree->type = EX_VALUE;
3971           tree->opval.val = valCastLiteral (
3972             LTYPE (tree),
3973             element->offset
3974             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3975           );
3976
3977           TTYPE (tree) = tree->opval.val->type;
3978           TETYPE (tree) = getSpec (TTYPE (tree));
3979           tree->left = NULL;
3980           tree->right = NULL;
3981           return tree;
3982         }
3983       }
3984
3985       /* if the right is a literal replace the tree */
3986       if (IS_LITERAL (RETYPE (tree))) {
3987         #if 0
3988         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3989           /* rewrite      (type *)litaddr
3990              as           &temp
3991              and define   type at litaddr temp
3992              (but only if type's storage class is not generic)
3993           */
3994           ast *newTree = newNode ('&', NULL, NULL);
3995           symbol *sym;
3996
3997           TTYPE (newTree) = LTYPE (tree);
3998           TETYPE (newTree) = getSpec(LTYPE (tree));
3999
4000           /* define a global symbol at the casted address*/
4001           sym = newSymbol(genSymName (0), 0);
4002           sym->type = LTYPE (tree)->next;
4003           if (!sym->type)
4004             sym->type = newLink (V_VOID);
4005           sym->etype = getSpec(sym->type);
4006           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4007           sym->lineDef = tree->lineno;
4008           sym->cdef = 1;
4009           sym->isref = 1;
4010           SPEC_STAT (sym->etype) = 1;
4011           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4012           SPEC_ABSA(sym->etype) = 1;
4013           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4014           allocGlobal (sym);
4015
4016           newTree->left = newAst_VALUE(symbolVal(sym));
4017           newTree->left->filename = tree->filename;
4018           newTree->left->lineno = tree->lineno;
4019           LTYPE (newTree) = sym->type;
4020           LETYPE (newTree) = sym->etype;
4021           LLVAL (newTree) = 1;
4022           LRVAL (newTree) = 0;
4023           TLVAL (newTree) = 1;
4024           return newTree;
4025         }
4026         #endif
4027         if (!IS_PTR (LTYPE (tree))) {
4028           tree->type = EX_VALUE;
4029           tree->opval.val =
4030           valCastLiteral (LTYPE (tree),
4031                           floatFromVal (valFromType (RTYPE (tree))));
4032           TTYPE (tree) = tree->opval.val->type;
4033           tree->left = NULL;
4034           tree->right = NULL;
4035           tree->values.literalFromCast = 1;
4036           TETYPE (tree) = getSpec (TTYPE (tree));
4037           return tree;
4038         }
4039       }
4040       TTYPE (tree) = LTYPE (tree);
4041       LRVAL (tree) = 1;
4042
4043 #endif
4044       TETYPE (tree) = getSpec (TTYPE (tree));
4045
4046       return tree;
4047
4048       /*------------------------------------------------------------------*/
4049       /*----------------------------*/
4050       /*       logical &&, ||       */
4051       /*----------------------------*/
4052     case AND_OP:
4053     case OR_OP:
4054       /* each must be arithmetic type or be a pointer */
4055       if (!IS_PTR (LTYPE (tree)) &&
4056           !IS_ARRAY (LTYPE (tree)) &&
4057           !IS_INTEGRAL (LTYPE (tree)))
4058         {
4059           werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4060           goto errorTreeReturn;
4061         }
4062
4063       if (!IS_PTR (RTYPE (tree)) &&
4064           !IS_ARRAY (RTYPE (tree)) &&
4065           !IS_INTEGRAL (RTYPE (tree)))
4066         {
4067           werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4068           goto errorTreeReturn;
4069         }
4070       /* if they are both literal then */
4071       /* rewrite the tree */
4072       if (IS_LITERAL (RTYPE (tree)) &&
4073           IS_LITERAL (LTYPE (tree)))
4074         {
4075           tree->type = EX_VALUE;
4076           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4077                                            valFromType (RTYPE (tree)),
4078                                            tree->opval.op);
4079           tree->right = tree->left = NULL;
4080           TETYPE (tree) = getSpec (TTYPE (tree) =
4081                                    tree->opval.val->type);
4082           return tree;
4083         }
4084       LRVAL (tree) = RRVAL (tree) = 1;
4085       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4086       return tree;
4087
4088       /*------------------------------------------------------------------*/
4089       /*----------------------------*/
4090       /*     comparison operators   */
4091       /*----------------------------*/
4092     case '>':
4093     case '<':
4094     case LE_OP:
4095     case GE_OP:
4096     case EQ_OP:
4097     case NE_OP:
4098       {
4099         ast *lt = optimizeCompare (tree);
4100
4101         if (tree != lt)
4102           return lt;
4103       }
4104
4105       /* if they are pointers they must be castable */
4106       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4107         {
4108           if (tree->opval.op==EQ_OP &&
4109               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4110             // we cannot cast a gptr to a !gptr: switch the leaves
4111             struct ast *s=tree->left;
4112             tree->left=tree->right;
4113             tree->right=s;
4114           }
4115           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4116             {
4117               werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4118               fprintf (stderr, "comparing type ");
4119               printTypeChain (LTYPE (tree), stderr);
4120               fprintf (stderr, "to type ");
4121               printTypeChain (RTYPE (tree), stderr);
4122               fprintf (stderr, "\n");
4123               goto errorTreeReturn;
4124             }
4125         }
4126       /* else they should be promotable to one another */
4127       else
4128         {
4129           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4130                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4131
4132             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4133               {
4134                 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4135                 fprintf (stderr, "comparing type ");
4136                 printTypeChain (LTYPE (tree), stderr);
4137                 fprintf (stderr, "to type ");
4138                 printTypeChain (RTYPE (tree), stderr);
4139                 fprintf (stderr, "\n");
4140                 goto errorTreeReturn;
4141               }
4142         }
4143
4144       {
4145         CCR_RESULT ccr_result = CCR_OK;
4146
4147         /* if left is integral and right is literal
4148            then check constant range */
4149         if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4150           ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4151                                            tree->opval.op, FALSE);
4152         if (ccr_result == CCR_OK &&
4153             IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4154           ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4155                                            tree->opval.op, TRUE);
4156         switch (ccr_result)
4157             {
4158               case CCR_ALWAYS_TRUE:
4159               case CCR_ALWAYS_FALSE:
4160                 if (!options.lessPedantic)
4161                   werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4162                           ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4163                 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4164               case CCR_OK:
4165               default:
4166                 break;
4167             }
4168       }
4169
4170       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4171       if (tree->opval.op == '>' &&
4172           SPEC_USIGN(LETYPE(tree)) &&
4173           IS_LITERAL(RTYPE(tree))  &&
4174           ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4175         {
4176           if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4177             {
4178               /* the parent is an ifx: */
4179               /* if (unsigned value) */
4180               return tree->left;
4181             }
4182
4183           /* (unsigned value) ? 1 : 0 */
4184           tree->opval.op = '?';
4185           tree->right = newNode (':',
4186                                   newAst_VALUE (constCharVal (1)),
4187                                   tree->right); /* val 0 */
4188           tree->right->filename = tree->filename;
4189           tree->right->lineno = tree->lineno;
4190           tree->right->left->filename = tree->filename;
4191           tree->right->left->lineno = tree->lineno;
4192           tree->decorated = 0;
4193           return decorateType (tree, resultType);
4194         }
4195
4196       /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4197       if (IS_LITERAL(RTYPE(tree))  &&
4198           floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4199           tree->opval.op == EQ_OP &&
4200           (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4201         {
4202           tree->opval.op = '!';
4203           tree->right = NULL;
4204           tree->decorated = 0;
4205           return decorateType (tree, resultType);
4206         }
4207
4208       /* if they are both literal then */
4209       /* rewrite the tree */
4210       if (IS_LITERAL (RTYPE (tree)) &&
4211           IS_LITERAL (LTYPE (tree)))
4212         {
4213           tree->type = EX_VALUE;
4214           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4215                                         valFromType (RETYPE (tree)),
4216                                         tree->opval.op);
4217           tree->right = tree->left = NULL;
4218           TETYPE (tree) = getSpec (TTYPE (tree) =
4219                                    tree->opval.val->type);
4220           return tree;
4221         }
4222
4223       /* if one is 'signed char ' and the other one is 'unsigned char' */
4224       /* it's necessary to promote to int */
4225       if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4226           (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4227         {
4228           /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4229              if it's possible to use a 'signed char' */
4230
4231               /* is left a 'unsigned char'? */
4232           if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4233               /* the value range of a 'unsigned char' is 0...255;
4234                  if the actual value is < 128 it can be changed to signed */
4235               (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4236             {
4237               /* now we've got 2 'signed char'! */
4238               SPEC_USIGN (RETYPE (tree)) = 0;
4239             }
4240                    /* same test for the left operand: */
4241           else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4242               (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4243             {
4244               SPEC_USIGN (LETYPE (tree)) = 0;
4245             }
4246           else
4247             {
4248               werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4249               tree->left  = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4250               tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4251             }
4252         }
4253
4254       LRVAL (tree) = RRVAL (tree) = 1;
4255       TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4256
4257       /* condition transformations */
4258       {
4259         unsigned transformedOp = 0;
4260
4261         switch (tree->opval.op)
4262           {
4263             case '<':             /* transform (a < b)  to !(a >= b)  */
4264               if (port->lt_nge)
4265                 transformedOp = GE_OP;
4266               break;
4267             case '>':             /* transform (a > b)  to !(a <= b)  */
4268               if (port->gt_nle)
4269                 transformedOp = LE_OP;
4270               break;
4271             case LE_OP:           /* transform (a <= b) to !(a > b)   */
4272               if (port->le_ngt)
4273                 transformedOp = '>';
4274               break;
4275             case GE_OP:           /* transform (a >= b) to !(a < b)   */
4276               if (port->ge_nlt)
4277                 transformedOp = '<';
4278               break;
4279             case NE_OP:           /* transform (a != b) to !(a == b)   */
4280               if (port->ne_neq)
4281                 transformedOp = EQ_OP;
4282               break;
4283             case EQ_OP:           /* transform (a == b) to !(a != b)   */
4284               if (port->eq_nne)
4285                 transformedOp = NE_OP;
4286               break;
4287             default:
4288               break;
4289           }
4290         if (transformedOp)
4291           {
4292             tree->opval.op = transformedOp;
4293             tree->decorated = 0;
4294             tree = newNode ('!', tree, NULL);
4295             tree->filename = tree->left->filename;
4296             tree->lineno = tree->left->lineno;
4297             return decorateType (tree, resultType);
4298           }
4299       }
4300
4301       return tree;
4302
4303       /*------------------------------------------------------------------*/
4304       /*----------------------------*/
4305       /*             sizeof         */
4306       /*----------------------------*/
4307     case SIZEOF:                /* evaluate wihout code generation */
4308       /* change the type to a integer */
4309       {
4310         int size = getSize (tree->right->ftype);
4311
4312         SNPRINTF(buffer, sizeof(buffer), "%d", size);
4313         if (!size && !IS_VOID(tree->right->ftype))
4314           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4315       }
4316       tree->type = EX_VALUE;
4317       tree->opval.val = constVal (buffer);
4318       tree->right = tree->left = NULL;
4319       TETYPE (tree) = getSpec (TTYPE (tree) =
4320                                tree->opval.val->type);
4321
4322       return tree;
4323
4324       /*------------------------------------------------------------------*/
4325       /*----------------------------*/
4326       /*             typeof         */
4327       /*----------------------------*/
4328     case TYPEOF:
4329         /* return typeof enum value */
4330         tree->type = EX_VALUE;
4331         {
4332             int typeofv = 0;
4333             if (IS_SPEC(tree->right->ftype)) {
4334                 switch (SPEC_NOUN(tree->right->ftype)) {
4335                 case V_INT:
4336                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4337                     else typeofv = TYPEOF_INT;
4338                     break;
4339                 case V_FLOAT:
4340                     typeofv = TYPEOF_FLOAT;
4341                     break;
4342                 case V_FIXED16X16:
4343                     typeofv = TYPEOF_FIXED16X16;
4344                     break;
4345                 case V_CHAR:
4346                     typeofv = TYPEOF_CHAR;
4347                     break;
4348                 case V_VOID:
4349                     typeofv = TYPEOF_VOID;
4350                     break;
4351                 case V_STRUCT:
4352                     typeofv = TYPEOF_STRUCT;
4353                     break;
4354                 case V_BITFIELD:
4355                     typeofv = TYPEOF_BITFIELD;
4356                     break;
4357                 case V_BIT:
4358                     typeofv = TYPEOF_BIT;
4359                     break;
4360                 case V_SBIT:
4361                     typeofv = TYPEOF_SBIT;
4362                     break;
4363                 default:
4364                     break;
4365                 }
4366             } else {
4367                 switch (DCL_TYPE(tree->right->ftype)) {
4368                 case POINTER:
4369                     typeofv = TYPEOF_POINTER;
4370                     break;
4371                 case FPOINTER:
4372                     typeofv = TYPEOF_FPOINTER;
4373                     break;
4374                 case CPOINTER:
4375                     typeofv = TYPEOF_CPOINTER;
4376                     break;
4377                 case GPOINTER:
4378                     typeofv = TYPEOF_GPOINTER;
4379                     break;
4380                 case PPOINTER:
4381                     typeofv = TYPEOF_PPOINTER;
4382                     break;
4383                 case IPOINTER:
4384                     typeofv = TYPEOF_IPOINTER;
4385                     break;
4386                 case ARRAY:
4387                     typeofv = TYPEOF_ARRAY;
4388                     break;
4389                 case FUNCTION:
4390                     typeofv = TYPEOF_FUNCTION;
4391                     break;
4392                 default:
4393                     break;
4394                 }
4395             }
4396             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4397             tree->opval.val = constVal (buffer);
4398             tree->right = tree->left = NULL;
4399             TETYPE (tree) = getSpec (TTYPE (tree) =
4400                                      tree->opval.val->type);
4401         }
4402         return tree;
4403       /*------------------------------------------------------------------*/
4404       /*----------------------------*/
4405       /* conditional operator  '?'  */
4406       /*----------------------------*/
4407     case '?':
4408       /* the type is value of the colon operator (on the right) */
4409       assert (IS_COLON_OP (tree->right));
4410
4411       /* If already known then replace the tree : optimizer will do it
4412          but faster to do it here. If done before decorating tree->right
4413          this can save generating unused const strings. */
4414       if (IS_LITERAL (LTYPE (tree)))
4415         {
4416           if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4417             return decorateType (tree->right->left, resultTypeProp);
4418           else
4419             return decorateType (tree->right->right, resultTypeProp);
4420         }
4421
4422       tree->right = decorateType (tree->right,  resultTypeProp);
4423
4424       if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4425           ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4426         {
4427           double valTrue = AST_FLOAT_VALUE (tree->right->left);
4428           double valFalse = AST_FLOAT_VALUE (tree->right->right);
4429
4430           if ((valTrue != 0) && (valFalse == 0))
4431             {
4432               /* assign cond to result */
4433               tree->left->decorated = 0;
4434               return decorateType (tree->left, resultTypeProp);
4435             }
4436           else if ((valTrue == 0) && (valFalse != 0))
4437             {
4438               /* assign !cond to result */
4439               tree->opval.op = '!';
4440               tree->decorated = 0;
4441               tree->right = NULL;
4442               return decorateType (tree, resultTypeProp);
4443             }
4444           else
4445             {
4446               /* they have the same boolean value, make them equal */
4447               tree->right->left = tree->right->right;
4448             }
4449         }
4450
4451       /* if they are equal then replace the tree */
4452       if (isAstEqual (tree->right->left, tree->right->right))
4453         {
4454           return tree->right->left;
4455         }
4456
4457       TTYPE (tree) = RTYPE (tree);
4458       TETYPE (tree) = getSpec (TTYPE (tree));
4459       return tree;
4460
4461     case ':':
4462       /* if they don't match we have a problem */
4463       if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4464           (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4465         {
4466           werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4467           goto errorTreeReturn;
4468         }
4469
4470       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4471                                   resultType, tree->opval.op);
4472       TETYPE (tree) = getSpec (TTYPE (tree));
4473       return tree;
4474
4475
4476 #if 0 // assignment operators are converted by the parser
4477       /*------------------------------------------------------------------*/
4478       /*----------------------------*/
4479       /*    assignment operators    */
4480       /*----------------------------*/
4481     case MUL_ASSIGN:
4482     case DIV_ASSIGN:
4483       /* for these it must be both must be integral */
4484       if (!IS_ARITHMETIC (LTYPE (tree)) ||
4485           !IS_ARITHMETIC (RTYPE (tree)))
4486         {
4487           werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4488           goto errorTreeReturn;
4489         }
4490       RRVAL (tree) = 1;
4491       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4492
4493       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4494         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4495
4496       if (LRVAL (tree))
4497         {
4498           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4499           goto errorTreeReturn;
4500         }
4501       LLVAL (tree) = 1;
4502
4503       return tree;
4504
4505     case AND_ASSIGN:
4506     case OR_ASSIGN:
4507     case XOR_ASSIGN:
4508     case RIGHT_ASSIGN:
4509     case LEFT_ASSIGN:
4510       /* for these it must be both must be integral */
4511       if (!IS_INTEGRAL (LTYPE (tree)) ||
4512           !IS_INTEGRAL (RTYPE (tree)))
4513         {
4514           werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4515           goto errorTreeReturn;
4516         }
4517       RRVAL (tree) = 1;
4518       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4519
4520       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4521         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4522
4523       if (LRVAL (tree))
4524         {
4525           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4526           goto errorTreeReturn;
4527         }
4528       LLVAL (tree) = 1;
4529
4530       return tree;
4531
4532       /*------------------------------------------------------------------*/
4533       /*----------------------------*/
4534       /*    -= operator             */
4535       /*----------------------------*/
4536     case SUB_ASSIGN:
4537       if (!(IS_PTR (LTYPE (tree)) ||
4538             IS_ARITHMETIC (LTYPE (tree))))
4539         {
4540           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4541           goto errorTreeReturn;
4542         }
4543
4544       if (!(IS_PTR (RTYPE (tree)) ||
4545             IS_ARITHMETIC (RTYPE (tree))))
4546         {
4547           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4548           goto errorTreeReturn;
4549         }
4550       RRVAL (tree) = 1;
4551       TETYPE (tree) = getSpec (TTYPE (tree) =
4552                                computeType (LTYPE (tree),
4553                                             RTYPE (tree),
4554                                             RESULT_TYPE_NOPROM,
4555                                             tree->opval.op));
4556
4557       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4558         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4559
4560       if (LRVAL (tree))
4561         {
4562           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4563           goto errorTreeReturn;
4564         }
4565       LLVAL (tree) = 1;
4566
4567       return tree;
4568
4569       /*------------------------------------------------------------------*/
4570       /*----------------------------*/
4571       /*          += operator       */
4572       /*----------------------------*/
4573     case ADD_ASSIGN:
4574       /* this is not a unary operation */
4575       /* if both pointers then problem */
4576       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4577         {
4578           werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4579           goto errorTreeReturn;
4580         }
4581
4582       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4583         {
4584           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4585           goto errorTreeReturn;
4586         }
4587
4588       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4589         {
4590           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4591           goto errorTreeReturn;
4592         }
4593       RRVAL (tree) = 1;
4594       TETYPE (tree) = getSpec (TTYPE (tree) =
4595                                computeType (LTYPE (tree),
4596                                             RTYPE (tree),
4597                                             RESULT_TYPE_NOPROM,
4598                                             tree->opval.op));
4599
4600       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4601         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4602
4603       if (LRVAL (tree))
4604         {
4605           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4606           goto errorTreeReturn;
4607         }
4608
4609       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4610       tree->opval.op = '=';
4611
4612       return tree;
4613 #endif
4614
4615       /*------------------------------------------------------------------*/
4616       /*----------------------------*/
4617       /*      straight assignemnt   */
4618       /*----------------------------*/
4619     case '=':
4620       /* cannot be an aggregate */
4621       if (IS_AGGREGATE (LTYPE (tree)))
4622         {
4623           werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4624           goto errorTreeReturn;
4625         }
4626
4627       /* they should either match or be castable */
4628       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4629         {
4630           werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4631           printFromToType(RTYPE(tree),LTYPE(tree));
4632         }
4633
4634       /* if the left side of the tree is of type void
4635          then report error */
4636       if (IS_VOID (LTYPE (tree)))
4637         {
4638           werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4639           printFromToType(RTYPE(tree), LTYPE(tree));
4640         }
4641
4642       TETYPE (tree) = getSpec (TTYPE (tree) =
4643                                LTYPE (tree));
4644       RRVAL (tree) = 1;
4645       LLVAL (tree) = 1;
4646       if (!tree->initMode ) {
4647         if (IS_CONSTANT(LTYPE(tree)))
4648           werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4649       }
4650       if (LRVAL (tree))
4651         {
4652           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4653           goto errorTreeReturn;
4654         }
4655
4656       return tree;
4657
4658       /*------------------------------------------------------------------*/
4659       /*----------------------------*/
4660       /*      comma operator        */
4661       /*----------------------------*/
4662     case ',':
4663       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4664       return tree;
4665
4666       /*------------------------------------------------------------------*/
4667       /*----------------------------*/
4668       /*       function call        */
4669       /*----------------------------*/
4670     case CALL:
4671
4672       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4673       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4674         {
4675           if (tree->left->opval.op == '*' && !tree->left->right)
4676             tree->left = tree->left->left;
4677         }
4678
4679       /* require a function or pointer to function */
4680       if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4681         {
4682           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4683           goto errorTreeReturn;
4684         }
4685
4686       /* if there are parms, make sure that
4687          parms are decorate / process / reverse only once */
4688       if (!tree->right ||
4689           !tree->right->decorated)
4690         {
4691           sym_link *functype;
4692           parmNumber = 1;
4693
4694           if (IS_FUNCPTR (LTYPE (tree)))
4695             {
4696               functype = LTYPE (tree)->next;
4697               processFuncPtrArgs (functype);
4698             }
4699           else
4700             functype = LTYPE (tree);
4701
4702           if (processParms (tree->left, FUNC_ARGS(functype),
4703                             &tree->right, &parmNumber, TRUE))
4704             {
4705               goto errorTreeReturn;
4706             }
4707
4708           if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4709              !IFFUNC_ISBUILTIN(functype))
4710             {
4711               reverseParms (tree->right);
4712             }
4713
4714            TTYPE (tree) = functype->next;
4715            TETYPE (tree) = getSpec (TTYPE (tree));
4716         }
4717       return tree;
4718
4719       /*------------------------------------------------------------------*/
4720       /*----------------------------*/
4721       /*     return statement       */
4722       /*----------------------------*/
4723     case RETURN:
4724       if (!tree->right)
4725         goto voidcheck;
4726
4727       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4728         {
4729           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4730           printFromToType (RTYPE(tree), currFunc->type->next);
4731           goto errorTreeReturn;
4732         }
4733
4734       if (IS_VOID (currFunc->type->next)
4735           && tree->right &&
4736           !IS_VOID (RTYPE (tree)))
4737         {
4738           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4739           goto errorTreeReturn;
4740         }
4741
4742       /* if there is going to be a casting required then add it */
4743       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4744         {
4745           tree->right =
4746             decorateType (newNode (CAST,
4747                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4748                                         tree->right),
4749                           RESULT_TYPE_NONE);
4750         }
4751
4752       RRVAL (tree) = 1;
4753       return tree;
4754
4755     voidcheck:
4756
4757       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4758         {
4759           werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4760           goto errorTreeReturn;
4761         }
4762
4763       TTYPE (tree) = TETYPE (tree) = NULL;
4764       return tree;
4765
4766       /*------------------------------------------------------------------*/
4767       /*----------------------------*/
4768       /*     switch statement       */
4769       /*----------------------------*/
4770     case SWITCH:
4771       /* the switch value must be an integer */
4772       if (!IS_INTEGRAL (LTYPE (tree)))
4773         {
4774           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4775           goto errorTreeReturn;
4776         }
4777       LRVAL (tree) = 1;
4778       TTYPE (tree) = TETYPE (tree) = NULL;
4779       return tree;
4780
4781       /*------------------------------------------------------------------*/
4782       /*----------------------------*/
4783       /* ifx Statement              */
4784       /*----------------------------*/
4785     case IFX:
4786       tree->left = backPatchLabels (tree->left,
4787                                     tree->trueLabel,
4788                                     tree->falseLabel);
4789       TTYPE (tree) = TETYPE (tree) = NULL;
4790       return tree;
4791
4792       /*------------------------------------------------------------------*/
4793       /*----------------------------*/
4794       /* for Statement              */
4795       /*----------------------------*/
4796     case FOR:
4797
4798       AST_FOR (tree, initExpr) = decorateType (
4799                   resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4800       AST_FOR (tree, condExpr) = decorateType (
4801                   resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4802       AST_FOR (tree, loopExpr) = decorateType (
4803                   resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4804
4805       /* if the for loop is reversible then
4806          reverse it otherwise do what we normally
4807          do */
4808       {
4809         symbol *sym;
4810         ast *init, *end;
4811
4812         if (isLoopReversible (tree, &sym, &init, &end))
4813           return reverseLoop (tree, sym, init, end);
4814         else
4815           return decorateType (createFor (AST_FOR (tree, trueLabel),
4816                                           AST_FOR (tree, continueLabel),
4817                                           AST_FOR (tree, falseLabel),
4818                                           AST_FOR (tree, condLabel),
4819                                           AST_FOR (tree, initExpr),
4820                                           AST_FOR (tree, condExpr),
4821                                           AST_FOR (tree, loopExpr),
4822                                           tree->left), RESULT_TYPE_NONE);
4823       }
4824     case PARAM:
4825       werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4826               "node PARAM shouldn't be processed here");
4827               /* but in processParams() */
4828       return tree;
4829     default:
4830       TTYPE (tree) = TETYPE (tree) = NULL;
4831       return tree;
4832     }
4833
4834   /* some error found this tree will be killed */
4835 errorTreeReturn:
4836   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4837   tree->opval.op = NULLOP;
4838   tree->isError = 1;
4839
4840   return tree;
4841 }
4842
4843 /*-----------------------------------------------------------------*/
4844 /* sizeofOp - processes size of operation                          */
4845 /*-----------------------------------------------------------------*/
4846 value *
4847 sizeofOp (sym_link * type)
4848 {
4849   char buff[10];
4850   int size;
4851
4852   /* make sure the type is complete and sane */
4853   checkTypeSanity(type, "(sizeof)");
4854
4855   /* get the size and convert it to character  */
4856   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4857   if (!size && !IS_VOID(type))
4858     werror (E_SIZEOF_INCOMPLETE_TYPE);
4859
4860   /* now convert into value  */
4861   return constVal (buff);
4862 }
4863
4864
4865 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4866 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4867 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4868 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4869 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4870 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4871 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4872
4873 /*-----------------------------------------------------------------*/
4874 /* backPatchLabels - change and or not operators to flow control    */
4875 /*-----------------------------------------------------------------*/
4876 static ast *
4877 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4878 {
4879
4880   if (!tree)
4881     return NULL;
4882
4883   /* while-loops insert a label between the IFX and the condition,
4884      therefore look behind the label too */
4885   if (tree->opval.op == LABEL &&
4886       tree->right &&
4887       IS_ANDORNOT (tree->right))
4888     {
4889       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4890       return tree;
4891     }
4892
4893   if (!(IS_ANDORNOT (tree)))
4894     return tree;
4895
4896   /* if this an and */
4897   if (IS_AND (tree))
4898     {
4899       static int localLbl = 0;
4900       symbol *localLabel;
4901
4902       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4903       localLabel = newSymbol (buffer, NestLevel);
4904
4905       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4906
4907       /* if left is already a IFX then just change the if true label in that */
4908       if (!IS_IFX (tree->left))
4909         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4910
4911       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4912       /* right is a IFX then just join */
4913       if (IS_IFX (tree->right))
4914         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4915
4916       tree->right = createLabel (localLabel, tree->right);
4917       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4918
4919       return newNode (NULLOP, tree->left, tree->right);
4920     }
4921
4922   /* if this is an or operation */
4923   if (IS_OR (tree))
4924     {
4925       static int localLbl = 0;
4926       symbol *localLabel;
4927
4928       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4929       localLabel = newSymbol (buffer, NestLevel);
4930
4931       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4932
4933       /* if left is already a IFX then just change the if true label in that */
4934       if (!IS_IFX (tree->left))
4935         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4936
4937       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4938       /* right is a IFX then just join */
4939       if (IS_IFX (tree->right))
4940         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4941
4942       tree->right = createLabel (localLabel, tree->right);
4943       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4944
4945       return newNode (NULLOP, tree->left, tree->right);
4946     }
4947
4948   /* change not */
4949   if (IS_NOT (tree))
4950     {
4951       /* call with exchanged labels */
4952       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4953
4954       /* if left isn't already a IFX */
4955       if (!IS_IFX (tree->left))
4956         {
4957           tree->left = newNode (IFX, tree->left, NULL);
4958           tree->left->trueLabel = falseLabel;
4959           tree->left->falseLabel = trueLabel;
4960         }
4961       return tree->left;
4962      }
4963
4964   if (IS_IFX (tree))
4965     {
4966       tree->trueLabel = trueLabel;
4967       tree->falseLabel = falseLabel;
4968     }
4969
4970   return tree;
4971 }
4972
4973
4974 /*-----------------------------------------------------------------*/
4975 /* createBlock - create expression tree for block                  */
4976 /*-----------------------------------------------------------------*/
4977 ast *
4978 createBlock (symbol * decl, ast * body)
4979 {
4980   ast *ex;
4981
4982   /* if the block has nothing */
4983   if (!body && !decl)
4984     return NULL;
4985
4986   ex = newNode (BLOCK, NULL, body);
4987   ex->values.sym = decl;
4988
4989   ex->level++;
4990   ex->filename = NULL;
4991   ex->lineno = 0;
4992   return ex;
4993 }
4994
4995 /*-----------------------------------------------------------------*/
4996 /* createLabel - creates the expression tree for labels            */
4997 /*-----------------------------------------------------------------*/
4998 ast *
4999 createLabel (symbol * label, ast * stmnt)
5000 {
5001   symbol *csym;
5002   char name[SDCC_NAME_MAX + 1];
5003   ast *rValue;
5004
5005   /* must create fresh symbol if the symbol name  */
5006   /* exists in the symbol table, since there can  */
5007   /* be a variable with the same name as the labl */
5008   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5009       (csym->level == label->level))
5010     label = newSymbol (label->name, label->level);
5011
5012   /* change the name before putting it in add _ */
5013   SNPRINTF(name, sizeof(name), "%s", label->name);
5014
5015   /* put the label in the LabelSymbol table    */
5016   /* but first check if a label of the same    */
5017   /* name exists                               */
5018   if ((csym = findSym (LabelTab, NULL, name)))
5019     werror (E_DUPLICATE_LABEL, label->name);
5020   else
5021     addSym (LabelTab, label, name, label->level, 0, 0);
5022
5023   label->isitmp = 1;
5024   label->islbl = 1;
5025   label->key = labelKey++;
5026   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5027   rValue->filename = NULL;
5028   rValue->lineno = 0;
5029
5030   return rValue;
5031 }
5032
5033 /*-----------------------------------------------------------------*/
5034 /* createCase - generates the parsetree for a case statement       */
5035 /*-----------------------------------------------------------------*/
5036 ast *
5037 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5038 {
5039   char caseLbl[SDCC_NAME_MAX + 1];
5040   ast *rexpr;
5041   value *val;
5042
5043   /* if the switch statement does not exist */
5044   /* then case is out of context            */
5045   if (!swStat)
5046     {
5047       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5048       return NULL;
5049     }
5050
5051   caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5052   /* if not a constant then error  */
5053   if (!IS_LITERAL (caseVal->ftype))
5054     {
5055       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5056       return NULL;
5057     }
5058
5059   /* if not a integer than error */
5060   if (!IS_INTEGRAL (caseVal->ftype))
5061     {
5062       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5063       return NULL;
5064     }
5065
5066   /* find the end of the switch values chain   */
5067   if (!(val = swStat->values.switchVals.swVals))
5068     swStat->values.switchVals.swVals = caseVal->opval.val;
5069   else
5070     {
5071       /* also order the cases according to value */
5072       value *pval = NULL;
5073       int cVal = (int) ulFromVal (caseVal->opval.val);
5074       while (val && (int) ulFromVal (val) < cVal)
5075         {
5076           pval = val;
5077           val = val->next;
5078         }
5079
5080       /* if we reached the end then */
5081       if (!val)
5082         {
5083           pval->next = caseVal->opval.val;
5084         }
5085       else if ((int) ulFromVal (val) == cVal)
5086         {
5087           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5088                     "case");
5089           return NULL;
5090         }
5091       else
5092         {
5093           /* we found a value greater than */
5094           /* the current value we must add this */
5095           /* before the value */
5096           caseVal->opval.val->next = val;
5097
5098           /* if this was the first in chain */
5099           if (swStat->values.switchVals.swVals == val)
5100             swStat->values.switchVals.swVals =
5101               caseVal->opval.val;
5102           else
5103             pval->next = caseVal->opval.val;
5104         }
5105
5106     }
5107
5108   /* create the case label   */
5109   SNPRINTF(caseLbl, sizeof(caseLbl),
5110            "_case_%d_%d",
5111            swStat->values.switchVals.swNum,
5112            (int) ulFromVal (caseVal->opval.val));
5113
5114   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5115   rexpr->filename = 0;
5116   rexpr->lineno = 0;
5117   return rexpr;
5118 }
5119
5120 /*-----------------------------------------------------------------*/
5121 /* createDefault - creates the parse tree for the default statement */
5122 /*-----------------------------------------------------------------*/
5123 ast *
5124 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5125 {
5126   char defLbl[SDCC_NAME_MAX + 1];
5127
5128   /* if the switch statement does not exist */
5129   /* then case is out of context            */
5130   if (!swStat)
5131     {
5132       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5133       return NULL;
5134     }
5135
5136   if (swStat->values.switchVals.swDefault)
5137     {
5138       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5139                 "default");
5140       return NULL;
5141     }
5142
5143   /* turn on the default flag   */
5144   swStat->values.switchVals.swDefault = 1;
5145
5146   /* create the label  */
5147   SNPRINTF (defLbl, sizeof(defLbl),
5148             "_default_%d", swStat->values.switchVals.swNum);
5149   return createLabel (newSymbol (defLbl, 0), stmnt);
5150 }
5151
5152 /*-----------------------------------------------------------------*/
5153 /* createIf - creates the parsetree for the if statement           */
5154 /*-----------------------------------------------------------------*/
5155 ast *
5156 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5157 {
5158   static int Lblnum = 0;
5159   ast *ifTree;
5160   symbol *ifTrue, *ifFalse, *ifEnd;
5161
5162   /* if neither exists */
5163   if (!elseBody && !ifBody) {
5164     // if there are no side effects (i++, j() etc)
5165     if (!hasSEFcalls(condAst)) {
5166       return condAst;
5167     }
5168   }
5169
5170   /* create the labels */
5171   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5172   ifFalse = newSymbol (buffer, NestLevel);
5173   /* if no else body then end == false */
5174   if (!elseBody)
5175     ifEnd = ifFalse;
5176   else
5177     {
5178       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5179       ifEnd = newSymbol (buffer, NestLevel);
5180     }
5181
5182   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5183   ifTrue = newSymbol (buffer, NestLevel);
5184
5185   Lblnum++;
5186
5187   /* attach the ifTrue label to the top of it body */
5188   ifBody = createLabel (ifTrue, ifBody);
5189   /* attach a goto end to the ifBody if else is present */
5190   if (elseBody)
5191     {
5192       ifBody = newNode (NULLOP, ifBody,
5193                         newNode (GOTO,
5194                                  newAst_VALUE (symbolVal (ifEnd)),
5195                                  NULL));
5196       /* put the elseLabel on the else body */
5197       elseBody = createLabel (ifFalse, elseBody);
5198       /* out the end at the end of the body */
5199       elseBody = newNode (NULLOP,
5200                           elseBody,
5201                           createLabel (ifEnd, NULL));
5202     }
5203   else
5204     {
5205       ifBody = newNode (NULLOP, ifBody,
5206                         createLabel (ifFalse, NULL));
5207     }
5208   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5209   if (IS_IFX (condAst))
5210     ifTree = condAst;
5211   else
5212     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5213
5214   return newNode (NULLOP, ifTree,
5215                   newNode (NULLOP, ifBody, elseBody));
5216
5217 }
5218
5219 /*-----------------------------------------------------------------*/
5220 /* createDo - creates parse tree for do                            */
5221 /*        _dobody_n:                                               */
5222 /*            statements                                           */
5223 /*        _docontinue_n:                                           */
5224 /*            condition_expression +-> trueLabel -> _dobody_n      */
5225 /*                                 |                               */
5226 /*                                 +-> falseLabel-> _dobreak_n     */
5227 /*        _dobreak_n:                                              */
5228 /*-----------------------------------------------------------------*/
5229 ast *
5230 createDo (symbol * trueLabel, symbol * continueLabel,
5231           symbol * falseLabel, ast * condAst, ast * doBody)
5232 {
5233   ast *doTree;
5234
5235
5236   /* if the body does not exist then it is simple */
5237   if (!doBody)
5238     {
5239       condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5240       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5241                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5242       doTree->trueLabel = continueLabel;
5243       doTree->falseLabel = NULL;
5244
5245       doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5246       return doTree;
5247     }
5248
5249   /* otherwise we have a body */
5250   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5251
5252   /* attach the body label to the top */
5253   doBody = createLabel (trueLabel, doBody);
5254   /* attach the continue label to end of body */
5255   doBody = newNode (NULLOP, doBody,
5256                     createLabel (continueLabel, NULL));
5257
5258   /* now put the break label at the end */
5259   if (IS_IFX (condAst))
5260     doTree = condAst;
5261   else
5262     doTree = newIfxNode (condAst, trueLabel, falseLabel);
5263
5264   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5265
5266   /* putting it together */
5267   return newNode (NULLOP, doBody, doTree);
5268 }
5269
5270 /*-----------------------------------------------------------------*/
5271 /* createFor - creates parse tree for 'for' statement              */
5272 /*        initExpr                                                 */
5273 /*   _forcond_n:                                                   */
5274 /*        condExpr  +-> trueLabel -> _forbody_n                    */
5275 /*                  |                                              */
5276 /*                  +-> falseLabel-> _forbreak_n                   */
5277 /*   _forbody_n:                                                   */
5278 /*        statements                                               */
5279 /*   _forcontinue_n:                                               */
5280 /*        loopExpr                                                 */
5281 /*        goto _forcond_n ;                                        */
5282 /*   _forbreak_n:                                                  */
5283 /*-----------------------------------------------------------------*/
5284 ast *
5285 createFor (symbol * trueLabel, symbol * continueLabel,
5286            symbol * falseLabel, symbol * condLabel,
5287            ast * initExpr, ast * condExpr, ast * loopExpr,
5288            ast * forBody)
5289 {
5290   ast *forTree;
5291
5292   /* if loopexpression not present then we can generate it */
5293   /* the same way as a while */
5294   if (!loopExpr)
5295     return newNode (NULLOP, initExpr,
5296                     createWhile (trueLabel, continueLabel,
5297                                  falseLabel, condExpr, forBody));
5298   /* vanilla for statement */
5299   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5300
5301   if (condExpr && !IS_IFX (condExpr))
5302     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5303
5304
5305   /* attach condition label to condition */
5306   condExpr = createLabel (condLabel, condExpr);
5307
5308   /* attach body label to body */
5309   forBody = createLabel (trueLabel, forBody);
5310
5311   /* attach continue to forLoop expression & attach */
5312   /* goto the forcond @ and of loopExpression       */
5313   loopExpr = createLabel (continueLabel,
5314                           newNode (NULLOP,
5315                                    loopExpr,
5316                                    newNode (GOTO,
5317                                        newAst_VALUE (symbolVal (condLabel)),
5318                                             NULL)));
5319   /* now start putting them together */
5320   forTree = newNode (NULLOP, initExpr, condExpr);
5321   forTree = newNode (NULLOP, forTree, forBody);
5322   forTree = newNode (NULLOP, forTree, loopExpr);
5323   /* finally add the break label */
5324   forTree = newNode (NULLOP, forTree,
5325                      createLabel (falseLabel, NULL));
5326   return forTree;
5327 }
5328
5329 /*-----------------------------------------------------------------*/
5330 /* createWhile - creates parse tree for while statement            */
5331 /*               the while statement will be created as follows    */
5332 /*                                                                 */
5333 /*      _while_continue_n:                                         */
5334 /*            condition_expression +-> trueLabel -> _while_boby_n  */
5335 /*                                 |                               */
5336 /*                                 +-> falseLabel -> _while_break_n */
5337 /*      _while_body_n:                                             */
5338 /*            statements                                           */
5339 /*            goto _while_continue_n                               */
5340 /*      _while_break_n:                                            */
5341 /*-----------------------------------------------------------------*/
5342 ast *
5343 createWhile (symbol * trueLabel, symbol * continueLabel,
5344              symbol * falseLabel, ast * condExpr, ast * whileBody)
5345 {
5346   ast *whileTree;
5347
5348   /* put the continue label */
5349   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5350   condExpr = createLabel (continueLabel, condExpr);
5351   condExpr->filename = NULL;
5352   condExpr->lineno = 0;
5353
5354   /* put the body label in front of the body */
5355   whileBody = createLabel (trueLabel, whileBody);
5356   whileBody->filename = NULL;
5357   whileBody->lineno = 0;
5358   /* put a jump to continue at the end of the body */
5359   /* and put break label at the end of the body */
5360   whileBody = newNode (NULLOP,
5361                        whileBody,
5362                        newNode (GOTO,
5363                                 newAst_VALUE (symbolVal (continueLabel)),
5364                                 createLabel (falseLabel, NULL)));
5365
5366   /* put it all together */
5367   if (IS_IFX (condExpr))
5368     whileTree = condExpr;
5369   else
5370     {
5371       whileTree = newNode (IFX, condExpr, NULL);
5372       /* put the true & false labels in place */
5373       whileTree->trueLabel = trueLabel;
5374       whileTree->falseLabel = falseLabel;
5375     }
5376
5377   return newNode (NULLOP, whileTree, whileBody);
5378 }
5379
5380 /*-----------------------------------------------------------------*/
5381 /* isShiftRightLitVal _BitAndLitVal - helper function              */
5382 /*-----------------------------------------------------------------*/
5383 static ast *
5384 isShiftRightLitVal_BitAndLitVal (ast * tree)
5385 {
5386   /* if this is not a bit and */
5387   if (!IS_BITAND (tree))
5388     return NULL;
5389
5390   /* will look for tree of the form
5391      ( expr >> litval2) & litval1 */
5392   if (!IS_AST_LIT_VALUE (tree->right))
5393     return NULL;
5394
5395   if (!IS_RIGHT_OP (tree->left))
5396     return NULL;
5397
5398   if (!IS_AST_LIT_VALUE (tree->left->right))
5399     return NULL;
5400
5401   return tree->left->left;
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* isBitAndPowOf2 - helper function                                */
5406 /*-----------------------------------------------------------------*/
5407 static int
5408 isBitAndPow2 (ast * tree)
5409 {
5410   /* if this is not a bit and */
5411   if (!IS_BITAND (tree))
5412     return -1;
5413
5414   /* will look for tree of the form
5415      ( expr & (1 << litval) */
5416   if (!IS_AST_LIT_VALUE (tree->right))
5417     return -1;
5418
5419   return powof2 (AST_ULONG_VALUE (tree->right));
5420 }
5421
5422 /*-----------------------------------------------------------------*/
5423 /* optimizeGetHbit - get highest order bit of the expression       */
5424 /*-----------------------------------------------------------------*/
5425 ast *
5426 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5427 {
5428   unsigned int i, j;
5429   ast * expr;
5430
5431   expr = isShiftRightLitVal_BitAndLitVal(tree);
5432   if (expr)
5433     {
5434       if ((AST_ULONG_VALUE (tree->right) != 1) ||
5435           ((i = AST_ULONG_VALUE (tree->left->right)) !=
5436           (j = (getSize (TTYPE (expr)) * 8 - 1))))
5437         expr = NULL;
5438     }
5439   if (!expr && (resultType == RESULT_TYPE_BIT))
5440     {
5441       expr = tree->left;
5442       if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5443         expr = NULL;
5444     }
5445   if (!expr)
5446     return tree;
5447
5448   /* make sure the port supports GETHBIT */
5449   if (port->hasExtBitOp
5450       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5451     return tree;
5452
5453   return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5454 }
5455
5456 /*-----------------------------------------------------------------*/
5457 /* optimizeGetAbit - get a single bit of the expression            */
5458 /*-----------------------------------------------------------------*/
5459 ast *
5460 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5461 {
5462   ast * expr;
5463   ast * count = NULL;
5464
5465   expr = isShiftRightLitVal_BitAndLitVal(tree);
5466   if (expr)
5467     {
5468   if (AST_ULONG_VALUE (tree->right) != 1)
5469         expr = NULL;
5470       count = tree->left->right;
5471     }
5472   if (!expr && (resultType == RESULT_TYPE_BIT))
5473     {
5474       int p2 = isBitAndPow2 (tree);
5475       if (p2 >= 0)
5476         {
5477           expr = tree->left;
5478           count = newAst_VALUE (valueFromLit (p2));
5479         }
5480     }
5481   if (!expr)
5482     return tree;
5483
5484   /* make sure the port supports GETABIT */
5485   if (port->hasExtBitOp
5486       && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5487     return tree;
5488
5489   return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5490
5491 }
5492
5493 /*-----------------------------------------------------------------*/
5494 /* optimizeGetByte - get a byte of the expression                  */
5495 /*-----------------------------------------------------------------*/
5496 ast *
5497 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5498 {
5499   unsigned int i = 0;
5500   ast * expr;
5501   ast * count = NULL;
5502
5503   expr = isShiftRightLitVal_BitAndLitVal(tree);
5504   if (expr)
5505     {
5506       i = AST_ULONG_VALUE (tree->left->right);
5507       count = tree->left->right;
5508       if (AST_ULONG_VALUE (tree->right) != 0xFF)
5509         expr = NULL;
5510     }
5511   if (!expr && resultType == RESULT_TYPE_CHAR)
5512     {
5513       /* if this is a right shift over a multiple of 8 */
5514       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5515         {
5516           i = AST_ULONG_VALUE (tree->right);
5517           count = tree->right;
5518             expr = tree->left;
5519         }
5520     }
5521   if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5522     return tree;
5523
5524   /* make sure the port supports GETBYTE */
5525   if (port->hasExtBitOp
5526       && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5527     return tree;
5528
5529   return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5530 }
5531
5532 /*-----------------------------------------------------------------*/
5533 /* optimizeGetWord - get two bytes of the expression               */
5534 /*-----------------------------------------------------------------*/
5535 ast *
5536 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5537 {
5538   unsigned int i = 0;
5539   ast * expr;
5540   ast * count = NULL;
5541
5542   expr = isShiftRightLitVal_BitAndLitVal(tree);
5543   if (expr)
5544     {
5545       i = AST_ULONG_VALUE (tree->left->right);
5546       count = tree->left->right;
5547       if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5548         expr = NULL;
5549     }
5550   if (!expr && resultType == RESULT_TYPE_INT)
5551     {
5552       /* if this is a right shift over a multiple of 8 */
5553       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5554         {
5555           i = AST_ULONG_VALUE (tree->right);
5556           count = tree->right;
5557             expr = tree->left;
5558         }
5559     }
5560   if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5561     return tree;
5562
5563   /* make sure the port supports GETWORD */
5564   if (port->hasExtBitOp
5565       && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5566     return tree;
5567
5568   return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5569 }
5570
5571 /*-----------------------------------------------------------------*/
5572 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
5573 /*-----------------------------------------------------------------*/
5574 ast *
5575 optimizeRRCRLC (ast * root)
5576 {
5577   /* will look for trees of the form
5578      (?expr << 1) | (?expr >> 7) or
5579      (?expr >> 7) | (?expr << 1) will make that
5580      into a RLC : operation ..
5581      Will also look for
5582      (?expr >> 1) | (?expr << 7) or
5583      (?expr << 7) | (?expr >> 1) will make that
5584      into a RRC operation
5585      note : by 7 I mean (number of bits required to hold the
5586      variable -1 ) */
5587   /* if the root operation is not a | operation then not */
5588   if (!IS_BITOR (root))
5589     return root;
5590
5591   /* I have to think of a better way to match patterns this sucks */
5592   /* that aside let's start looking for the first case : I use a
5593      negative check a lot to improve the efficiency */
5594   /* (?expr << 1) | (?expr >> 7) */
5595   if (IS_LEFT_OP (root->left) &&
5596       IS_RIGHT_OP (root->right))
5597     {
5598
5599       if (!SPEC_USIGN (TETYPE (root->left->left)))
5600         return root;
5601
5602       if (!IS_AST_LIT_VALUE (root->left->right) ||
5603           !IS_AST_LIT_VALUE (root->right->right))
5604         goto tryNext0;
5605
5606       /* make sure it is the same expression */
5607       if (!isAstEqual (root->left->left,
5608                        root->right->left))
5609         goto tryNext0;
5610
5611       if (AST_ULONG_VALUE (root->left->right) != 1)
5612         goto tryNext0;
5613
5614       if (AST_ULONG_VALUE (root->right->right) !=
5615           (getSize (TTYPE (root->left->left)) * 8 - 1))
5616         goto tryNext0;
5617
5618       /* make sure the port supports RLC */
5619       if (port->hasExtBitOp
5620           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5621         return root;
5622
5623       /* whew got the first case : create the AST */
5624       return newNode (RLC, root->left->left, NULL);
5625     }
5626
5627 tryNext0:
5628   /* check for second case */
5629   /* (?expr >> 7) | (?expr << 1) */
5630   if (IS_LEFT_OP (root->right) &&
5631       IS_RIGHT_OP (root->left))
5632     {
5633
5634       if (!SPEC_USIGN (TETYPE (root->left->left)))
5635         return root;
5636
5637       if (!IS_AST_LIT_VALUE (root->left->right) ||
5638           !IS_AST_LIT_VALUE (root->right->right))
5639         goto tryNext1;
5640
5641       /* make sure it is the same symbol */
5642       if (!isAstEqual (root->left->left,
5643                        root->right->left))
5644         goto tryNext1;
5645
5646       if (AST_ULONG_VALUE (root->right->right) != 1)
5647         goto tryNext1;
5648
5649       if (AST_ULONG_VALUE (root->left->right) !=
5650           (getSize (TTYPE (root->left->left)) * 8 - 1))
5651         goto tryNext1;
5652
5653       /* make sure the port supports RLC */
5654       if (port->hasExtBitOp
5655           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5656         return root;
5657
5658       /* whew got the first case : create the AST */
5659       return newNode (RLC, root->left->left, NULL);
5660
5661     }
5662
5663 tryNext1:
5664   /* third case for RRC */
5665   /*  (?symbol >> 1) | (?symbol << 7) */
5666   if (IS_LEFT_OP (root->right) &&
5667       IS_RIGHT_OP (root->left))
5668     {
5669
5670       if (!SPEC_USIGN (TETYPE (root->left->left)))
5671         return root;
5672
5673       if (!IS_AST_LIT_VALUE (root->left->right) ||
5674           !IS_AST_LIT_VALUE (root->right->right))
5675         goto tryNext2;
5676
5677       /* make sure it is the same symbol */
5678       if (!isAstEqual (root->left->left,
5679                        root->right->left))
5680         goto tryNext2;
5681
5682       if (AST_ULONG_VALUE (root->left->right) != 1)
5683         goto tryNext2;
5684
5685       if (AST_ULONG_VALUE (root->right->right) !=
5686           (getSize (TTYPE (root->left->left)) * 8 - 1))
5687         goto tryNext2;
5688
5689       /* make sure the port supports RRC */
5690       if (port->hasExtBitOp
5691           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5692         return root;
5693
5694       /* whew got the first case : create the AST */
5695       return newNode (RRC, root->left->left, NULL);
5696
5697     }
5698 tryNext2:
5699   /* fourth and last case for now */
5700   /* (?symbol << 7) | (?symbol >> 1) */
5701   if (IS_RIGHT_OP (root->right) &&
5702       IS_LEFT_OP (root->left))
5703     {
5704
5705       if (!SPEC_USIGN (TETYPE (root->left->left)))
5706         return root;
5707
5708       if (!IS_AST_LIT_VALUE (root->left->right) ||
5709           !IS_AST_LIT_VALUE (root->right->right))
5710         return root;
5711
5712       /* make sure it is the same symbol */
5713       if (!isAstEqual (root->left->left,
5714                        root->right->left))
5715         return root;
5716
5717       if (AST_ULONG_VALUE (root->right->right) != 1)
5718         return root;
5719
5720       if (AST_ULONG_VALUE (root->left->right) !=
5721           (getSize (TTYPE (root->left->left)) * 8 - 1))
5722         return root;
5723
5724       /* make sure the port supports RRC */
5725       if (port->hasExtBitOp
5726           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5727         return root;
5728
5729       /* whew got the first case : create the AST */
5730       return newNode (RRC, root->left->left, NULL);
5731
5732     }
5733
5734   /* not found return root */
5735   return root;
5736 }
5737
5738 /*-----------------------------------------------------------------*/
5739 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5740 /*-----------------------------------------------------------------*/
5741 ast *
5742 optimizeSWAP (ast * root)
5743 {
5744   /* will look for trees of the form
5745      (?expr << 4) | (?expr >> 4) or
5746      (?expr >> 4) | (?expr << 4) will make that
5747      into a SWAP : operation ..
5748      note : by 4 I mean (number of bits required to hold the
5749      variable /2 ) */
5750   /* if the root operation is not a | operation then not */
5751   if (!IS_BITOR (root))
5752     return root;
5753
5754   /* (?expr << 4) | (?expr >> 4) */
5755   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5756       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5757     {
5758
5759       if (!SPEC_USIGN (TETYPE (root->left->left)))
5760         return root;
5761
5762       if (!IS_AST_LIT_VALUE (root->left->right) ||
5763           !IS_AST_LIT_VALUE (root->right->right))
5764         return root;
5765
5766       /* make sure it is the same expression */
5767       if (!isAstEqual (root->left->left,
5768                        root->right->left))
5769         return root;
5770
5771       if (AST_ULONG_VALUE (root->left->right) !=
5772           (getSize (TTYPE (root->left->left)) * 4))
5773         return root;
5774
5775       if (AST_ULONG_VALUE (root->right->right) !=
5776           (getSize (TTYPE (root->left->left)) * 4))
5777         return root;
5778
5779       /* make sure the port supports SWAP */
5780       if (port->hasExtBitOp
5781           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5782         return root;
5783
5784       /* found it : create the AST */
5785       return newNode (SWAP, root->left->left, NULL);
5786     }
5787
5788
5789   /* not found return root */
5790   return root;
5791 }
5792
5793 /*-----------------------------------------------------------------*/
5794 /* optimizeCompare - optimizes compares for bit variables          */
5795 /*-----------------------------------------------------------------*/
5796 static ast *
5797 optimizeCompare (ast * root)
5798 {
5799   ast *optExpr = NULL;
5800   value *vleft;
5801   value *vright;
5802   unsigned int litValue;
5803
5804   /* if nothing then return nothing */
5805   if (!root)
5806     return NULL;
5807
5808   /* if not a compare op then do leaves */
5809   if (!IS_COMPARE_OP (root))
5810     {
5811       root->left = optimizeCompare (root->left);
5812       root->right = optimizeCompare (root->right);
5813       return root;
5814     }
5815
5816   /* if left & right are the same then depending
5817      of the operation do */
5818   if (isAstEqual (root->left, root->right))
5819     {
5820       switch (root->opval.op)
5821         {
5822         case '>':
5823         case '<':
5824         case NE_OP:
5825           optExpr = newAst_VALUE (constCharVal (0));
5826           break;
5827         case GE_OP:
5828         case LE_OP:
5829         case EQ_OP:
5830           optExpr = newAst_VALUE (constCharVal (1));
5831           break;
5832         }
5833
5834       return decorateType (optExpr, RESULT_TYPE_NONE);
5835     }
5836
5837   vleft = (root->left->type == EX_VALUE ?
5838            root->left->opval.val : NULL);
5839
5840   vright = (root->right->type == EX_VALUE ?
5841             root->right->opval.val : NULL);
5842
5843   /* if left is a BITVAR in BITSPACE */
5844   /* and right is a LITERAL then     */
5845   /* optimize else do nothing        */
5846   if (vleft && vright &&
5847       IS_BITVAR (vleft->etype) &&
5848       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5849       IS_LITERAL (vright->etype))
5850     {
5851
5852       /* if right side > 1 then comparison may never succeed */
5853       if ((litValue = (int) ulFromVal (vright)) > 1)
5854         {
5855           werror (W_BAD_COMPARE);
5856           goto noOptimize;
5857         }
5858
5859       if (litValue)
5860         {
5861           switch (root->opval.op)
5862             {
5863             case '>':           /* bit value greater than 1 cannot be */
5864               werror (W_BAD_COMPARE);
5865               goto noOptimize;
5866               break;
5867
5868             case '<':           /* bit value < 1 means 0 */
5869             case NE_OP:
5870               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5871               break;
5872
5873             case LE_OP: /* bit value <= 1 means no check */
5874               optExpr = newAst_VALUE (vright);
5875               break;
5876
5877             case GE_OP: /* bit value >= 1 means only check for = */
5878             case EQ_OP:
5879               optExpr = newAst_VALUE (vleft);
5880               break;
5881             }
5882         }
5883       else
5884         {                       /* literal is zero */
5885           switch (root->opval.op)
5886             {
5887             case '<':           /* bit value < 0 cannot be */
5888               werror (W_BAD_COMPARE);
5889               goto noOptimize;
5890               break;
5891
5892             case '>':           /* bit value > 0 means 1 */
5893             case NE_OP:
5894               optExpr = newAst_VALUE (vleft);
5895               break;
5896
5897             case LE_OP: /* bit value <= 0 means no check */
5898             case GE_OP: /* bit value >= 0 means no check */
5899               werror (W_BAD_COMPARE);
5900               goto noOptimize;
5901               break;
5902
5903             case EQ_OP: /* bit == 0 means ! of bit */
5904               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5905               break;
5906             }
5907         }
5908       return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5909     }                           /* end-of-if of BITVAR */
5910
5911 noOptimize:
5912   return root;
5913 }
5914
5915 /*-----------------------------------------------------------------*/
5916 /* addSymToBlock : adds the symbol to the first block we find      */
5917 /*-----------------------------------------------------------------*/
5918 void
5919 addSymToBlock (symbol * sym, ast * tree)
5920 {
5921   /* reached end of tree or a leaf */
5922   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5923     return;
5924
5925   /* found a block */
5926   if (IS_AST_OP (tree) &&
5927       tree->opval.op == BLOCK)
5928     {
5929
5930       symbol *lsym = copySymbol (sym);
5931
5932       lsym->next = AST_VALUES (tree, sym);
5933       AST_VALUES (tree, sym) = lsym;
5934       return;
5935     }
5936
5937   addSymToBlock (sym, tree->left);
5938   addSymToBlock (sym, tree->right);
5939 }
5940
5941 /*-----------------------------------------------------------------*/
5942 /* processRegParms - do processing for register parameters         */
5943 /*-----------------------------------------------------------------*/
5944 static void
5945 processRegParms (value * args, ast * body)
5946 {
5947   while (args)
5948     {
5949       if (IS_REGPARM (args->etype))
5950         addSymToBlock (args->sym, body);
5951       args = args->next;
5952     }
5953 }
5954
5955 /*-----------------------------------------------------------------*/
5956 /* resetParmKey - resets the operandkeys for the symbols           */
5957 /*-----------------------------------------------------------------*/
5958 DEFSETFUNC (resetParmKey)
5959 {
5960   symbol *sym = item;
5961
5962   sym->key = 0;
5963   sym->defs = NULL;
5964   sym->uses = NULL;
5965   sym->remat = 0;
5966   return 1;
5967 }
5968
5969
5970
5971 /*------------------------------------------------------------------*/
5972 /* fixupInlineLabel - change a label in an inlined function so that */
5973 /*                    it is always unique no matter how many times  */
5974 /*                    the function is inlined.                      */
5975 /*------------------------------------------------------------------*/
5976 static void
5977 fixupInlineLabel (symbol * sym)
5978 {
5979   char name[SDCC_NAME_MAX + 1];
5980
5981   SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5982   strcpy (sym->name, name);
5983 }
5984
5985
5986 /*------------------------------------------------------------------*/
5987 /* copyAstLoc - copy location information (file, line, block, etc.) */
5988 /*              from one ast node to another                        */
5989 /*------------------------------------------------------------------*/
5990 static void
5991 copyAstLoc (ast * dest, ast * src)
5992 {
5993   dest->filename = src->filename;
5994   dest->lineno = src->lineno;
5995   dest->level = src->level;
5996   dest->block = src->block;
5997   dest->seqPoint = src->seqPoint;
5998
5999 }
6000
6001
6002 /*-----------------------------------------------------------------*/
6003 /* fixupInline - perform various fixups on an inline function tree */
6004 /*               to take into account that it is no longer a       */
6005 /*               stand-alone function.                             */
6006 /*-----------------------------------------------------------------*/
6007 static void
6008 fixupInline (ast * tree, int level)
6009 {
6010   tree->block = currBlockno;
6011
6012   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6013     {
6014       symbol * decls;
6015
6016       currBlockno++;
6017       level++;
6018
6019       /* Add any declared variables back into the symbol table */
6020       decls = tree->values.sym;
6021       while (decls)
6022         {
6023           decls->level = level;
6024           decls->block = currBlockno;
6025           addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6026           decls = decls->next;
6027         }
6028     }
6029
6030   tree->level = level;
6031
6032   /* Update symbols */
6033   if (IS_AST_VALUE (tree) &&
6034       tree->opval.val->sym)
6035     {
6036       symbol * sym = tree->opval.val->sym;
6037
6038       sym->level = level;
6039       sym->block = currBlockno;
6040
6041       sym->reqv = NULL;
6042       SYM_SPIL_LOC (sym) = NULL;
6043       sym->key = 0;
6044
6045       /* If the symbol is a label, we need to renumber it */
6046       if (sym->islbl)
6047         fixupInlineLabel (sym);
6048     }
6049
6050   /* Update IFX target labels */
6051   if (tree->type == EX_OP && tree->opval.op == IFX)
6052     {
6053       if (tree->trueLabel)
6054         fixupInlineLabel (tree->trueLabel);
6055       if (tree->falseLabel)
6056         fixupInlineLabel (tree->falseLabel);
6057     }
6058
6059   /* Replace RETURN with optional assignment and a GOTO to the end */
6060   /* of the inlined function */
6061   if (tree->type == EX_OP && tree->opval.op == RETURN)
6062     {
6063       ast * assignTree = NULL;
6064       ast * gotoTree;
6065
6066       if (inlineState.retsym && tree->right)
6067         {
6068           assignTree = newNode ('=',
6069                                 newAst_VALUE (symbolVal (inlineState.retsym)),
6070                                 tree->right);
6071           copyAstLoc (assignTree, tree);
6072         }
6073
6074       gotoTree = newNode (GOTO,
6075                           newAst_VALUE (symbolVal (inlineState.retlab)),
6076                           NULL);
6077       copyAstLoc (gotoTree, tree);
6078
6079       tree->opval.op = NULLOP;
6080       tree->left = assignTree;
6081       tree->right = gotoTree;
6082     }
6083
6084    /* Update any children */
6085    if (tree->left)
6086       fixupInline (tree->left, level);
6087    if (tree->right)
6088       fixupInline (tree->right, level);
6089
6090   if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6091     {
6092       symbol * label = tree->left->opval.val->sym;
6093
6094       label->key = labelKey++;
6095       /* Add this label back into the symbol table */
6096       addSym (LabelTab, label, label->name, label->level, 0, 0);
6097     }
6098
6099
6100   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6101     {
6102       level--;
6103     }
6104 }
6105
6106 /*-----------------------------------------------------------------*/
6107 /* inlineAddDecl - add a variable declaration to an ast block. It  */
6108 /*                 is also added to the symbol table if addSymTab  */
6109 /*                 is nonzero.                                     */
6110 /*-----------------------------------------------------------------*/
6111 static void
6112 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6113 {
6114   sym->reqv = NULL;
6115   SYM_SPIL_LOC (sym) = NULL;
6116   sym->key = 0;
6117   if (block != NULL)
6118     {
6119       symbol **decl = &(block->values.sym);
6120
6121       sym->level = block->level;
6122       sym->block = block->block;
6123
6124       while (*decl)
6125         {
6126           if (strcmp ((*decl)->name, sym->name) == 0)
6127             return;
6128           decl = &( (*decl)->next );
6129         }
6130
6131       *decl = sym;
6132
6133       if (addSymTab)
6134         addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6135
6136     }
6137 }
6138
6139
6140 /*-----------------------------------------------------------------*/
6141 /* inlineTempVar - create a temporary variable for inlining        */
6142 /*-----------------------------------------------------------------*/
6143 static symbol *
6144 inlineTempVar (sym_link * type, int level)
6145 {
6146   symbol * sym;
6147
6148   sym = newSymbol (genSymName(level), level );
6149   sym->type = copyLinkChain (type);
6150   sym->etype = getSpec(sym->type);
6151   SPEC_SCLS (sym->etype) = S_AUTO;
6152   SPEC_OCLS (sym->etype) = NULL;
6153   SPEC_EXTR (sym->etype) = 0;
6154   SPEC_STAT (sym->etype) = 0;
6155   if IS_SPEC (sym->type)
6156     SPEC_VOLATILE (sym->type) = 0;
6157   else
6158     DCL_PTR_VOLATILE (sym->type) = 0;
6159   SPEC_ABSA (sym->etype) = 0;
6160
6161   return sym;
6162 }
6163
6164
6165 /*-----------------------------------------------------------------*/
6166 /* inlineFindParmRecurse - recursive function for inlineFindParm   */
6167 /*-----------------------------------------------------------------*/
6168 static ast *
6169 inlineFindParmRecurse (ast * parms, int *index)
6170 {
6171   if (!parms)
6172     return NULL;
6173
6174   if (parms->type == EX_OP && parms->opval.op == PARAM)
6175   {
6176     ast * p;
6177
6178     p=inlineFindParmRecurse (parms->left, index);
6179     if (p)
6180       return p;
6181     p=inlineFindParmRecurse (parms->right, index);
6182     if (p)
6183       return p;
6184   }
6185   if (!*index)
6186     return parms;
6187   (*index)--;
6188   return NULL;
6189 }
6190
6191
6192 /*-----------------------------------------------------------------*/
6193 /* inlineFindParm - search an ast tree of parameters to find one   */
6194 /*                  at a particular index (0=first parameter).     */
6195 /*                  Returns NULL if not found.                     */
6196 /*-----------------------------------------------------------------*/
6197 static ast *
6198 inlineFindParm (ast * parms, int index)
6199 {
6200   return inlineFindParmRecurse (parms, &index);
6201 }
6202
6203 /*-----------------------------------------------------------------*/
6204 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6205 /*-----------------------------------------------------------------*/
6206 static int
6207 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6208 {
6209   int tempBlockno;
6210
6211   if (!tree)
6212     return maxBlockno;
6213
6214   tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6215   if (tempBlockno > maxBlockno)
6216     maxBlockno = tempBlockno;
6217
6218   tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6219   if (tempBlockno > maxBlockno)
6220     maxBlockno = tempBlockno;
6221
6222   if (tree->block > maxBlockno)
6223     maxBlockno = tree->block;
6224   return maxBlockno;
6225 }
6226
6227
6228
6229
6230 /*-----------------------------------------------------------------*/
6231 /* expandInlineFuncs - replace calls to inline functions with the  */
6232 /*                     function itself                             */
6233 /*-----------------------------------------------------------------*/
6234 static void
6235 expandInlineFuncs (ast * tree, ast * block)
6236 {
6237   if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6238       && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6239     {
6240       symbol * func = tree->left->opval.val->sym;
6241       symbol * csym;
6242
6243       /* The symbol is probably not bound yet, so find the real one */
6244       csym = findSymWithLevel (SymbolTab, func);
6245       if (csym)
6246         func = csym;
6247
6248       /* Is this an inline function that we can inline? */
6249       if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6250         {
6251           symbol * retsym = NULL;
6252           symbol * retlab;
6253           ast * inlinetree;
6254           ast * inlinetree2;
6255           ast * temptree;
6256           value * args;
6257           int argIndex;
6258
6259           /* Generate a label for the inlined function to branch to */
6260           /* in case it contains a return statement */
6261           retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6262           retlab->isitmp = 1;
6263           retlab->islbl = 1;
6264           inlineState.retlab = retlab;
6265
6266           /* Build the subtree for the inlined function in the form: */
6267           /* { //inlinetree block                                    */
6268           /*   { //inlinetree2 block                                 */
6269           /*     inline_function_code;                               */
6270           /*     retlab:                                             */
6271           /*   }                                                     */
6272           /* }                                                       */
6273           temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6274           copyAstLoc (temptree, tree);
6275           temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6276           copyAstLoc (temptree, tree);
6277           temptree = newNode (BLOCK, NULL, temptree);
6278           copyAstLoc (temptree, tree);
6279           inlinetree2 = temptree;
6280           inlinetree = newNode (BLOCK, NULL, inlinetree2);
6281           copyAstLoc (inlinetree, tree);
6282
6283           /* To pass parameters to the inlined function, we need some  */
6284           /* intermediate variables. This avoids scoping problems      */
6285           /* when the parameter declaration names are used differently */
6286           /* during the function call. For example, a function         */
6287           /* declared as func(int x, int y) but called as func(y,x).   */
6288           /* { //inlinetree block                                      */
6289           /*   type1 temparg1 = argument1;                             */
6290           /*   ...                                                     */
6291           /*   typen tempargn = argumentn;                             */
6292           /*   { //inlinetree2 block                                   */
6293           /*     type1 param1 = temparg1;                              */
6294           /*     ...                                                   */
6295           /*     typen paramn = tempargn;                              */
6296           /*     inline_function_code;                                 */
6297           /*     retlab:                                               */
6298           /*   }                                                       */
6299           /* }                                                         */
6300           args = FUNC_ARGS (func->type);
6301           argIndex = 0;
6302           while (args)
6303             {
6304               symbol * temparg;
6305               ast * assigntree;
6306               symbol * parm;
6307               ast * passedarg = inlineFindParm (tree->right, argIndex);
6308
6309               if (!passedarg)
6310                 {
6311                   werror(E_TOO_FEW_PARMS);
6312                   break;
6313                 }
6314
6315               temparg = inlineTempVar (args->sym->type, tree->level+1);
6316               inlineAddDecl (temparg, inlinetree, FALSE);
6317
6318               assigntree = newNode ('=',
6319                                     newAst_VALUE (symbolVal (temparg)),
6320                                     passedarg);
6321               assigntree->initMode=1; // tell that assignment is initializer
6322               inlinetree->right = newNode (NULLOP,
6323                                            assigntree,
6324                                            inlinetree->right);
6325
6326               parm = copySymbol (args->sym);
6327               inlineAddDecl (parm, inlinetree2, FALSE);
6328               parm->_isparm = 0;
6329
6330               assigntree = newNode ('=',
6331                                     newAst_VALUE (symbolVal (parm)),
6332                                     newAst_VALUE (symbolVal (temparg)));
6333               assigntree->initMode=1; // tell that assignment is initializer
6334               inlinetree2->right = newNode (NULLOP,
6335                                            assigntree,
6336                                            inlinetree2->right);
6337
6338               args = args->next;
6339               argIndex++;
6340             }
6341
6342           /* Handle the return type */
6343           if (!IS_VOID (func->type->next))
6344             {
6345               /* Create a temporary symbol to hold the return value and   */
6346               /* join it with the inlined function using the comma        */
6347               /* operator. The fixupInline function will take care of     */
6348               /* changing return statements into assignments to retsym.   */
6349               /* (parameter passing and return label omitted for clarity) */
6350               /* rettype retsym;                                          */
6351               /* ...                                                      */
6352               /* {{inline_function_code}}, retsym                         */
6353
6354               retsym = inlineTempVar (func->type->next, tree->level);
6355               inlineAddDecl (retsym, block, TRUE);
6356
6357               tree->opval.op = ',';
6358               tree->left = inlinetree;
6359               tree->right = newAst_VALUE (symbolVal (retsym));
6360             }
6361           else
6362             {
6363               tree->opval.op = NULLOP;
6364               tree->left = NULL;
6365               tree->right = inlinetree;
6366             }
6367           inlineState.retsym = retsym;
6368
6369           /* Renumber the various internal counters on the inlined   */
6370           /* function's tree nodes and symbols. Add the inlined      */
6371           /* function's local variables to the appropriate scope(s). */
6372           /* Convert inlined return statements to an assignment to   */
6373           /* retsym (if needed) and a goto retlab.                   */
6374           fixupInline (inlinetree, inlinetree->level);
6375           inlineState.count++;
6376         }
6377     }
6378
6379   /* Recursively continue to search for functions to inline. */
6380   if (IS_AST_OP (tree))
6381     {
6382       if (tree->opval.op == BLOCK)
6383         block = tree;
6384
6385       if (tree->left)
6386         expandInlineFuncs (tree->left, block);
6387       if (tree->right)
6388         expandInlineFuncs (tree->right, block);
6389     }
6390 }
6391
6392
6393 /*-----------------------------------------------------------------*/
6394 /* createFunction - This is the key node that calls the iCode for  */
6395 /*                  generating the code for a function. Note code  */
6396 /*                  is generated function by function, later when  */
6397 /*                  add inter-procedural analysis this will change */
6398 /*-----------------------------------------------------------------*/
6399 ast *
6400 createFunction (symbol * name, ast * body)
6401 {
6402   ast *ex;
6403   symbol *csym;
6404   int stack = 0;
6405   sym_link *fetype;
6406   iCode *piCode = NULL;
6407   int savedBlockno;
6408
6409   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6410     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6411
6412   /* if check function return 0 then some problem */
6413   if (checkFunction (name, NULL) == 0)
6414     return NULL;
6415
6416   /* create a dummy block if none exists */
6417   if (!body)
6418     body = newNode (BLOCK, NULL, NULL);
6419
6420   noLineno++;
6421
6422   /* check if the function name already in the symbol table */
6423   if ((csym = findSym (SymbolTab, NULL, name->name)))
6424     {
6425       name = csym;
6426       /* special case for compiler defined functions
6427          we need to add the name to the publics list : this
6428          actually means we are now compiling the compiler
6429          support routine */
6430       if (name->cdef)
6431         {
6432           addSet (&publics, name);
6433         }
6434     }
6435   else
6436     {
6437       addSymChain (&name);
6438       allocVariables (name);
6439     }
6440   name->lastLine = lexLineno;
6441   currFunc = name;
6442
6443   /* set the stack pointer */
6444   stackPtr  = -port->stack.direction * port->stack.call_overhead;
6445   xstackPtr = 0;
6446
6447   if (IFFUNC_ISISR (name->type))
6448     stackPtr -= port->stack.direction * port->stack.isr_overhead;
6449
6450   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6451     {
6452       if (options.useXstack)
6453         xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6454       else
6455         stackPtr  -= port->stack.direction * port->stack.reent_overhead;
6456     }
6457
6458   fetype = getSpec (name->type);        /* get the specifier for the function */
6459   /* if this is a reentrant function then */
6460   if (IFFUNC_ISREENT (name->type))
6461     reentrant++;
6462
6463   inlineState.count = 0;
6464   savedBlockno = currBlockno;
6465   currBlockno = inlineFindMaxBlockno (body, 0);
6466   expandInlineFuncs (body, NULL);
6467   currBlockno = savedBlockno;
6468
6469   if (FUNC_ISINLINE (name->type))
6470     name->funcTree = copyAst (body);
6471
6472   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
6473
6474   /* do processing for parameters that are passed in registers */
6475   processRegParms (FUNC_ARGS(name->type), body);
6476
6477   /* set the stack pointer */
6478   stackPtr = 0;
6479   xstackPtr = -1;
6480
6481   gatherImplicitVariables (body, NULL);  /* move implicit variables into blocks */
6482
6483   /* allocate & autoinit the block variables */
6484   processBlockVars (body, &stack, ALLOCATE);
6485
6486   /* name needs to be mangled */
6487   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6488
6489   body = resolveSymbols (body); /* resolve the symbols */
6490   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6491
6492   /* save the stack information */
6493   if (options.useXstack)
6494     name->xstack = SPEC_STAK (fetype) = stack;
6495   else
6496     name->stack = SPEC_STAK (fetype) = stack;
6497
6498   ex = newAst_VALUE (symbolVal (name)); /* create name */
6499   ex = newNode (FUNCTION, ex, body);
6500   ex->values.args = FUNC_ARGS(name->type);
6501   ex->decorated=1;
6502   if (options.dump_tree)
6503     PA(ex);
6504   if (fatalError)
6505     goto skipall;
6506
6507   /* Do not generate code for inline functions unless extern also. */
6508 #if 0
6509   if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6510     goto skipall;
6511 #else
6512   /* Temporary hack: always generate code for static inline functions. */
6513   /* Ideally static inline functions should only be generated if needed. */
6514   if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6515     goto skipall;
6516 #endif
6517
6518   /* create the node & generate intermediate code */
6519   GcurMemmap = code;
6520   codeOutBuf = &code->oBuf;
6521   piCode = iCodeFromAst (ex);
6522   name->generated = 1;
6523
6524   if (fatalError)
6525     goto skipall;
6526
6527   eBBlockFromiCode (piCode);
6528
6529   /* if there are any statics then do them */
6530   if (staticAutos)
6531     {
6532       GcurMemmap = statsg;
6533       codeOutBuf = &statsg->oBuf;
6534       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6535       staticAutos = NULL;
6536     }
6537
6538 skipall:
6539
6540   /* dealloc the block variables */
6541   processBlockVars (body, &stack, DEALLOCATE);
6542   outputDebugStackSymbols();
6543   /* deallocate paramaters */
6544   deallocParms (FUNC_ARGS(name->type));
6545
6546   if (IFFUNC_ISREENT (name->type))
6547     reentrant--;
6548
6549   /* we are done freeup memory & cleanup */
6550   noLineno--;
6551   if (port->reset_labelKey) labelKey = 1;
6552   name->key = 0;
6553   FUNC_HASBODY(name->type) = 1;
6554   addSet (&operKeyReset, name);
6555   applyToSet (operKeyReset, resetParmKey);
6556
6557   if (options.debug)
6558     cdbStructBlock(1);
6559
6560   cleanUpLevel (LabelTab, 0);
6561   cleanUpBlock (StructTab, 1);
6562   cleanUpBlock (TypedefTab, 1);
6563
6564   xstack->syms = NULL;
6565   istack->syms = NULL;
6566   return NULL;
6567 }
6568
6569
6570 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6571 /*-----------------------------------------------------------------*/
6572 /* ast_print : prints the ast (for debugging purposes)             */
6573 /*-----------------------------------------------------------------*/
6574
6575 void ast_print (ast * tree, FILE *outfile, int indent)
6576 {
6577
6578   if (!tree) return ;
6579
6580   /* can print only decorated trees */
6581   if (!tree->decorated) return;
6582
6583   /* if any child is an error | this one is an error do nothing */
6584   if (tree->isError ||
6585     (tree->left && tree->left->isError) ||
6586     (tree->right && tree->right->isError)) {
6587     fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6588   }
6589
6590
6591   /* print the line          */
6592   /* if not block & function */
6593   if (tree->type == EX_OP &&
6594     (tree->opval.op != FUNCTION &&
6595     tree->opval.op != BLOCK &&
6596     tree->opval.op != NULLOP)) {
6597   }
6598
6599   if (tree->opval.op == FUNCTION) {
6600     int arg=0;
6601     value *args=FUNC_ARGS(tree->left->opval.val->type);
6602     fprintf(outfile,"FUNCTION (%s=%p) type (",
6603       tree->left->opval.val->name, tree);
6604     printTypeChain (tree->left->opval.val->type->next,outfile);
6605     fprintf(outfile,") args (");
6606     do {
6607       if (arg) {
6608         fprintf (outfile, ", ");
6609       }
6610       printTypeChain (args ? args->type : NULL, outfile);
6611       arg++;
6612       args= args ? args->next : NULL;
6613     } while (args);
6614     fprintf(outfile,")\n");
6615     ast_print(tree->left,outfile,indent);
6616     ast_print(tree->right,outfile,indent);
6617     return ;
6618   }
6619   if (tree->opval.op == BLOCK) {
6620     symbol *decls = tree->values.sym;
6621     INDENT(indent,outfile);
6622     fprintf(outfile,"{\n");
6623     while (decls) {
6624       INDENT(indent+2,outfile);
6625       fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6626         decls->name, decls);
6627       printTypeChain(decls->type,outfile);
6628       fprintf(outfile,")\n");
6629
6630       decls = decls->next;
6631     }
6632     ast_print(tree->right,outfile,indent+2);
6633     INDENT(indent,outfile);
6634     fprintf(outfile,"}\n");
6635     return;
6636   }
6637   if (tree->opval.op == NULLOP) {
6638     ast_print(tree->left,outfile,indent);
6639     ast_print(tree->right,outfile,indent);
6640     return ;
6641   }
6642   INDENT(indent,outfile);
6643
6644   /*------------------------------------------------------------------*/
6645   /*----------------------------*/
6646   /*   leaf has been reached    */
6647   /*----------------------------*/
6648   /* if this is of type value */
6649   /* just get the type        */
6650   if (tree->type == EX_VALUE) {
6651
6652     if (IS_LITERAL (tree->opval.val->etype)) {
6653       fprintf(outfile,"CONSTANT (%p) value = ", tree);
6654       if (SPEC_USIGN (tree->opval.val->etype))
6655         fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6656       else
6657         fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6658       fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6659         floatFromVal(tree->opval.val));
6660     } else if (tree->opval.val->sym) {
6661       /* if the undefined flag is set then give error message */
6662       if (tree->opval.val->sym->undefined) {
6663         fprintf(outfile,"UNDEFINED SYMBOL ");
6664       } else {
6665         fprintf(outfile,"SYMBOL ");
6666       }
6667       fprintf(outfile,"(%s=%p @ %p)",
6668         tree->opval.val->sym->name, tree, tree->opval.val->sym);
6669     }
6670     if (tree->ftype) {
6671       fprintf(outfile," type (");
6672       printTypeChain(tree->ftype,outfile);
6673       fprintf(outfile,")\n");
6674     } else {
6675       fprintf(outfile,"\n");
6676     }
6677     return ;
6678   }
6679
6680   /* if type link for the case of cast */
6681   if (tree->type == EX_LINK) {
6682     fprintf(outfile,"TYPENODE (%p) type = (",tree);
6683     printTypeChain(tree->opval.lnk,outfile);
6684     fprintf(outfile,")\n");
6685     return ;
6686   }
6687
6688
6689   /* depending on type of operator do */
6690
6691   switch (tree->opval.op) {
6692     /*------------------------------------------------------------------*/
6693     /*----------------------------*/
6694     /*        array node          */
6695     /*----------------------------*/
6696   case '[':
6697     fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6698     printTypeChain(tree->ftype,outfile);
6699     fprintf(outfile,")\n");
6700     ast_print(tree->left,outfile,indent+2);
6701     ast_print(tree->right,outfile,indent+2);
6702     return;
6703
6704     /*------------------------------------------------------------------*/
6705     /*----------------------------*/
6706     /*      struct/union          */
6707     /*----------------------------*/
6708   case '.':
6709     fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6710     printTypeChain(tree->ftype,outfile);
6711     fprintf(outfile,")\n");
6712     ast_print(tree->left,outfile,indent+2);
6713     ast_print(tree->right,outfile,indent+2);
6714     return ;
6715
6716     /*------------------------------------------------------------------*/
6717     /*----------------------------*/
6718     /*    struct/union pointer    */
6719     /*----------------------------*/
6720   case PTR_OP:
6721     fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6722     printTypeChain(tree->ftype,outfile);
6723     fprintf(outfile,")\n");
6724     ast_print(tree->left,outfile,indent+2);
6725     ast_print(tree->right,outfile,indent+2);
6726     return ;
6727
6728     /*------------------------------------------------------------------*/
6729     /*----------------------------*/
6730     /*  ++/-- operation           */
6731     /*----------------------------*/
6732   case INC_OP:
6733     if (tree->left)
6734       fprintf(outfile,"post-");
6735     else
6736       fprintf(outfile,"pre-");
6737     fprintf(outfile,"INC_OP (%p) type (",tree);
6738     printTypeChain(tree->ftype,outfile);
6739     fprintf(outfile,")\n");
6740     ast_print(tree->left,outfile,indent+2); /* postincrement case */
6741     ast_print(tree->right,outfile,indent+2); /* preincrement case */
6742     return ;
6743
6744   case DEC_OP:
6745     if (tree->left)
6746       fprintf(outfile,"post-");
6747     else
6748       fprintf(outfile,"pre-");
6749     fprintf(outfile,"DEC_OP (%p) type (",tree);
6750     printTypeChain(tree->ftype,outfile);
6751     fprintf(outfile,")\n");
6752     ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6753     ast_print(tree->right,outfile,indent+2); /* predecrement case */
6754     return ;
6755
6756     /*------------------------------------------------------------------*/
6757     /*----------------------------*/
6758     /*  bitwise and               */
6759     /*----------------------------*/
6760   case '&':
6761     if (tree->right) {
6762       fprintf(outfile,"& (%p) type (",tree);
6763       printTypeChain(tree->ftype,outfile);
6764       fprintf(outfile,")\n");
6765       ast_print(tree->left,outfile,indent+2);
6766       ast_print(tree->right,outfile,indent+2);
6767     } else {
6768       fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6769       printTypeChain(tree->ftype,outfile);
6770       fprintf(outfile,")\n");
6771       ast_print(tree->left,outfile,indent+2);
6772       ast_print(tree->right,outfile,indent+2);
6773     }
6774     return ;
6775     /*----------------------------*/
6776     /*  bitwise or                */
6777     /*----------------------------*/
6778   case '|':
6779     fprintf(outfile,"OR (%p) type (",tree);
6780     printTypeChain(tree->ftype,outfile);
6781     fprintf(outfile,")\n");
6782     ast_print(tree->left,outfile,indent+2);
6783     ast_print(tree->right,outfile,indent+2);
6784     return ;
6785     /*------------------------------------------------------------------*/
6786     /*----------------------------*/
6787     /*  bitwise xor               */
6788     /*----------------------------*/
6789   case '^':
6790     fprintf(outfile,"XOR (%p) type (",tree);
6791     printTypeChain(tree->ftype,outfile);
6792     fprintf(outfile,")\n");
6793     ast_print(tree->left,outfile,indent+2);
6794     ast_print(tree->right,outfile,indent+2);
6795     return ;
6796
6797     /*------------------------------------------------------------------*/
6798     /*----------------------------*/
6799     /*  division                  */
6800     /*----------------------------*/
6801   case '/':
6802     fprintf(outfile,"DIV (%p) type (",tree);
6803     printTypeChain(tree->ftype,outfile);
6804     fprintf(outfile,")\n");
6805     ast_print(tree->left,outfile,indent+2);
6806     ast_print(tree->right,outfile,indent+2);
6807     return ;
6808     /*------------------------------------------------------------------*/
6809     /*----------------------------*/
6810     /*            modulus         */
6811     /*----------------------------*/
6812   case '%':
6813     fprintf(outfile,"MOD (%p) type (",tree);
6814     printTypeChain(tree->ftype,outfile);
6815     fprintf(outfile,")\n");
6816     ast_print(tree->left,outfile,indent+2);
6817     ast_print(tree->right,outfile,indent+2);
6818     return ;
6819
6820     /*------------------------------------------------------------------*/
6821     /*----------------------------*/
6822     /*  address dereference       */
6823     /*----------------------------*/
6824   case '*':                       /* can be unary  : if right is null then unary operation */
6825     if (!tree->right) {
6826       fprintf(outfile,"DEREF (%p) type (",tree);
6827       printTypeChain(tree->ftype,outfile);
6828       fprintf(outfile,")\n");
6829       ast_print(tree->left,outfile,indent+2);
6830       return ;
6831     }
6832     /*------------------------------------------------------------------*/
6833     /*----------------------------*/
6834     /*      multiplication        */
6835     /*----------------------------*/
6836     fprintf(outfile,"MULT (%p) type (",tree);
6837     printTypeChain(tree->ftype,outfile);
6838     fprintf(outfile,")\n");
6839     ast_print(tree->left,outfile,indent+2);
6840     ast_print(tree->right,outfile,indent+2);
6841     return ;
6842
6843
6844     /*------------------------------------------------------------------*/
6845     /*----------------------------*/
6846     /*    unary '+' operator      */
6847     /*----------------------------*/
6848   case '+':
6849     /* if unary plus */
6850     if (!tree->right) {
6851       fprintf(outfile,"UPLUS (%p) type (",tree);
6852       printTypeChain(tree->ftype,outfile);
6853       fprintf(outfile,")\n");
6854       ast_print(tree->left,outfile,indent+2);
6855     } else {
6856       /*------------------------------------------------------------------*/
6857       /*----------------------------*/
6858       /*      addition              */
6859       /*----------------------------*/
6860       fprintf(outfile,"ADD (%p) type (",tree);
6861       printTypeChain(tree->ftype,outfile);
6862       fprintf(outfile,")\n");
6863       ast_print(tree->left,outfile,indent+2);
6864       ast_print(tree->right,outfile,indent+2);
6865     }
6866     return;
6867     /*------------------------------------------------------------------*/
6868     /*----------------------------*/
6869     /*      unary '-'             */
6870     /*----------------------------*/
6871   case '-':                       /* can be unary   */
6872     if (!tree->right) {
6873       fprintf(outfile,"UMINUS (%p) type (",tree);
6874       printTypeChain(tree->ftype,outfile);
6875       fprintf(outfile,")\n");
6876       ast_print(tree->left,outfile,indent+2);
6877     } else {
6878       /*------------------------------------------------------------------*/
6879       /*----------------------------*/
6880       /*      subtraction           */
6881       /*----------------------------*/
6882       fprintf(outfile,"SUB (%p) type (",tree);
6883       printTypeChain(tree->ftype,outfile);
6884       fprintf(outfile,")\n");
6885       ast_print(tree->left,outfile,indent+2);
6886       ast_print(tree->right,outfile,indent+2);
6887     }
6888     return;
6889     /*------------------------------------------------------------------*/
6890     /*----------------------------*/
6891     /*    complement              */
6892     /*----------------------------*/
6893   case '~':
6894     fprintf(outfile,"COMPL (%p) type (",tree);
6895     printTypeChain(tree->ftype,outfile);
6896     fprintf(outfile,")\n");
6897     ast_print(tree->left,outfile,indent+2);
6898     return ;
6899     /*------------------------------------------------------------------*/
6900     /*----------------------------*/
6901     /*           not              */
6902     /*----------------------------*/
6903   case '!':
6904     fprintf(outfile,"NOT (%p) type (",tree);
6905     printTypeChain(tree->ftype,outfile);
6906     fprintf(outfile,")\n");
6907     ast_print(tree->left,outfile,indent+2);
6908     return ;
6909     /*------------------------------------------------------------------*/
6910     /*----------------------------*/
6911     /*           shift            */
6912     /*----------------------------*/
6913   case RRC:
6914     fprintf(outfile,"RRC (%p) type (",tree);
6915     printTypeChain(tree->ftype,outfile);
6916     fprintf(outfile,")\n");
6917     ast_print(tree->left,outfile,indent+2);
6918     return ;
6919
6920   case RLC:
6921     fprintf(outfile,"RLC (%p) type (",tree);
6922     printTypeChain(tree->ftype,outfile);
6923     fprintf(outfile,")\n");
6924     ast_print(tree->left,outfile,indent+2);
6925     return ;
6926   case SWAP:
6927     fprintf(outfile,"SWAP (%p) type (",tree);
6928     printTypeChain(tree->ftype,outfile);
6929     fprintf(outfile,")\n");
6930     ast_print(tree->left,outfile,indent+2);
6931     return ;
6932   case GETHBIT:
6933     fprintf(outfile,"GETHBIT (%p) type (",tree);
6934     printTypeChain(tree->ftype,outfile);
6935     fprintf(outfile,")\n");
6936     ast_print(tree->left,outfile,indent+2);
6937     return ;
6938   case GETABIT:
6939     fprintf(outfile,"GETABIT (%p) type (",tree);
6940     printTypeChain(tree->ftype,outfile);
6941     fprintf(outfile,")\n");
6942     ast_print(tree->left,outfile,indent+2);
6943     ast_print(tree->right,outfile,indent+2);
6944     return ;
6945   case GETBYTE:
6946     fprintf(outfile,"GETBYTE (%p) type (",tree);
6947     printTypeChain(tree->ftype,outfile);
6948     fprintf(outfile,")\n");
6949     ast_print(tree->left,outfile,indent+2);
6950     ast_print(tree->right,outfile,indent+2);
6951     return ;
6952   case GETWORD:
6953     fprintf(outfile,"GETWORD (%p) type (",tree);
6954     printTypeChain(tree->ftype,outfile);
6955     fprintf(outfile,")\n");
6956     ast_print(tree->left,outfile,indent+2);
6957     ast_print(tree->right,outfile,indent+2);
6958     return ;
6959   case LEFT_OP:
6960     fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6961     printTypeChain(tree->ftype,outfile);
6962     fprintf(outfile,")\n");
6963     ast_print(tree->left,outfile,indent+2);
6964     ast_print(tree->right,outfile,indent+2);
6965     return ;
6966   case RIGHT_OP:
6967     fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6968     printTypeChain(tree->ftype,outfile);
6969     fprintf(outfile,")\n");
6970     ast_print(tree->left,outfile,indent+2);
6971     ast_print(tree->right,outfile,indent+2);
6972     return ;
6973     /*------------------------------------------------------------------*/
6974     /*----------------------------*/
6975     /*         casting            */
6976     /*----------------------------*/
6977   case CAST:                      /* change the type   */
6978     fprintf(outfile,"CAST (%p) from type (",tree);
6979     printTypeChain(tree->right->ftype,outfile);
6980     fprintf(outfile,") to type (");
6981     printTypeChain(tree->ftype,outfile);
6982     fprintf(outfile,")\n");
6983     ast_print(tree->right,outfile,indent+2);
6984     return ;
6985
6986   case AND_OP:
6987     fprintf(outfile,"ANDAND (%p) type (",tree);
6988     printTypeChain(tree->ftype,outfile);
6989     fprintf(outfile,")\n");
6990     ast_print(tree->left,outfile,indent+2);
6991     ast_print(tree->right,outfile,indent+2);
6992     return ;
6993   case OR_OP:
6994     fprintf(outfile,"OROR (%p) type (",tree);
6995     printTypeChain(tree->ftype,outfile);
6996     fprintf(outfile,")\n");
6997     ast_print(tree->left,outfile,indent+2);
6998     ast_print(tree->right,outfile,indent+2);
6999     return ;
7000
7001     /*------------------------------------------------------------------*/
7002     /*----------------------------*/
7003     /*     comparison operators   */
7004     /*----------------------------*/
7005   case '>':
7006     fprintf(outfile,"GT(>) (%p) type (",tree);
7007     printTypeChain(tree->ftype,outfile);
7008     fprintf(outfile,")\n");
7009     ast_print(tree->left,outfile,indent+2);
7010     ast_print(tree->right,outfile,indent+2);
7011     return ;
7012   case '<':
7013     fprintf(outfile,"LT(<) (%p) type (",tree);
7014     printTypeChain(tree->ftype,outfile);
7015     fprintf(outfile,")\n");
7016     ast_print(tree->left,outfile,indent+2);
7017     ast_print(tree->right,outfile,indent+2);
7018     return ;
7019   case LE_OP:
7020     fprintf(outfile,"LE(<=) (%p) type (",tree);
7021     printTypeChain(tree->ftype,outfile);
7022     fprintf(outfile,")\n");
7023     ast_print(tree->left,outfile,indent+2);
7024     ast_print(tree->right,outfile,indent+2);
7025     return ;
7026   case GE_OP:
7027     fprintf(outfile,"GE(>=) (%p) type (",tree);
7028     printTypeChain(tree->ftype,outfile);
7029     fprintf(outfile,")\n");
7030     ast_print(tree->left,outfile,indent+2);
7031     ast_print(tree->right,outfile,indent+2);
7032     return ;
7033   case EQ_OP:
7034     fprintf(outfile,"EQ(==) (%p) type (",tree);
7035     printTypeChain(tree->ftype,outfile);
7036     fprintf(outfile,")\n");
7037     ast_print(tree->left,outfile,indent+2);
7038     ast_print(tree->right,outfile,indent+2);
7039     return ;
7040   case NE_OP:
7041     fprintf(outfile,"NE(!=) (%p) type (",tree);
7042     printTypeChain(tree->ftype,outfile);
7043     fprintf(outfile,")\n");
7044     ast_print(tree->left,outfile,indent+2);
7045     ast_print(tree->right,outfile,indent+2);
7046     /*------------------------------------------------------------------*/
7047     /*----------------------------*/
7048     /*             sizeof         */
7049     /*----------------------------*/
7050   case SIZEOF:            /* evaluate wihout code generation */
7051     fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7052     return ;
7053
7054     /*------------------------------------------------------------------*/
7055     /*----------------------------*/
7056     /* conditional operator  '?'  */
7057     /*----------------------------*/
7058   case '?':
7059     fprintf(outfile,"QUEST(?) (%p) type (",tree);
7060     printTypeChain(tree->ftype,outfile);
7061     fprintf(outfile,")\n");
7062     ast_print(tree->left,outfile,indent+2);
7063     ast_print(tree->right,outfile,indent+2);
7064     return;
7065
7066   case ':':
7067     fprintf(outfile,"COLON(:) (%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     /*------------------------------------------------------------------*/
7075     /*----------------------------*/
7076     /*    assignment operators    */
7077     /*----------------------------*/
7078   case MUL_ASSIGN:
7079     fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7080     printTypeChain(tree->ftype,outfile);
7081     fprintf(outfile,")\n");
7082     ast_print(tree->left,outfile,indent+2);
7083     ast_print(tree->right,outfile,indent+2);
7084     return;
7085   case DIV_ASSIGN:
7086     fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7087     printTypeChain(tree->ftype,outfile);
7088     fprintf(outfile,")\n");
7089     ast_print(tree->left,outfile,indent+2);
7090     ast_print(tree->right,outfile,indent+2);
7091     return;
7092   case AND_ASSIGN:
7093     fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7094     printTypeChain(tree->ftype,outfile);
7095     fprintf(outfile,")\n");
7096     ast_print(tree->left,outfile,indent+2);
7097     ast_print(tree->right,outfile,indent+2);
7098     return;
7099   case OR_ASSIGN:
7100     fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7101     printTypeChain(tree->ftype,outfile);
7102     fprintf(outfile,")\n");
7103     ast_print(tree->left,outfile,indent+2);
7104     ast_print(tree->right,outfile,indent+2);
7105     return;
7106   case XOR_ASSIGN:
7107     fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7108     printTypeChain(tree->ftype,outfile);
7109     fprintf(outfile,")\n");
7110     ast_print(tree->left,outfile,indent+2);
7111     ast_print(tree->right,outfile,indent+2);
7112     return;
7113   case RIGHT_ASSIGN:
7114     fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7115     printTypeChain(tree->ftype,outfile);
7116     fprintf(outfile,")\n");
7117     ast_print(tree->left,outfile,indent+2);
7118     ast_print(tree->right,outfile,indent+2);
7119     return;
7120   case LEFT_ASSIGN:
7121     fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7122     printTypeChain(tree->ftype,outfile);
7123     fprintf(outfile,")\n");
7124     ast_print(tree->left,outfile,indent+2);
7125     ast_print(tree->right,outfile,indent+2);
7126     return;
7127     /*------------------------------------------------------------------*/
7128     /*----------------------------*/
7129     /*    -= operator             */
7130     /*----------------------------*/
7131   case SUB_ASSIGN:
7132     fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7133     printTypeChain(tree->ftype,outfile);
7134     fprintf(outfile,")\n");
7135     ast_print(tree->left,outfile,indent+2);
7136     ast_print(tree->right,outfile,indent+2);
7137     return;
7138     /*------------------------------------------------------------------*/
7139     /*----------------------------*/
7140     /*          += operator       */
7141     /*----------------------------*/
7142   case ADD_ASSIGN:
7143     fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7144     printTypeChain(tree->ftype,outfile);
7145     fprintf(outfile,")\n");
7146     ast_print(tree->left,outfile,indent+2);
7147     ast_print(tree->right,outfile,indent+2);
7148     return;
7149     /*------------------------------------------------------------------*/
7150     /*----------------------------*/
7151     /*      straight assignemnt   */
7152     /*----------------------------*/
7153   case '=':
7154     fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7155     printTypeChain(tree->ftype,outfile);
7156     fprintf(outfile,")\n");
7157     ast_print(tree->left,outfile,indent+2);
7158     ast_print(tree->right,outfile,indent+2);
7159     return;
7160     /*------------------------------------------------------------------*/
7161     /*----------------------------*/
7162     /*      comma operator        */
7163     /*----------------------------*/
7164   case ',':
7165     fprintf(outfile,"COMMA(,) (%p) type (",tree);
7166     printTypeChain(tree->ftype,outfile);
7167     fprintf(outfile,")\n");
7168     ast_print(tree->left,outfile,indent+2);
7169     ast_print(tree->right,outfile,indent+2);
7170     return;
7171     /*------------------------------------------------------------------*/
7172     /*----------------------------*/
7173     /*       function call        */
7174     /*----------------------------*/
7175   case CALL:
7176   case PCALL:
7177     fprintf(outfile,"CALL (%p) type (",tree);
7178     printTypeChain(tree->ftype,outfile);
7179     fprintf(outfile,")\n");
7180     ast_print(tree->left,outfile,indent+2);
7181     ast_print(tree->right,outfile,indent+2);
7182     return;
7183   case PARAM:
7184     fprintf(outfile,"PARMS\n");
7185     ast_print(tree->left,outfile,indent+2);
7186     if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7187       ast_print(tree->right,outfile,indent+2);
7188     }
7189     return ;
7190     /*------------------------------------------------------------------*/
7191     /*----------------------------*/
7192     /*     return statement       */
7193     /*----------------------------*/
7194   case RETURN:
7195     fprintf(outfile,"RETURN (%p) type (",tree);
7196     if (tree->right) {
7197       printTypeChain(tree->right->ftype,outfile);
7198     }
7199     fprintf(outfile,")\n");
7200     ast_print(tree->right,outfile,indent+2);
7201     return ;
7202     /*------------------------------------------------------------------*/
7203     /*----------------------------*/
7204     /*     label statement        */
7205     /*----------------------------*/
7206   case LABEL :
7207     fprintf(outfile,"LABEL (%p)\n",tree);
7208     ast_print(tree->left,outfile,indent+2);
7209     ast_print(tree->right,outfile,indent);
7210     return;
7211     /*------------------------------------------------------------------*/
7212     /*----------------------------*/
7213     /*     switch statement       */
7214     /*----------------------------*/
7215   case SWITCH:
7216     {
7217       value *val;
7218       fprintf(outfile,"SWITCH (%p) ",tree);
7219       ast_print(tree->left,outfile,0);
7220       for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7221         INDENT(indent+2,outfile);
7222         fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7223           (int) ulFromVal(val),
7224           tree->values.switchVals.swNum,
7225           (int) ulFromVal(val));
7226       }
7227       ast_print(tree->right,outfile,indent);
7228     }
7229     return ;
7230     /*------------------------------------------------------------------*/
7231     /*----------------------------*/
7232     /* ifx Statement              */
7233     /*----------------------------*/
7234   case IFX:
7235     fprintf(outfile,"IF (%p) \n",tree);
7236     ast_print(tree->left,outfile,indent+2);
7237     if (tree->trueLabel) {
7238       INDENT(indent+2,outfile);
7239       fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7240     }
7241     if (tree->falseLabel) {
7242       INDENT(indent+2,outfile);
7243       fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7244     }
7245     ast_print(tree->right,outfile,indent+2);
7246     return ;
7247     /*----------------------------*/
7248     /* goto Statement              */
7249     /*----------------------------*/
7250   case GOTO:
7251     fprintf(outfile,"GOTO (%p) \n",tree);
7252     ast_print(tree->left,outfile,indent+2);
7253     fprintf(outfile,"\n");
7254     return ;
7255     /*------------------------------------------------------------------*/
7256     /*----------------------------*/
7257     /* for Statement              */
7258     /*----------------------------*/
7259   case FOR:
7260     fprintf(outfile,"FOR (%p) \n",tree);
7261     if (AST_FOR( tree, initExpr)) {
7262       INDENT(indent+2,outfile);
7263       fprintf(outfile,"INIT EXPR ");
7264       ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7265     }
7266     if (AST_FOR( tree, condExpr)) {
7267       INDENT(indent+2,outfile);
7268       fprintf(outfile,"COND EXPR ");
7269       ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7270     }
7271     if (AST_FOR( tree, loopExpr)) {
7272       INDENT(indent+2,outfile);
7273       fprintf(outfile,"LOOP EXPR ");
7274       ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7275     }
7276     fprintf(outfile,"FOR LOOP BODY \n");
7277     ast_print(tree->left,outfile,indent+2);
7278     return ;
7279   case CRITICAL:
7280     fprintf(outfile,"CRITICAL (%p) \n",tree);
7281     ast_print(tree->left,outfile,indent+2);
7282   default:
7283     return ;
7284   }
7285 }
7286
7287 void PA(ast *t)
7288 {
7289   ast_print(t,stdout,0);
7290 }
7291
7292 /*-----------------------------------------------------------------*/
7293 /* astErrors : returns non-zero if errors present in tree          */
7294 /*-----------------------------------------------------------------*/
7295 int astErrors(ast *t)
7296 {
7297   int errors=0;
7298
7299   if (t)
7300     {
7301       if (t->isError)
7302         errors++;
7303
7304       if (t->type == EX_VALUE
7305           && t->opval.val->sym
7306           && t->opval.val->sym->undefined)
7307         errors++;
7308
7309       errors += astErrors(t->left);
7310       errors += astErrors(t->right);
7311     }
7312
7313   return errors;
7314 }