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