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