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